Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 726711f

Browse files
RaisinTenmhdawson
authored andcommittedJan 24, 2022
node-api: add node_api_symbol_for()
Fixes: #41294 Signed-off-by: Darshan Sen <raisinten@gmail.com> PR-URL: #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>
1 parent 3657c14 commit 726711f

File tree

7 files changed

+135
-6
lines changed

7 files changed

+135
-6
lines changed
 

‎doc/api/n-api.md

+32
Original file line numberDiff line numberDiff line change
@@ -2492,6 +2492,38 @@ This API creates a JavaScript `symbol` value from a UTF8-encoded C string.
24922492
The JavaScript `symbol` type is described in [Section 19.4][]
24932493
of the ECMAScript Language Specification.
24942494
2495+
#### `node_api_symbol_for`
2496+
2497+
<!-- YAML
2498+
added: REPLACEME
2499+
napiVersion: REPLACEME
2500+
-->
2501+
2502+
> Stability: 1 - Experimental
2503+
2504+
```c
2505+
napi_status node_api_symbol_for(napi_env env,
2506+
const char* utf8description,
2507+
size_t length,
2508+
napi_value* result)
2509+
```
2510+
2511+
* `[in] env`: The environment that the API is invoked under.
2512+
* `[in] utf8description`: UTF-8 C string representing the text to be used as the
2513+
description for the symbol.
2514+
* `[in] length`: The length of the description string in bytes, or
2515+
`NAPI_AUTO_LENGTH` if it is null-terminated.
2516+
* `[out] result`: A `napi_value` representing a JavaScript `symbol`.
2517+
2518+
Returns `napi_ok` if the API succeeded.
2519+
2520+
This API searches in the global registry for an existing symbol with the given
2521+
description. If the symbol already exists it will be returned, otherwise a new
2522+
symbol will be created in the registry.
2523+
2524+
The JavaScript `symbol` type is described in [Section 19.4][] of the ECMAScript
2525+
Language Specification.
2526+
24952527
#### `napi_create_typedarray`
24962528
24972529
<!-- YAML

‎src/js_native_api.h

+6
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ NAPI_EXTERN napi_status napi_create_string_utf16(napi_env env,
9393
NAPI_EXTERN napi_status napi_create_symbol(napi_env env,
9494
napi_value description,
9595
napi_value* result);
96+
#ifdef NAPI_EXPERIMENTAL
97+
NAPI_EXTERN napi_status node_api_symbol_for(napi_env env,
98+
const char* utf8description,
99+
size_t length,
100+
napi_value* result);
101+
#endif // NAPI_EXPERIMENTAL
96102
NAPI_EXTERN napi_status napi_create_function(napi_env env,
97103
const char* utf8name,
98104
size_t length,

‎src/js_native_api_v8.cc

+21
Original file line numberDiff line numberDiff line change
@@ -1662,6 +1662,27 @@ napi_status napi_create_symbol(napi_env env,
16621662
return napi_clear_last_error(env);
16631663
}
16641664

1665+
napi_status node_api_symbol_for(napi_env env,
1666+
const char* utf8description,
1667+
size_t length,
1668+
napi_value* result) {
1669+
CHECK_ENV(env);
1670+
CHECK_ARG(env, result);
1671+
1672+
napi_value js_description_string;
1673+
STATUS_CALL(napi_create_string_utf8(env,
1674+
utf8description,
1675+
length,
1676+
&js_description_string));
1677+
v8::Local<v8::String> description_string =
1678+
v8impl::V8LocalValueFromJsValue(js_description_string).As<v8::String>();
1679+
1680+
*result = v8impl::JsValueFromV8LocalValue(
1681+
v8::Symbol::For(env->isolate, description_string));
1682+
1683+
return napi_clear_last_error(env);
1684+
}
1685+
16651686
static inline napi_status set_error_code(napi_env env,
16661687
v8::Local<v8::Value> error,
16671688
napi_value code,

‎test/js-native-api/test_properties/test.js

+5-6
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,11 @@ assert.ok(!propertyNames.includes('readwriteAccessor2'));
3535
assert.ok(!propertyNames.includes('readonlyAccessor1'));
3636
assert.ok(!propertyNames.includes('readonlyAccessor2'));
3737

38-
// Validate property created with symbol
39-
const start = 'Symbol('.length;
40-
const end = start + 'NameKeySymbol'.length;
41-
const symbolDescription =
42-
String(Object.getOwnPropertySymbols(test_object)[0]).slice(start, end);
43-
assert.strictEqual(symbolDescription, 'NameKeySymbol');
38+
// Validate properties created with symbol
39+
const propertySymbols = Object.getOwnPropertySymbols(test_object);
40+
assert.strictEqual(propertySymbols[0].toString(), 'Symbol(NameKeySymbol)');
41+
assert.strictEqual(propertySymbols[1].toString(), 'Symbol()');
42+
assert.strictEqual(propertySymbols[2], Symbol.for('NameKeySymbolFor'));
4443

4544
// The napi_writable attribute should be ignored for accessors.
4645
const readwriteAccessor1Descriptor =

‎test/js-native-api/test_properties/test_properties.c

+13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#define NAPI_EXPERIMENTAL
12
#include <js_native_api.h>
23
#include "../common.h"
34

@@ -77,13 +78,25 @@ napi_value Init(napi_env env, napi_value exports) {
7778
NODE_API_CALL(env,
7879
napi_create_symbol(env, symbol_description, &name_symbol));
7980

81+
napi_value name_symbol_descriptionless;
82+
NODE_API_CALL(env,
83+
napi_create_symbol(env, NULL, &name_symbol_descriptionless));
84+
85+
napi_value name_symbol_for;
86+
NODE_API_CALL(env, node_api_symbol_for(env,
87+
"NameKeySymbolFor",
88+
NAPI_AUTO_LENGTH,
89+
&name_symbol_for));
90+
8091
napi_property_descriptor properties[] = {
8192
{ "echo", 0, Echo, 0, 0, 0, napi_enumerable, 0 },
8293
{ "readwriteValue", 0, 0, 0, 0, number, napi_enumerable | napi_writable, 0 },
8394
{ "readonlyValue", 0, 0, 0, 0, number, napi_enumerable, 0},
8495
{ "hiddenValue", 0, 0, 0, 0, number, napi_default, 0},
8596
{ NULL, name_value, 0, 0, 0, number, napi_enumerable, 0},
8697
{ NULL, name_symbol, 0, 0, 0, number, napi_enumerable, 0},
98+
{ NULL, name_symbol_descriptionless, 0, 0, 0, number, napi_enumerable, 0},
99+
{ NULL, name_symbol_for, 0, 0, 0, number, napi_enumerable, 0},
87100
{ "readwriteAccessor1", 0, 0, GetValue, SetValue, 0, napi_default, 0},
88101
{ "readwriteAccessor2", 0, 0, GetValue, SetValue, 0, napi_writable, 0},
89102
{ "readonlyAccessor1", 0, 0, GetValue, NULL, 0, napi_default, 0},

‎test/js-native-api/test_reference/test.js

+19
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,25 @@ async function runTests() {
2121
})();
2222
test_reference.deleteReference();
2323

24+
(() => {
25+
const symbol = test_reference.createSymbolFor('testSymFor');
26+
test_reference.createReference(symbol, 0);
27+
assert.strictEqual(test_reference.referenceValue, symbol);
28+
assert.strictEqual(test_reference.referenceValue, Symbol.for('testSymFor'));
29+
})();
30+
test_reference.deleteReference();
31+
32+
(() => {
33+
const symbol = test_reference.createSymbolForEmptyString();
34+
test_reference.createReference(symbol, 0);
35+
assert.strictEqual(test_reference.referenceValue, symbol);
36+
assert.strictEqual(test_reference.referenceValue, Symbol.for(''));
37+
})();
38+
test_reference.deleteReference();
39+
40+
assert.throws(() => test_reference.createSymbolForIncorrectLength(),
41+
/Invalid argument/);
42+
2443
(() => {
2544
const value = test_reference.createExternal();
2645
assert.strictEqual(test_reference.finalizeCount, 0);

‎test/js-native-api/test_reference/test_reference.c

+39
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#define NAPI_EXPERIMENTAL
12
#include <stdlib.h>
23
#include <assert.h>
34
#include <js_native_api.h>
@@ -49,6 +50,41 @@ static napi_value CreateSymbol(napi_env env, napi_callback_info info) {
4950
return result_symbol;
5051
}
5152

53+
static napi_value CreateSymbolFor(napi_env env, napi_callback_info info) {
54+
55+
size_t argc = 1;
56+
napi_value args[1];
57+
58+
char description[256];
59+
size_t description_length;
60+
61+
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL,NULL));
62+
NODE_API_ASSERT(env, argc == 1, "Expect one argument only (symbol description)");
63+
64+
NODE_API_CALL(env, napi_get_value_string_utf8(env, args[0], description, sizeof(description), &description_length));
65+
NODE_API_ASSERT(env, description_length <= 255, "Cannot accommodate descriptions longer than 255 bytes");
66+
67+
napi_value result_symbol;
68+
69+
NODE_API_CALL(env, node_api_symbol_for(env,
70+
description,
71+
description_length,
72+
&result_symbol));
73+
return result_symbol;
74+
}
75+
76+
static napi_value CreateSymbolForEmptyString(napi_env env, napi_callback_info info) {
77+
napi_value result_symbol;
78+
NODE_API_CALL(env, node_api_symbol_for(env, NULL, 0, &result_symbol));
79+
return result_symbol;
80+
}
81+
82+
static napi_value CreateSymbolForIncorrectLength(napi_env env, napi_callback_info info) {
83+
napi_value result_symbol;
84+
NODE_API_CALL(env, node_api_symbol_for(env, NULL, 5, &result_symbol));
85+
return result_symbol;
86+
}
87+
5288
static napi_value
5389
CreateExternalWithFinalize(napi_env env, napi_callback_info info) {
5490
napi_value result;
@@ -190,6 +226,9 @@ napi_value Init(napi_env env, napi_value exports) {
190226
DECLARE_NODE_API_PROPERTY("checkExternal", CheckExternal),
191227
DECLARE_NODE_API_PROPERTY("createReference", CreateReference),
192228
DECLARE_NODE_API_PROPERTY("createSymbol", CreateSymbol),
229+
DECLARE_NODE_API_PROPERTY("createSymbolFor", CreateSymbolFor),
230+
DECLARE_NODE_API_PROPERTY("createSymbolForEmptyString", CreateSymbolForEmptyString),
231+
DECLARE_NODE_API_PROPERTY("createSymbolForIncorrectLength", CreateSymbolForIncorrectLength),
193232
DECLARE_NODE_API_PROPERTY("deleteReference", DeleteReference),
194233
DECLARE_NODE_API_PROPERTY("incrementRefcount", IncrementRefcount),
195234
DECLARE_NODE_API_PROPERTY("decrementRefcount", DecrementRefcount),

0 commit comments

Comments
 (0)
Please sign in to comment.