This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 29421 - Should getters on a global without an explicit 'this' really throw TypeError?
Summary: Should getters on a global without an explicit 'this' really throw TypeError?
Status: RESOLVED FIXED
Alias: None
Product: WebAppsWG
Classification: Unclassified
Component: WebIDL (show other bugs)
Version: unspecified
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Domenic Denicola
QA Contact: public-webapps-bugzilla
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-02-05 17:04 UTC by Chris Dumez
Modified: 2017-01-20 08:24 UTC (History)
8 users (show)

See Also:


Attachments

Description Chris Dumez 2016-02-05 17:04:30 UTC
According to [1], the getter should use 'this' value and does not mention anything about using something else when there is no explicit this.

The section about [ImplicitThis][2] clearly states that it applies to operations but NOT attribute getters, and that throwing is the right thing to do for attribute getters.

The section about operations [3] does state:
"""
Otherwise, if the interface on which the operation appears has an [ImplicitThis] extended attribute, and the this value is null or undefined, then O is the ECMAScript global object associated with the Function object.
"""

Should the attribute getter section be updated to do the same thing as operations when  [ImplicitThis] is specified? This seems to be Firefox's behavior. idlharness.js, which is used by W3C web-platform-tests also tests that attribute getters on the Window do not require an explicit 'this'. I tried filing a bug against idlharness.js [4][5] but Ms2ger suggested I file a bug against the Web IDL specification instead.

[1] http://heycam.github.io/webidl/#dfn-attribute-getter
[2] http://heycam.github.io/webidl/#ImplicitThis
[3] http://heycam.github.io/webidl/#es-operations
[4] https://github.com/w3c/testharness.js/issues/182
[5] https://github.com/w3c/testharness.js/pull/183
Comment 1 Boris Zbarsky 2016-02-05 17:58:24 UTC
So the big web compat constraint here is that this should do the right thing:

  var perf = performance;

needs to work.  I believe in spec terms this ends up in http://www.ecma-international.org/ecma-262/6.0/#sec-object-environment-records-getbindingvalue-n-s which lands in http://www.ecma-international.org/ecma-262/6.0/#sec-get-o-p which will use the object associated with the object enviroment record (in this case the global) as "this".  So for this part to work, no effort is needed on the part of IDL.

You're correct that the current Firefox behavior makes this also work:

  Object.getOwnPropertyDescriptor(window, "performance").get.call()

I tried this in a few other browsers, with the following results:

1) Chrome.  Seems to not actually have accessor properties on the window yet.  Presumably they're still updating to Web IDL for the window...  In any case, Object.getOwnPropertyDescriptor(window, "performance") returns a value descriptor.

2) Safari.  Has some bizarre setup where descriptors on the global have undefined get and no value, but stuff somehow still works.  Basically, totally violates the ES spec.

3) IE11.  This seems to put the properties on window.__proto__, not window.  Subject to that constraint, Object.getOwnPropertyDescriptor(window.__proto__, "performance").get.call() works.

4) Edge.  Object.getOwnPropertyDescriptor(window, "performance").get.call() works.

Speccing the Firefox/Edge behavior makes some sense to me, especially because the only reason the bareword works otherwise is because it takes a weird path to the getter.
Comment 2 Chris Dumez 2016-02-05 19:40:28 UTC
(In reply to Boris Zbarsky from comment #1)
> So the big web compat constraint here is that this should do the right thing:
> 
>   var perf = performance;
> 
> needs to work.  I believe in spec terms this ends up in
> http://www.ecma-international.org/ecma-262/6.0/#sec-object-environment-
> records-getbindingvalue-n-s which lands in
> http://www.ecma-international.org/ecma-262/6.0/#sec-get-o-p which will use
> the object associated with the object enviroment record (in this case the
> global) as "this".  So for this part to work, no effort is needed on the
> part of IDL.
> 
> You're correct that the current Firefox behavior makes this also work:
> 
>   Object.getOwnPropertyDescriptor(window, "performance").get.call()
> 
> I tried this in a few other browsers, with the following results:
> 
> 1) Chrome.  Seems to not actually have accessor properties on the window
> yet.  Presumably they're still updating to Web IDL for the window...  In any
> case, Object.getOwnPropertyDescriptor(window, "performance") returns a value
> descriptor.
> 
> 2) Safari.  Has some bizarre setup where descriptors on the global have
> undefined get and no value, but stuff somehow still works.  Basically,
> totally violates the ES spec.

Yes, I work on WebKit and am currently fixing this issue. This is also why I wanted the behavior of implicit 'this' for the global Window Object to be clarified.

On WebKit nightly, it does return getters/setters now but the following:
$ Object.getOwnPropertyDescriptor(window.__proto__, "performance").get.call()
throws a "TypeError: The DOMWindow.performance getter can only be used on instances of DOMWindow" for now.

> 
> 3) IE11.  This seems to put the properties on window.__proto__, not window. 
> Subject to that constraint,
> Object.getOwnPropertyDescriptor(window.__proto__, "performance").get.call()
> works.
> 
> 4) Edge.  Object.getOwnPropertyDescriptor(window, "performance").get.call()
> works.
> 
> Speccing the Firefox/Edge behavior makes some sense to me, especially
> because the only reason the bareword works otherwise is because it takes a
> weird path to the getter.

Also, I think we should be clear about which window we should fall back to when 'this' is null/undefined, in the case of subframes. E.g.

otherWin = open("about:blank");
locationGetter = Object.getOwnPropertyDescriptor(otherWin, "location");
locationGetter.call()

should this be identical to:
locationGetter.call(otherWin)
or
locationGetter.call(window)
?
Comment 3 Chris Dumez 2016-02-05 19:50:08 UTC
(In reply to Christophe Dumez from comment #2)
> (In reply to Boris Zbarsky from comment #1)
> > So the big web compat constraint here is that this should do the right thing:
> > 
> >   var perf = performance;
> > 
> > needs to work.  I believe in spec terms this ends up in
> > http://www.ecma-international.org/ecma-262/6.0/#sec-object-environment-
> > records-getbindingvalue-n-s which lands in
> > http://www.ecma-international.org/ecma-262/6.0/#sec-get-o-p which will use
> > the object associated with the object enviroment record (in this case the
> > global) as "this".  So for this part to work, no effort is needed on the
> > part of IDL.
> > 
> > You're correct that the current Firefox behavior makes this also work:
> > 
> >   Object.getOwnPropertyDescriptor(window, "performance").get.call()
> > 
> > I tried this in a few other browsers, with the following results:
> > 
> > 1) Chrome.  Seems to not actually have accessor properties on the window
> > yet.  Presumably they're still updating to Web IDL for the window...  In any
> > case, Object.getOwnPropertyDescriptor(window, "performance") returns a value
> > descriptor.
> > 
> > 2) Safari.  Has some bizarre setup where descriptors on the global have
> > undefined get and no value, but stuff somehow still works.  Basically,
> > totally violates the ES spec.
> 
> Yes, I work on WebKit and am currently fixing this issue. This is also why I
> wanted the behavior of implicit 'this' for the global Window Object to be
> clarified.
> 
> On WebKit nightly, it does return getters/setters now but the following:
> $ Object.getOwnPropertyDescriptor(window.__proto__, "performance").get.call()
> throws a "TypeError: The DOMWindow.performance getter can only be used on
> instances of DOMWindow" for now.
> 
> > 
> > 3) IE11.  This seems to put the properties on window.__proto__, not window. 
> > Subject to that constraint,
> > Object.getOwnPropertyDescriptor(window.__proto__, "performance").get.call()
> > works.
> > 
> > 4) Edge.  Object.getOwnPropertyDescriptor(window, "performance").get.call()
> > works.
> > 
> > Speccing the Firefox/Edge behavior makes some sense to me, especially
> > because the only reason the bareword works otherwise is because it takes a
> > weird path to the getter.
> 
> Also, I think we should be clear about which window we should fall back to
> when 'this' is null/undefined, in the case of subframes. E.g.
> 
> otherWin = open("about:blank");
> locationGetter = Object.getOwnPropertyDescriptor(otherWin, "location").get;
> locationGetter.call()
> 
> should this be identical to:
> locationGetter.call(otherWin)
> or
> locationGetter.call(window)
> ?

FYI, in this case, I would expect locationGetter.call() to behave the same way as locationGetter.call(window) as I think this is how it works in EcmaScript.

However, Firefox seems to do locationGetter.call(otherWin) in this case.
Comment 4 Boris Zbarsky 2016-02-05 19:54:05 UTC
> Yes, I work on WebKit and am currently fixing this issue.

Ah, awesome.  :)

If we spec auto-picking a global, we should fall back to the global of the Realm of the getter function (basically, do what a non-strict scripted function would do).  So in your example, for the same-origin case, that would be mean locationGetter.call() and locationGetter.call(otherWin) do the same thing.

For the cross-origin case, given the current spec proposals for cross-origin objects, the getter would be created in the Realm of the thing touching the cross-origin object, so locationGetter.call() would be equivalent to locationGetter.call(window).  This slight weirdness only affects things one can get cross-origin on a window, which is just "location"... so I think I'm ok with it.
Comment 5 Chris Dumez 2016-02-05 20:07:10 UTC
(In reply to Boris Zbarsky from comment #4)
> > Yes, I work on WebKit and am currently fixing this issue.
> 
> Ah, awesome.  :)
> 
> If we spec auto-picking a global, we should fall back to the global of the
> Realm of the getter function (basically, do what a non-strict scripted
> function would do).  So in your example, for the same-origin case, that
> would be mean locationGetter.call() and locationGetter.call(otherWin) do the
> same thing.

Oh right, never mind. After re-reading the EcmaScript again, my initial expectation was incorrect. Firefox does seem to behave correctly then.

> 
> For the cross-origin case, given the current spec proposals for cross-origin
> objects, the getter would be created in the Realm of the thing touching the
> cross-origin object, so locationGetter.call() would be equivalent to
> locationGetter.call(window).  This slight weirdness only affects things one
> can get cross-origin on a window, which is just "location"... so I think I'm
> ok with it.
Comment 6 Chris Dumez 2016-02-05 20:11:28 UTC
If this gets spec'd, I will work on supporting this in WebKit as well so Safari and Firefox would behave the same.
Comment 7 Chris Dumez 2016-02-08 01:01:50 UTC
By the way, I have just noticed that the Window interface is not marked as [ImplicitThis] in the latest HTML specification:
https://github.com/whatwg/html/issues/643
Comment 8 Anne 2016-02-11 16:28:19 UTC
Is this a duplicate of bug 18547 now?
Comment 9 Boris Zbarsky 2016-02-11 16:44:12 UTC
Depends on whether "methods" includes attribute getters/setters or not.
Comment 10 Domenic Denicola 2016-02-11 16:46:03 UTC
It should, right? I can edit the title; I guess that was just an assumption on my part.
Comment 11 Boris Zbarsky 2016-02-11 16:46:50 UTC
If we expand the other bug to include accessors, then dupping seems fine to me.
Comment 12 Chris Dumez 2016-02-11 17:07:05 UTC
FYI, this was implemented in WebKit to match Firefox's behavior:
http://trac.webkit.org/changeset/196303
Comment 13 Domenic Denicola 2016-11-01 15:07:21 UTC
I think this is not fixed for attributes, only for operations, so we can use this bug to track it. I'll take this since I fixed operations. In the process I'll probably overhaul the attribute getter/setter definitions to be modern.
Comment 14 Tobie Langel 2017-01-20 08:24:02 UTC
Fixed in https://github.com/heycam/webidl/commit/4c9c298