Skip to content

Commit

Permalink
src: add napi_create_symbol_for()
Browse files Browse the repository at this point in the history
Fixes: nodejs#41294

Signed-off-by: Darshan Sen <darshan.sen@postman.com>
  • Loading branch information
RaisinTen committed Dec 26, 2021
1 parent 587b167 commit 9d3dc30
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 6 deletions.
27 changes: 27 additions & 0 deletions doc/api/n-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2492,6 +2492,33 @@ This API creates a JavaScript `symbol` value from a UTF8-encoded C string.
The JavaScript `symbol` type is described in [Section 19.4][]
of the ECMAScript Language Specification.
#### `napi_create_symbol_for`
<!-- YAML
added: REPLACEME
napiVersion: REPLACEME
-->
```c
napi_status napi_create_symbol_for(napi_env env,
napi_value description,
napi_value* result)
```
* `[in] env`: The environment that the API is invoked under.
* `[in] description`: Optional `napi_value` which refers to a JavaScript
`string` to be set as the description for the symbol.
* `[out] result`: A `napi_value` representing a JavaScript `symbol`.
Returns `napi_ok` if the API succeeded.
This API searches in the global registry for an existing symbol with the given
description. If the symbol already exists it will be returned, otherwise a new
symbol will be created in the registry.
The JavaScript `symbol` type is described in [Section 19.4][]
of the ECMAScript Language Specification.
#### `napi_create_typedarray`
<!-- YAML
Expand Down
3 changes: 3 additions & 0 deletions src/js_native_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ NAPI_EXTERN napi_status napi_create_string_utf16(napi_env env,
NAPI_EXTERN napi_status napi_create_symbol(napi_env env,
napi_value description,
napi_value* result);
NAPI_EXTERN napi_status napi_create_symbol_for(napi_env env,
napi_value description,
napi_value* result);
NAPI_EXTERN napi_status napi_create_function(napi_env env,
const char* utf8name,
size_t length,
Expand Down
22 changes: 22 additions & 0 deletions src/js_native_api_v8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1662,6 +1662,28 @@ napi_status napi_create_symbol(napi_env env,
return napi_clear_last_error(env);
}

napi_status napi_create_symbol_for(napi_env env,
napi_value description,
napi_value* result) {
CHECK_ENV(env);
CHECK_ARG(env, result);

v8::Isolate* isolate = env->isolate;

v8::Local<v8::Value> desc;
if (description == nullptr) {
CHECK_NEW_FROM_UTF8(env, desc, "undefined");
} else {
desc = v8impl::V8LocalValueFromJsValue(description);
RETURN_STATUS_IF_FALSE(env, desc->IsString(), napi_string_expected);
}

*result = v8impl::JsValueFromV8LocalValue(
v8::Symbol::For(isolate, desc.As<v8::String>()));

return napi_clear_last_error(env);
}

static inline napi_status set_error_code(napi_env env,
v8::Local<v8::Value> error,
napi_value code,
Expand Down
14 changes: 8 additions & 6 deletions test/js-native-api/test_properties/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ assert.ok(!propertyNames.includes('readwriteAccessor2'));
assert.ok(!propertyNames.includes('readonlyAccessor1'));
assert.ok(!propertyNames.includes('readonlyAccessor2'));

// Validate property created with symbol
const start = 'Symbol('.length;
const end = start + 'NameKeySymbol'.length;
const symbolDescription =
String(Object.getOwnPropertySymbols(test_object)[0]).slice(start, end);
assert.strictEqual(symbolDescription, 'NameKeySymbol');
// Validate properties created with symbol
const propertySymbols = Object.getOwnPropertySymbols(test_object);
assert.strictEqual(String(propertySymbols[0]), 'Symbol(NameKeySymbol)');
assert.strictEqual(String(propertySymbols[1]), 'Symbol()');
assert.strictEqual(propertySymbols[2], Symbol.for('NameKeySymbolFor'));
assert.strictEqual(propertySymbols[3], Symbol.for());
assert.strictEqual(propertySymbols[3], Symbol.for(undefined));
assert.strictEqual(propertySymbols[3], Symbol.for('undefined'));

// The napi_writable attribute should be ignored for accessors.
const readwriteAccessor1Descriptor =
Expand Down
19 changes: 19 additions & 0 deletions test/js-native-api/test_properties/test_properties.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,32 @@ napi_value Init(napi_env env, napi_value exports) {
NODE_API_CALL(env,
napi_create_symbol(env, symbol_description, &name_symbol));

napi_value name_symbol_undefined;
NODE_API_CALL(env,
napi_create_symbol(env, NULL, &name_symbol_undefined));

napi_value symbol_for_description;
napi_value name_symbol_for;
NODE_API_CALL(env,
napi_create_string_utf8(
env, "NameKeySymbolFor", NAPI_AUTO_LENGTH, &symbol_for_description));
NODE_API_CALL(env,
napi_create_symbol_for(env, symbol_for_description, &name_symbol_for));

napi_value name_symbol_for_undefined;
NODE_API_CALL(env,
napi_create_symbol_for(env, NULL, &name_symbol_for_undefined));

napi_property_descriptor properties[] = {
{ "echo", 0, Echo, 0, 0, 0, napi_enumerable, 0 },
{ "readwriteValue", 0, 0, 0, 0, number, napi_enumerable | napi_writable, 0 },
{ "readonlyValue", 0, 0, 0, 0, number, napi_enumerable, 0},
{ "hiddenValue", 0, 0, 0, 0, number, napi_default, 0},
{ NULL, name_value, 0, 0, 0, number, napi_enumerable, 0},
{ NULL, name_symbol, 0, 0, 0, number, napi_enumerable, 0},
{ NULL, name_symbol_undefined, 0, 0, 0, number, napi_enumerable, 0},
{ NULL, name_symbol_for, 0, 0, 0, number, napi_enumerable, 0},
{ NULL, name_symbol_for_undefined, 0, 0, 0, number, napi_enumerable, 0},
{ "readwriteAccessor1", 0, 0, GetValue, SetValue, 0, napi_default, 0},
{ "readwriteAccessor2", 0, 0, GetValue, SetValue, 0, napi_writable, 0},
{ "readonlyAccessor1", 0, 0, GetValue, NULL, 0, napi_default, 0},
Expand Down
7 changes: 7 additions & 0 deletions test/js-native-api/test_reference/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ async function runTests() {
})();
test_reference.deleteReference();

(() => {
const symbol = test_reference.createSymbolFor('testSymFor');
test_reference.createReference(Symbol.for('testSymFor'), 0);
assert.strictEqual(test_reference.referenceValue, symbol);
})();
test_reference.deleteReference();

(() => {
const value = test_reference.createExternal();
assert.strictEqual(test_reference.finalizeCount, 0);
Expand Down
15 changes: 15 additions & 0 deletions test/js-native-api/test_reference/test_reference.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ static napi_value CreateSymbol(napi_env env, napi_callback_info info) {
return result_symbol;
}

static napi_value CreateSymbolFor(napi_env env, napi_callback_info info) {

size_t argc = 1;
napi_value args[1];

NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL,NULL));
NODE_API_ASSERT(env, argc == 1, "Expect one argument only (symbol description)");

napi_value result_symbol;

NODE_API_CALL(env, napi_create_symbol_for(env, args[0], &result_symbol));
return result_symbol;
}

static napi_value
CreateExternalWithFinalize(napi_env env, napi_callback_info info) {
napi_value result;
Expand Down Expand Up @@ -190,6 +204,7 @@ napi_value Init(napi_env env, napi_value exports) {
DECLARE_NODE_API_PROPERTY("checkExternal", CheckExternal),
DECLARE_NODE_API_PROPERTY("createReference", CreateReference),
DECLARE_NODE_API_PROPERTY("createSymbol", CreateSymbol),
DECLARE_NODE_API_PROPERTY("createSymbolFor", CreateSymbolFor),
DECLARE_NODE_API_PROPERTY("deleteReference", DeleteReference),
DECLARE_NODE_API_PROPERTY("incrementRefcount", IncrementRefcount),
DECLARE_NODE_API_PROPERTY("decrementRefcount", DecrementRefcount),
Expand Down

0 comments on commit 9d3dc30

Please sign in to comment.