-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
console.log
should *not* be a constructor
#25987
Comments
Essentially we should create the |
Console methods can't be arrow functions, since they are bound to a Console instance. Defining them as methods should work. Also, if inspector is attached, all methods are wrapped, thus something like this is also needed: diff --git a/src/inspector_js_api.cc b/src/inspector_js_api.cc
index 48ebd73817..a7d72bd327 100644
--- a/src/inspector_js_api.cc
+++ b/src/inspector_js_api.cc
@@ -146,6 +146,12 @@ void CallAndPauseOnStart(const FunctionCallbackInfo<v8::Value>& args) {
}
void InspectorConsoleCall(const FunctionCallbackInfo<Value>& info) {
+ Isolate* iso = Isolate::GetCurrent();
+ if (info.IsConstructCall()) {
+ iso->ThrowException(v8::Exception::TypeError(String::NewFromUtf8(
+ iso, "Console methods are not constructors")));
+ return;
+ }
Environment* env = Environment::GetCurrent(info);
Isolate* isolate = env->isolate();
Local<Context> context = isolate->GetCurrentContext(); I would like to open a PR if this looks good. |
@Hakerh400 I think rather than us throwing an exception, we could use V8’s ability to prevent constructor behaviour altogether – you can search around for More generally, there is a Lines 750 to 756 in c2d374f
Changing |
Yeah, throwing an error if var p = new Proxy(console.log, {
construct: () => {
throw new Error("This should never be called");
}
});
new p(); |
Is this covered by the |
Maybe not. But, in the ECMAScript standard, primordials have a consistent constructor / non-constructor behaviour. I've made a script that reveals all the primordials that do not have a consistent constructor behavior. It only print the functions of the
const done = new Set();
const isconstructor = (value) => {
try {
Reflect.construct(Boolean, [], value);
return true;
} catch (error) {
return false;
}
};
const loop = (value, path) => {
if (value !== null && (typeof value === "object" || typeof value === "function")) {
if (!done.has(value)) {
done.add(value);
if (isconstructor(value) && !Reflect.getOwnPropertyDescriptor(value, "prototype"))
console.log(path);
Reflect.ownKeys(value).forEach((key) => {
const descriptor = Reflect.getOwnPropertyDescriptor(value, key);
if ("value" in descriptor) {
loop(descriptor.value, path+"."+String(key));
} else {
loop(descriptor.get, path+"."+String(key)+"[get]");
loop(descriptor.set, path+"."+String(key)+"[set]");
}
});
loop(Reflect.getPrototypeOf(value, path+".[__proto__]"));
}
}
};
loop(global, "global"); |
Ah okay. We should ping folks involved in that effort to see about covering any gap: |
The Console Standard does not cover it directly, but by virtue of the method being defined through Web IDL, Web IDL rules apply – and they are that the method should not be a constructor. |
@Hakerh400 The changes look okay, but I would suggest making separate PRs for the changes to the console source code and to |
This can probably be closed as fixed. |
@Hakerh400 Changing |
Fixed in #26700. |
In node,
console.log
behaves like a constructor without aprototype
field. Other runtimes throw a proper type error in both lines below:Much love,
Laurent
The text was updated successfully, but these errors were encountered: