summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2019-03-07 15:45:31 +0100
committerAnna Henningsen <anna@addaleax.net>2019-03-15 16:54:19 +0100
commitb0de48e85441ff710aab240fdfa8a34adbbee976 (patch)
tree9b0d0ee1ca888a2d0db99d6350044d6095a84570
parent7e2088f773d97e00e29cacdc20e1a36b80528be0 (diff)
downloadandroid-node-v8-b0de48e85441ff710aab240fdfa8a34adbbee976.tar.gz
android-node-v8-b0de48e85441ff710aab240fdfa8a34adbbee976.tar.bz2
android-node-v8-b0de48e85441ff710aab240fdfa8a34adbbee976.zip
src,lib: make DOMException available in all Contexts
This allows using `DOMException` from Node.js code for any `vm.Context`. PR-URL: https://github.com/nodejs/node/pull/26497 Reviewed-By: James M Snell <jasnell@gmail.com>
-rw-r--r--lib/internal/bootstrap/cache.js1
-rw-r--r--lib/internal/bootstrap/node.js9
-rw-r--r--lib/internal/per_context/domexception.js (renamed from lib/internal/domexception.js)10
-rw-r--r--node.gyp2
-rw-r--r--src/api/environment.cc36
-rw-r--r--src/node_internals.h2
-rw-r--r--src/node_messaging.cc42
-rw-r--r--test/parallel/test-bootstrap-modules.js3
-rw-r--r--test/wpt/test-url.js16
9 files changed, 84 insertions, 37 deletions
diff --git a/lib/internal/bootstrap/cache.js b/lib/internal/bootstrap/cache.js
index 80073ebe61..1b07fa5a81 100644
--- a/lib/internal/bootstrap/cache.js
+++ b/lib/internal/bootstrap/cache.js
@@ -25,6 +25,7 @@ const cannotBeRequired = [
'internal/bootstrap/node',
'internal/per_context/setup',
+ 'internal/per_context/domexception',
];
// Skip modules that cannot be required when they are not
diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js
index 0bd1a3f363..f8cddb3153 100644
--- a/lib/internal/bootstrap/node.js
+++ b/lib/internal/bootstrap/node.js
@@ -214,8 +214,6 @@ if (!config.noBrowserGlobals) {
defineOperation(global, 'setImmediate', timers.setImmediate);
}
-setupDOMException();
-
// process.allowedNodeEnvironmentFlags
Object.defineProperty(process, 'allowedNodeEnvironmentFlags', {
get() {
@@ -394,13 +392,6 @@ function createGlobalConsole(consoleFromVM) {
return consoleFromNode;
}
-function setupDOMException() {
- // Registers the constructor with C++.
- const DOMException = NativeModule.require('internal/domexception');
- const { registerDOMException } = internalBinding('messaging');
- registerDOMException(DOMException);
-}
-
// https://heycam.github.io/webidl/#es-namespaces
function exposeNamespace(target, name, namespaceObject) {
Object.defineProperty(target, name, {
diff --git a/lib/internal/domexception.js b/lib/internal/per_context/domexception.js
index 9845919e49..795acf76c0 100644
--- a/lib/internal/domexception.js
+++ b/lib/internal/per_context/domexception.js
@@ -1,6 +1,12 @@
'use strict';
-const { ERR_INVALID_THIS } = require('internal/errors').codes;
+class ERR_INVALID_THIS extends TypeError {
+ constructor(type) {
+ super('Value of "this" must be of ' + type);
+ }
+
+ get code() { return 'ERR_INVALID_THIS'; }
+}
const internalsMap = new WeakMap();
@@ -83,4 +89,4 @@ for (const [name, codeName, value] of [
nameToCodeMap.set(name, value);
}
-module.exports = DOMException;
+exports.DOMException = DOMException;
diff --git a/node.gyp b/node.gyp
index 4fbdb58183..0c6aee7f80 100644
--- a/node.gyp
+++ b/node.gyp
@@ -32,6 +32,7 @@
'lib/internal/bootstrap/node.js',
'lib/internal/bootstrap/pre_execution.js',
'lib/internal/per_context/setup.js',
+ 'lib/internal/per_context/domexception.js',
'lib/async_hooks.js',
'lib/assert.js',
'lib/buffer.js',
@@ -115,7 +116,6 @@
'lib/internal/dgram.js',
'lib/internal/dns/promises.js',
'lib/internal/dns/utils.js',
- 'lib/internal/domexception.js',
'lib/internal/dtrace.js',
'lib/internal/encoding.js',
'lib/internal/errors.js',
diff --git a/src/api/environment.cc b/src/api/environment.cc
index c4a8120d1c..6e3c61fac1 100644
--- a/src/api/environment.cc
+++ b/src/api/environment.cc
@@ -15,6 +15,7 @@
namespace node {
using v8::Context;
+using v8::EscapableHandleScope;
using v8::Function;
using v8::HandleScope;
using v8::Isolate;
@@ -22,7 +23,9 @@ using v8::Local;
using v8::MaybeLocal;
using v8::Message;
using v8::MicrotasksPolicy;
+using v8::Object;
using v8::ObjectTemplate;
+using v8::Private;
using v8::String;
using v8::Value;
@@ -279,6 +282,26 @@ void FreePlatform(MultiIsolatePlatform* platform) {
delete platform;
}
+MaybeLocal<Object> GetPerContextExports(Local<Context> context) {
+ Isolate* isolate = context->GetIsolate();
+ EscapableHandleScope handle_scope(isolate);
+
+ Local<Object> global = context->Global();
+ Local<Private> key = Private::ForApi(isolate,
+ FIXED_ONE_BYTE_STRING(isolate, "node:per_context_binding_exports"));
+
+ Local<Value> existing_value;
+ if (!global->GetPrivate(context, key).ToLocal(&existing_value))
+ return MaybeLocal<Object>();
+ if (existing_value->IsObject())
+ return handle_scope.Escape(existing_value.As<Object>());
+
+ Local<Object> exports = Object::New(isolate);
+ if (context->Global()->SetPrivate(context, key, exports).IsNothing())
+ return MaybeLocal<Object>();
+ return handle_scope.Escape(exports);
+}
+
Local<Context> NewContext(Isolate* isolate,
Local<ObjectTemplate> object_template) {
auto context = Context::New(isolate, nullptr, object_template);
@@ -291,16 +314,25 @@ Local<Context> NewContext(Isolate* isolate,
{
// Run per-context JS files.
Context::Scope context_scope(context);
+ Local<Object> exports;
+ if (!GetPerContextExports(context).ToLocal(&exports))
+ return Local<Context>();
+
+ Local<String> global_string = FIXED_ONE_BYTE_STRING(isolate, "global");
+ Local<String> exports_string = FIXED_ONE_BYTE_STRING(isolate, "exports");
static const char* context_files[] = {
"internal/per_context/setup",
+ "internal/per_context/domexception",
nullptr
};
for (const char** module = context_files; *module != nullptr; module++) {
std::vector<Local<String>> parameters = {
- FIXED_ONE_BYTE_STRING(isolate, "global")};
- Local<Value> arguments[] = {context->Global()};
+ global_string,
+ exports_string
+ };
+ Local<Value> arguments[] = {context->Global(), exports};
MaybeLocal<Function> maybe_fn =
per_process::native_module_loader.LookupAndCompile(
context, *module, &parameters, nullptr);
diff --git a/src/node_internals.h b/src/node_internals.h
index d2eadf5109..bc6a36d9db 100644
--- a/src/node_internals.h
+++ b/src/node_internals.h
@@ -296,6 +296,8 @@ void DefineZlibConstants(v8::Local<v8::Object> target);
v8::MaybeLocal<v8::Value> RunBootstrapping(Environment* env);
v8::MaybeLocal<v8::Value> StartExecution(Environment* env,
const char* main_script_id);
+v8::MaybeLocal<v8::Object> GetPerContextExports(v8::Local<v8::Context> context);
+
namespace profiler {
void StartCoverageCollection(Environment* env);
}
diff --git a/src/node_messaging.cc b/src/node_messaging.cc
index 650d64b395..9b9bab0814 100644
--- a/src/node_messaging.cc
+++ b/src/node_messaging.cc
@@ -177,19 +177,30 @@ uint32_t Message::AddWASMModule(WasmModuleObject::TransferrableModule&& mod) {
namespace {
-void ThrowDataCloneException(Environment* env, Local<String> message) {
+void ThrowDataCloneException(Local<Context> context, Local<String> message) {
+ Isolate* isolate = context->GetIsolate();
Local<Value> argv[] = {
message,
- FIXED_ONE_BYTE_STRING(env->isolate(), "DataCloneError")
+ FIXED_ONE_BYTE_STRING(isolate, "DataCloneError")
};
Local<Value> exception;
- Local<Function> domexception_ctor = env->domexception_function();
- CHECK(!domexception_ctor.IsEmpty());
- if (!domexception_ctor->NewInstance(env->context(), arraysize(argv), argv)
+
+ Local<Object> per_context_bindings;
+ Local<Value> domexception_ctor_val;
+ if (!GetPerContextExports(context).ToLocal(&per_context_bindings) ||
+ !per_context_bindings->Get(context,
+ FIXED_ONE_BYTE_STRING(isolate, "DOMException"))
+ .ToLocal(&domexception_ctor_val)) {
+ return;
+ }
+
+ CHECK(domexception_ctor_val->IsFunction());
+ Local<Function> domexception_ctor = domexception_ctor_val.As<Function>();
+ if (!domexception_ctor->NewInstance(context, arraysize(argv), argv)
.ToLocal(&exception)) {
return;
}
- env->isolate()->ThrowException(exception);
+ isolate->ThrowException(exception);
}
// This tells V8 how to serialize objects that it does not understand
@@ -201,7 +212,7 @@ class SerializerDelegate : public ValueSerializer::Delegate {
: env_(env), context_(context), msg_(m) {}
void ThrowDataCloneError(Local<String> message) override {
- ThrowDataCloneException(env_, message);
+ ThrowDataCloneException(context_, message);
}
Maybe<bool> WriteHostObject(Isolate* isolate, Local<Object> object) override {
@@ -309,7 +320,7 @@ Maybe<bool> Message::Serialize(Environment* env,
if (std::find(array_buffers.begin(), array_buffers.end(), ab) !=
array_buffers.end()) {
ThrowDataCloneException(
- env,
+ context,
FIXED_ONE_BYTE_STRING(
env->isolate(),
"Transfer list contains duplicate ArrayBuffer"));
@@ -326,7 +337,7 @@ Maybe<bool> Message::Serialize(Environment* env,
// Check if the source MessagePort is being transferred.
if (!source_port.IsEmpty() && entry == source_port) {
ThrowDataCloneException(
- env,
+ context,
FIXED_ONE_BYTE_STRING(env->isolate(),
"Transfer list contains source port"));
return Nothing<bool>();
@@ -334,7 +345,7 @@ Maybe<bool> Message::Serialize(Environment* env,
MessagePort* port = Unwrap<MessagePort>(entry.As<Object>());
if (port == nullptr || port->IsDetached()) {
ThrowDataCloneException(
- env,
+ context,
FIXED_ONE_BYTE_STRING(
env->isolate(),
"MessagePort in transfer list is already detached"));
@@ -343,7 +354,7 @@ Maybe<bool> Message::Serialize(Environment* env,
if (std::find(delegate.ports_.begin(), delegate.ports_.end(), port) !=
delegate.ports_.end()) {
ThrowDataCloneException(
- env,
+ context,
FIXED_ONE_BYTE_STRING(
env->isolate(),
"Transfer list contains duplicate MessagePort"));
@@ -811,13 +822,6 @@ static void MessageChannel(const FunctionCallbackInfo<Value>& args) {
.FromJust();
}
-static void RegisterDOMException(const FunctionCallbackInfo<Value>& args) {
- Environment* env = Environment::GetCurrent(args);
- CHECK_EQ(args.Length(), 1);
- CHECK(args[0]->IsFunction());
- env->set_domexception_function(args[0].As<Function>());
-}
-
static void InitMessaging(Local<Object> target,
Local<Value> unused,
Local<Context> context,
@@ -839,8 +843,6 @@ static void InitMessaging(Local<Object> target,
GetMessagePortConstructor(env, context).ToLocalChecked())
.FromJust();
- env->SetMethod(target, "registerDOMException", RegisterDOMException);
-
// These are not methods on the MessagePort prototype, because
// the browser equivalents do not provide them.
env->SetMethod(target, "stopMessagePort", MessagePort::Stop);
diff --git a/test/parallel/test-bootstrap-modules.js b/test/parallel/test-bootstrap-modules.js
index efae4725cf..e65098b922 100644
--- a/test/parallel/test-bootstrap-modules.js
+++ b/test/parallel/test-bootstrap-modules.js
@@ -17,7 +17,6 @@ const expectedModules = new Set([
'Internal Binding credentials',
'Internal Binding fs',
'Internal Binding inspector',
- 'Internal Binding messaging',
'Internal Binding module_wrap',
'Internal Binding native_module',
'Internal Binding options',
@@ -38,7 +37,6 @@ const expectedModules = new Set([
'NativeModule internal/console/constructor',
'NativeModule internal/console/global',
'NativeModule internal/constants',
- 'NativeModule internal/domexception',
'NativeModule internal/encoding',
'NativeModule internal/errors',
'NativeModule internal/fixed_queue',
@@ -74,6 +72,7 @@ if (common.isMainThread) {
expectedModules.add('NativeModule internal/process/stdio');
} else {
expectedModules.add('Internal Binding heap_utils');
+ expectedModules.add('Internal Binding messaging');
expectedModules.add('Internal Binding serdes');
expectedModules.add('Internal Binding stream_wrap');
expectedModules.add('Internal Binding symbols');
diff --git a/test/wpt/test-url.js b/test/wpt/test-url.js
index 8734452940..4b909988dd 100644
--- a/test/wpt/test-url.js
+++ b/test/wpt/test-url.js
@@ -3,6 +3,7 @@
// Flags: --expose-internals
require('../common');
+const assert = require('assert');
const { WPTRunner } = require('../common/wpt');
const runner = new WPTRunner('url');
@@ -10,9 +11,22 @@ const runner = new WPTRunner('url');
// Copy global descriptors from the global object
runner.copyGlobalsFromObject(global, ['URL', 'URLSearchParams']);
// Needed by urlsearchparams-constructor.any.js
+let DOMException;
runner.defineGlobal('DOMException', {
get() {
- return require('internal/domexception');
+ // A 'hack' to get the DOMException constructor since we don't have it
+ // on the global object.
+ if (DOMException === undefined) {
+ const port = new (require('worker_threads').MessagePort)();
+ const ab = new ArrayBuffer(1);
+ try {
+ port.postMessage(ab, [ab, ab]);
+ } catch (err) {
+ DOMException = err.constructor;
+ }
+ assert.strictEqual(DOMException.name, 'DOMException');
+ }
+ return DOMException;
}
});