Skip to content

Commit 3f18a83

Browse files
joyeecheungdanielleadams
authored andcommitted
util: use private symbols in JS land directly
Instead of calling into C++ to use the private symbols, use an ObjectTemplate to create an object that holds the symbols and use them directly from JS land. PR-URL: #45379 Backport-PR-URL: #45674 Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Signed-off-by: Daeyeon Jeong <daeyeon.dev@gmail.com>
1 parent 7e386f8 commit 3f18a83

File tree

7 files changed

+51
-94
lines changed

7 files changed

+51
-94
lines changed

lib/internal/bootstrap/node.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,9 @@ const {
7777
exposeInterface,
7878
} = require('internal/util');
7979
const {
80-
exiting_aliased_Uint32Array,
81-
getHiddenValue,
80+
privateSymbols: {
81+
exiting_aliased_Uint32Array,
82+
},
8283
} = internalBinding('util');
8384

8485
setupProcessObject();
@@ -88,8 +89,7 @@ setupBuffer();
8889

8990
process.domain = null;
9091
{
91-
const exitingAliasedUint32Array =
92-
getHiddenValue(process, exiting_aliased_Uint32Array);
92+
const exitingAliasedUint32Array = process[exiting_aliased_Uint32Array];
9393
ObjectDefineProperty(process, '_exiting', {
9494
__proto__: null,
9595
get() {

lib/internal/buffer.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ const {
3232
utf8Write,
3333
getZeroFillToggle
3434
} = internalBinding('buffer');
35+
3536
const {
36-
untransferable_object_private_symbol,
37-
setHiddenValue,
37+
privateSymbols: {
38+
untransferable_object_private_symbol,
39+
},
3840
} = internalBinding('util');
3941

4042
// Temporary buffers to convert numbers.
@@ -1048,7 +1050,7 @@ function addBufferPrototypeMethods(proto) {
10481050
function markAsUntransferable(obj) {
10491051
if ((typeof obj !== 'object' && typeof obj !== 'function') || obj === null)
10501052
return; // This object is a primitive and therefore already untransferable.
1051-
setHiddenValue(obj, untransferable_object_private_symbol, true);
1053+
obj[untransferable_object_private_symbol] = true;
10521054
}
10531055

10541056
// A toggle used to access the zero fill setting of the array buffer allocator

lib/internal/errors.js

+6-8
Original file line numberDiff line numberDiff line change
@@ -816,16 +816,14 @@ const fatalExceptionStackEnhancers = {
816816
}
817817
};
818818

819+
const {
820+
privateSymbols: {
821+
arrow_message_private_symbol,
822+
}
823+
} = internalBinding('util');
819824
// Ensures the printed error line is from user code.
820-
let _kArrowMessagePrivateSymbol, _setHiddenValue;
821825
function setArrowMessage(err, arrowMessage) {
822-
if (!_kArrowMessagePrivateSymbol) {
823-
({
824-
arrow_message_private_symbol: _kArrowMessagePrivateSymbol,
825-
setHiddenValue: _setHiddenValue,
826-
} = internalBinding('util'));
827-
}
828-
_setHiddenValue(err, _kArrowMessagePrivateSymbol, arrowMessage);
826+
err[arrow_message_private_symbol] = arrowMessage;
829827
}
830828

831829
// Hide stack lines before the first user code line.

lib/internal/util.js

+7-8
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ const {
4242
} = require('internal/errors');
4343
const { signals } = internalBinding('constants').os;
4444
const {
45-
getHiddenValue,
46-
setHiddenValue,
47-
arrow_message_private_symbol: kArrowMessagePrivateSymbolIndex,
48-
decorated_private_symbol: kDecoratedPrivateSymbolIndex,
45+
privateSymbols: {
46+
arrow_message_private_symbol,
47+
decorated_private_symbol,
48+
},
4949
sleep: _sleep,
5050
toUSVString: _toUSVString,
5151
} = internalBinding('util');
@@ -140,15 +140,14 @@ function deprecate(fn, msg, code) {
140140
}
141141

142142
function decorateErrorStack(err) {
143-
if (!(isError(err) && err.stack) ||
144-
getHiddenValue(err, kDecoratedPrivateSymbolIndex) === true)
143+
if (!(isError(err) && err.stack) || err[decorated_private_symbol])
145144
return;
146145

147-
const arrow = getHiddenValue(err, kArrowMessagePrivateSymbolIndex);
146+
const arrow = err[arrow_message_private_symbol];
148147

149148
if (arrow) {
150149
err.stack = arrow + err.stack;
151-
setHiddenValue(err, kDecoratedPrivateSymbolIndex, true);
150+
err[decorated_private_symbol] = true;
152151
}
153152
}
154153

src/node_util.cc

+12-49
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ using v8::Object;
2626
using v8::ONLY_CONFIGURABLE;
2727
using v8::ONLY_ENUMERABLE;
2828
using v8::ONLY_WRITABLE;
29-
using v8::Private;
3029
using v8::Promise;
3130
using v8::PropertyFilter;
3231
using v8::Proxy;
@@ -159,44 +158,6 @@ static void PreviewEntries(const FunctionCallbackInfo<Value>& args) {
159158
Array::New(env->isolate(), ret, arraysize(ret)));
160159
}
161160

162-
inline Local<Private> IndexToPrivateSymbol(Environment* env, uint32_t index) {
163-
#define V(name, _) &Environment::name,
164-
static Local<Private> (Environment::*const methods[])() const = {
165-
PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V)
166-
};
167-
#undef V
168-
CHECK_LT(index, arraysize(methods));
169-
return (env->*methods[index])();
170-
}
171-
172-
static void GetHiddenValue(const FunctionCallbackInfo<Value>& args) {
173-
Environment* env = Environment::GetCurrent(args);
174-
175-
CHECK(args[0]->IsObject());
176-
CHECK(args[1]->IsUint32());
177-
178-
Local<Object> obj = args[0].As<Object>();
179-
uint32_t index = args[1].As<Uint32>()->Value();
180-
Local<Private> private_symbol = IndexToPrivateSymbol(env, index);
181-
Local<Value> ret;
182-
if (obj->GetPrivate(env->context(), private_symbol).ToLocal(&ret))
183-
args.GetReturnValue().Set(ret);
184-
}
185-
186-
static void SetHiddenValue(const FunctionCallbackInfo<Value>& args) {
187-
Environment* env = Environment::GetCurrent(args);
188-
189-
CHECK(args[0]->IsObject());
190-
CHECK(args[1]->IsUint32());
191-
192-
Local<Object> obj = args[0].As<Object>();
193-
uint32_t index = args[1].As<Uint32>()->Value();
194-
Local<Private> private_symbol = IndexToPrivateSymbol(env, index);
195-
bool ret;
196-
if (obj->SetPrivate(env->context(), private_symbol, args[2]).To(&ret))
197-
args.GetReturnValue().Set(ret);
198-
}
199-
200161
static void Sleep(const FunctionCallbackInfo<Value>& args) {
201162
CHECK(args[0]->IsUint32());
202163
uint32_t msec = args[0].As<Uint32>()->Value();
@@ -386,8 +347,6 @@ static void ToUSVString(const FunctionCallbackInfo<Value>& args) {
386347
}
387348

388349
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
389-
registry->Register(GetHiddenValue);
390-
registry->Register(SetHiddenValue);
391350
registry->Register(GetPromiseDetails);
392351
registry->Register(GetProxyDetails);
393352
registry->Register(PreviewEntries);
@@ -412,16 +371,22 @@ void Initialize(Local<Object> target,
412371
Environment* env = Environment::GetCurrent(context);
413372
Isolate* isolate = env->isolate();
414373

415-
#define V(name, _) \
416-
target->Set(context, \
417-
FIXED_ONE_BYTE_STRING(env->isolate(), #name), \
418-
Integer::NewFromUnsigned(env->isolate(), index++)).Check();
419374
{
420-
uint32_t index = 0;
375+
Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
376+
#define V(PropertyName, _) \
377+
tmpl->Set(FIXED_ONE_BYTE_STRING(env->isolate(), #PropertyName), \
378+
env->PropertyName());
379+
421380
PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V)
422-
}
423381
#undef V
424382

383+
target
384+
->Set(context,
385+
FIXED_ONE_BYTE_STRING(isolate, "privateSymbols"),
386+
tmpl->NewInstance(context).ToLocalChecked())
387+
.Check();
388+
}
389+
425390
#define V(name) \
426391
target->Set(context, \
427392
FIXED_ONE_BYTE_STRING(env->isolate(), #name), \
@@ -432,8 +397,6 @@ void Initialize(Local<Object> target,
432397
V(kRejected);
433398
#undef V
434399

435-
SetMethodNoSideEffect(context, target, "getHiddenValue", GetHiddenValue);
436-
SetMethod(context, target, "setHiddenValue", SetHiddenValue);
437400
SetMethodNoSideEffect(
438401
context, target, "getPromiseDetails", GetPromiseDetails);
439402
SetMethodNoSideEffect(context, target, "getProxyDetails", GetProxyDetails);

test/parallel/test-internal-util-decorate-error-stack.js

+8-7
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ const fixtures = require('../common/fixtures');
55
const assert = require('assert');
66
const internalUtil = require('internal/util');
77
const { internalBinding } = require('internal/test/binding');
8-
const binding = internalBinding('util');
8+
const {
9+
privateSymbols: {
10+
arrow_message_private_symbol,
11+
decorated_private_symbol,
12+
}
13+
} = internalBinding('util');
914
const spawnSync = require('child_process').spawnSync;
1015

11-
const kArrowMessagePrivateSymbolIndex = binding.arrow_message_private_symbol;
12-
const kDecoratedPrivateSymbolIndex = binding.decorated_private_symbol;
13-
1416
const decorateErrorStack = internalUtil.decorateErrorStack;
1517

1618
// Verify that decorateErrorStack does not throw with non-objects.
@@ -73,9 +75,8 @@ const arrowMessage = 'arrow_message';
7375
err = new Error('foo');
7476
originalStack = err.stack;
7577

76-
binding.setHiddenValue(err, kArrowMessagePrivateSymbolIndex, arrowMessage);
78+
err[arrow_message_private_symbol] = arrowMessage;
7779
decorateErrorStack(err);
7880

7981
assert.strictEqual(err.stack, `${arrowMessage}${originalStack}`);
80-
assert.strictEqual(
81-
binding.getHiddenValue(err, kDecoratedPrivateSymbolIndex), true);
82+
assert.strictEqual(err[decorated_private_symbol], true);

test/parallel/test-util-internal.js

+9-15
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,24 @@ const fixtures = require('../common/fixtures');
77
const { internalBinding } = require('internal/test/binding');
88

99
const {
10-
getHiddenValue,
11-
setHiddenValue,
12-
arrow_message_private_symbol: kArrowMessagePrivateSymbolIndex
10+
privateSymbols: {
11+
arrow_message_private_symbol,
12+
},
1313
} = internalBinding('util');
1414

15-
assert.strictEqual(
16-
getHiddenValue({}, kArrowMessagePrivateSymbolIndex),
17-
undefined);
18-
1915
const obj = {};
20-
assert.strictEqual(
21-
setHiddenValue(obj, kArrowMessagePrivateSymbolIndex, 'bar'),
22-
true);
23-
assert.strictEqual(
24-
getHiddenValue(obj, kArrowMessagePrivateSymbolIndex),
25-
'bar');
16+
assert.strictEqual(obj[arrow_message_private_symbol], undefined);
17+
18+
obj[arrow_message_private_symbol] = 'bar';
19+
assert.strictEqual(obj[arrow_message_private_symbol], 'bar');
20+
assert.deepStrictEqual(Reflect.ownKeys(obj), []);
2621

2722
let arrowMessage;
2823

2924
try {
3025
require(fixtures.path('syntax', 'bad_syntax'));
3126
} catch (err) {
32-
arrowMessage =
33-
getHiddenValue(err, kArrowMessagePrivateSymbolIndex);
27+
arrowMessage = err[arrow_message_private_symbol];
3428
}
3529

3630
assert.match(arrowMessage, /bad_syntax\.js:1/);

0 commit comments

Comments
 (0)