lib,src: drop dependency on v8::Private::ForApi()
Said function requires that a v8::Context has been entered first, introducing a chicken-and-egg problem when creating the first context. PR-URL: https://github.com/nodejs/node/pull/7082 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
This commit is contained in:
parent
c3cd453cba
commit
334ef4f19d
@ -3,6 +3,9 @@
|
|||||||
const binding = process.binding('util');
|
const binding = process.binding('util');
|
||||||
const prefix = `(${process.release.name}:${process.pid}) `;
|
const prefix = `(${process.release.name}:${process.pid}) `;
|
||||||
|
|
||||||
|
const kArrowMessagePrivateSymbolIndex = binding['arrow_message_private_symbol'];
|
||||||
|
const kDecoratedPrivateSymbolIndex = binding['decorated_private_symbol'];
|
||||||
|
|
||||||
exports.getHiddenValue = binding.getHiddenValue;
|
exports.getHiddenValue = binding.getHiddenValue;
|
||||||
exports.setHiddenValue = binding.setHiddenValue;
|
exports.setHiddenValue = binding.setHiddenValue;
|
||||||
|
|
||||||
@ -65,14 +68,14 @@ exports._deprecate = function(fn, msg) {
|
|||||||
|
|
||||||
exports.decorateErrorStack = function decorateErrorStack(err) {
|
exports.decorateErrorStack = function decorateErrorStack(err) {
|
||||||
if (!(exports.isError(err) && err.stack) ||
|
if (!(exports.isError(err) && err.stack) ||
|
||||||
exports.getHiddenValue(err, 'node:decorated') === true)
|
exports.getHiddenValue(err, kDecoratedPrivateSymbolIndex) === true)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const arrow = exports.getHiddenValue(err, 'node:arrowMessage');
|
const arrow = exports.getHiddenValue(err, kArrowMessagePrivateSymbolIndex);
|
||||||
|
|
||||||
if (arrow) {
|
if (arrow) {
|
||||||
err.stack = arrow + err.stack;
|
err.stack = arrow + err.stack;
|
||||||
exports.setHiddenValue(err, 'node:decorated', true);
|
exports.setHiddenValue(err, kDecoratedPrivateSymbolIndex, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -169,16 +169,10 @@ void Agent::WorkerRun() {
|
|||||||
Isolate::Scope isolate_scope(isolate);
|
Isolate::Scope isolate_scope(isolate);
|
||||||
|
|
||||||
HandleScope handle_scope(isolate);
|
HandleScope handle_scope(isolate);
|
||||||
|
IsolateData isolate_data(isolate, &child_loop_);
|
||||||
Local<Context> context = Context::New(isolate);
|
Local<Context> context = Context::New(isolate);
|
||||||
|
|
||||||
Context::Scope context_scope(context);
|
Context::Scope context_scope(context);
|
||||||
|
|
||||||
// FIXME(bnoordhuis) Work around V8 bug: v8::Private::ForApi() dereferences
|
|
||||||
// a nullptr when a context hasn't been entered first. The symbol registry
|
|
||||||
// is a lazily created JS object but object instantiation does not work
|
|
||||||
// without a context.
|
|
||||||
IsolateData isolate_data(isolate, &child_loop_);
|
|
||||||
|
|
||||||
Environment* env = CreateEnvironment(
|
Environment* env = CreateEnvironment(
|
||||||
&isolate_data,
|
&isolate_data,
|
||||||
context,
|
context,
|
||||||
|
@ -29,7 +29,7 @@ inline IsolateData::IsolateData(v8::Isolate* isolate, uv_loop_t* event_loop)
|
|||||||
#define V(PropertyName, StringValue) \
|
#define V(PropertyName, StringValue) \
|
||||||
PropertyName ## _( \
|
PropertyName ## _( \
|
||||||
isolate, \
|
isolate, \
|
||||||
v8::Private::ForApi( \
|
v8::Private::New( \
|
||||||
isolate, \
|
isolate, \
|
||||||
v8::String::NewFromOneByte( \
|
v8::String::NewFromOneByte( \
|
||||||
isolate, \
|
isolate, \
|
||||||
@ -545,10 +545,6 @@ inline v8::Local<v8::Object> Environment::NewInternalFieldObject() {
|
|||||||
ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V)
|
ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V)
|
||||||
#undef V
|
#undef V
|
||||||
|
|
||||||
#undef ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES
|
|
||||||
#undef PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES
|
|
||||||
#undef PER_ISOLATE_STRING_PROPERTIES
|
|
||||||
|
|
||||||
} // namespace node
|
} // namespace node
|
||||||
|
|
||||||
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
||||||
|
@ -4385,15 +4385,9 @@ static void StartNodeInstance(void* arg) {
|
|||||||
Locker locker(isolate);
|
Locker locker(isolate);
|
||||||
Isolate::Scope isolate_scope(isolate);
|
Isolate::Scope isolate_scope(isolate);
|
||||||
HandleScope handle_scope(isolate);
|
HandleScope handle_scope(isolate);
|
||||||
|
IsolateData isolate_data(isolate, instance_data->event_loop());
|
||||||
Local<Context> context = Context::New(isolate);
|
Local<Context> context = Context::New(isolate);
|
||||||
Context::Scope context_scope(context);
|
Context::Scope context_scope(context);
|
||||||
|
|
||||||
// FIXME(bnoordhuis) Work around V8 bug: v8::Private::ForApi() dereferences
|
|
||||||
// a nullptr when a context hasn't been entered first. The symbol registry
|
|
||||||
// is a lazily created JS object but object instantiation does not work
|
|
||||||
// without a context.
|
|
||||||
IsolateData isolate_data(isolate, instance_data->event_loop());
|
|
||||||
|
|
||||||
Environment* env = CreateEnvironment(&isolate_data,
|
Environment* env = CreateEnvironment(&isolate_data,
|
||||||
context,
|
context,
|
||||||
instance_data->argc(),
|
instance_data->argc(),
|
||||||
|
@ -9,11 +9,11 @@ namespace util {
|
|||||||
using v8::Array;
|
using v8::Array;
|
||||||
using v8::Context;
|
using v8::Context;
|
||||||
using v8::FunctionCallbackInfo;
|
using v8::FunctionCallbackInfo;
|
||||||
|
using v8::Integer;
|
||||||
using v8::Local;
|
using v8::Local;
|
||||||
using v8::Object;
|
using v8::Object;
|
||||||
using v8::Private;
|
using v8::Private;
|
||||||
using v8::Proxy;
|
using v8::Proxy;
|
||||||
using v8::String;
|
|
||||||
using v8::Value;
|
using v8::Value;
|
||||||
|
|
||||||
|
|
||||||
@ -53,18 +53,28 @@ static void GetProxyDetails(const FunctionCallbackInfo<Value>& args) {
|
|||||||
args.GetReturnValue().Set(ret);
|
args.GetReturnValue().Set(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Local<Private> IndexToPrivateSymbol(Environment* env, uint32_t index) {
|
||||||
|
#define V(name, _) &Environment::name,
|
||||||
|
static Local<Private> (Environment::*const methods[])() const = {
|
||||||
|
PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V)
|
||||||
|
};
|
||||||
|
#undef V
|
||||||
|
CHECK_LT(index, arraysize(methods));
|
||||||
|
return (env->*methods[index])();
|
||||||
|
}
|
||||||
|
|
||||||
static void GetHiddenValue(const FunctionCallbackInfo<Value>& args) {
|
static void GetHiddenValue(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
|
|
||||||
if (!args[0]->IsObject())
|
if (!args[0]->IsObject())
|
||||||
return env->ThrowTypeError("obj must be an object");
|
return env->ThrowTypeError("obj must be an object");
|
||||||
|
|
||||||
if (!args[1]->IsString())
|
if (!args[1]->IsUint32())
|
||||||
return env->ThrowTypeError("name must be a string");
|
return env->ThrowTypeError("index must be an uint32");
|
||||||
|
|
||||||
Local<Object> obj = args[0].As<Object>();
|
Local<Object> obj = args[0].As<Object>();
|
||||||
Local<String> name = args[1].As<String>();
|
auto index = args[1]->Uint32Value(env->context()).FromJust();
|
||||||
auto private_symbol = Private::ForApi(env->isolate(), name);
|
auto private_symbol = IndexToPrivateSymbol(env, index);
|
||||||
auto maybe_value = obj->GetPrivate(env->context(), private_symbol);
|
auto maybe_value = obj->GetPrivate(env->context(), private_symbol);
|
||||||
|
|
||||||
args.GetReturnValue().Set(maybe_value.ToLocalChecked());
|
args.GetReturnValue().Set(maybe_value.ToLocalChecked());
|
||||||
@ -76,12 +86,12 @@ static void SetHiddenValue(const FunctionCallbackInfo<Value>& args) {
|
|||||||
if (!args[0]->IsObject())
|
if (!args[0]->IsObject())
|
||||||
return env->ThrowTypeError("obj must be an object");
|
return env->ThrowTypeError("obj must be an object");
|
||||||
|
|
||||||
if (!args[1]->IsString())
|
if (!args[1]->IsUint32())
|
||||||
return env->ThrowTypeError("name must be a string");
|
return env->ThrowTypeError("index must be an uint32");
|
||||||
|
|
||||||
Local<Object> obj = args[0].As<Object>();
|
Local<Object> obj = args[0].As<Object>();
|
||||||
Local<String> name = args[1].As<String>();
|
auto index = args[1]->Uint32Value(env->context()).FromJust();
|
||||||
auto private_symbol = Private::ForApi(env->isolate(), name);
|
auto private_symbol = IndexToPrivateSymbol(env, index);
|
||||||
auto maybe_value = obj->SetPrivate(env->context(), private_symbol, args[2]);
|
auto maybe_value = obj->SetPrivate(env->context(), private_symbol, args[2]);
|
||||||
|
|
||||||
args.GetReturnValue().Set(maybe_value.FromJust());
|
args.GetReturnValue().Set(maybe_value.FromJust());
|
||||||
@ -97,6 +107,16 @@ void Initialize(Local<Object> target,
|
|||||||
VALUE_METHOD_MAP(V)
|
VALUE_METHOD_MAP(V)
|
||||||
#undef V
|
#undef V
|
||||||
|
|
||||||
|
#define V(name, _) \
|
||||||
|
target->Set(context, \
|
||||||
|
FIXED_ONE_BYTE_STRING(env->isolate(), #name), \
|
||||||
|
Integer::NewFromUnsigned(env->isolate(), index++));
|
||||||
|
{
|
||||||
|
uint32_t index = 0;
|
||||||
|
PER_ISOLATE_PRIVATE_SYMBOL_PROPERTIES(V)
|
||||||
|
}
|
||||||
|
#undef V
|
||||||
|
|
||||||
env->SetMethod(target, "getHiddenValue", GetHiddenValue);
|
env->SetMethod(target, "getHiddenValue", GetHiddenValue);
|
||||||
env->SetMethod(target, "setHiddenValue", SetHiddenValue);
|
env->SetMethod(target, "setHiddenValue", SetHiddenValue);
|
||||||
env->SetMethod(target, "getProxyDetails", GetProxyDetails);
|
env->SetMethod(target, "getProxyDetails", GetProxyDetails);
|
||||||
|
@ -6,15 +6,18 @@ const assert = require('assert');
|
|||||||
const internalUtil = require('internal/util');
|
const internalUtil = require('internal/util');
|
||||||
const spawnSync = require('child_process').spawnSync;
|
const spawnSync = require('child_process').spawnSync;
|
||||||
|
|
||||||
function getHiddenValue(obj, name) {
|
const binding = process.binding('util');
|
||||||
|
const kArrowMessagePrivateSymbolIndex = binding['arrow_message_private_symbol'];
|
||||||
|
|
||||||
|
function getHiddenValue(obj, index) {
|
||||||
return function() {
|
return function() {
|
||||||
internalUtil.getHiddenValue(obj, name);
|
internalUtil.getHiddenValue(obj, index);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function setHiddenValue(obj, name, val) {
|
function setHiddenValue(obj, index, val) {
|
||||||
return function() {
|
return function() {
|
||||||
internalUtil.setHiddenValue(obj, name, val);
|
internalUtil.setHiddenValue(obj, index, val);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,29 +26,36 @@ assert.throws(getHiddenValue(null, 'foo'), /obj must be an object/);
|
|||||||
assert.throws(getHiddenValue(undefined, 'foo'), /obj must be an object/);
|
assert.throws(getHiddenValue(undefined, 'foo'), /obj must be an object/);
|
||||||
assert.throws(getHiddenValue('bar', 'foo'), /obj must be an object/);
|
assert.throws(getHiddenValue('bar', 'foo'), /obj must be an object/);
|
||||||
assert.throws(getHiddenValue(85, 'foo'), /obj must be an object/);
|
assert.throws(getHiddenValue(85, 'foo'), /obj must be an object/);
|
||||||
assert.throws(getHiddenValue({}), /name must be a string/);
|
assert.throws(getHiddenValue({}), /index must be an uint32/);
|
||||||
assert.throws(getHiddenValue({}, null), /name must be a string/);
|
assert.throws(getHiddenValue({}, null), /index must be an uint32/);
|
||||||
assert.throws(getHiddenValue({}, []), /name must be a string/);
|
assert.throws(getHiddenValue({}, []), /index must be an uint32/);
|
||||||
assert.deepStrictEqual(internalUtil.getHiddenValue({}, 'foo'), undefined);
|
assert.deepStrictEqual(
|
||||||
|
internalUtil.getHiddenValue({}, kArrowMessagePrivateSymbolIndex),
|
||||||
|
undefined);
|
||||||
|
|
||||||
assert.throws(setHiddenValue(), /obj must be an object/);
|
assert.throws(setHiddenValue(), /obj must be an object/);
|
||||||
assert.throws(setHiddenValue(null, 'foo'), /obj must be an object/);
|
assert.throws(setHiddenValue(null, 'foo'), /obj must be an object/);
|
||||||
assert.throws(setHiddenValue(undefined, 'foo'), /obj must be an object/);
|
assert.throws(setHiddenValue(undefined, 'foo'), /obj must be an object/);
|
||||||
assert.throws(setHiddenValue('bar', 'foo'), /obj must be an object/);
|
assert.throws(setHiddenValue('bar', 'foo'), /obj must be an object/);
|
||||||
assert.throws(setHiddenValue(85, 'foo'), /obj must be an object/);
|
assert.throws(setHiddenValue(85, 'foo'), /obj must be an object/);
|
||||||
assert.throws(setHiddenValue({}), /name must be a string/);
|
assert.throws(setHiddenValue({}), /index must be an uint32/);
|
||||||
assert.throws(setHiddenValue({}, null), /name must be a string/);
|
assert.throws(setHiddenValue({}, null), /index must be an uint32/);
|
||||||
assert.throws(setHiddenValue({}, []), /name must be a string/);
|
assert.throws(setHiddenValue({}, []), /index must be an uint32/);
|
||||||
const obj = {};
|
const obj = {};
|
||||||
assert.strictEqual(internalUtil.setHiddenValue(obj, 'foo', 'bar'), true);
|
assert.strictEqual(
|
||||||
assert.strictEqual(internalUtil.getHiddenValue(obj, 'foo'), 'bar');
|
internalUtil.setHiddenValue(obj, kArrowMessagePrivateSymbolIndex, 'bar'),
|
||||||
|
true);
|
||||||
|
assert.strictEqual(
|
||||||
|
internalUtil.getHiddenValue(obj, kArrowMessagePrivateSymbolIndex),
|
||||||
|
'bar');
|
||||||
|
|
||||||
let arrowMessage;
|
let arrowMessage;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
require('../fixtures/syntax/bad_syntax');
|
require('../fixtures/syntax/bad_syntax');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
arrowMessage = internalUtil.getHiddenValue(err, 'node:arrowMessage');
|
arrowMessage =
|
||||||
|
internalUtil.getHiddenValue(err, kArrowMessagePrivateSymbolIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(/bad_syntax\.js:1/.test(arrowMessage));
|
assert(/bad_syntax\.js:1/.test(arrowMessage));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user