-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
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: