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 21946 - Ignoring non-null values of opener does not seem to be web-compatible
Summary: Ignoring non-null values of opener does not seem to be web-compatible
Status: RESOLVED FIXED
Alias: None
Product: WHATWG
Classification: Unclassified
Component: HTML (show other bugs)
Version: unspecified
Hardware: Other other
: P3 normal
Target Milestone: Unsorted
Assignee: Ian 'Hixie' Hickson
QA Contact: contributor
URL: http://www.whatwg.org/specs/web-apps/...
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-05-07 03:45 UTC by contributor
Modified: 2014-05-29 19:49 UTC (History)
6 users (show)

See Also:


Attachments

Description contributor 2013-05-07 03:45:20 UTC
Specification: http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html
Multipage: http://www.whatwg.org/C#dom-opener
Complete: http://www.whatwg.org/c#dom-opener
Referrer: http://www.whatwg.org/specs/web-apps/current-work/multipage/

Comment:
Ignoring non-null values of opener does not seem to be web-compatible

Posted from: 98.110.194.206 by bzbarsky@mit.edu
User agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20130503 Firefox/23.0
Comment 1 Boris Zbarsky 2013-05-07 03:52:13 UTC
The Magento CMS, which is pretty widely used, has this bit:

    getTargetElement: function() {
        if (typeof(tinyMCE) != 'undefined' && tinyMCE.get(this.targetElementId)) {
            if ((opener = this.getMediaBrowserOpener())) {
                var targetElementId = tinyMceEditors.get(this.targetElementId).getMediaBrowserTargetElementId();
                return opener.document.getElementById(targetElementId);

note the assignment to "opener".  When Gecko implemented what the spec currently says for opener, this code broke.  See https://bugzilla.mozilla.org/show_bug.cgi?id=868996

I just tested, and this script:

    opener = 20; alert(opener);

alerts 20 in Firefox 19, Chrome, Safari, Opera, and IE9.  This one:

  opener = window; alert(opener);

alerts the window in older IE versions too...
Comment 2 Boris Zbarsky 2013-05-07 17:18:25 UTC
But note that there are probably complications in terms of what happens to the opener value on navigation....
Comment 3 Boris Zbarsky 2013-05-08 19:46:12 UTC
So what I will be implementing in Gecko is to make this setter behave just like replaceable properties if called with a non-null Window argument.  We will still restrict to Window arguments.
Comment 4 Ian 'Hixie' Hickson 2013-06-07 22:58:36 UTC
heycam, any chance you can make [Replaceable] apply to non-readonly attributes, and have it behave as needed here, namely, as for [Replaceable] on readonly properties if the value is one that would normally throw TypeError, and as a regular attribute otherwise?
Comment 5 Boris Zbarsky 2013-06-08 02:36:12 UTC
Note that comment 3 and comment 4 are saying very different things.

The basic web compat requirements here, as far as I know them, are:

1) Setting opener to null should set it to null on the navigation context.
2) Setting opener to any other Window value should set it to that value for the
   lifetime of the current page.

UA behavior ... differs.  Some UAs allow setting opener to any value.  Some UAs persist that setting across page loads depending on the value even for some non-null values.

I strongly believe that non-null values should NOT be persisted across page loads, for what it's worth.
Comment 6 Cameron McCormack 2013-06-08 04:29:23 UTC
(In reply to comment #5)
> Note that comment 3 and comment 4 are saying very different things.
> 
> The basic web compat requirements here, as far as I know them, are:
> 
> 1) Setting opener to null should set it to null on the navigation context.
> 2) Setting opener to any other Window value should set it to that value for
> the
>    lifetime of the current page.

Can we handle this not as a [Replaceable] thing in the IDL actually, but just the behaviour of the opener IDL attribute?  So have a flag on the browsing context that represents whether a (null or Window) value has been assigned to opener, and also a thing that stores that value, and have the opener IDL attribute return that value if the flag is set.
Comment 7 Boris Zbarsky 2013-06-08 04:33:40 UTC
The point is that when something non-null is set it needs to not be stored on the browsing context.

It could be stored on the Window, of course; then the opener getter would be a lot more complicated.
Comment 8 Cameron McCormack 2013-06-08 04:35:55 UTC
(In reply to comment #7)
> It could be stored on the Window, of course; then the opener getter would be
> a lot more complicated.

I guess that's what I was suggesting.  I'm just not sure it's great to make [Replaceable] even more complicated.
Comment 9 Boris Zbarsky 2013-06-08 04:37:21 UTC
Right.  Fwiw, in this case we do the replaceable-like thing entirely in the code equivalent of "spec prose", not in bindings.  I don't think it's worth adding this to WebIDL since this seems like a one-off case.
Comment 10 Ian 'Hixie' Hickson 2013-06-14 18:35:33 UTC
Roger. Will do it in prose.

Just to make sure I understand this:

- 1. make window.opener:
       attribute any opener;

- 2. define a Window-specific (not Document-specific, so it survives the case when 
     Window is reused for a same-origin Document replacing about:blank) internal
     value that can hold any value, and that is initially null.

- 3. on getting, if the internal value is not null, return that. Otherwise, return 
     the actual opener value.

- 4. on setting, if the new value is "null", set the actual opener value to null.
     Otherwise, set the internal value to the new value.

Is that right?
Comment 11 Boris Zbarsky 2013-06-14 18:37:42 UTC
It could be done that way, yes.

Why do we want 'any' as opposed to just allowing 'Window'?
Comment 12 Ian 'Hixie' Hickson 2013-06-21 16:19:56 UTC
If the value isn't "any", then WebIDL will coerce the values or throw an exception, before we see them in the prose.
Comment 13 Boris Zbarsky 2013-06-21 18:22:56 UTC
Sure.  Why is that a problem?  Again, what Gecko is currently shipping is that the value is a Window in the IDL, and if it's non-null we redefine the property in a [Replaceable]-like way.  But we only do that for Windows; we have found no one depending on setting opener to non-Window things so far.
Comment 14 Ian 'Hixie' Hickson 2013-07-02 22:53:45 UTC
I don't understand what you mean by "redefine the property in a [Replaceable]-like way" if you don't mean "allow it to be set to any arbitrary value". Isn't what you're describing just "the property can be set"? What's "[Replaceable]-like" about it, exactly?

Based on my best guess of what you're describing, a revised proposal:

- 1. define a Window-specific (not Document-specific, so it survives the
     case when Window is reused for a same-origin Document replacing
     about:blank) internal value that can hold a WindowProxy, and that is
     set, when the Window is created, to the actual opener value's WindowProxy.

- 2. on getting, .opener returns the internal value.

- 3. on setting, .opener sets the internal value to the new value, and, if
     the new value is "null", also set the actual opener value to null.
Comment 15 Boris Zbarsky 2013-07-02 22:57:14 UTC
What Gecko currently implements is that when you set .opener we check that you're setting it to a Window or null and throw if you aren't (this is all done by the WebIDL layer).  Then if you're not setting it to null, we Object.defineProperty a new property on the "this" object, which is a value property whose value is the thing that was passed in.  This is handled by the "prose" part of the algorithm.

This is not quite identical to your proposal, though your proposal seems like it would be fine.
Comment 16 Ian 'Hixie' Hickson 2013-07-03 22:04:57 UTC
Actually what I described wouldn't work because if you go to a page, then go to another that resets the opener to null, then come back, it should remain reset. My proposal would have the first window still pointing to the real opener.

I don't mind doing the property-setting thing, but I've no idea what the right prose to do that is. heycam, can you help me out with the right terminology?
Comment 17 Cameron McCormack 2013-07-03 22:15:53 UTC
Make the type of the attribute "Window?", and then in the prose write something like (where /value/ is the new value):

  If /value/ is null, then ...
  Otherwise, call the [[DefineOwnProperty]] method of the Window object, passing property name "opener", Property Descriptor { [[Value]]: /value/, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }, and false.

(That ignores the difference between IDL values an ECMAScript values, though in this case there's not enough of a difference to really worry about it.)
Comment 18 Ian 'Hixie' Hickson 2013-10-22 18:15:06 UTC
I couldn't work out what the "and false" bit was for. I left it out, since it didn't seem to map to anything in the JS spec.

Let me know if the new text is ok!
Comment 19 contributor 2013-10-22 18:15:30 UTC
Checked in as WHATWG revision r8235.
Check-in comment: Try to make window.opener more compatible
http://html5.org/tools/web-apps-tracker?from=8234&to=8235
Comment 20 Ms2ger 2013-10-22 19:46:34 UTC
(In reply to Ian 'Hixie' Hickson from comment #18)
> I couldn't work out what the "and false" bit was for. I left it out, since
> it didn't seem to map to anything in the JS spec.

In ES5, [[DefineOwnProperty]] takes three arguments (P, Desc, Throw); in ES6, just two (P, Desc).
Comment 21 Ian 'Hixie' Hickson 2013-10-22 21:21:10 UTC
Ah. Was the third argument just always ignored or always false or something?
Comment 22 Boris Zbarsky 2013-10-22 23:21:48 UTC
Neither.  They just have totally different signatures/contracts.

In ES5, [[DefineOwnProperty]] is supposed to throw if it fails in cases when the Throw argument is true, and silently do nothing when it's false.  The caller is responsible for calling in the correct value of Throw.

In ES6, [[DefineOwnProperty]] just returns a boolean indicating whether it succeeded; the callers then throw in some cases but not others in failure cases, depending on what the callee is, exactly.

So if you're speccing this in ES6 terms, you just want to make sure to handle the return value without throwing; I think the spec text your wrote is ok, since it does exactly that.
Comment 23 Ian 'Hixie' Hickson 2013-10-23 19:09:26 UTC
I really want this to be targetting tomorrow's most up to date draft, whatever that is.
Comment 24 Boris Zbarsky 2013-10-23 20:17:49 UTC
Yeah, targeting ES6 makes sense here.
Comment 25 Ian 'Hixie' Hickson 2013-11-18 23:22:17 UTC
Ok. So the text in the spec is ok then? Maybe I should add a reference to the current ES draft or something?
Comment 26 Boris Zbarsky 2013-11-19 01:23:04 UTC
I think the text in the spec right now is ok, yes.
Comment 27 Ian 'Hixie' Hickson 2013-11-19 21:05:14 UTC
Okie dokie.
Comment 28 Boris Zbarsky 2013-11-19 21:23:08 UTC
Wait, I meant just the ES bits.  I'm still not sure why we're allowing all values here instead of just window-or-null.
Comment 29 Ian 'Hixie' Hickson 2013-11-19 21:40:00 UTC
Where does it allow all values?
Comment 30 Boris Zbarsky 2013-11-19 21:43:15 UTC
Oh, sorry.  I misread the bug and failed to read what the spec actually says now.  We're good here, and my apologies for the noise!
Comment 31 Boris Zbarsky 2014-05-29 19:49:44 UTC
> we have found no one depending on setting opener to non-Window things so far.

That was because we had it on the proto chain, so

  var opener = {};

shadowed instead of setting.  But global props are supposed to go on the global, and sites depend on the above to work (e.g. see https://bugzilla.mozilla.org/show_bug.cgi?id=989584 ).  I filed bug 25917 to change to "any" here.