Skip to content
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

Static console functions / binding #3

Closed
terinjokes opened this issue Sep 24, 2014 · 64 comments
Closed

Static console functions / binding #3

terinjokes opened this issue Sep 24, 2014 · 64 comments

Comments

@terinjokes
Copy link
Collaborator

Right now assigning a console function to a local variable kind of sucks, since they're expected to be called within the context of console. This requires the developer to bind.

var log = console.log.bind(console);
log('\(゜ロ\)ココハドコ? (/ロ゜)/アタシハダアレ?');

Except this doesn't work in some versions of IE because the console functions aren't instances of Function!

var log = Function.prototype.bind.call(console.log, console);
log('(ノಠ益ಠ)ノ彡┻━┻');

Which is a lot to type for a pretty simple and common task.

var log = console.log;
log('\(◎o◎)/!');

It makes sense to me that this is soemthing worth supporting.

@sindresorhus
Copy link

👍 This is very convenient when you want to log the output of a callback .catch(console.error) or create a shortcut const log = console.log. This is also how it works in Node.js.

@domenic
Copy link
Member

domenic commented Jan 10, 2016

I don't think any browsers currently support this, although Node.js does. I think it's sensible, but I think we'd have some work to do before getting it in browsers:

  • Web IDL would need to be updated with some kind of [Bound] attribute. Hmm, I wonder if [Unforgeable] would work? It wasn't meant for that purpose, but seems worth checking...
  • We'd need to get at least a couple browsers to implement that.

@alexkozy
Copy link

FYI.
Link to chromium discussion about this: https://crbug.com/167911
And older and more informative webkit issue: https://bugs.webkit.org/show_bug.cgi?id=20141#c40

@pwnall
Copy link

pwnall commented Jan 12, 2016

I'd be happy to try to revisit WebKit and Blink implementations for bound console.log and its siblings if the standard goes in that direction. I'm still a bit annoyed when I can't pass console.log as a callback when debugging or feeling my way around new browser features, so I'd be sufficiently motivated to get it implemented.

@paulirish
Copy link

Chrome DevTools team discussed this yesterday and it's doable though more work than it appears to be. These methods are implemented in native, rather than JS. We may fix this in the next few months, though we'd be happy for your help with it @pwnall

@domenic
Copy link
Member

domenic commented Jan 17, 2016

@paulirish one approach that the spec might consider is to change the IDL from

[NoInterfaceObject]
interface Console {
  void assert(boolean condition, optional any message);
  void clear();
  ...
};

partial interface Window {
  attribute Console console;
};

to

// [NoInterfaceObject is gone]
interface console { // note lowercase
  static void assert(boolean condition, optional any message);
  static void clear();
};

// no need for adding it to Window explicitly

This would change things slightly: typeof window.console === "function" would now be true, among the obvious prototype chain changes (i.e. there's no Console.prototype object). But maybe run that by your team and see what they think.

The alternative would be custom bindings of a sort.

@pwnall
Copy link

pwnall commented Jan 19, 2016

@paulirish @domenic Is this definitely going to happen in spec-land? I'm asking to make sure I don't waste effort trying to implement it. If so, I can probably find some time in the second half of February. Also, 🎆

@domenic
Copy link
Member

domenic commented Jan 19, 2016

@pwnall well, specs are driven by implementation willingness, so that question is kind of backward. If we can get at least two implementations to pledge to implement something then we can in good conscience put it in the spec.

@robertkowalski
Copy link
Member

a typical chicken-egg situation. :)

@frewsxcv what do you think about it in regard to FF?

@frewsxcv
Copy link
Member

For the record, I'm not in any way associated with Mozilla, other than occasional volunteer contributions for Servo. I'll link this thread to the Servo/Firefox people hoping someone more official will answer.

@jlongster
Copy link

Apparently we (Firefox) used to do this. I found this: https://bugzilla.mozilla.org/show_bug.cgi?id=989619

I can't speak for my team (devtools) but I bet most people would be fine with this. My coworker also filed this bug a while bug on a (seemingly defunct) different console repo: DeveloperToolsWG/console-object#27

@domenic
Copy link
Member

domenic commented Feb 9, 2016

OK, so as discussed in #1 (comment) and the related mailing list thread, this issue is kind of the biggest outstanding issue on this repo. And it's essentially blocked on implementer interest. Web developers really want this, as can be seen from previous discussions.

My sketch in #1 (comment) shows how this can be done without any custom IDL bindings, which should ease the burden on implementers. But we still need at the very least explicit signals from two implementers that they are willing to do the work.

It seems like from #3 (comment) there's some support from Chrome, on the timeline of a few months, and in https://lists.w3.org/Archives/Public/public-whatwg-archive/2016Feb/0007.html it seems like @bzbarsky voiced support if someone can volunteer to do the work in Firefox. I wouldn't say this is enough support to conclusively change the spec yet though... it would be different if someone from Firefox could commit to doing the work.

Any thoughts from Safari (@hober?) or Microsoft (@travisleithead?)?

@zcorpan
Copy link
Member

zcorpan commented Feb 10, 2016

If this is implementable with only copying webidl, it seems like it could be a "good first bug" for Firefox that @bzbarsky could mentor, maybe? Is there a bug filed?

Just changing the spec could also get the ball rolling...

@bzbarsky
Copy link

This is not a "good first bug". It requires some tricky under-the-hood changes to the console implementation in Gecko (due to no longer having an actual Console object), and especially to its interactions with memory management and the garbage collector. It wouldn't be so bad if console only existed on the main thread, but its existence on workers, and the ensuing need to communicate to the main-thread console, make all this very much not a "good first bug".

So the real problem on the Gecko end is that the set of people who could quickly (a few days of work) fix this is very limited and they're all busy with other things...

@RReverser
Copy link
Member

due to no longer having an actual Console object

I don't know the Gecko internals, but would be it possible to make this an implementation detail for now? (like, leave Console object, but auto-bind methods when exposing)

@bzbarsky
Copy link

That would be even harder, with a smaller pool of people who can do it, actually; all that stuff is completely automated right now via the bindings generator and would require some fundamental changes to the generator to introduce that sort of hack.

Anyway, my points are: 1) this is not something we're likely to prototype quickly, and hence not likely to invest effort into unless we're pretty sure it should be done. 2) Even once we're sure it should be done it's likely to take a few months to get to it.

@domenic
Copy link
Member

domenic commented Feb 10, 2016

@bzbarsky would "we're pretty sure it should be done" be influenced by changing the spec? I'd prefer to be conservative and not change without implementer support, but I recognize there's a potential chicken-egg problem here, depending on how adventurous implementers are feeling.

@bzbarsky
Copy link

would "we're pretty sure it should be done" be influenced by changing the spec?

Probably not; it would be influenced by other implementors committing to doing it...

@foolip
Copy link
Member

foolip commented Mar 7, 2016

function log() { console.log.apply(console, arguments); } works in Edge, but which versions of IE was there a problem with console.log not being a function? Whatever the answer, this can't be remedied by updating Edge and other engines.

Is this situation substantially different from, say, document.createElement?

@domenic
Copy link
Member

domenic commented Mar 7, 2016

@foolip I think the difference is largely that developers have been asking for this for a long time, and behaviors in old-Firefox and in Node.js influenced them to expect it. The common case is arr.forEach(console.log) or similar.

@foolip
Copy link
Member

foolip commented Mar 7, 2016

Oh, Node.js, I skimmed past that. Going with statics would make it similar to CSS.supports, although having an interface called console would be quite unusual. WebKit seems to implement console without using IDL now, maybe it would be worth a look: http://trac.webkit.org/changeset/165199

@alexkozy
Copy link

ToT Chromium supports calls to console related methods without console: crbug.com/167911 is fixed.

@bzbarsky
Copy link

Er, with what behavior? Is there still a window.Console, for example? @domenic

@domenic
Copy link
Member

domenic commented Apr 25, 2016

Woah. Browsing https://codereview.chromium.org/1859293002 it looks like they've made major changes which are not at all aligned with other browsers, like moving to a data property instead of a getter/replaceable setter on the prototype. That seems quite bad.

I can't tell about window.Console right now.

@bzbarsky
Copy link

@domenic Can you talk to whoever is involved and figure out what the story is, please? ;)

@alexkozy
Copy link

I've attached screenshot of window.console output in Chrome and Mozilla. In the both implementation we have Console object with ConsolePrototype that contains all console related methods. And it's better then was before when in Chrome we have Console with ConsoleBase prototype.
console is replaceable and each property is replaceable. I can't see the different between replaceble setter/getter and attribute. Could you figure out this?
window.Console behavior wasn't changed in Chrome it is still undefined but we can define it with constructor if necessary.
image

@bzbarsky
Copy link

and each property is replaceable.

Replaceable in what sense? In Gecko you can set console.log = whatever and this will shadow the prototype property, obviously, but Console.prototype.log will still be the original thing, of course. If you're putting props on a prototype in Chrome, that should give the same behavior, obviously.

There shouldn't be any getters/setters here, because Console has no attributes, only methods ("operations" in IDL-speak).

@domenic
Copy link
Member

domenic commented Apr 25, 2016

There's the question of what Object.getOwnPropertyDescriptor(window, "console") returns. That is what is changed by the Chrome patch to be incompatible with other browsers.

@domenic
Copy link
Member

domenic commented May 18, 2016

This seems like something we'd need implementers to decide on.

Per that bug, WebKit has gone with adding an empty object named __proto__ to console. (If I were to spec that, I'd probably add an extended attribute [LegacyDummyProto] for use on namespaces, which hopefully only console would ever use; with luck CSS could get away without it.)

But how does Gecko feel about the potential compatibility hit? How does Chrome? (@paulirish @ak239) Edge? (@andysterland) If most browsers are interested in pushing through without such a hack, we probably shouldn't spec it, but I don't really know yet.

@domenic
Copy link
Member

domenic commented May 18, 2016

Oh, and there's two potential hacks here:

(A) Make console's [[Prototype]] a new empty object
(B) Add an own property named "__proto__" whose value is an empty object.

(The difference is observable because for (A), Object.getPrototypeOf(console) will return the empty object; for (B) it will return Object.prototype.)

WebKit seems to have gone with (A). I was originally thinking that (B) would be better, but upon reflection it's probably too weird and could potentially cause compatibility issues.

Note that neither (A) nor (B) really fixes the original demo code shown by @JosephPecoraro:

console.__proto__.debug = function(format) {
    if (window.DEBUG) {
        var varargs = Array.prototype.slice.call(arguments);
        console.__proto__.info.apply(this, varargs)
    }
}

I believe that this will still fail, once it reaches the line console.__proto__.info.apply(this, varargs). Maybe that line is reached more rarely than the for-in he talked about, though.

@JosephPecoraro
Copy link

I believe that this will still fail, once it reaches the line console.__proto__.info.apply(this, varargs)

We were aware of the possible issue, but were fine with the trade offs.

You are correct that the apply would fail, but in practice it is unlikely to be reached. This particular page doesn't seem to call console.debug anywhere or make use of its new function by any other name. However, were the page were to do console.debug("foo") (which we considered the most likely use) it would use the unaffected native console.debug on the namespace object and not the fragile console.__proto__.debug the page defined.

@zcorpan
Copy link
Member

zcorpan commented May 19, 2016

@domenic if the hack is a one-off, it can be prose in the console spec rather than new extended attribute in Web IDL.

@zcorpan
Copy link
Member

zcorpan commented May 19, 2016

I did a quick search in httparchive (494k pages), only 3 resources that do __proto__ or getPrototypeOf on console or CSS.

SELECT COUNT(*) AS num, REGEXP_EXTRACT(body, r'(\b(?:(?:CSS|console)\.__proto__|getPrototypeOf\(\s*(?:[a-zA-Z]+\.)*(?:CSS|console)\s*\)).*)') as match
FROM [httparchive:har.2016_04_15_chrome_requests_bodies]
GROUP BY match
ORDER BY num DESC
Row num match
1 17616995 null
2 1 `console.proto.debug=function(format){if(window.DEBUG){var varargs=Array.prototype.slice.call(arguments);console.proto.info.apply(this,varargs)}},_mu.utils.renderTemplate=function(elementId,data,namespace){if("string"!=typeof elementId
3 1 `console.proto;.each(.keys(functions),function(key){if(typeof functions[key]=="function"){this[key]=function(){if(self.logging){console[key].apply(console,arguments)}};self.enabled[key]=true}},this)}else{window.console=this}.each(consoleInterface,function(functionName){if(this[functionName]===undefined){this[functionName]=function(){};self.enabled[functionName]=false}},this)}})(window,window.jQuery,window.,window.console,window.SiteTools.Core);Namespace("SiteTools.Core");(function(window,$,,console,core){window.SiteTools.Core.Event=new function(){var self=this;this.logging=true;this.log=function(groupTitle,groupArgs){if(this.logging){if(core.Console.enabled.groupCollapsed){console.groupCollapsed(groupTitle);if(core.Console.enabled.dir){console.dir(groupArgs)}else{console.log(groupArgs)}console.groupEnd()}else{console.log(groupTitle)}}};this.Bindings=[];this.Trigger=function(event,args){self.log(String.Format("Event '{0}' triggered",event),{"Arguments":args});var curBindings=.filter(this.Bindings,function(binding){return binding.event==event});.every(this.Bindings,function(binding){if(binding.context.nodeName&&binding.context!==window.document){if(!$(binding.context).closest("html").length){self.Unbind(binding.event,binding.eventHandler,binding.context)}}});.every(curBindings,function(binding){var eventArgs={type:event,data:args,cancelBubble:false};binding.eventHandler.call({},eventArgs);if(eventArgs.cancelBubble===true){self.log(String.Format("Event bubble canceled for event '{0}'",event),{"Arguments":eventArgs});return false}else{return true}});if(event!="EventTrigger"){this.Trigger("EventTrigger",{type:event,data:args})}};this.Bind=function(event,eventHandler,context){context=context
4 1 `console.proto;.each(.keys(functions),function(key){if(typeof functions[key]=="function"){this[key]=function(){if(self.logging){console[key].apply(console,arguments)}};self.enabled[key]=true}},this)}else{window.console=this}.each(consoleInterface,function(functionName){if(this[functionName]===undefined){this[functionName]=function(){};self.enabled[functionName]=false}},this)}})(window,window.jQuery,window.,window.console,window.SiteTools.Core);Namespace("SiteTools.Core");(function(window,$,,console,core){window.SiteTools.Core.Event=new function(){var self=this;this.logging=true;this.log=function(groupTitle,groupArgs){if(this.logging){if(core.Console.enabled.groupCollapsed){console.groupCollapsed(groupTitle);if(core.Console.enabled.dir){console.dir(groupArgs)}else{console.log(groupArgs)}console.groupEnd()}else{console.log(groupTitle)}}};this.Bindings=[];this.Trigger=function(event,args){self.log(String.Format("Event '{0}' triggered",event),{Arguments:args});var curBindings=.filter(this.Bindings,function(binding){return binding.event==event});.every(this.Bindings,function(binding){if(binding.context.nodeName&&binding.context!==window.document){if(!$(binding.context).closest("html").length){self.Unbind(binding.event,binding.eventHandler,binding.context)}}});.every(curBindings,function(binding){var eventArgs={type:event,data:args,cancelBubble:false};binding.eventHandler.call({},eventArgs);if(eventArgs.cancelBubble===true){self.log(String.Format("Event bubble canceled for event '{0}'",event),{Arguments:eventArgs});return false}else{return true}});if(event!="EventTrigger"){this.Trigger("EventTrigger",{type:event,data:args})}};this.Bind=function(event,eventHandler,context){context=context

@alexkozy
Copy link

alexkozy commented May 20, 2016

In Chrome we'd like to fix problem with console.proto as soon as possible and are going to land (A) as temporary solution.
I think that we can add a warning message when someone set something on console.proto .

@danzen
Copy link

danzen commented Jun 19, 2016

Hi folks, over the last couple of versions of Firefox, the binding of console.log is no longer giving the file and line numbers in very right hand column of the console. It now says (unknown). Other browsers still work. Is there a way for me to solve this as it is important for my public library http://zimjs.com. I am using:

var log = console.log.bind(console);

also tried with no success:

var log = Function.prototype.bind.call(console.log, console);

Thank you!

@domenic
Copy link
Member

domenic commented Jun 19, 2016

@danzen that seems unrelated to this issue; I'd suggest filing a bug on the Firefox issue tracker, not commenting on an issue on the console standard.

@danzen
Copy link

danzen commented Jun 19, 2016

@domenic thanks - I think I did that a few weeks ago - I will check on that... sorry did not realize that this was for standards. Cheers for all your work. Just looked and could not find my bug report. So added another: https://bugzilla.mozilla.org/show_bug.cgi?id=1280818#c0 if you are interested!

bzbarsky pushed a commit to whatwg/webidl that referenced this issue Aug 25, 2016
* Add namespaces

This adds the concept of namespaces, as discussed in whatwg/console#3 (starting especially around whatwg/console#3 (comment)). They can only contain regular operations.

The ES binding for namespaces here is written in a fully modern style, and so differs slightly from similar prose for interfaces' ES binding. It is hoped that it can provide a template for eventually updating interfaces' ES binding to modern ES.

* Address most code review comments:

- Missing some [SecureContext] stuff
- Not yet addressed the operation-creation stuff

* Stick with "declared on" instead of "declared within"

It doesn't read quite right to me, but let's keep it as-is for now and investigate any issues in #153.

* Move "creating an operation function" out to #es-operations
@domenic
Copy link
Member

domenic commented Oct 17, 2016

Thanks everyone for your help along this long journey! The spec is now updated, including the special prototype object.

joyeecheung added a commit to joyeecheung/node that referenced this issue Oct 25, 2018
From the WHATWG console spec:

> For historical web-compatibility reasons, the namespace object for
> console must have as its [[Prototype]] an empty object, created as
> if by ObjectCreate(%ObjectPrototype%), instead of %ObjectPrototype%.

Since in Node.js, the Console constructor has been exposed through
require('console'), we need to keep the Console constructor but
we cannot actually use `new Console` to construct the global console.
This patch changes the prototype chain of the global console object,
the console.Console.prototype is not in the global console prototype
chain anymore, which means

```
global.console instanceof global.console.Console
```

is no longer true after this patch.

This fixes a case in the console Web Platform Test that we commented
out.

Refs: https://console.spec.whatwg.org/#console-namespace
Refs: whatwg/console#3
joyeecheung added a commit to joyeecheung/node that referenced this issue Oct 25, 2018
From the WHATWG console spec:

> For historical web-compatibility reasons, the namespace object for
> console must have as its [[Prototype]] an empty object, created as
> if by ObjectCreate(%ObjectPrototype%), instead of %ObjectPrototype%.

Since in Node.js, the Console constructor has been exposed through
require('console'), we need to keep the Console constructor but
we cannot actually use `new Console` to construct the global console.

This patch changes the prototype chain of the global console object,
so the console.Console.prototype is not in the global console prototype
chain anymore.

```
const proto = Object.getPrototypeOf(global.console);
// Before this patch
proto.constructor === global.console.Console
// After this patch
proto.constructor === Object
```

But, we still maintain that

```
global.console instanceof global.console.Console
```

through a custom Symbol.hasInstance function of Console that tests
for a special symbol kIsConsole for backwards compatibility.

This fixes a case in the console Web Platform Test that we commented
out.

Refs: https://console.spec.whatwg.org/#console-namespace
Refs: whatwg/console#3
danbev pushed a commit to nodejs/node that referenced this issue Oct 26, 2018
From the WHATWG console spec:

> For historical web-compatibility reasons, the namespace object for
> console must have as its [[Prototype]] an empty object, created as
> if by ObjectCreate(%ObjectPrototype%), instead of %ObjectPrototype%.

Since in Node.js, the Console constructor has been exposed through
require('console'), we need to keep the Console constructor but
we cannot actually use `new Console` to construct the global console.

This patch changes the prototype chain of the global console object,
so the console.Console.prototype is not in the global console prototype
chain anymore.

```
const proto = Object.getPrototypeOf(global.console);
// Before this patch
proto.constructor === global.console.Console
// After this patch
proto.constructor === Object
```

But, we still maintain that

```
global.console instanceof global.console.Console
```

through a custom Symbol.hasInstance function of Console that tests
for a special symbol kIsConsole for backwards compatibility.

This fixes a case in the console Web Platform Test that we commented
out.

PR-URL: #23509
Refs: whatwg/console#3
Refs: https://console.spec.whatwg.org/#console-namespace
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: John-David Dalton <john.david.dalton@gmail.com>
joyeecheung added a commit to joyeecheung/node that referenced this issue Jan 9, 2019
From the WHATWG console spec:

> For historical web-compatibility reasons, the namespace object for
> console must have as its [[Prototype]] an empty object, created as
> if by ObjectCreate(%ObjectPrototype%), instead of %ObjectPrototype%.

Since in Node.js, the Console constructor has been exposed through
require('console'), we need to keep the Console constructor but
we cannot actually use `new Console` to construct the global console.

This patch changes the prototype chain of the global console object,
so the console.Console.prototype is not in the global console prototype
chain anymore.

```
const proto = Object.getPrototypeOf(global.console);
// Before this patch
proto.constructor === global.console.Console
// After this patch
proto.constructor === Object
```

But, we still maintain that

```
global.console instanceof global.console.Console
```

through a custom Symbol.hasInstance function of Console that tests
for a special symbol kIsConsole for backwards compatibility.

This fixes a case in the console Web Platform Test that we commented
out.

PR-URL: nodejs#23509
Refs: whatwg/console#3
Refs: https://console.spec.whatwg.org/#console-namespace
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: John-David Dalton <john.david.dalton@gmail.com>
BridgeAR pushed a commit to nodejs/node that referenced this issue Jan 9, 2019
From the WHATWG console spec:

> For historical web-compatibility reasons, the namespace object for
> console must have as its [[Prototype]] an empty object, created as
> if by ObjectCreate(%ObjectPrototype%), instead of %ObjectPrototype%.

Since in Node.js, the Console constructor has been exposed through
require('console'), we need to keep the Console constructor but
we cannot actually use `new Console` to construct the global console.

This patch changes the prototype chain of the global console object,
so the console.Console.prototype is not in the global console prototype
chain anymore.

```
const proto = Object.getPrototypeOf(global.console);
// Before this patch
proto.constructor === global.console.Console
// After this patch
proto.constructor === Object
```

But, we still maintain that

```
global.console instanceof global.console.Console
```

through a custom Symbol.hasInstance function of Console that tests
for a special symbol kIsConsole for backwards compatibility.

This fixes a case in the console Web Platform Test that we commented
out.

PR-URL: #23509
Refs: whatwg/console#3
Refs: https://console.spec.whatwg.org/#console-namespace
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: John-David Dalton <john.david.dalton@gmail.com>
BridgeAR pushed a commit to BridgeAR/node that referenced this issue Jan 16, 2019
From the WHATWG console spec:

> For historical web-compatibility reasons, the namespace object for
> console must have as its [[Prototype]] an empty object, created as
> if by ObjectCreate(%ObjectPrototype%), instead of %ObjectPrototype%.

Since in Node.js, the Console constructor has been exposed through
require('console'), we need to keep the Console constructor but
we cannot actually use `new Console` to construct the global console.

This patch changes the prototype chain of the global console object,
so the console.Console.prototype is not in the global console prototype
chain anymore.

```
const proto = Object.getPrototypeOf(global.console);
// Before this patch
proto.constructor === global.console.Console
// After this patch
proto.constructor === Object
```

But, we still maintain that

```
global.console instanceof global.console.Console
```

through a custom Symbol.hasInstance function of Console that tests
for a special symbol kIsConsole for backwards compatibility.

This fixes a case in the console Web Platform Test that we commented
out.

PR-URL: nodejs#23509
Refs: whatwg/console#3
Refs: https://console.spec.whatwg.org/#console-namespace
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: John-David Dalton <john.david.dalton@gmail.com>
juliyvchirkov added a commit to juliyvchirkov/polyfill-library-ft that referenced this issue Aug 1, 2023
Turning ``this`` from ``null`` to ``console`` accorging to whatwg/console#3 to avoid issues under antique engines

Thanks again to @zloirock for mentioning this
JakeChampion pushed a commit to juliyvchirkov/polyfill-library-ft that referenced this issue Aug 9, 2023
Turning ``this`` from ``null`` to ``console`` accorging to whatwg/console#3 to avoid issues under antique engines

Thanks again to @zloirock for mentioning this
JakeChampion pushed a commit to juliyvchirkov/polyfill-library-ft that referenced this issue Aug 17, 2023
Turning ``this`` from ``null`` to ``console`` accorging to whatwg/console#3 to avoid issues under antique engines

Thanks again to @zloirock for mentioning this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests