node-api: add node_api_symbol_for()
Fixes: https://github.com/nodejs/node/issues/41294 Signed-off-by: Darshan Sen <raisinten@gmail.com> PR-URL: https://github.com/nodejs/node/pull/41329 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Michael Dawson <midawson@redhat.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
3657c14598
commit
726711fe4e
@ -2492,6 +2492,38 @@ 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.
|
||||
|
||||
#### `node_api_symbol_for`
|
||||
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
napiVersion: REPLACEME
|
||||
-->
|
||||
|
||||
> Stability: 1 - Experimental
|
||||
|
||||
```c
|
||||
napi_status node_api_symbol_for(napi_env env,
|
||||
const char* utf8description,
|
||||
size_t length,
|
||||
napi_value* result)
|
||||
```
|
||||
|
||||
* `[in] env`: The environment that the API is invoked under.
|
||||
* `[in] utf8description`: UTF-8 C string representing the text to be used as the
|
||||
description for the symbol.
|
||||
* `[in] length`: The length of the description string in bytes, or
|
||||
`NAPI_AUTO_LENGTH` if it is null-terminated.
|
||||
* `[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
|
||||
|
@ -93,6 +93,12 @@ 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);
|
||||
#ifdef NAPI_EXPERIMENTAL
|
||||
NAPI_EXTERN napi_status node_api_symbol_for(napi_env env,
|
||||
const char* utf8description,
|
||||
size_t length,
|
||||
napi_value* result);
|
||||
#endif // NAPI_EXPERIMENTAL
|
||||
NAPI_EXTERN napi_status napi_create_function(napi_env env,
|
||||
const char* utf8name,
|
||||
size_t length,
|
||||
|
@ -1662,6 +1662,27 @@ napi_status napi_create_symbol(napi_env env,
|
||||
return napi_clear_last_error(env);
|
||||
}
|
||||
|
||||
napi_status node_api_symbol_for(napi_env env,
|
||||
const char* utf8description,
|
||||
size_t length,
|
||||
napi_value* result) {
|
||||
CHECK_ENV(env);
|
||||
CHECK_ARG(env, result);
|
||||
|
||||
napi_value js_description_string;
|
||||
STATUS_CALL(napi_create_string_utf8(env,
|
||||
utf8description,
|
||||
length,
|
||||
&js_description_string));
|
||||
v8::Local<v8::String> description_string =
|
||||
v8impl::V8LocalValueFromJsValue(js_description_string).As<v8::String>();
|
||||
|
||||
*result = v8impl::JsValueFromV8LocalValue(
|
||||
v8::Symbol::For(env->isolate, description_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,
|
||||
|
@ -35,12 +35,11 @@ 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(propertySymbols[0].toString(), 'Symbol(NameKeySymbol)');
|
||||
assert.strictEqual(propertySymbols[1].toString(), 'Symbol()');
|
||||
assert.strictEqual(propertySymbols[2], Symbol.for('NameKeySymbolFor'));
|
||||
|
||||
// The napi_writable attribute should be ignored for accessors.
|
||||
const readwriteAccessor1Descriptor =
|
||||
|
@ -1,3 +1,4 @@
|
||||
#define NAPI_EXPERIMENTAL
|
||||
#include <js_native_api.h>
|
||||
#include "../common.h"
|
||||
|
||||
@ -77,6 +78,16 @@ 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_descriptionless;
|
||||
NODE_API_CALL(env,
|
||||
napi_create_symbol(env, NULL, &name_symbol_descriptionless));
|
||||
|
||||
napi_value name_symbol_for;
|
||||
NODE_API_CALL(env, node_api_symbol_for(env,
|
||||
"NameKeySymbolFor",
|
||||
NAPI_AUTO_LENGTH,
|
||||
&name_symbol_for));
|
||||
|
||||
napi_property_descriptor properties[] = {
|
||||
{ "echo", 0, Echo, 0, 0, 0, napi_enumerable, 0 },
|
||||
{ "readwriteValue", 0, 0, 0, 0, number, napi_enumerable | napi_writable, 0 },
|
||||
@ -84,6 +95,8 @@ napi_value Init(napi_env env, napi_value exports) {
|
||||
{ "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_descriptionless, 0, 0, 0, number, napi_enumerable, 0},
|
||||
{ NULL, name_symbol_for, 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},
|
||||
|
@ -21,6 +21,25 @@ async function runTests() {
|
||||
})();
|
||||
test_reference.deleteReference();
|
||||
|
||||
(() => {
|
||||
const symbol = test_reference.createSymbolFor('testSymFor');
|
||||
test_reference.createReference(symbol, 0);
|
||||
assert.strictEqual(test_reference.referenceValue, symbol);
|
||||
assert.strictEqual(test_reference.referenceValue, Symbol.for('testSymFor'));
|
||||
})();
|
||||
test_reference.deleteReference();
|
||||
|
||||
(() => {
|
||||
const symbol = test_reference.createSymbolForEmptyString();
|
||||
test_reference.createReference(symbol, 0);
|
||||
assert.strictEqual(test_reference.referenceValue, symbol);
|
||||
assert.strictEqual(test_reference.referenceValue, Symbol.for(''));
|
||||
})();
|
||||
test_reference.deleteReference();
|
||||
|
||||
assert.throws(() => test_reference.createSymbolForIncorrectLength(),
|
||||
/Invalid argument/);
|
||||
|
||||
(() => {
|
||||
const value = test_reference.createExternal();
|
||||
assert.strictEqual(test_reference.finalizeCount, 0);
|
||||
|
@ -1,3 +1,4 @@
|
||||
#define NAPI_EXPERIMENTAL
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <js_native_api.h>
|
||||
@ -49,6 +50,41 @@ 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];
|
||||
|
||||
char description[256];
|
||||
size_t description_length;
|
||||
|
||||
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)");
|
||||
|
||||
NODE_API_CALL(env, napi_get_value_string_utf8(env, args[0], description, sizeof(description), &description_length));
|
||||
NODE_API_ASSERT(env, description_length <= 255, "Cannot accommodate descriptions longer than 255 bytes");
|
||||
|
||||
napi_value result_symbol;
|
||||
|
||||
NODE_API_CALL(env, node_api_symbol_for(env,
|
||||
description,
|
||||
description_length,
|
||||
&result_symbol));
|
||||
return result_symbol;
|
||||
}
|
||||
|
||||
static napi_value CreateSymbolForEmptyString(napi_env env, napi_callback_info info) {
|
||||
napi_value result_symbol;
|
||||
NODE_API_CALL(env, node_api_symbol_for(env, NULL, 0, &result_symbol));
|
||||
return result_symbol;
|
||||
}
|
||||
|
||||
static napi_value CreateSymbolForIncorrectLength(napi_env env, napi_callback_info info) {
|
||||
napi_value result_symbol;
|
||||
NODE_API_CALL(env, node_api_symbol_for(env, NULL, 5, &result_symbol));
|
||||
return result_symbol;
|
||||
}
|
||||
|
||||
static napi_value
|
||||
CreateExternalWithFinalize(napi_env env, napi_callback_info info) {
|
||||
napi_value result;
|
||||
@ -190,6 +226,9 @@ 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("createSymbolForEmptyString", CreateSymbolForEmptyString),
|
||||
DECLARE_NODE_API_PROPERTY("createSymbolForIncorrectLength", CreateSymbolForIncorrectLength),
|
||||
DECLARE_NODE_API_PROPERTY("deleteReference", DeleteReference),
|
||||
DECLARE_NODE_API_PROPERTY("incrementRefcount", IncrementRefcount),
|
||||
DECLARE_NODE_API_PROPERTY("decrementRefcount", DecrementRefcount),
|
||||
|
Loading…
x
Reference in New Issue
Block a user