-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
src,lib: re-implement DOMException as a cloneable native object #41044
Conversation
This comment has been minimized.
This comment has been minimized.
7121630
to
afdcc0e
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Refs: nodejs#41038 Signed-off-by: James M Snell <jasnell@gmail.com>
Refs: nodejs#41038 Signed-off-by: James M Snell <jasnell@gmail.com>
Refs: nodejs#41038 Signed-off-by: James M Snell <jasnell@gmail.com>
afdcc0e
to
ab28941
Compare
@@ -270,6 +276,97 @@ void DecorateErrorStack(Environment* env, | |||
const errors::TryCatchScope& try_catch); | |||
} // namespace errors | |||
|
|||
class DOMException : public BaseObject { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not inherit from JSTransferable?
Lines 318 to 321 in 3f51f05
// Provide a base class from which JS classes that should be transferable or | |
// cloneable by postMesssage() can inherit. | |
// See e.g. FileHandle in internal/fs/promises.js for an example. | |
class JSTransferable : public BaseObject { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we can't. See the referenced issue for detail: #41038
} | ||
Local<Object> err = Exception::Error(message_str).As<Object>(); | ||
|
||
if (!err->Set(env->context(), env->name_string(), name_str).FromJust()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!err->Set(env->context(), env->name_string(), name_str).FromJust()) { | |
if (err->Set(env->context(), env->name_string(), name_str).IsNothing()) { |
Why crash the process in case of an ongoing exception?
env, | ||
obj, | ||
message, | ||
String::NewFromUtf8(env->isolate(), name.c_str()).ToLocalChecked()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
String::NewFromUtf8(env->isolate(), name.c_str()).ToLocalChecked()); | |
String::NewFromUtf8(env->isolate(), name.c_str()) | |
.FromMaybe(Local<String>())); |
Why crash the process in case of an ongoing exception?
args.GetReturnValue().Set(ret); | ||
#undef V |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
args.GetReturnValue().Set(ret); | |
#undef V | |
#undef V | |
args.GetReturnValue().Set(ret); |
Setting the return value does not need to be done in the scope of V, does it?
const std::string& name) | ||
: BaseObject(env, object) { | ||
Local<Value> message_value = | ||
String::NewFromUtf8(env->isolate(), message.c_str()).ToLocalChecked(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can get rid of the calls to the *Check*()
functions in the constructors and still signal to the caller if a failure occurs by using a factory function to construct these objects and return a nullish value when there is an exception. Such a thing is already implemented by the MessagePort
class constructors:
Line 221 in 3f51f05
class MessagePort : public HandleWrap { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a huge amount of unnecessary complexity, compared to making JSTransferable support transferables in the clone information … are you sure you want to do this?
return Global<Value>(); | ||
} | ||
|
||
return Global<Value>(env->isolate(), stack); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this return a Global
rather than a Local
?
private: | ||
v8::Global<v8::Value> message; | ||
v8::Global<v8::Value> name; | ||
v8::Global<v8::Value> stack; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these always strings?
That does not actually solve the problem here. The issue is that custom error objects like |
// This is annoying, but v8 does not give a nice way of getting a good | ||
// stack property so we have to create an error object and capture a | ||
// stack that way. | ||
Global<Value> MakeErrorStack( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't seem nice that we have to re-implement all these error properties in C++. If the only problem with implementing them in JS (which seems nicer in comparison since we can do multiple inheritance there) is getting hold of C++ stuff before internalBinding
and require
become available, I think we can simply put JSTransferable and the symbols to some object (primordials
would do if we are being lazy and not want to invent a new argument) in InitializePrimordials
and pass them into the per-context script for DOMException to use?
The JavaScript-implemented
DOMException
is not structured cloneable without ugly hacks.This re-implements it in C++ as a cloneable
BaseObject
.Also makes
AbortError
structured cloneable.Refs: #41038