messaging: use actual DOMException for DataCloneError
PR-URL: https://github.com/nodejs/node/pull/21540 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
602da6492f
commit
5f3bdb016a
@ -125,6 +125,10 @@
|
||||
setupGlobalURL();
|
||||
}
|
||||
|
||||
if (process.binding('config').experimentalWorker) {
|
||||
setupDOMException();
|
||||
}
|
||||
|
||||
// On OpenBSD process.execPath will be relative unless we
|
||||
// get the full path before process.execPath is used.
|
||||
if (process.platform === 'openbsd') {
|
||||
@ -405,6 +409,11 @@
|
||||
});
|
||||
}
|
||||
|
||||
function setupDOMException() {
|
||||
// Registers the constructor with C++.
|
||||
NativeModule.require('internal/domexception');
|
||||
}
|
||||
|
||||
function setupInspector(originalConsole, wrappedConsole, CJSModule) {
|
||||
if (!process.config.variables.v8_enable_inspector) {
|
||||
return;
|
||||
|
83
lib/internal/domexception.js
Normal file
83
lib/internal/domexception.js
Normal file
@ -0,0 +1,83 @@
|
||||
'use strict';
|
||||
|
||||
const { internalBinding } = require('internal/bootstrap/loaders');
|
||||
const { registerDOMException } = internalBinding('messaging');
|
||||
const { ERR_INVALID_THIS } = require('internal/errors').codes;
|
||||
|
||||
const internalsMap = new WeakMap();
|
||||
|
||||
const nameToCodeMap = new Map();
|
||||
|
||||
class DOMException extends Error {
|
||||
constructor(message = '', name = 'Error') {
|
||||
super();
|
||||
internalsMap.set(this, {
|
||||
message: `${message}`,
|
||||
name: `${name}`
|
||||
});
|
||||
}
|
||||
|
||||
get name() {
|
||||
const internals = internalsMap.get(this);
|
||||
if (internals === undefined) {
|
||||
throw new ERR_INVALID_THIS('DOMException');
|
||||
}
|
||||
return internals.name;
|
||||
}
|
||||
|
||||
get message() {
|
||||
const internals = internalsMap.get(this);
|
||||
if (internals === undefined) {
|
||||
throw new ERR_INVALID_THIS('DOMException');
|
||||
}
|
||||
return internals.message;
|
||||
}
|
||||
|
||||
get code() {
|
||||
const internals = internalsMap.get(this);
|
||||
if (internals === undefined) {
|
||||
throw new ERR_INVALID_THIS('DOMException');
|
||||
}
|
||||
const code = nameToCodeMap.get(internals.name);
|
||||
return code === undefined ? 0 : code;
|
||||
}
|
||||
}
|
||||
|
||||
for (const [name, codeName, value] of [
|
||||
['IndexSizeError', 'INDEX_SIZE_ERR', 1],
|
||||
['DOMStringSizeError', 'DOMSTRING_SIZE_ERR', 2],
|
||||
['HierarchyRequestError', 'HIERARCHY_REQUEST_ERR', 3],
|
||||
['WrongDocumentError', 'WRONG_DOCUMENT_ERR', 4],
|
||||
['InvalidCharacterError', 'INVALID_CHARACTER_ERR', 5],
|
||||
['NoDataAllowedError', 'NO_DATA_ALLOWED_ERR', 6],
|
||||
['NoModificationAllowedError', 'NO_MODIFICATION_ALLOWED_ERR', 7],
|
||||
['NotFoundError', 'NOT_FOUND_ERR', 8],
|
||||
['NotSupportedError', 'NOT_SUPPORTED_ERR', 9],
|
||||
['InUseAttributeError', 'INUSE_ATTRIBUTE_ERR', 10],
|
||||
['InvalidStateError', 'INVALID_STATE_ERR', 11],
|
||||
['SyntaxError', 'SYNTAX_ERR', 12],
|
||||
['InvalidModificationError', 'INVALID_MODIFICATION_ERR', 13],
|
||||
['NamespaceError', 'NAMESPACE_ERR', 14],
|
||||
['InvalidAccessError', 'INVALID_ACCESS_ERR', 15],
|
||||
['ValidationError', 'VALIDATION_ERR', 16],
|
||||
['TypeMismatchError', 'TYPE_MISMATCH_ERR', 17],
|
||||
['SecurityError', 'SECURITY_ERR', 18],
|
||||
['NetworkError', 'NETWORK_ERR', 19],
|
||||
['AbortError', 'ABORT_ERR', 20],
|
||||
['URLMismatchError', 'URL_MISMATCH_ERR', 21],
|
||||
['QuotaExceededError', 'QUOTA_EXCEEDED_ERR', 22],
|
||||
['TimeoutError', 'TIMEOUT_ERR', 23],
|
||||
['InvalidNodeTypeError', 'INVALID_NODE_TYPE_ERR', 24],
|
||||
['DataCloneError', 'DATA_CLONE_ERR', 25]
|
||||
// There are some more error names, but since they don't have codes assigned,
|
||||
// we don't need to care about them.
|
||||
]) {
|
||||
const desc = { enumerable: true, value };
|
||||
Object.defineProperty(DOMException, codeName, desc);
|
||||
Object.defineProperty(DOMException.prototype, codeName, desc);
|
||||
nameToCodeMap.set(name, value);
|
||||
}
|
||||
|
||||
module.exports = DOMException;
|
||||
|
||||
registerDOMException(DOMException);
|
1
node.gyp
1
node.gyp
@ -106,6 +106,7 @@
|
||||
'lib/internal/constants.js',
|
||||
'lib/internal/dns/promises.js',
|
||||
'lib/internal/dns/utils.js',
|
||||
'lib/internal/domexception.js',
|
||||
'lib/internal/encoding.js',
|
||||
'lib/internal/errors.js',
|
||||
'lib/internal/error-serdes.js',
|
||||
|
@ -322,6 +322,7 @@ struct PackageConfig {
|
||||
V(buffer_prototype_object, v8::Object) \
|
||||
V(context, v8::Context) \
|
||||
V(domain_callback, v8::Function) \
|
||||
V(domexception_function, v8::Function) \
|
||||
V(fdclose_constructor_template, v8::ObjectTemplate) \
|
||||
V(fd_constructor_template, v8::ObjectTemplate) \
|
||||
V(filehandlereadwrap_template, v8::ObjectTemplate) \
|
||||
|
@ -144,6 +144,21 @@ void Message::AddMessagePort(std::unique_ptr<MessagePortData>&& data) {
|
||||
|
||||
namespace {
|
||||
|
||||
void ThrowDataCloneError(Environment* env, Local<String> message) {
|
||||
Local<Value> argv[] = {
|
||||
message,
|
||||
FIXED_ONE_BYTE_STRING(env->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)
|
||||
.ToLocal(&exception)) {
|
||||
return;
|
||||
}
|
||||
env->isolate()->ThrowException(exception);
|
||||
}
|
||||
|
||||
// This tells V8 how to serialize objects that it does not understand
|
||||
// (e.g. C++ objects) into the output buffer, in a way that our own
|
||||
// DeserializerDelegate understands how to unpack.
|
||||
@ -153,7 +168,7 @@ class SerializerDelegate : public ValueSerializer::Delegate {
|
||||
: env_(env), context_(context), msg_(m) {}
|
||||
|
||||
void ThrowDataCloneError(Local<String> message) override {
|
||||
env_->isolate()->ThrowException(Exception::Error(message));
|
||||
ThrowDataCloneError(env_, message);
|
||||
}
|
||||
|
||||
Maybe<bool> WriteHostObject(Isolate* isolate, Local<Object> object) override {
|
||||
@ -688,6 +703,13 @@ 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,
|
||||
@ -708,6 +730,8 @@ static void InitMessaging(Local<Object> target,
|
||||
env->message_port_constructor_string(),
|
||||
GetMessagePortConstructor(env, context).ToLocalChecked())
|
||||
.FromJust();
|
||||
|
||||
env->SetMethod(target, "registerDOMException", RegisterDOMException);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
Loading…
x
Reference in New Issue
Block a user