<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://www.w3.org/Bugs/Public/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4"
          urlbase="https://www.w3.org/Bugs/Public/"
          
          maintainer="sysbot+bugzilla@w3.org"
>

    <bug>
          <bug_id>20701</bug_id>
          
          <creation_ts>2013-01-17 22:04:36 +0000</creation_ts>
          <short_desc>Security: Redesign how cross-origin-visible objects work (Location, Window)</short_desc>
          <delta_ts>2017-11-27 00:53:08 +0000</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WHATWG</product>
          <component>HTML</component>
          <version>unspecified</version>
          <rep_platform>Other</rep_platform>
          <op_sys>Linux</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>MOVED</resolution>
          
          
          <bug_file_loc>http://www.whatwg.org/specs/web-apps/current-work/#security-3</bug_file_loc>
          <status_whiteboard>spec_lags_implementation</status_whiteboard>
          <keywords></keywords>
          <priority>P1</priority>
          <bug_severity>critical</bug_severity>
          <target_milestone>Unsorted</target_milestone>
          
          <blocked>21674</blocked>
    
    <blocked>22346</blocked>
    
    <blocked>27128</blocked>
          <everconfirmed>1</everconfirmed>
          <reporter>contributor</reporter>
          <assigned_to name="Ian &apos;Hixie&apos; Hickson">ian</assigned_to>
          <cc>adrianba</cc>
    
    <cc>annevk</cc>
    
    <cc>bobbyholley</cc>
    
    <cc>bobowencode</cc>
    
    <cc>bruant.d</cc>
    
    <cc>bzbarsky</cc>
    
    <cc>cam</cc>
    
    <cc>contributor</cc>
    
    <cc>dghrjyan</cc>
    
    <cc>erights</cc>
    
    <cc>ian</cc>
    
    <cc>josh</cc>
    
    <cc>jrossi</cc>
    
    <cc>Kikaayala12</cc>
    
    <cc>kukkik.club42</cc>
    
    <cc>m.maxwell1189</cc>
    
    <cc>mathias</cc>
    
    <cc>mike</cc>
    
    <cc>rb8484</cc>
    
    <cc>shark101die</cc>
    
    <cc>thuychu17889</cc>
    
    <cc>Tobias-Braun1004</cc>
    
    <cc>tonyaestill</cc>
    
    <cc>travil</cc>
    
    <cc>tross</cc>
    
    <cc>w3c</cc>
    
    <cc>zcorpan</cc>
          
          <qa_contact>contributor</qa_contact>

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>81549</commentid>
    <comment_count>0</comment_count>
    <who name="">contributor</who>
    <bug_when>2013-01-17 22:04:36 +0000</bug_when>
    <thetext>Specification: http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html
Multipage: http://www.whatwg.org/C#security-3
Complete: http://www.whatwg.org/c#security-3

Comment:
Location security restrictions are over-restrictive

Posted from: 173.48.81.109 by bzbarsky@mit.edu
User agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) Gecko/20130108 Firefox/21.0</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>81550</commentid>
    <comment_count>1</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-01-17 22:06:22 +0000</bug_when>
    <thetext>Since Location objects are per-Window, if you have your hand on one that means you&apos;re same-origin (or at least same-origin-enough) with that Window to start with.  There is therefore no need to prevent sets of random non-IDL properties on the object if the browsing context of its Window has since been navigated to a different-origin document.

The thing that needs to be prevented are the getters and setters of various of the IDL attributes on the interface.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>84377</commentid>
    <comment_count>2</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-03-13 23:48:24 +0000</bug_when>
    <thetext>There&apos;s just one Location object per Document, shared between all origins, according to the spec, unless I&apos;m missing something major (in which case I really need to make that clearer). Did we conclude that there should be a unique instance per origin and I just screwed up actually doing that or something? That sounds familiar, but I don&apos;t recall what the conclusion was. From what I can tell, the spec matches what WebKit and IE do.


(If Location object were per-origin, then:

So the main risk we&apos;re worried about is someone finding out where the user navigated to, right? That, and the author navigating a frame to a different (spoof) page than the user intended to go to.

So we have to prevent reads of the URL data when the effective script origin of the Location&apos;s Document&apos;s browsing context&apos;s active document doesn&apos;t match the entry script&apos;s effective script origin.

And we have to prevent writes to any of the URL data and all the methods, when the Location&apos;s Document&apos;s browsing context&apos;s active document&apos;s effective script origin doesn&apos;t match the entry script&apos;s effective script origin, except that we allow invocations of .href&apos;s setter and the .replace() method in the specific case of the entry script&apos;s browsing context being allowed to navigate the Location&apos;s Document&apos;s browsing context.)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>84386</commentid>
    <comment_count>3</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-03-14 00:53:06 +0000</bug_when>
    <thetext>&gt; There&apos;s just one Location object per Document,

Yes, but the origin of a Document is immutable, so the origin of that Location object is likewise immutable: it&apos;s the origin of the document.

Or do you mean there&apos;s one Location object per WindowProxy? I was pretty sure that this was NOT the setup we agreed on.

I agree that we need various restrictions on the IDL-defined bits of Location.  I just don&apos;t see why we need restrictions on setting .myMagicBeansProperty on some Location object you already have a reference to.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>84447</commentid>
    <comment_count>4</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-03-14 22:39:31 +0000</bug_when>
    <thetext>Per the spec today, the Location object&apos;s members expose the address of the object&apos;s associated Document object&apos;s browsing context&apos;s active document, not address of the object&apos;s associated Document.

Gecko does what the spec says as far as I can tell (scroll down in the iframe and click &quot;fun&quot;):
   http://software.hixie.ch/utilities/js/live-dom-viewer/saved/2162

Chrome seems to neuter the Location object entirely after navigation. Not sure what&apos;s going on there.

Did we decide to change the spec on this? I do recall discussing this, but I thought that thread had concluded with all the relevant changes being made. It&apos;s possible that I poorly communicated about what I had concluded needed changing, or that I edited the spec incorrectly, or that I haven&apos;t actually dealt with the relevant feedback yet, or that you disagreed and that it is still open somewhere that I haven&apos;t gotten to yet... :-|</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>84454</commentid>
    <comment_count>5</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-03-15 01:02:48 +0000</bug_when>
    <thetext>&gt; Did we decide to change the spec on this?

No, I don&apos;t think we did.

We all agree what should happen with the IDL-defined location members.

This bug is about &quot;expandos&quot; on Location objects.  The current spec phrasing prohibits them based on whether your origin matches the origin of the browsing context&apos;s current document, which doesn&apos;t seem necessary unless I&apos;m missing something.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>84495</commentid>
    <comment_count>6</comment_count>
    <who name="">contributor</who>
    <bug_when>2013-03-15 23:01:00 +0000</bug_when>
    <thetext>Checked in as WHATWG revision r7758.
Check-in comment: Allow custom properties on Location objects to work for the Document whose Location object it originally was.
http://html5.org/tools/web-apps-tracker?from=7757&amp;to=7758</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>84496</commentid>
    <comment_count>7</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-03-15 23:05:08 +0000</bug_when>
    <thetext>Oh, oh, I get it, I&apos;m sorry. I&apos;m just slow. And dumb. Please don&apos;t mind me.

Ok, I&apos;ve tried to fix this. Given my clear lack of competence in this bug, I highly recommend you check my work. :-)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>84775</commentid>
    <comment_count>8</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-03-21 15:10:43 +0000</bug_when>
    <thetext>So what it says now is:

  Any properties not defined in the IDL for the Location object or indirectly
  via one of those properties (e.g. toString(), which is defined via the
  stringifier keyword), if the entry script&apos;s effective script origin is the
  same origin as the Location object&apos;s associated Document&apos;s effective script
  origin 

but this is assuming that the entry script&apos;s effective script origin is the same as the effective script origin of the script doing the access, which is generally not a good assumption.  In any case, it&apos;s better to just fall back to the default same-origin policy (whatever that ends up being) rather than redefining it here.

I think it would be better to lift the language about &quot;IDL-defined&quot; into the paragraph that talks about the restriction instead of listing it as an exception.  So more like so:

  When accessing any attribute or calling any method defined in the IDL for a
  Location object, or indirectly via the IDL (e.g. toString(), which is
  defined via the stringifier keyword), user agents must throw a SecurityError
  when the entry script&apos;s effective script origin is not the same as the
  Location object&apos;s associated Document&apos;s browsing context&apos;s active document&apos;s
  effective script origin, with the following exceptions:

  * The href setter, if the entry script&apos;s script&apos;s browsing context is allowed
    to navigate the browsing context with which the Location object is
    associated
  * The replace() method, if the entry script&apos;s script&apos;s browsing context is
    allowed to navigate the browsing context with which the Location object is
    associated

or something.  Note that this also makes it clear that doing .assign on the Location is fine; it&apos;s _calling_ it that throws, which is I assume the intent.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>86911</commentid>
    <comment_count>9</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-04-26 23:30:17 +0000</bug_when>
    <thetext>&gt; this is assuming that the entry script&apos;s effective script origin is the
&gt; same as the effective script origin of the script doing the access, which is
&gt; generally not a good assumption.

The only time it can be anything else is when a script has changed document.domain after passing a reference to one of its functions to another script in the same original origin as it had, with that function then being invoked by that other script, as far as I can tell.
 
Let&apos;s first define some terms:

Script A is a script in origin X.
Script B is a script in origin X, which then sets document.domain to switch to origin Y.
Script C is a script in origin Z, which then sets document.domain to switch to origin Y as well.
Script D is a script in origin Z.

If we check the entry script, then what matters is what script begins the sequence of events that ends with a function in A, B, C, or D accessing the Location object.

If we check the calling script, then it has to be A doing the final access, but any of B, C, or D can actually start the process that invokes that function.

I guess for completeness we really want to check both. If either is possible (i.e. if A or B leaked a function one way or the other, and that function gets called by someone), the other is probably possible too.

If we want to check the calling script, this probably becomes dependent on the bug about defining what that means exactly.


&gt; Note that this also makes it clear that doing .assign on the
&gt; Location is fine; it&apos;s _calling_ it that throws

Do we really want it to be possible to take a reference to Location.assign without throwing? That seems like asking for trouble...</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>86936</commentid>
    <comment_count>10</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-04-29 00:07:42 +0000</bug_when>
    <thetext>&gt; The only time it can be anything else is when a script has changed
&gt; document.domain after passing a reference to one of its functions to another
&gt; script

This is the case in the web platform as you&apos;ve defined it, but not in all implementations of the web platform now, and not necessarily in all such implementations in the future.

A simple counterexample would be a UA that implements parts of its DOM in (self-hosted) JS, which for example Blink is claiming it wants to do.  At that point you have to worry about which scripts are part of the &quot;UA&quot; and which are part of &quot;web pages&quot;, if nothing else.

&gt; Do we really want it to be possible to take a reference to Location.assign
&gt; without throwing?

You can always do that: just run |var x = Object.getOwnPropertyDescriptor(location, &quot;assign&quot;)| in a window which you control.  (It&apos;s an own property because of the unforgeable bits; otherwise you can do that on the prototype with the same effect.)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>86937</commentid>
    <comment_count>11</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-04-29 00:36:32 +0000</bug_when>
    <thetext>(In reply to comment #10)
&gt; &gt; The only time it can be anything else is when a script has changed
&gt; &gt; document.domain after passing a reference to one of its functions to another
&gt; &gt; script
&gt; 
&gt; This is the case in the web platform as you&apos;ve defined it, but not in all
&gt; implementations of the web platform now, and not necessarily in all such
&gt; implementations in the future.
&gt; 
&gt; A simple counterexample would be a UA that implements parts of its DOM in
&gt; (self-hosted) JS, which for example Blink is claiming it wants to do.  At
&gt; that point you have to worry about which scripts are part of the &quot;UA&quot; and
&gt; which are part of &quot;web pages&quot;, if nothing else.

We&apos;re unlikely to use self-hosted JavaScript for objects that are visible across origins.  That&apos;s just not worth the complexity.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>86945</commentid>
    <comment_count>12</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-04-29 13:37:32 +0000</bug_when>
    <thetext>My point is that unless the use of self-hosting is incredibly restricted I expect that the self-hosted JS will effectively run with a different origin from the page scripts, because it needs to be able to do things that normal scripts can&apos;t do (e.g. it may well need to be able to set the values of file controls and such).  Which means that if you have page script calling into self-hosted JS that then calls into some method on an object that method needs to know that it&apos;s called from the self-hosted JS and not from the page.

Again, unless the expected use of self-hosting is very very limited.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>87010</commentid>
    <comment_count>13</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-04-30 15:42:02 +0000</bug_when>
    <thetext>I don&apos;t fully understand the problem.  It&apos;s likely we haven&apos;t gotten far enough into the implementation to run into this issue.

It seems that the spec only covers web site JS.  Any JS used by the user agent internally is an implementation detail of the UA and need not follow the rules in the spec.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>87011</commentid>
    <comment_count>14</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-04-30 15:58:48 +0000</bug_when>
    <thetext>While that&apos;s true, the spec is making requirements on the underlying DOM implementation that assume things about the script entry point being the relevant thing for security purposes, and the fact that UA JS is on the stack won&apos;t change the script entry point (because the fact that UA JS even exists needs to be transparent to the web page).

The upshot of all of which is that the spec becomes much less useful once you start implementing parts of your UA in JS and you have to read between the lines to try to figure out what it _really_ meant instead of just implementing the spec exactly like it says.

Which is why I would prefer, if possible, just defining things in the spec in such a way that they work whether your UA is implemented in privileged JS, or in C++, or in Rust, or in whatever the heck you want.  If it&apos;s not possible, of course, then the spec will just need to get ignored for internal UA JS as needed, as you say.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>87021</commentid>
    <comment_count>15</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-04-30 17:42:48 +0000</bug_when>
    <thetext>If you want to change the security model of the Web, please file a separate bug. For the purposes of this bug, let&apos;s assume that the security model is what the spec says.

I&apos;m not familiar with Object.getOwnPropertyDescriptor(); can you elaborate on how you would use that to fiddle with a different Location object? (Which would have a different prototype, etc.)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>87034</commentid>
    <comment_count>16</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-04-30 18:25:43 +0000</bug_when>
    <thetext>&gt; let&apos;s assume that the security model is what the spec says.

&lt;shrug&gt;.  To the extent that this assumption is false and the spec wants to assume it when it&apos;s not needed the spec is less useful. But fine.

&gt; I&apos;m not familiar with Object.getOwnPropertyDescriptor()

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor

&gt; can you elaborate on how you would use that to fiddle with a different Location
&gt; object?

Assuming that &quot;location&quot; is from your window and &quot;otherLocation&quot; is from some other window:

  var desc = Object.getOwnPropertyDescriptor(location, &quot;assign&quot;);
  desc.value.call(otherLocation, &quot;some string here&quot;);

This requires the actual assign method to perform the security check if you want there to be a security check here; performing it while getting the method doesn&apos;t work, since it&apos;s gotten from a same-origin object.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>88856</commentid>
    <comment_count>17</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-06-06 20:40:04 +0000</bug_when>
    <thetext>How is that different from:

  var ourAssign = location.assign;
  ourAssign.call(otherLocation, &quot;some string here&quot;);

...? Why are location and otherLocation, which have different prototypes (right?) type-compatible enough for this to work?

Is this specific to Location? It seems like if you could work around restrictions like this, you could easily work around Document&apos;s, too, and walk any random origin&apos;s DOM tree by just using your own methods on their objects.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>88858</commentid>
    <comment_count>18</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-06-06 20:44:58 +0000</bug_when>
    <thetext>&gt; How is that different from:

It&apos;s not.

&gt; Why are location and otherLocation, which have different prototypes
&gt; (right?) type-compatible enough for this to work?

Because that&apos;s how DOM objects generally work.  There are libraries that depend on this behavior in various case for nodes, for sure.

&gt; Is this specific to Location?

No.

&gt; you could easily work around Document&apos;s, too, and walk
&gt; any random origin&apos;s DOM tree by just using your own methods on their objects.

Which is why WebIDL methods have to do security checks at call time, conceptually.  And do in UAs, last I checked.  There&apos;s been lots of discussion about the fact that the spec needs to define this behavior.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>88860</commentid>
    <comment_count>19</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-06-06 20:47:14 +0000</bug_when>
    <thetext>&gt; Which is why WebIDL methods have to do security checks at call time,

And getters and setters, of course.

&gt; Because that&apos;s how DOM objects generally work.

And more precisely, different-origin objects should _not_ be considered &quot;type-compatible enough&quot;.  Which is exactly what the call-time security check would need to check.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>89222</commentid>
    <comment_count>20</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-06-13 00:23:29 +0000</bug_when>
    <thetext>Ok, then this is a more generic problem, it&apos;s not about Location. Is there a bug filed on the more generic problem already?

I&apos;ve filed bug 22346 for this for now, on the assumption that there isn&apos;t.

I&apos;ve closed this bug, since that is the only remaining issue here as far as I&apos;m aware. If there&apos;s something else I missed specific to Location, please feel free to reopen this bug.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>89232</commentid>
    <comment_count>21</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-06-13 05:01:13 +0000</bug_when>
    <thetext>Are the issues from comment 8 now addressed?  They sure don&apos;t seem to be.

Apart from the editorial aspects, why are we still disallowing .replace (as opposed to .replace())?  There&apos;s no reason to disallow it, imo.

This also still using the entry script&apos;s effective script origin, not the origin we really want...</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>89667</commentid>
    <comment_count>22</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-06-20 22:52:14 +0000</bug_when>
    <thetext>(In reply to comment #21)
&gt;
&gt; Apart from the editorial aspects, why are we still disallowing .replace (as
&gt; opposed to .replace())?  There&apos;s no reason to disallow it, imo.

Are you interpreting &quot;The replace() method&quot; as meaning that .replace is disallowed when .replace() is not? If so, that isn&apos;t my intent. My intent is to prevent access to the method, which is called &quot;replace()&quot;, and which is accessed using .replace, and then called by using &quot;()&quot;. The wording here is consistent with the wording throughout the spec.


&gt; This also still using the entry script&apos;s effective script origin, not the
&gt; origin we really want...

Gecko uses the incumbent script.
IE uses the entry script.
Safari uses the incumbent script but uses a different failure mode (undefined rather than throwing an exception).

http://www.hixie.ch/tests/adhoc/dom/level0/location/cross-origin/003.html

(Chrome fails 001, the control test, so I&apos;m ignoring it here.)

I guess we could change this to the entry script, but it&apos;s not clear to me it really matters (see comment 9 for details). Is matching Gecko better than matching IE here?


For comment 8:
&gt; So what it says now is:
&gt; 
&gt;   Any properties not defined in the IDL for the Location object or indirectly
&gt;   via one of those properties (e.g. toString(), which is defined via the
&gt;   stringifier keyword), if the entry script&apos;s effective script origin is the
&gt;   same origin as the Location object&apos;s associated Document&apos;s effective script
&gt;   origin 
&gt; 
&gt; but this is assuming that the entry script&apos;s effective script origin is the
&gt; same as the effective script origin of the script doing the access, which is
&gt; generally not a good assumption.

It&apos;s a fine assumption in the absence of document.domain. For a discussion of the implications of document.domain, see comment 9. For the issue of changing the security model of the Web in general, I have a pending e-mail from you to respond to.


&gt; In any case, it&apos;s better to just fall back to the default same-origin policy
&gt; (whatever that ends up being) rather than redefining it here.

What&apos;s &quot;the default same-origin policy&quot;? As far as I can tell, there is no such thing. All the objects that present origin barriers (Window, Document, Location, and Storage are the ones that come to mind) have subtly different rules.


&gt; I think it would be better to lift the language about &quot;IDL-defined&quot; into the
&gt; paragraph that talks about the restriction instead of listing it as an
&gt; exception.  So more like so:
&gt; 
&gt;   When accessing any attribute or calling any method defined in the IDL for a
&gt;   Location object, or indirectly via the IDL (e.g. toString(), which is
&gt;   defined via the stringifier keyword), user agents must throw a
&gt;   SecurityError when the entry script&apos;s effective script origin is not the 
&gt;   same as the Location object&apos;s associated Document&apos;s browsing context&apos;s 
&gt;   active document&apos;s effective script origin, with the following exceptions:
&gt; 
&gt;   * The href setter, if the entry script&apos;s script&apos;s browsing context is
&gt;     allowed to navigate the browsing context with which the Location object
&gt;     is associated
&gt;   * The replace() method, if the entry script&apos;s script&apos;s browsing context is
&gt;     allowed to navigate the browsing context with which the Location object
&gt;     is associated
&gt; 
&gt; or something. 

The reason it&apos;s written as it is now is to make the security sections have a consistent format between each such section, so you can tell how they differ more easily. I agree that in a vacuum, the above might be clearer. But in context, it would obscure the fact that the Window object doesn&apos;t have that exception (such that you can&apos;t actually access its &quot;expando&quot; properties at all while you&apos;re cross-origin with the active Document), unlike with Location, where you can if it is &quot;your&quot; Location object, despite the active document being in a different origin.


&gt; Note that this also makes it clear that doing .assign on the
&gt; Location is fine; it&apos;s _calling_ it that throws, which is I assume the
&gt; intent.

The intent is that getting it fails. If we wanted to make just calling it fail, we&apos;d just put that in the method&apos;s definition. (Calling it will fail if getting it fails, because of bug 22346.)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>89673</commentid>
    <comment_count>23</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-06-21 03:51:57 +0000</bug_when>
    <thetext>&gt; Are you interpreting

I&apos;m interpreting it as &quot;.replace is not allowed&quot;.  My point is that there is no reason to disallow it.  What _should_ be disallowed is the invocation of the method, whether it&apos;s as otherLocation.replace() or location.replace.call(otherLocation).  We&apos;re now disallowing that, but for some reason still also disallowing otherLocation.replace, which I think there&apos;s no particular reason to do.

&gt; I guess we could change this to the entry script

Did you mean the &quot;incumbent script&quot;?

I think that any time we&apos;re doing a security check we should be using the actual thing doing the access.  Note that this matches neither &quot;entry script&quot; nor &quot;incumbent script&quot; as you&apos;ve defined them.

&gt; What&apos;s &quot;the default same-origin policy&quot;? 

Whenever you talk about things being &quot;same-origin&quot; you have to first say what those things are.

For purposes of property access on the web, typically, what you are interested in is the effective script origin of the thing (&quot;code&quot;?  It&apos;s a bit complicated) doing the access, which is not exactly well-defined in the specs right now but should be, and the effective script origin of the object being accessed (which is typically derived from the effective script origin of the document or Window it&apos;s associated with).  Presumably this setup will get well-defined at some point, at which point we should, imo, just use that definition here.

Is that clearer?

&gt; so you can tell how they differ more easily

I&apos;m not sure that&apos;s more important than understanding what the sections actually say, though...  Anyway, I think the difference is just clarity, not substance, so I&apos;m not going to fight too hard over it.

&gt; The intent is that getting it fails. 

I think I disagree with that being desirable.  As you note, calling it will already fail; there is no particular reason to prevent getting it.

But again, I&apos;m not going to push on that too hard, depending on what Bobby thinks.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>89674</commentid>
    <comment_count>24</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-06-21 03:52:22 +0000</bug_when>
    <thetext>Oh, and for the next two weeks or so responses from me will be very laggy at best, unfortunately.  :(</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>89719</commentid>
    <comment_count>25</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-06-21 18:00:38 +0000</bug_when>
    <thetext>&gt; I think I disagree with that being desirable.

Here is why I disagree, after thinking on it.

If the security checks on Location just happen in the normal way (on all property gets for cross-origin access, but only on actual DOM getter/setter/method invocations for your own Location, then you can just have Location be a normal object, with the cross-origin case mediated by a security membrane.

But if you require random property gets which would normally find the property on the _prototype_ to not work on same-origin Location objects, then you require Location to be implemented as some sort of proxy, which significantly over-constrains implementations.

So the spec is introducing additional implementation complexity (given that the check in the DOM getter/setter/method need to be done no matter what anyway), for no particularly good reason that I can see.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>89910</commentid>
    <comment_count>26</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-06-26 18:08:20 +0000</bug_when>
    <thetext>(In reply to comment #25)
&gt; If the security checks on Location just happen in the normal way (on all
&gt; property gets for cross-origin access, but only on actual DOM
&gt; getter/setter/method invocations for your own Location, then you can just
&gt; have Location be a normal object, with the cross-origin case mediated by a
&gt; security membrane.
&gt; 
&gt; But if you require random property gets which would normally find the
&gt; property on the _prototype_ to not work on same-origin Location objects,
&gt; then you require Location to be implemented as some sort of proxy, which
&gt; significantly over-constrains implementations.
&gt; 
&gt; So the spec is introducing additional implementation complexity (given that
&gt; the check in the DOM getter/setter/method need to be done no matter what
&gt; anyway), for no particularly good reason that I can see.

Yes. This.

In response to our discussion about Location last year, I reimplemented our Location security checks to happen in the actual C++ implementation of the operations. This means that window.location is just a regular object like window.document, with no special security wrapper or anything.

But since Gecko implements property-access checks with security wrappers, we don&apos;t have any way to deny access to the property itself for script running in the same global (since, aside from Location, all the security checks in the spec involve the origin of associated document, not the current origin of the browsing context). Changing that, as Boris points out, would be a huge undertaking requiring rewriting our Location implementation as some sort of Proxy. And it&apos;s not one I&apos;m likely to undertake without more compelling rationale.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>90181</commentid>
    <comment_count>27</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-07-02 23:29:52 +0000</bug_when>
    <thetext>I think we&apos;re talking at cross-purposes here.

What the spec is saying is that in the cross-origin case:

   getting Location.assign throws a SecurityError exception

   directly invoking Location.assign isn&apos;t possible since you can&apos;t get it

   indirectly invoking Location.assign&apos;s [[Call]] does too, because of bug 22346

   setting Location.assign has no effect

   getting Location.replace throws a SecurityError exception if certain
   conditions aren&apos;t met (to do with &quot;allows to navigate&quot;)

   directly invoking Location.replace&apos;s [[Call]] works if getting it would work,
   as per bug 22346

   indirectly invoking Location.replace&apos;s [[Call]] also works if getting it
   would work, as per bug 22346

Are you saying you want .assign to return a method (which can never be invoked on the object since we&apos;re cross-origin)? This would be inconsistent with the way that every non-method property throws an exception on Location, and the way every method property throws an exception on, e.g., Window. For example:

   &lt;!-- on software.hixie.ch: --&gt;
   &lt;!DOCTYPE html&gt;
   &lt;iframe src=&quot;http://damowmow.com/&quot;&gt;&lt;/iframe&gt;
   &lt;script&gt;
    onload = function () {
      var f = frames[0];
      w(f.showModalDialog);
    }
   &lt;/script&gt;

This throws a SecurityError, because you can&apos;t get that method.

   http://software.hixie.ch/utilities/js/live-dom-viewer/saved/2390

Why would things be different for Location?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>90193</commentid>
    <comment_count>28</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-07-02 23:48:06 +0000</bug_when>
    <thetext>&gt; What the spec is saying is that in the cross-origin case:

Define &quot;cross-origin case&quot;?

What the spec is saying right this second is that whether I can get Location.assign depends on &quot;the Location object&apos;s associated Document&apos;s browsing context&apos;s active document&apos;s effective script origin&quot;.

This means that whether script in some window can touch Location.assign in that same window (which is normally considered a _same_ origin access) depends on some random other bits of state.  I don&apos;t think it should depend on those bits of state.

&gt; Are you saying you want .assign to return a method (which can never be invoked
&gt; on the object since we&apos;re cross-origin)?

Yes.  For example, the method can be invoked on some other object.

&gt; This would be inconsistent with the way that every non-method property throws
&gt; an exception on Location

How so?  Value properties on Location shouldn&apos;t throw exceptions on getting: that&apos;s what this bug is about.  The WebIDL getters and setters for WebIDL-defined accessor properties throw exceptions when invoked with the &quot;wrong&quot; Location object (as determined by the active document stuff quoted above).

&gt; and the way every method property throws an exception on, e.g., Window.

With a Window there&apos;s an actual cross-origin vs same-origin check, not taking and object that&apos;s actually in your global and treating it as different-origin sometimes randomly.

&gt; Why would things be different for Location?

Because the definition of &quot;cross-origin&quot; you&apos;re trying to use for Location is a crazy one and shouldn&apos;t be used as a definition of &quot;cross-origin&quot;.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>90274</commentid>
    <comment_count>29</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-07-03 22:18:33 +0000</bug_when>
    <thetext>&gt;&gt; This would be inconsistent with the way that every non-method property throws
&gt;&gt; an exception on Location
&gt; 
&gt; How so?  Value properties on Location shouldn&apos;t throw exceptions on getting:
&gt; that&apos;s what this bug is about.

I&apos;m talking about &quot;.href&quot; and &quot;.hash&quot; and &quot;.hostname&quot; and so on.

http://software.hixie.ch/utilities/js/live-dom-viewer/saved/2391

Click the button once the cat has loaded, and you get a security error.
Why would you not want the same security error for .assign?

I understand that at some theoretical level this is different than Window, but honestly I don&apos;t think most authors are going to get the difference between grabbing the Location object of the iframe when it was created, and grabbing a Location object from that iframe after they&apos;ve made the iframe load a cross-origin document. It just seems very confusing.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>90290</commentid>
    <comment_count>30</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-07-03 23:03:06 +0000</bug_when>
    <thetext>(In reply to comment #29)
&gt; Click the button once the cat has loaded, and you get a security error.

&apos;you get&apos; is underdefined here, but I&apos;ll interpret it as &quot;In Firefox&quot;, since that&apos;s the behavior that Boris and I are advocating here.

&gt; Why would you not want the same security error for .assign?

Because, from an EcmaScript/WebIDL perspective, accessing L.href calls a setter, whereas accessing L.assign just accesses a value prop. If you look at it another way, Object.getOwnPropertyDescriptor(L, &apos;href&apos;) does not throw a security error. Why should Object.getOwnPropertyDescriptor(L, &apos;assign&apos;) throw one?

&gt; I understand that at some theoretical level this is different than Window

It is _very_ different, because of the way our discussion about Location ended up this past winter. As we ended up speccing it, Location is an object with a per-Document identity, but per-BrowsingContext security characteristics. If we could just treat Location either like Window or like Document, it would be fine. As it stands, the current spec is very difficult for Gecko to implement, and the rationale for making it that way is not super compelling.

In Gecko, property-access checks happen at the boundary between different globals. Because the security characteristics of Location change dynamically with the state of the browsing context, we currently do Location security checks by doing security checks in the underlying C++ method. The spec requires that these checks happen at property descriptor level (even if no DOM functionality is ever invoked). If we were to follow it, we&apos;d need to make Location some sort of Proxy with dynamic property lookup behavior, which is needlessly complicated. So implementing the current spec is a hardship for Gecko.

On the flip side, implementing Boris&apos; proposal is unlikely to be a hardship for other implementations, because everybody already has to guard against:

var hrefGetter = Object.getOwnPropertyDescriptor(win.location, &apos;href&apos;).get;
/* Navigate win */
hrefGetter.apply(win.location);

That is to say - the security situation in the current world already requires the underlying methods to do security checks. But it doesn&apos;t require them at property access time.

&gt; but honestly I don&apos;t think most authors are going to get the difference
&gt; between grabbing the Location object of the iframe when it was created, and
&gt; grabbing a Location object from that iframe after they&apos;ve made the iframe
&gt; load a cross-origin document. It just seems very confusing.

Quite honestly, most authors aren&apos;t going to grok the details no matter what we do. In practice, the only observably-different behavior here happens when running code in navigated-away-from Windows. My primary interest here is a sane spec that vendors will implement, so that we get consistent behavior.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>90320</commentid>
    <comment_count>31</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-07-04 03:17:42 +0000</bug_when>
    <thetext>&gt; I&apos;m talking about &quot;.href&quot; and &quot;.hash&quot; and &quot;.hostname&quot; and so on.

Those aren&apos;t value properties.  They&apos;re accessor properties.

&gt; Why would you not want the same security error for .assign?

Because that requires adding a third kind of security thing (in addition to the existing &quot;Window&quot; and &quot;every other object&quot; cases) to the platform.  That&apos;s a steep price to pay for making .assign not work... while properties that the page polyfills on Location or Location.prototype continue to work.  And more to the point there is no security reason for .assign to work.

&gt; I understand that at some theoretical level this is different than Window,

It&apos;s not a theoretical level.  It&apos;s a practical one: it significantly increases the implementation burden for no benefit I can see.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>90531</commentid>
    <comment_count>32</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-07-09 20:59:38 +0000</bug_when>
    <thetext>Well I don&apos;t want to make it hard to implement; that&apos;s good to know.


So what you&apos;re saying is that you want the security model here to be totally different than Window&apos;s. Rather than doing something for all properties, what you really want is:

- The getters for everything on URLUtils imported by Location must throw
  SecurityError if the incumbent script has an effective script origin that&apos;s
  not the same as Location object&apos;s associated Document&apos;s browsing context&apos;s 
  active document&apos;s effective script origin.

- The setters for everything on URLUtils imported by Location other than &apos;href&apos; 
  must throw SecurityError if the incumbent script has an effective script 
  origin that&apos;s not the same as Location object&apos;s associated Document&apos;s
  browsing context&apos;s active document&apos;s effective script origin.

- All the methods on Location other than replace() must throw SecurityError
  when called if the incumbent script has an effective script origin that&apos;s
  not the same as Location object&apos;s associated Document&apos;s browsing context&apos;s
  active document&apos;s effective script origin.

- The href setter and the replace() method must throw SecurityError when called
  if the incumbent script&apos;s script browsing context is not allowed to navigate
  the Location object&apos;s associated Document&apos;s browsing context.

Furthermore, we&apos;re saying Location is immune to bug 22346&apos;s future logic.

We&apos;d be leaving the current mechanism by which each Document gets its own Location (which reflects the browsing context&apos;s location, not the Document&apos;s), and we&apos;d be leaving these two paragraphs:

# When the entry script&apos;s effective script origin is different than a Location 
# object&apos;s associated Document&apos;s effective script origin, the user agent must 
# act as if any changes to that Location object&apos;s properties, getters, setters, 
# etc, were not present, and as if all the properties of that Location object 
# had their [[Enumerable]] attribute set to false.
#
# For members that return objects (including function objects), each distinct 
# effective script origin that is not the same origin as the Location object&apos;s 
# Document&apos;s effective script origin must be provided with a separate set of 
# objects. These objects must have the prototype chain appropriate for the 
# script for which the objects are created (not those that would be appropriate 
# for scripts whose script&apos;s global object is the Location object&apos;s Document&apos;s 
# Window object).

Is all that right?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>90537</commentid>
    <comment_count>33</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-07-09 21:20:39 +0000</bug_when>
    <thetext>That sounds about like what I&apos;m after to me, yes.  Bobby?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>90616</commentid>
    <comment_count>34</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-07-10 20:58:36 +0000</bug_when>
    <thetext>Thanks for taking the time to dive into this, Hixie. Boris and I spoke about this on the phone for almost an hour last night, which (along with the length of this comment) should be some indication of how much of a swamp this Location stuff is. ;-)

I think the proposal in comment 32 would be quite straightforward for us to implement But I have some concerns, and I&apos;d like to make sure we think through its implications first, for the sake of future implementations. Let&apos;s start by defining some terms.

There are two origins at play here: the origin of the Document associated with the Location object (henceforth &apos;Document Origin&apos;), and the origin of the Location object&apos;s associated Document&apos;s associated Browsing Context&apos;s active Document (henceforth &apos;Browsing Context Origin&apos;). The former is immutable modulo document.domain, the latter is not (this has important implications, which I&apos;ll discuss shortly).

There are also two places where security checks might be performed. The first is in the implementation of the ES5 Meta-Object Protocol, when properties are accessed (henceforth &apos;Property-Access Checks&apos;). The second is in the implementation of the various getters, setter, and methods returned by the MOP, when executed (henceforth &apos;Method-Call Checks&apos;).

IIUC, the spec currently mandate Property-Access Checks that compare the Incumbent Script Origin to the Browsing Context Origin. The spec currently requires no Method-Call Checks, but we know that&apos;s broken and are fixing the spec in bug 22346.

Gecko currently does both Property-Access Checks with the Document origin and Method-Call Checks with the Browsing Context Origin. 

Boris filed this bug to argue that Property-Access Checks on the Browsing Context Origin are needlessly burdensome on the implementation, because it requires Location to be some sort of Proxy under the hood.

Hixie&apos;s proposal in comment 32 is to remove Property-Access Checks on Location entirely, and do Method-Call Checks comparing the Incumbent Script Origin to the Browsing Context Origin.

This proposal is satisfactory security-wise in terms of the methods and attributes defined in the Location interface. However, when it comes to other properties, it exposes very new behavior to the web: for some cross-origin iframe window |xoWin|, script can now set |xoWin.location.foopy = 2;|. That is to say, it permits &quot;expandos&quot; (Gecko parlance, not sure if there&apos;s a spec equivalent) on objects in the scope of cross-origin globals. Since there can by any number of origins involved, and since we presumably don&apos;t want them to see each others&apos; expandos, there would need to be a separate view of the target object for each origin. The spec would probably have to be updated to specify this explicitly.

The de-facto web platform currently never allows expando properties to be set on any object that is not same-origin with the incumbent script. The spec requires a &quot;vanilla object&quot; to be created for cross-origin access to Window, but that object is immutable, which means that implementations could potentially share the same instance between _all_ non-same-origin consumers, or have read-only view to the native properties.

Because of its embedding requirements, Gecko already has a mechanism to maintain such a map of per-origin expandos on cross-origin objects. But that mechanism is quite complicated. And so while we could implement the proposal here without any trouble, it could be a major roadblock for other implementations. Gecko&apos;s machinery also just ignores document.domain for the expando map, and I&apos;m not convinced that there&apos;s a sane way to take it into account.

In a nutshell, the security requirements of the web mandate Method-Call Checks against the Browsing Context Origin. But we also need something on the MOP level to prevent multiple third-party origins from viewing each other&apos;s expandos on a Location object they&apos;re both observing.

Because the Browsing Context Origin is mutable, it&apos;s not an ideal thing to use here (since a page could set an expando and then have it suddenly become inaccessible due to a navigation). As such, we probably want to use the Document origin, here. At which point we have two options that I can think of:

(1) Property-Access Checks against the Document origin
(2) No checks, but mandate that implementations somehow keep different origins from viewing each others&apos; expandos on the same object.

I think (2) is likely to be much harder to spec clearly, and much harder to implement. (1) is what Gecko currently does, and what I think makes the most sense.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>90717</commentid>
    <comment_count>35</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-07-13 15:22:14 +0000</bug_when>
    <thetext>&gt; There are two origins at play here:

There&apos;s also the incumbent effective script origin, so at least three origins.

In general, I agree with your description.


&gt; However, when it comes to
&gt; other properties, it exposes very new behavior to the web: for some
&gt; cross-origin iframe window |xoWin|, script can now set |xoWin.location.foopy
&gt; = 2;|. That is to say, it permits &quot;expandos&quot; (Gecko parlance, not sure if
&gt; there&apos;s a spec equivalent) on objects in the scope of cross-origin globals.
&gt; Since there can by any number of origins involved, and since we presumably
&gt; don&apos;t want them to see each others&apos; expandos, there would need to be a
&gt; separate view of the target object for each origin. The spec would probably
&gt; have to be updated to specify this explicitly.

The idea of the first of the two paragraphs quoted at the end of comment 32 is that if it&apos;s not &quot;your&quot; Location object, you can&apos;t modify it, and you can&apos;t see any modifications on it.

Also note that Window.location returns a &quot;new&quot; object for each origin:

# For members that return objects (including function objects), each distinct 
# effective script origin that is not the same as the Window object&apos;s Document&apos;s 
# effective script origin must be provided with a separate set of objects. These 
# objects must have the prototype chain appropriate for the script for which the 
# objects are created (not those that would be appropriate for scripts whose 
# script&apos;s global object is the Window object in question).

Is that text insufficient? (I will be the first to admit that I&apos;m not sure if that text is written correctly and clearly enough to achieve the effect I want here. I&apos;m still not fully versed in the implications of such things.)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>90823</commentid>
    <comment_count>36</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-07-16 22:51:21 +0000</bug_when>
    <thetext>(In reply to comment #35)
&gt; &gt; There are two origins at play here:
&gt; 
&gt; There&apos;s also the incumbent effective script origin, so at least three
&gt; origins.

Right, fair point.

&gt; Is that text insufficient? (I will be the first to admit that I&apos;m not sure
&gt; if that text is written correctly and clearly enough to achieve the effect I
&gt; want here. I&apos;m still not fully versed in the implications of such things.)

I think it&apos;s problematic. Consider the following passage:

&gt; These objects must have the prototype chain appropriate for the script for
&gt; which the objects are created

The notion of &apos;the script for which the objects are created&apos; is underdefined here. Suppose we have two windows, A and B, with origin foo.com. These two windows access cross-origin objects from window C, which has origin bar.com. What prototype chain does A observe for objects from C, and what does B observe? Are they the same? If they&apos;re the same, then we need to specify whether the prototype chain leads to A.Object.prototype or B.object.prototype, which seems pretty arbitrary and hard to do.

The more elegant solution is for them to be different - each observer gets its own view. But then we have to figure out what to do about expandos. If A can set C.location.foopy = 2 and read it back, then presumably B should be able to see it too. But this requires dynamically sharing expando properties between multiple distinct objects - something that Gecko has the machinery to do, but IMO not something we should bake into the web platform when we don&apos;t need to.

The simpler thing to do here is just to forbid expandos on cross-origin objects, since it makes the objects immutable and makes this issue unobservable. This brings us back to my proposal in comment 34.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>92005</commentid>
    <comment_count>37</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-08-13 20:30:26 +0000</bug_when>
    <thetext>I don&apos;t think forbidding custom properties helps, since the prototype still has to be distinct per origin in the same way, and you could just fiddle with the prototype to get the same effect. No?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>92021</commentid>
    <comment_count>38</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-08-14 04:09:05 +0000</bug_when>
    <thetext>(In reply to comment #37)
&gt; I don&apos;t think forbidding custom properties helps, since the prototype still
&gt; has to be distinct per origin in the same way

Well, it depends on how one interprets &quot;These objects must have the prototype chain appropriate for the script for which the objects are created&quot;, which I maintain (from comment 36) is underdefined. There are a number of things it could mean:

(1) For any set of same-origin scripts observing cross-origin objects, the objects have a prototype chain in the scope of whichever script observed them first (if A touches C first, then B sees C.__proto__ == A.__proto__).
(2) Each script sees a prototype chain in the scope of its global (A sees C.__proto__ == A.__proto__, B sees C.__proto__ == B.__proto__).
(3) C gets its own unique proto that is neither in A&apos;s scope nor in B&apos;s scope. This object may or may not do security checks (these objects are behind opaque security wrappers in Gecko, so you can&apos;t do much with them).
(4) The objects get some cop-out proto like null or undefined.

IMO (1) is crappy. (2) is possible in Gecko, but I severely doubt it&apos;s possible in other UAs. (3) is what Gecko does. (4) might not be ES-kosher, but that could maybe be fixed.

I wrote a testcase to see what different browsers do here, and the results aren&apos;t pretty.

http://people.mozilla.org/~bholley/testcases/xoprotos/main.html

Chrome and Safari throw a security error while trying to read the prototype, and return undefined. IE (9) returns null.

So Gecko is the only UA I tested with actual interesting behavior here. This makes sense, because our architecture (frontend implemented in privileged JS) forces us to think about this stuff, and makes it worthwhile for us to treat this as a general problem, rather than a specific edge case involving Window and Location.

Anyway, the prototype discussion might be fodder for another bug. But this is all to say that there aren&apos;t any UAs out there that let you twiddle with the prototypes of cross-origin objects, and that&apos;s unlikely to change. So I don&apos;t think the point in comment 37 (if I&apos;m reading it right) is valid.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>93666</commentid>
    <comment_count>39</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-09-23 19:22:09 +0000</bug_when>
    <thetext>I meant 2, I think. I don&apos;t quite understand the difference between 2 and 3.

Throwing an exception seems like a pretty reasonable option as well, though presumably that breaks things like &quot;instanceof&quot; pretty badly (not that that isn&apos;t already pretty broken in cross-global JS).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>93692</commentid>
    <comment_count>40</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-09-23 21:56:33 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #39)
&gt; I meant 2, I think. I don&apos;t quite understand the difference between 2 and 3.

The difference is whether window.location.prototype == xoifr.contentWindow.location.prototype. In (2) it is, in (3) it isn&apos;t.

&gt; Throwing an exception seems like a pretty reasonable option as well, though
&gt; presumably that breaks things like &quot;instanceof&quot; pretty badly (not that that
&gt; isn&apos;t already pretty broken in cross-global JS).

Broken for ES objects yes, but not DOM objects. I think we should continue to make it work for DOM objects.

Anyway, this is all a bit of a digression from the bug at hand. Comment 34 and comment 36 still reflect my view on things here.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>93761</commentid>
    <comment_count>41</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-09-24 22:35:31 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #40)
&gt; (In reply to Ian &apos;Hixie&apos; Hickson from comment #39)
&gt; &gt; I meant 2, I think. I don&apos;t quite understand the difference between 2 and 3.
&gt; 
&gt; The difference is whether window.location.prototype ==
&gt; xoifr.contentWindow.location.prototype. In (2) it is, in (3) it isn&apos;t.

Ah, ok. Yeah, I meant 2.


&gt; &gt; Throwing an exception seems like a pretty reasonable option as well, though
&gt; &gt; presumably that breaks things like &quot;instanceof&quot; pretty badly (not that that
&gt; &gt; isn&apos;t already pretty broken in cross-global JS).
&gt; 
&gt; Broken for ES objects yes, but not DOM objects. I think we should continue
&gt; to make it work for DOM objects.

How are they not broken for DOM objects? Do origins have cross-global prototypes a là option 3 above? What spec requires that?

Note that Firefox and Chrome/Safari disagree here:
   http://software.hixie.ch/utilities/js/live-dom-viewer/saved/2542


&gt; Anyway, this is all a bit of a digression from the bug at hand. Comment 34
&gt; and comment 36 still reflect my view on things here.

I think we need to resolve all these issues at the same time, so we should consider them in scope for this. Otherwise I&apos;ll keep putting it off...</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>93768</commentid>
    <comment_count>42</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-09-25 00:04:21 +0000</bug_when>
    <thetext>&gt; Do origins have cross-global prototypes a là option 3 above?

No, but WebIDL interface objects have a non-default [[HasInstance]].

&gt; What spec requires that?

http://dev.w3.org/2006/webapi/WebIDL/#es-interface-hasinstance

&gt; Note that Firefox and Chrome/Safari disagree here:

Yep, they haven&apos;t implemented this part of WebIDL (or indeed most of WebIDL) yet.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>93770</commentid>
    <comment_count>43</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-09-25 01:00:42 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #41)
&gt; (In reply to Bobby Holley (:bholley) from comment #40)
&gt; &gt; (In reply to Ian &apos;Hixie&apos; Hickson from comment #39)
&gt; Ah, ok. Yeah, I meant 2.

Ok. As noted in comment 38, I believe that (2) is only possible in UAs like Gecko with a membrane between globals, since it requires that script from different same-origin globals observe different prototypes for the same object. And it wouldn&apos;t be all that pretty in Gecko either.

I think (3) is the best option here. Just as each origin effectively sees a unique version of xowin.location, each origin should also see a unique version of xowin.location.__proto__. So xowin.location.__proto__ is neither winA.location.__proto__ nor winB.location.__proto__, but both winA and winB observe the same value for xowin.location.__proto__.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>93773</commentid>
    <comment_count>44</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-09-25 02:00:18 +0000</bug_when>
    <thetext>(In reply to Boris Zbarsky from comment #42)
&gt; WebIDL interface objects have a non-default [[HasInstance]].

Oh, wow, I didn&apos;t know you could even override that. That&apos;s wild.


&gt; Ok. As noted in comment 38, I believe that (2) is only possible in UAs like
&gt; Gecko with a membrane between globals, since it requires that script from
&gt; different same-origin globals observe different prototypes for the same
&gt; object. And it wouldn&apos;t be all that pretty in Gecko either.

I don&apos;t understand why this would require anything that fancy. You &quot;just&quot; have to return a different object when you&apos;re fetching the prototype. As far as I can tell that&apos;s exactly what we&apos;re doing with window.location in the first place anyway (&quot;the user agent must act as if any changes to that Location object&apos;s properties, getters, setters, etc, were not present [in cross-origin accesses]&quot;).


&gt; I think (3) is the best option here. Just as each origin effectively sees a
&gt; unique version of xowin.location, each origin should also see a unique
&gt; version of xowin.location.__proto__.

How is that not #2?


&gt; So xowin.location.__proto__ is neither
&gt; winA.location.__proto__ nor winB.location.__proto__, but both winA and winB
&gt; observe the same value for xowin.location.__proto__.

Doesn&apos;t that say exactly the opposite of your previous sentence?

How can anyone tell if winA and winB observe the same value, if they&apos;re cross-origin? I&apos;m not sure I understand what that means.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>93775</commentid>
    <comment_count>45</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-09-25 02:06:12 +0000</bug_when>
    <thetext>&gt; Oh, wow, I didn&apos;t know you could even override that.

Fwiw, ES6 drafts have an explicit @@hasInstance that can be defined as needed to do whatever you want (though there&apos;s no way to do it from user script yet, afaict).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>93776</commentid>
    <comment_count>46</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-09-25 02:18:25 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #44)

I think the key misunderstanding underlying all of this relates to the origins of winA and winB. I&apos;m talking about the case when winA and winB are same-origin, but are jointly observing a cross-origin winC. Per spec and per the web, winA and winB jointly observe the same identity for winC.location.

The question here is what prototype chain they observe. (2) requires that they do _not_ observe the same prototype chain for winC.location, which I think is problematic.

Does that clear things up?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>93793</commentid>
    <comment_count>47</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-09-25 13:44:40 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #46)
&gt; (In reply to Ian &apos;Hixie&apos; Hickson from comment #44)
&gt; 
&gt; I think the key misunderstanding underlying all of this relates to the
&gt; origins of winA and winB.

(and in particular, note that the origins I&apos;m referring to here are the origins of the document/global, not the origins of the browsing context).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>93821</commentid>
    <comment_count>48</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-09-25 18:38:05 +0000</bug_when>
    <thetext>Sure, if they&apos;re same-origin scripts, then they should see the same object and it should have the same prototype chain. Doing anything else would be massively confusing. I apologise if anything I said gave you the impression that I thought that was not the case.

(Browsing contexts don&apos;t have origins.)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>93823</commentid>
    <comment_count>49</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-09-25 18:55:05 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #48)
&gt; Sure, if they&apos;re same-origin scripts, then they should see the same object
&gt; and it should have the same prototype chain. Doing anything else would be
&gt; massively confusing. I apologise if anything I said gave you the impression
&gt; that I thought that was not the case.

Right. Does my proposal for (3) in comment 38 make more sense in that light?

&gt; (Browsing contexts don&apos;t have origins.)

Yeah, it was shorthand for &quot;the origin of the document of the active window in the browsing context&quot;.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94563</commentid>
    <comment_count>50</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-10-10 19:58:28 +0000</bug_when>
    <thetext>IRC discussion suggests that comment 32&apos;s first bit is ok, but the #-prefixed paragraphs should be changed to something like (proposal):

---8&lt;---
When the entry script&apos;s effective script origin is different than a Location object&apos;s associated Document&apos;s effective script origin, the user agent must act as if the Location object is an alien object.

An alien object must act as if any changes to that object&apos;s properties, getters, setters, etc, were not present, as if all the properties of that object had their [[Enumerable]] attribute set to false, as if the object&apos;s prototype was null, and as if any objects returned by members of that object (including, for instance, function objects) were themselves alien objects.
---8&lt;---</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94564</commentid>
    <comment_count>51</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-10-10 20:10:58 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #50)
&gt; When the entry script&apos;s

Don&apos;t we want |incumbent script| here?

&gt; An alien object

The key part that I&apos;m pushing for with alien objects is that callers should not be able to define or modify properties.

&gt; must act as if any changes to that object&apos;s properties,
&gt; getters, setters, etc, were not present, as if all the properties of that
&gt; object had their [[Enumerable]] attribute set to false, as if the object&apos;s
&gt; prototype was null, and as if any objects returned by members of that object
&gt; (including, for instance, function objects) were themselves alien objects.

I was mistaken about the function objects and companyin Gecko - they&apos;re currently just regular functions whose prototype is the caller&apos;s Function.prototype. But this understandably introduces the same problem that caused us to null out the prototype of alien objects. So I&apos;m happy to try to modify our implementation to null out the prototypes and Freeze the objects themselves to make them behave like alien objects, if we&apos;re willing to define alien objects that way.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94565</commentid>
    <comment_count>52</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-10-10 20:14:43 +0000</bug_when>
    <thetext>I&apos;m fine with changing to incumbent script here, I think. (The only possible difference is with document.domain in non-Gecko-like environments, I think.)

Reusing the freeze logic would make sense if the freeze logic is staying and does what we want in non-strict and strict JS modes.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94566</commentid>
    <comment_count>53</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-10-10 20:16:56 +0000</bug_when>
    <thetext>&gt; The key part that I&apos;m pushing for with alien objects is that callers should not
&gt; be able to define or modify properties.

Isn&apos;t that the &quot;over-restrictive&quot; bit I initially filed this bug on?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94568</commentid>
    <comment_count>54</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-10-10 21:48:27 +0000</bug_when>
    <thetext>&gt; Isn&apos;t that the &quot;over-restrictive&quot; bit I initially filed this bug on?

No, I just can&apos;t read.  The important part in comment 50 is &quot;associated Document&apos;s effective script origin&quot;.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94569</commentid>
    <comment_count>55</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-10-10 21:52:24 +0000</bug_when>
    <thetext>Adam, if you could comment on this that&apos;d be great. In particular, if you don&apos;t like the last proposal above, it would be good if you could describe how you would like Location and Window to work cross-origin.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94572</commentid>
    <comment_count>56</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-10-10 23:08:34 +0000</bug_when>
    <thetext>So the proposal from bholley and I, as I understand it, is:

For Location:

- The getters for everything on URLUtils imported by Location must throw
  SecurityError if the incumbent script has an effective script origin that&apos;s
  not the same as the Location object&apos;s associated Document&apos;s browsing
  context&apos;s active document&apos;s effective script origin.

- The setters for everything on URLUtils imported by Location other than &apos;href&apos; 
  must throw SecurityError if the incumbent script has an effective script 
  origin that&apos;s not the same as the Location object&apos;s associated Document&apos;s
  browsing context&apos;s active document&apos;s effective script origin.

- All the methods on Location other than replace() must throw SecurityError
  when called if the incumbent script has an effective script origin that&apos;s
  not the same as the Location object&apos;s associated Document&apos;s browsing
  context&apos;s active document&apos;s effective script origin. (bug 22346)

- The href setter and the replace() method must throw SecurityError when called
  if the incumbent script&apos;s script browsing context is not allowed to navigate
  the Location object&apos;s associated Document&apos;s browsing context.

- When the incumbent script&apos;s effective script origin is different than a
  Location object&apos;s associated Document&apos;s effective script origin, the user
  agent must act as if the Location object is an Alien Object.

For Window:

- The getters for everything on Window except those Exempted Properties listed 
  below must throw SecurityError if the incumbent script has an effective script 
  origin that&apos;s not the same as the Window object&apos;s Document&apos;s effective script
  origin.

- The setters for everything on Window must throw SecurityError if the
  incumbent script has an effective script origin that&apos;s not the same as the
  Window object&apos;s Document&apos;s effective script origin.

- All the methods on Window except those in the Exempted Properties list below 
  must throw SecurityError when called if the incumbent script has an effective
  script origin that&apos;s not the same as the Window object&apos;s Document&apos;s effective
  script origin. (bug 22346)

- When the incumbent script&apos;s effective script origin is different than a
  Window object&apos;s Document&apos;s effective script origin, the user agent must act
  as if the Window object is an Alien Object.

- The Exempted Properties are:
   The location attribute
   The postMessage() method
   The window attribute
   The frames attribute
   The self attribute
   The top attribute
   The parent attribute
   The opener attribute
   The closed attribute
   The close() method
   The blur() method
   The focus() method
   Any supported property names that refer to other browsing contexts and that
     do not have a name that clashes with a property that is defined on the
     Window object itself (e.g. &quot;history&quot;)

For both:

- An Alien Object must:
   * promote all the members found on its prototypes, including supported
     property indices and supported property names if any, to &quot;own&quot; properties
     on the object itself.
   * act as if any changes to that object&apos;s properties, getters, setters, etc,
     were not present (i.e. can&apos;t see custom properties and changes from the
     object&apos;s &quot;home&quot; origin).
   * act as if all the properties of that object had their [[Enumerable]]
     attribute set to false.
   * have their prototype set to null.
   * throw a SecurityError for any attempt to set or configure a property on
     the object.
   * act as if all objects returned by members of that object (including, for
     instance, function objects) were frozen.

(We&apos;re not sure if the last bullet point in particular is enough. Does that prevent you from messing around with e.g. the other origin&apos;s Function prototype or whatnot? Also, we&apos;re not sure if Window and Location should throw SecurityError or instead try to more precisely simulate being frozen. Naturally we can&apos;t actually freeze them, since they have mutable state and stuff.)


This would replace all the security stuff for cross-origin accesses currently in the spec, and would be partly implemented using bug 22346&apos;s hooks. We would especially like to know if this is something other vendors are interested in implementing. Right now the spec has all kinds of security vulnerabilities and generally doesn&apos;t match reality (or even make sense, in some places).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94576</commentid>
    <comment_count>57</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-10-11 02:02:16 +0000</bug_when>
    <thetext>&gt; We would especially like to know if this is something other vendors are interested in implementing.

I understand why folks who work on Gecko are excited about this approach.  It matches some technology that exists in Gecko for other purposes.  However, implementing this in Blink (and WebKit for that matter) would require developing the same wrapper technology.  However, that technology is extremely subtle, and Mozilla has spent years fighting through all the security vulnerabilities in their implementation.  We&apos;re not interested in implementing wrapper technology in Blink.  In fact, we&apos;ve gone through great lengths to avoid having to do that.  For example, we moved the entire Web Inspector to a separate process to avoid having to create wrapper technology.  (JavaScriptCore in WebKit briefly had wrapper technology, but it was full of security bugs.)

The approach used in Blink (and WebKit) today is much simpler and doesn&apos;t require any additional technology apart from what&apos;s already required to implement the web platform.  Essentially the way it works is that when a script views a cross-origin object (say the Location object associated with a cross-origin Document), the script doesn&apos;t receive a reference to the same JS object that same-origin viewers receive.  Instead, the viewer receives a brand new JS interface object with a reduced set of properties and behavior appropriate to the cross-origin scenario.  There is no connection between this JS interface object and the JS interface object that same-origin viewers receive.  Furthermore, this new JS interface object&apos;s prototype chain is connected up to the *viewer* prototype objects.  For that reason, there&apos;s no subtly about promoting properties from the prototype to the object itself and there&apos;s no need to freeze or protect anything in the prototype chain.

Personally, I don&apos;t have any interest in changing Blink&apos;s implementation in this area.  It&apos;s simple, and it works well.  I can understand why Mozilla would want to make use of their extensively debugged wrapper technology in Gecko, but I don&apos;t see any real benefit from implementing that technology in Blink.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94577</commentid>
    <comment_count>58</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-10-11 02:03:43 +0000</bug_when>
    <thetext>&gt; We&apos;re not sure if the last bullet point in particular is enough.

I&apos;m pretty sure that&apos;s insufficient.  The document might store secret values in its prototype chain.  Freezing them just makes them read-only.  It doesn&apos;t stop a malicious viewer from learning those secret values.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94578</commentid>
    <comment_count>59</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-10-11 02:20:58 +0000</bug_when>
    <thetext>&gt; Essentially the way it works is that when a
&gt; script views a cross-origin object (say the Location object associated with
&gt; a cross-origin Document), the script doesn&apos;t receive a reference to the same
&gt; JS object that same-origin viewers receive. Instead, the viewer receives a
&gt; brand new JS interface object with a reduced set of properties and behavior
&gt; appropriate to the cross-origin scenario.  There is no connection between
&gt; this JS interface object and the JS interface object that same-origin
&gt; viewers receive.

The model described above is intended to actually be implementable in an indistinguishable fashion using either the WebKit/Blink model or the Gecko model an the backend. What you describe here is, as far as I can tell, the same thing, basically.


&gt; Furthermore, this new JS interface object&apos;s prototype
&gt; chain is connected up to the *viewer* prototype objects.

In the Blink model, this isn&apos;t observable, because trying to read the prototype throws an exception (right?). The only difference between this and the model above is that the prototype instead returns null.

The reason the model above also promotes the members to the object (essentially flattening the prototype chain into the object) is to make the object appear sane from a JavaScript perspective. However, there&apos;s actually no way that I can see to tell if this is what is going on or not, since all the methods that can be used to introspect the object will throw in the cross-origin case. (Right?)

So maybe the solution here is to just not mention the flattening. It&apos;s possible that there&apos;s not actually any observable difference in behaviour one way or the other.

(Is returning null instead of throwing for the prototype a problem? I would imagine that for Gecko it&apos;s much the same one way or the other, so if you prefer to throw I guess we can do that instead.)


&gt; object itself and there&apos;s no need to freeze or protect anything in the
&gt; prototype chain.

The idea of the freezing is that it enables implementations to avoid the cost of having multiple objects (one per origin) for all the objects involved here. This seems like a decent win in terms of flexibility for different implementation strategies. Would it be an issue to implement this in WebKit/Blink?


&gt; Personally, I don&apos;t have any interest in changing Blink&apos;s implementation in
&gt; this area.  It&apos;s simple, and it works well.

The idea here is to find a compromise that everyone can implement, that is still simple and works well, and that gets us interoperability, without requiring anyone to change their architecture, while simultaneously allowing other optimisations in the future (e.g. using a way to display &quot;views&quot; of the objects on the fly, so that everyone can have the same objects, yet still not have any security problems). I would hope you agree that&apos;s a good goal.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94579</commentid>
    <comment_count>60</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-10-11 02:39:23 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #59)
&gt; The model described above is intended to actually be implementable in an
&gt; indistinguishable fashion using either the WebKit/Blink model or the Gecko
&gt; model an the backend. What you describe here is, as far as I can tell, the
&gt; same thing, basically.

That&apos;s not correct.  For example, suppose you have three frames, A, B, and C, with A and B in the same origin and C in a different origin.  Script running in A and B grab C&apos;s Location object and then compare the JS interface object they receive with ===.  In Blink&apos;s implementation, they&apos;ll get back |false| because they each receive separate interface objects that are wired up to their respective prototypes.

&gt; &gt; Furthermore, this new JS interface object&apos;s prototype
&gt; &gt; chain is connected up to the *viewer* prototype objects.
&gt; 
&gt; In the Blink model, this isn&apos;t observable, because trying to read the
&gt; prototype throws an exception (right?). The only difference between this and
&gt; the model above is that the prototype instead returns null.

alert(frames[0].location.replace.apply === Function.prototype.apply)

In Blink, that will alert |true| because the cross-origin Location object&apos;s prototype is wired up to the viewer&apos;s own Function.prototype.  That means that function objects you grab off the prototype are identical to the function objects you can get from inspecting your own constellation of prototype objects.  Importantly, that also means they&apos;re safe to return to the script because the script already has access to them.

&gt; The reason the model above also promotes the members to the object
&gt; (essentially flattening the prototype chain into the object) is to make the
&gt; object appear sane from a JavaScript perspective.

I understand.  However, the objects appear sane in the model I described above.  They are in fact more sane than in the promotion case because all the properties are stored in the usual places.

&gt; However, there&apos;s actually
&gt; no way that I can see to tell if this is what is going on or not, since all
&gt; the methods that can be used to introspect the object will throw in the
&gt; cross-origin case. (Right?)

There are lots of ways to tell where the object&apos;s prototypes come from.  Here&apos;s one example:

Object.prototype.foo = &quot;bar&quot;;
alert(frames[0].location.replace.foo);

This alerts |bar| in Blink.
 
&gt; (Is returning null instead of throwing for the prototype a problem? I would
&gt; imagine that for Gecko it&apos;s much the same one way or the other, so if you
&gt; prefer to throw I guess we can do that instead.)

Throwing is much better.  Returning |null| is problematic because the objects don&apos;t actually have null prototypes.  They have non-null prototypes, and that&apos;s observable.

Experimenting a bit, it looks like Blink only throws when you access __proto__ on the original interface (e.g., Location), not on any objects that you can obtain transitively from that interface (e.g., replace).  For those objects, you can just get the prototype directly.

&gt; The idea of the freezing is that it enables implementations to avoid the
&gt; cost of having multiple objects (one per origin)

It&apos;s more than just one per origin.  It&apos;s one per cross-origin script.

&gt; for all the objects
&gt; involved here. This seems like a decent win in terms of flexibility for
&gt; different implementation strategies. Would it be an issue to implement this
&gt; in WebKit/Blink?

The problem with freezing the objects is that the object Blink returns are the same objects you&apos;d get by other means.  There&apos;s no way to &quot;act as if&quot; they were frozen without magic.  They&apos;re either frozen or they&apos;re not.  We can&apos;t actually freeze them because that would disrupt the script when it accessed them normally.

&gt; &gt; Personally, I don&apos;t have any interest in changing Blink&apos;s implementation in
&gt; &gt; this area.  It&apos;s simple, and it works well.
&gt; 
&gt; The idea here is to find a compromise that everyone can implement, that is
&gt; still simple and works well, and that gets us interoperability, without
&gt; requiring anyone to change their architecture, while simultaneously allowing
&gt; other optimisations in the future (e.g. using a way to display &quot;views&quot; of
&gt; the objects on the fly, so that everyone can have the same objects, yet
&gt; still not have any security problems). I would hope you agree that&apos;s a good
&gt; goal.

I agree that interoperability is a good goal, but I don&apos;t see how to achieve it in this case because it&apos;s too easy for script to figure out which implementation approach is being used.  They just behave differently.  Trying to hide all the implementation details is going to end up being more complicated than the entire security mechanism.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94580</commentid>
    <comment_count>61</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-10-11 02:48:15 +0000</bug_when>
    <thetext>(In reply to Adam Barth from comment #60)
&gt; 
&gt; That&apos;s not correct.  For example, suppose you have three frames, A, B, and
&gt; C, with A and B in the same origin and C in a different origin.  Script
&gt; running in A and B grab C&apos;s Location object and then compare the JS
&gt; interface object they receive with ===.  In Blink&apos;s implementation, they&apos;ll
&gt; get back |false| because they each receive separate interface objects that
&gt; are wired up to their respective prototypes.

Isn&apos;t that considered a bug? That seems really bad. How do you decide what object to return, do you base it on the entry script or the incumbent script?


&gt; alert(frames[0].location.replace.apply === Function.prototype.apply)
&gt; 
&gt; In Blink, that will alert |true| because the cross-origin Location object&apos;s
&gt; prototype is wired up to the viewer&apos;s own Function.prototype.  That means
&gt; that function objects you grab off the prototype are identical to the
&gt; function objects you can get from inspecting your own constellation of
&gt; prototype objects.  Importantly, that also means they&apos;re safe to return to
&gt; the script because the script already has access to them.

That&apos;s kind of weird magic. Why would we want this? Is it also true of prototypes of things like HTMLAnchorElement and Object and so on?


&gt; There are lots of ways to tell where the object&apos;s prototypes come from. 
&gt; Here&apos;s one example:
&gt; 
&gt; Object.prototype.foo = &quot;bar&quot;;
&gt; alert(frames[0].location.replace.foo);
&gt; 
&gt; This alerts |bar| in Blink.

That seems like a really bad bug. That means that what code will execute depends in weird ways on how it was called, even in entirely same-origin situations, just because of what unrelated code has done to the prototypes in a different browsing context.


&gt; Experimenting a bit, it looks like Blink only throws when you access
&gt; __proto__ on the original interface (e.g., Location), not on any objects
&gt; that you can obtain transitively from that interface (e.g., replace).  For
&gt; those objects, you can just get the prototype directly.

Why do you throw at all, given the rest of how Blink works?


&gt; &gt; The idea of the freezing is that it enables implementations to avoid the
&gt; &gt; cost of having multiple objects (one per origin)
&gt; 
&gt; It&apos;s more than just one per origin.  It&apos;s one per cross-origin script.

All the more reason to avoid it...

(How do you avoid this being really expensive? Do you lazily create them?)


&gt; I agree that interoperability is a good goal, but I don&apos;t see how to achieve
&gt; it in this case because it&apos;s too easy for script to figure out which
&gt; implementation approach is being used.  They just behave differently. 

I agree that the current Blink behaviour is different than the behaviour described above.


Do you have any suggestions on how to get interoperability here?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94582</commentid>
    <comment_count>62</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-10-11 03:11:48 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #61)
&gt; (In reply to Adam Barth from comment #60)
&gt; &gt; 
&gt; &gt; That&apos;s not correct.  For example, suppose you have three frames, A, B, and
&gt; &gt; C, with A and B in the same origin and C in a different origin.  Script
&gt; &gt; running in A and B grab C&apos;s Location object and then compare the JS
&gt; &gt; interface object they receive with ===.  In Blink&apos;s implementation, they&apos;ll
&gt; &gt; get back |false| because they each receive separate interface objects that
&gt; &gt; are wired up to their respective prototypes.
&gt; 
&gt; Isn&apos;t that considered a bug?

I don&apos;t think it&apos;s important to preserve that behavior as such, but it&apos;s what makes the security so simple.

&gt; That seems really bad.

Why?  What problem does it cause?  The benefit is that there&apos;s no hysteresis.

Looking into the implementation more, it looks like we might actually return the same Location interface object to all viewers, but we&apos;ll definitely return separate copies of objects reachable from the Location object.

&gt; How do you decide what
&gt; object to return, do you base it on the entry script or the incumbent script?

To be 100% sure, I&apos;d have to review what these terms mean exactly now, but I suspect the incumbent script.

&gt; &gt; alert(frames[0].location.replace.apply === Function.prototype.apply)
&gt; &gt; 
&gt; &gt; In Blink, that will alert |true| because the cross-origin Location object&apos;s
&gt; &gt; prototype is wired up to the viewer&apos;s own Function.prototype.  That means
&gt; &gt; that function objects you grab off the prototype are identical to the
&gt; &gt; function objects you can get from inspecting your own constellation of
&gt; &gt; prototype objects.  Importantly, that also means they&apos;re safe to return to
&gt; &gt; the script because the script already has access to them.
&gt; 
&gt; That&apos;s kind of weird magic. Why would we want this? Is it also true of
&gt; prototypes of things like HTMLAnchorElement and Object and so on?

I don&apos;t understand what part of that you think is magic.  It works just the same what it would if you accessed window.location instead of frames[0].location.  The only difference is that interacting with the latter Location instance manipulates the child frame whereas interacting with the former Location instance manipulates the parent frame.  Imagine the following JS code:

get location() { return new %GetIncumbentWindow().Location(this); }

Where %GetIncumbentWindow is a built-in function that returns the incumbent Window.

It&apos;s not possible to get an HTMLAnchorElement interface to a cross-origin object, so there&apos;s no way to know how that would work.

&gt; &gt; There are lots of ways to tell where the object&apos;s prototypes come from. 
&gt; &gt; Here&apos;s one example:
&gt; &gt; 
&gt; &gt; Object.prototype.foo = &quot;bar&quot;;
&gt; &gt; alert(frames[0].location.replace.foo);
&gt; &gt; 
&gt; &gt; This alerts |bar| in Blink.
&gt; 
&gt; That seems like a really bad bug. That means that what code will execute
&gt; depends in weird ways on how it was called, even in entirely same-origin
&gt; situations, just because of what unrelated code has done to the prototypes
&gt; in a different browsing context.

You must be misunderstanding what I&apos;ve described because that&apos;s not the case.  None of this happens in same-origin scenarios.  In same-origin scenarios, all viewers get the identical instance of the Location interface.  It&apos;s only in cross-origin scenarios that each (cross-origin) viewer gets a fresh instance of the Location interface.

&gt; &gt; Experimenting a bit, it looks like Blink only throws when you access
&gt; &gt; __proto__ on the original interface (e.g., Location), not on any objects
&gt; &gt; that you can obtain transitively from that interface (e.g., replace).  For
&gt; &gt; those objects, you can just get the prototype directly.
&gt; 
&gt; Why do you throw at all, given the rest of how Blink works?

We wouldn&apos;t have to, but we wanted to work similarly to other browsers.  Compatibility doesn&apos;t require that we let scripts grab __proto__, so we might as well throw.

&gt; &gt; &gt; The idea of the freezing is that it enables implementations to avoid the
&gt; &gt; &gt; cost of having multiple objects (one per origin)
&gt; &gt; 
&gt; &gt; It&apos;s more than just one per origin.  It&apos;s one per cross-origin script.
&gt; 
&gt; All the more reason to avoid it...
&gt; 
&gt; (How do you avoid this being really expensive? Do you lazily create them?)

Yes, they&apos;re created on-demand, similarly to the JavaScript mentioned above.  I believe we cache them, but I wasn&apos;t able to find that code immediately.

&gt; Do you have any suggestions on how to get interoperability here?

I&apos;m happy to consider solutions that don&apos;t involve developing wrapper technology.  If the folks who work on Gecko are willing to use a mechanism other that wrappers to solve this problem, then we can probably find something interoperable.  If you all insist on a wrapper-based model, then we&apos;re not going to get interoperability anytime soon.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94586</commentid>
    <comment_count>63</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-10-11 13:53:20 +0000</bug_when>
    <thetext>(In reply to Adam Barth from comment #62)
&gt; I&apos;m happy to consider solutions that don&apos;t involve developing wrapper
&gt; technology.

Adam - Hixie and I are both well-aware that Blink doesn&apos;t plan to implement wrappers of any sort. Gecko has no plans to switch to Blink&apos;s architecture either. This is why we spent a number of hours together trying to come up with a security model for the spec that is easy to implement in either setting.

Most of the proposal in comment 56 does not describe what Gecko currently does. It was designed to be Blink-friendly, especially with respect to the null prototypes, which was what my sleuthing led me to believe that Blink was doing.

&gt; If the folks who work on Gecko are willing to use a mechanism
&gt; other that wrappers to solve this problem, then we can probably find
&gt; something interoperable.

Anything we implement is going to use our technology, just like anything you implement is going to use your technology. The goal here is to specify behavior that is straightforward for both of us to implement.

&gt; If you all insist on a wrapper-based model, then
&gt; we&apos;re not going to get interoperability anytime soon.

We&apos;re not insisting on anything, nor are we asking you to implement wrappers. But we are asking you to consider the design challenges from both ends, as well as overall spec sanity.

Our wrapper setup in Gecko is quite flexible. Our only major design constraint (which itself is negotiable) is that we don&apos;t want to allow arbitrary properties to be defined on cross-origin objects. From a high level, I don&apos;t imagine that Blink would find this constraint either unreasonable or difficult to implement.

So. Let&apos;s talk about how you want this stuff to work.

I&apos;m a bit confused about comment 62. Are you saying that a given Location object in Blink has (a) one JS reflection per global, (b) one JS reflection per origin, or (c) one JS reflection for the whole system? What does the prototype chain look like?

It sounds like the functions, getters, and setters you pull off cross-origin objects map to the Function.prototype of the script which is observing them. This is what Gecko does as well, and we only changed it in the proposal because I think it would be difficult for Blink and confusing to spec. If you want to keep doing that, I&apos;m happy to as well. But note that it introduces some weirdness: if |A| and |B| are same-origin, and both of them pull location.replace off of some cross-origin |C|&apos;s window.location, they will get observably different results, despite the fact that presumably the window.location will compare equal.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94602</commentid>
    <comment_count>64</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-10-11 21:49:08 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #63)
&gt; (In reply to Adam Barth from comment #62)
&gt; &gt; I&apos;m happy to consider solutions that don&apos;t involve developing wrapper
&gt; &gt; technology.
&gt; 
&gt; Adam - Hixie and I are both well-aware that Blink doesn&apos;t plan to implement
&gt; wrappers of any sort. Gecko has no plans to switch to Blink&apos;s architecture
&gt; either. This is why we spent a number of hours together trying to come up
&gt; with a security model for the spec that is easy to implement in either
&gt; setting.

What you proposed is not possible to implement securely without wrappers.

&gt; Most of the proposal in comment 56 does not describe what Gecko currently
&gt; does. It was designed to be Blink-friendly, especially with respect to the
&gt; null prototypes, which was what my sleuthing led me to believe that Blink
&gt; was doing.

As far as I can tell, the concept of an Alien Object implies the existence of wrappers.  The way you can tell is that is is specified in terms of a JavaScript object acting as if it had some quality that it doesn&apos;t actually have (e.g., being frozen).  The only way I know how to do that is to apply an interception layer between the code manipulating the object and the actual JS object.  That&apos;s what I meant by &quot;magic&quot; above.  As far as I can tell, that sort of interposition cannot be implemented without wrappers because that&apos;s what the wrapper does!

&gt; &gt; If the folks who work on Gecko are willing to use a mechanism
&gt; &gt; other that wrappers to solve this problem, then we can probably find
&gt; &gt; something interoperable.
&gt; 
&gt; Anything we implement is going to use our technology, just like anything you
&gt; implement is going to use your technology.

Why?  Wrappers are not required for security here.  There&apos;s also not required for compatibility.  Is there some reason you&apos;re opposed to a non-wrapper design?

&gt; The goal here is to specify
&gt; behavior that is straightforward for both of us to implement.

The two approach are different in observable ways.  In particular, the identity of various objects differ between the two approaches.  Without an interposition layer (read: wrapper) to make the objects &quot;act as if&quot; something else were true (read: magic), those observables are going to stay different.

&gt; &gt; If you all insist on a wrapper-based model, then
&gt; &gt; we&apos;re not going to get interoperability anytime soon.
&gt; 
&gt; We&apos;re not insisting on anything, nor are we asking you to implement
&gt; wrappers.

I don&apos;t see any way of implementing your proposal without wrappers.  It requires magic.  In practice, you as insisting on wrappers.

&gt; But we are asking you to consider the design challenges from both
&gt; ends, as well as overall spec sanity.

I&apos;m happy to consider designs that don&apos;t require Blink to implement wrappers.  I don&apos;t know of any designs that are secure other than ones that mint new JS interface objects for each cross-origin viewer.

There&apos;s a basic requirement that these objects act differently for different viewers.  You can either accomplish that by using wrappers to make the &quot;same&quot; JS object act differently in situations or you can actually use different JS objects that have different behavior.  I don&apos;t know how to have the same JS object have different behavior for different viewers without magic.

&gt; Our wrapper setup in Gecko is quite flexible. Our only major design
&gt; constraint (which itself is negotiable) is that we don&apos;t want to allow
&gt; arbitrary properties to be defined on cross-origin objects. From a high
&gt; level, I don&apos;t imagine that Blink would find this constraint either
&gt; unreasonable or difficult to implement.

It depends what you mean by a cross-origin object.  In the example earlier in the thread, would you consider frames[0].location.replace to be a cross-origin object?  In Blink, it&apos;s just a normal JS object, exactly the same kind you&apos;d get from window.location.replace.  It&apos;s even the case that frames[0].location.replace.__proto__ === window.location.replace.__proto__.

The only thing that&apos;s different about frames[0].location.replace and window.location.replace is that the former operates on frames[0] whereas the latter operates on window.  In particular, frames[0].location.replace is mutable just like window.location.replace.

&gt; So. Let&apos;s talk about how you want this stuff to work.
&gt; 
&gt; I&apos;m a bit confused about comment 62. Are you saying that a given Location
&gt; object in Blink has (a) one JS reflection per global, (b) one JS reflection
&gt; per origin, or (c) one JS reflection for the whole system? What does the
&gt; prototype chain look like?

None of those.  The way it works is just the way the following JavaScript would work:

get location() {
  var activeWindow = %GetIncumbentWindow();
  if (%IsSameOrigin(this, activeWindow)) {
    // Return the same full-featured Location instance
    // to all same-origin viewers.
    return this._location;
  return new activeWindow.Location(this);
}

Where %GetIncumbentWindow is a magic function that returns a reference to the Window object for the incumbent script and %IsSameOrigin is a magic function that returns true iff the two windows belong to the same origin.

Notice that all same-origin viewers get exactly the same instance of the Location object, and that object has a prototype chain that connects up with it&apos;s window&apos;s prototypes.

Each cross-origin viewer gets a fresh instance of the Location interface with a prototype chain that connects up with the viewer&apos;s prototype objects.  Notice that we pass |this| to the activeWindow.Location constructor to indicate that the newly constructed object should operate on |this| rather than on |activeWindow|.

That&apos;s the whole security mechanism in a nutshell.  It&apos;s super simple.  The only other facet is that the Location throws some security exceptions when the incumbent script tries to perform operations (like get the href property) that aren&apos;t allowed.  The JS interface object isn&apos;t really involved in those security checks.  They&apos;re done by the underlying implementation object.  The only one that&apos;s done by the JS engine is throwing an exception for getting __proto__, but that&apos;s not needed for security.  It&apos;s just to give us more flexibility in the future.

&gt; It sounds like the functions, getters, and setters you pull off cross-origin
&gt; objects map to the Function.prototype of the script which is observing them.

Correct.

&gt; This is what Gecko does as well, and we only changed it in the proposal
&gt; because I think it would be difficult for Blink and confusing to spec.

It&apos;s easy to spec.  In fact, there isn&apos;t really any spec text to write.  You just say that when you get the |location| property across origins, you get an instance of the incumbent&apos;s Location interface rather than an instance of the callee&apos;s Location interface.  Everything else follows from normal JavaScript rules.

&gt; If
&gt; you want to keep doing that, I&apos;m happy to as well. But note that it
&gt; introduces some weirdness: if |A| and |B| are same-origin, and both of them
&gt; pull location.replace off of some cross-origin |C|&apos;s window.location, they
&gt; will get observably different results,

That&apos;s fine.  They each get objects that belong to their own global object.  We haven&apos;t had any compat problems from this behavior.

&gt; despite the fact that presumably the window.location will compare equal.

There&apos;s no reason for the objects to compare equal.  We can make the comparison throw if you&apos;d like, but they&apos;re not the same object.  Cross-origin viewers get minted fresh objects.  That&apos;s what makes it secure.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94603</commentid>
    <comment_count>65</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-10-11 22:21:49 +0000</bug_when>
    <thetext>(In reply to Adam Barth from comment #60)
&gt; 
&gt; That&apos;s not correct.  For example, suppose you have three frames, A, B, and
&gt; C, with A and B in the same origin and C in a different origin.  Script
&gt; running in A and B grab C&apos;s Location object and then compare the JS
&gt; interface object they receive with ===.  In Blink&apos;s implementation, they&apos;ll
&gt; get back |false| because they each receive separate interface objects that
&gt; are wired up to their respective prototypes.

I don&apos;t understand how two scripts operating in the same origin, operating on the same object, getting different results, is not a bug.


&gt; frames[0].location.replace.__proto__ === window.location.replace.__proto__.

I don&apos;t know how to reconcile that with the fact that this is true (in a same-origin iframe):

   parent.document.appendChild.__proto__ !== document.appendChild.__proto__

Why do these two methods work differently?

Why is it not a bug that the following first alerts B? Why does it not alert B in the second call as well?

   assert(parent.location.__proto__ !== self.location.__proto__);
   self.location.replace.__proto__.toString = function () { return &apos;A&apos; };
   parent.location.replace.__proto__.toString = function () { return &apos;B&apos; };
   alert(location.replace); // &quot;B&quot;
   alert(parent.document.body.appendChild); // &quot;function appendChild() ...&quot;

The two Location objects here have different prototypes; it seems very strange to me that their functions can have the same prototype. This is &quot;magic&quot;.


The model in comment 56 is not intended to require wrappers. I don&apos;t understand why it would need wrappers. It just means making Window and Location check the origin of the caller when their properties are accessed, and acting differently. This already happens in Blink -- if you try to access otherWindow.localStorage cross-origin, you get an exception, but if you&apos;re same-origin, it works. Indeed, it seems to be exactly the same kind of logic that would enable making Location&apos;s method&apos;s prototypes appear to be local Function prototypes instead of being from the other browsing context. I don&apos;t understand what it is in comment 56 that&apos;s different from that.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94610</commentid>
    <comment_count>66</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-10-11 23:28:10 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #65)
&gt; I don&apos;t understand how two scripts operating in the same origin, operating
&gt; on the same object, getting different results, is not a bug.

What makes you say that it&apos;s the same object?  They&apos;re just accessing the same getter, which is returning different objects at different times.  It&apos;s easy to write in idiomatic JavaScript, and we do it all the time in the platform.  For example, document.body.firstChild will return different objects at different times.  That certainly isn&apos;t a bug.

&gt; &gt; frames[0].location.replace.__proto__ === window.location.replace.__proto__.
&gt; 
&gt; I don&apos;t know how to reconcile that with the fact that this is true (in a
&gt; same-origin iframe):
&gt; 
&gt;    parent.document.appendChild.__proto__ !== document.appendChild.__proto__
&gt; 
&gt; Why do these two methods work differently?

Is |parent| same-origin with |window|?  For the remainder of this response, I&apos;m going to assume they are not same-origin.  (If they were same-origin, then the location property works the same way the locationbar property works, which is to say extremely normally.)

Because parent.document instanceof parent.Document and window.document instance window.Document.  In the cross-origin location case, parent.location instanceof window.Location and window.location instanceof window.Location.

&gt; Why is it not a bug that the following first alerts B? Why does it not alert
&gt; B in the second call as well?
&gt; 
&gt;    assert(parent.location.__proto__ !== self.location.__proto__);

This throws an exception when trying to [[Get]] parent.location.__proto__.  If it didn&apos;t, the assert would fail.  The two objects have the same prototype.

&gt;    self.location.replace.__proto__.toString = function () { return &apos;A&apos; };
&gt;    parent.location.replace.__proto__.toString = function () { return &apos;B&apos; };
&gt;    alert(location.replace); // &quot;B&quot;
&gt;    alert(parent.document.body.appendChild); // &quot;function appendChild() ...&quot;
&gt; 
&gt; The two Location objects here have different prototypes;

Why?  In the approach I&apos;m describing, they have the same prototype (again, assuming we&apos;re talking about the cross-origin case).

&gt; it seems very
&gt; strange to me that their functions can have the same prototype. This is
&gt; &quot;magic&quot;.

It&apos;s not magic at all.  You can implement it directly in normal JavaScript using the snippet I posted earlier.

&gt; The model in comment 56 is not intended to require wrappers.

I claim it does.  Do you have an implementation that doesn&apos;t use wrappers?

&gt; I don&apos;t understand why it would need wrappers.

Because it uses the phrase &quot;as if&quot; to make the internal properties of the object appear to have different values than they do in reality.  That requires some sort of interposition to make these behavioral &quot;fixups.&quot;  The only way I know how to do that is to use wrappers.  That&apos;s in fact what the wrappers do!

&gt; It just means making Window and
&gt; Location check the origin of the caller when their properties are accessed,
&gt; and acting differently.

That&apos;s not what the text you wrote says.

&gt; This already happens in Blink -- if you try to
&gt; access otherWindow.localStorage cross-origin, you get an exception, but if
&gt; you&apos;re same-origin, it works.

Slow down.  You just switched from talking about Location to talking about Window.  The Window object is deeply magic and there&apos;s no getting away from that.  This bug is about Location.  Let&apos;s stick to that topic and not get distracted by the magic in Window.

I agree that Window cannot be implemented without magic.  I claim Location can be implemented securely without magic.  I don&apos;t want to introduce any more magic to the system than absolutely required.

&gt; Indeed, it seems to be exactly the same kind
&gt; of logic that would enable making Location&apos;s method&apos;s prototypes appear to
&gt; be local Function prototypes instead of being from the other browsing
&gt; context. I don&apos;t understand what it is in comment 56 that&apos;s different from
&gt; that.

The simplest example is the following:

&quot;act as if all objects returned by members of that object (including, for instance, function objects) were frozen.&quot;

parent.location.replace doesn&apos;t act as if it is frozen.  It&apos;s not frozen, and it doesn&apos;t act that way either.

I&apos;ll copy-and-paste this snippet again, because this is really the whole story:

get location() {
  var activeWindow = %GetIncumbentWindow();
  if (%IsSameOrigin(this, activeWindow)) {
    // Return the same full-featured Location instance
    // to all same-origin viewers.
    return this._location;
  }
  return new activeWindow.Location(this);
}

There&apos;s no magic &quot;act as if.&quot;  There&apos;s just normal JavaScript that plays by the normal JavaScript rules.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94613</commentid>
    <comment_count>67</comment_count>
    <who name="David Bruant">bruant.d</who>
    <bug_when>2013-10-12 01:04:25 +0000</bug_when>
    <thetext>(In reply to Adam Barth from comment #66)
&gt; get location() {
&gt;   var activeWindow = %GetIncumbentWindow();
&gt;   if (%IsSameOrigin(this, activeWindow)) {
&gt;     // Return the same full-featured Location instance
&gt;     // to all same-origin viewers.
&gt;     return this._location;
&gt;   }
&gt;   return new activeWindow.Location(this);
&gt; }
The last line is where the prototype objects (Function.prototype, Object.prototype) of the current frame (activeWindow) are grabbed to be used in the returned Location instance prototype chain, right?

This also means that as a cross-origin script, I get a different object everytime I ask for the location object? (since no record is kept of which activeWindow is being passed which Location instance)


&gt; &gt; &gt; frames[0].location.replace.__proto__ === window.location.replace.__proto__.
&gt; &gt; 
&gt; &gt; I don&apos;t know how to reconcile that with the fact that this is true (in a
&gt; &gt; same-origin iframe):
&gt; &gt; 
&gt; &gt;    parent.document.appendChild.__proto__ !== document.appendChild.__proto__
&gt; &gt; 
&gt; &gt; Why do these two methods work differently?
&gt; 
&gt; Is |parent| same-origin with |window|?  For the remainder of this response,
&gt; I&apos;m going to assume they are not same-origin.  (If they were same-origin,
&gt; then the location property works the same way the locationbar property
&gt; works, which is to say extremely normally.)
&gt; 
&gt; Because parent.document instanceof parent.Document and window.document
&gt; instance window.Document.  In the cross-origin location case,
&gt; parent.location instanceof window.Location and window.location instanceof
&gt; window.Location.
The last sentence is scary. It means that while cross-origin parent and window can communicate directly via window.Location.prototype. Is it a mistake? Am I missing something?


(In reply to Bobby Holley (:bholley) from comment #34)
&gt; The de-facto web platform currently never allows expando properties to be
&gt; set on any object that is not same-origin with the incumbent script. The
&gt; spec requires a &quot;vanilla object&quot; to be created for cross-origin access to
&gt; Window, but that object is immutable, which means that implementations could
&gt; potentially share the same instance between _all_ non-same-origin consumers,
&gt; or have read-only view to the native properties.
In the &quot;same instance&quot; case, what does the prototype chain looks like? Specifically, are Function.prototype and Object.prototype objects created at this occasion? Frozen versions of these objects?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94615</commentid>
    <comment_count>68</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-10-12 12:22:16 +0000</bug_when>
    <thetext>(In reply to Adam Barth from comment #64)
&gt; What you proposed is not possible to implement securely without wrappers.

&gt; As far as I can tell, the concept of an Alien Object implies the existence
&gt; of wrappers.

As noted, that was not the intention. We came up with the notion of &quot;Alien Object&quot; specifically as something that would be implementable with or without wrappers.

&gt; The way you can tell is that is is specified in terms of a
&gt; JavaScript object acting as if it had some quality that it doesn&apos;t actually
&gt; have (e.g., being frozen).

Who says the object doesn&apos;t have the property? The &quot;act as if&quot; bit was just a wink and a nod to the fact that Gecko would use wrapper magic to accomplish this. In Blink, we presumed that you&apos;d just freeze the object.

&gt; &gt; Anything we implement is going to use our technology, just like anything you
&gt; &gt; implement is going to use your technology.
&gt; 
&gt; Why?  Wrappers are not required for security here.  There&apos;s also not
&gt; required for compatibility.  Is there some reason you&apos;re opposed to a
&gt; non-wrapper design?

Our architecture is designed around wrappers. In particular, we have to use them here, because we can only have one JS reflector per native DOM object. This is true in Servo as well.
 
&gt; &gt; The goal here is to specify
&gt; &gt; behavior that is straightforward for both of us to implement.
&gt; 
&gt; The two approach are different in observable ways.

Only if we fail to specify behavior that we can both implement.

&gt; In particular, the
&gt; identity of various objects differ between the two approaches.

Which objects? Location? Function? We&apos;re quite flexible about what we do here in Gecko-land, so I&apos;m reasonably confident we can come up with behavior that works for everyone.

&gt; &gt; We&apos;re not insisting on anything, nor are we asking you to implement
&gt; &gt; wrappers.
&gt; 
&gt; I don&apos;t see any way of implementing your proposal without wrappers.  It
&gt; requires magic.  In practice, you as insisting on wrappers.

Adam, it&apos;s a proposal. It is something that we are distinctly _not_ insisting on. We are actively soliciting your feedback.
 
&gt; I&apos;m happy to consider designs that don&apos;t require Blink to implement
&gt; wrappers.

Great.

&gt; I don&apos;t know of any designs that are secure other than ones that
&gt; mint new JS interface objects for each cross-origin viewer.

This should be &quot;that are secure in Blink&quot;. I&apos;m aware that Blink is very unlikely to change its approach here. So the goal of the proposal was to massage the implementations (by neutering prototypes and freezing objects) such that Blink could keep doing what it&apos;s down, and Gecko could keep doing what it&apos;s doing.
 
&gt; I don&apos;t know how to have
&gt; the same JS object have different behavior for different viewers without
&gt; magic.

To discuss this meaningfully, we need to clarify what we mean by &quot;viewers&quot;. See below.

&gt; It depends what you mean by a cross-origin object.

That too is open for discussion.

&gt; In the example earlier
&gt; in the thread, would you consider frames[0].location.replace to be a
&gt; cross-origin object?  In Blink, it&apos;s just a normal JS object, exactly the
&gt; same kind you&apos;d get from window.location.replace.  It&apos;s even the case that
&gt; frames[0].location.replace.__proto__ === window.location.replace.__proto__.

As noted in the last paragraph of comment 63, this is what Gecko does as well, and I&apos;m entirely open to keeping this behavior.

&gt; The only thing that&apos;s different about frames[0].location.replace and
&gt; window.location.replace is that the former operates on frames[0] whereas the
&gt; latter operates on window.

Is there anything intrinsic to those methods that make them only able to operate on the original object (that is to say - are they bound)? This used to be the case in Gecko, but we considered it a bug and I fixed it. You can now call/apply any version of |replace| you find anywhere on any Location object, cross-origin or not.

&gt; The way it works is just the way the following JavaScript
&gt; would work:
&gt; 
&gt; get location() {
&gt;   var activeWindow = %GetIncumbentWindow();
&gt;   if (%IsSameOrigin(this, activeWindow)) {
&gt;     // Return the same full-featured Location instance
&gt;     // to all same-origin viewers.
&gt;     return this._location;
&gt;   return new activeWindow.Location(this);
&gt; }

As David points out in the first paragraph of comment 67, this implies that |xoWin.location != xoWin.location|, because you&apos;d get a new object each time. I&apos;m quite sure this isn&apos;t true in Blink, both from my testing and from my understanding of how Blink works. IIUC, you have a per-global (or per-origin?) hash that maps from the C++ DOM object to the JS reflector.

&gt; Notice that all same-origin viewers get exactly the same instance of the
&gt; Location object

This would imply that the hash is per-origin. Is that correct?

&gt; and that object has a prototype chain that connects up with
&gt; it&apos;s window&apos;s prototypes.

Which prototypes, exactly? In the case of multiple same-origin windows jointly observing a cross-origin Location object - do they share the same instance? If so, where does the prototype chain lead? To the Location.prototype of whoever touched it first?
 
&gt; That&apos;s fine.  They each get objects that belong to their own global object. 
&gt; We haven&apos;t had any compat problems from this behavior.
&gt; 
&gt; &gt; despite the fact that presumably the window.location will compare equal.
&gt; 
&gt; There&apos;s no reason for the objects to compare equal.

And _this_ implies that the hash is per-global. Which is it?

&gt; We can make the
&gt; comparison throw if you&apos;d like, but they&apos;re not the same object.

In terms of how the spec describes the DOM, they very much are the same object. 

&gt; Cross-origin viewers get minted fresh objects.  That&apos;s what makes it secure.

This is an implementation detail of Blink, as much as wrappers are an implementation detail of Gecko.

(In reply to Adam Barth from comment #66)
&gt; (In reply to Ian &apos;Hixie&apos; Hickson from comment #65)
&gt; What makes you say that it&apos;s the same object?  They&apos;re just accessing the
&gt; same getter, which is returning different objects at different times.  It&apos;s
&gt; easy to write in idiomatic JavaScript, and we do it all the time in the
&gt; platform.  For example, document.body.firstChild will return different
&gt; objects at different times.  That certainly isn&apos;t a bug.

Yes, but this generally doesn&apos;t change depending on the incumbent script.

Conceptually, it&apos;s a difference between the binding layer (with JS reflector objects) and the actual DOM. If the DOM changes (as in the firstChild case) you should get a different result. If it doesn&apos;t, you should get the same result.

&gt; The problem with freezing the objects is that the object Blink returns are
&gt; the same objects you&apos;d get by other means.  There&apos;s no way to &quot;act as if&quot;
&gt; they were frozen without magic.  They&apos;re either frozen or they&apos;re not.  We
&gt; can&apos;t actually freeze them because that would disrupt the script when it
&gt; accessed them normally.

I don&apos;t follow this part. As you noted, each origin gets a freshly-minted JS object in Blink. Why can&apos;t those fresh ones be frozen while the canonical one not be frozen?

&gt; &gt; &gt; Personally, I don&apos;t have any interest in changing Blink&apos;s implementation in
&gt; &gt; &gt; this area.  It&apos;s simple, and it works well.

&gt; I agree that interoperability is a good goal, but I don&apos;t see how to achieve
&gt; it in this case because it&apos;s too easy for script to figure out which
&gt; implementation approach is being used.

I don&apos;t agree. I believe that we can spec a compromise if the vendors come together in good faith.

&gt; They just behave differently. 
&gt; Trying to hide all the implementation details is going to end up being more
&gt; complicated than the entire security mechanism.

Are you really suggesting that we should cease our efforts to interoperate on security behavior?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94616</commentid>
    <comment_count>69</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-10-12 15:38:00 +0000</bug_when>
    <thetext>(In reply to David Bruant from comment #67)
&gt; (In reply to Adam Barth from comment #66)
&gt; &gt; get location() {
&gt; &gt;   var activeWindow = %GetIncumbentWindow();
&gt; &gt;   if (%IsSameOrigin(this, activeWindow)) {
&gt; &gt;     // Return the same full-featured Location instance
&gt; &gt;     // to all same-origin viewers.
&gt; &gt;     return this._location;
&gt; &gt;   }
&gt; &gt;   return new activeWindow.Location(this);
&gt; &gt; }
&gt; The last line is where the prototype objects (Function.prototype,
&gt; Object.prototype) of the current frame (activeWindow) are grabbed to be used
&gt; in the returned Location instance prototype chain, right?

Correct.

&gt; This also means that as a cross-origin script, I get a different object
&gt; everytime I ask for the location object? (since no record is kept of which
&gt; activeWindow is being passed which Location instance)

Correct

&gt; &gt; Because parent.document instanceof parent.Document and window.document
&gt; &gt; instance window.Document.  In the cross-origin location case,
&gt; &gt; parent.location instanceof window.Location and window.location instanceof
&gt; &gt; window.Location.
&gt;
&gt; The last sentence is scary. It means that while cross-origin parent and
&gt; window can communicate directly via window.Location.prototype. Is it a
&gt; mistake? Am I missing something?

Recall that the entire comment is describing the world from the perspective of the cross-origin viewer.  All it means is that the script can communicate with itself, which isn&apos;t scary.

(In reply to Bobby Holley (:bholley) from comment #68)
&gt; (In reply to Adam Barth from comment #64)
&gt; &gt; What you proposed is not possible to implement securely without wrappers.
&gt; 
&gt; &gt; As far as I can tell, the concept of an Alien Object implies the existence
&gt; &gt; of wrappers.
&gt; 
&gt; As noted, that was not the intention. We came up with the notion of &quot;Alien
&gt; Object&quot; specifically as something that would be implementable with or
&gt; without wrappers.

I understand that was your intent, but as far as I can tell, the thing you created cannot be implemented without wrappers.  Do you have a non-wrapper-based implementation I can study and learn from?

&gt; &gt; The way you can tell is that is is specified in terms of a
&gt; &gt; JavaScript object acting as if it had some quality that it doesn&apos;t actually
&gt; &gt; have (e.g., being frozen).
&gt; 
&gt; Who says the object doesn&apos;t have the property? The &quot;act as if&quot; bit was just
&gt; a wink and a nod to the fact that Gecko would use wrapper magic to
&gt; accomplish this. In Blink, we presumed that you&apos;d just freeze the object.

Why do we need winks and nods to wrapper magic?  If the behavior is observationally equivalent to normal JavaScript behavior, lets specify it as normal JavaScript behavior instead of with magic.

&gt; &gt; Why?  Wrappers are not required for security here.  There&apos;s also not
&gt; &gt; required for compatibility.  Is there some reason you&apos;re opposed to a
&gt; &gt; non-wrapper design?
&gt; 
&gt; Our architecture is designed around wrappers. In particular, we have to use
&gt; them here, because we can only have one JS reflector per native DOM object.
&gt; This is true in Servo as well.

That&apos;s an odd limitation.  In any case, it&apos;s not really a limitation here because you can create a new native DOM object at the same time you create the new JS interface objects.

&gt; &gt; In particular, the
&gt; &gt; identity of various objects differ between the two approaches.
&gt; 
&gt; Which objects? Location? Function?

Yes.

&gt; We&apos;re quite flexible about what we do
&gt; here in Gecko-land, so I&apos;m reasonably confident we can come up with behavior
&gt; that works for everyone.

Great!  Would you be willing to adopt the behavior I&apos;ve proposed in this thread?  I&apos;m confident that it&apos;s both secure and doesn&apos;t require any additional technology beyond what&apos;s already required to implement the web platform.

&gt; &gt; I don&apos;t see any way of implementing your proposal without wrappers.  It
&gt; &gt; requires magic.  In practice, you as insisting on wrappers.
&gt; 
&gt; Adam, it&apos;s a proposal. It is something that we are distinctly _not_
&gt; insisting on. We are actively soliciting your feedback.

My feedback is that proposal doesn&apos;t work for me because it requires complication technology that I don&apos;t want to build.  If you can show me how to implement it with normal JavaScript semantics (i.e., without wrapper magic), I&apos;d be willing to re-consider.

&gt; &gt; I don&apos;t know of any designs that are secure other than ones that
&gt; &gt; mint new JS interface objects for each cross-origin viewer.
&gt; 
&gt; This should be &quot;that are secure in Blink&quot;. I&apos;m aware that Blink is very
&gt; unlikely to change its approach here. So the goal of the proposal was to
&gt; massage the implementations (by neutering prototypes and freezing objects)
&gt; such that Blink could keep doing what it&apos;s down, and Gecko could keep doing
&gt; what it&apos;s doing.

That&apos;s a good goal, but the current proposal does not achieve that goal, as I&apos;ve explained repeatedly.

&gt; &gt; In the example earlier
&gt; &gt; in the thread, would you consider frames[0].location.replace to be a
&gt; &gt; cross-origin object?  In Blink, it&apos;s just a normal JS object, exactly the
&gt; &gt; same kind you&apos;d get from window.location.replace.  It&apos;s even the case that
&gt; &gt; frames[0].location.replace.__proto__ === window.location.replace.__proto__.
&gt; 
&gt; As noted in the last paragraph of comment 63, this is what Gecko does as
&gt; well, and I&apos;m entirely open to keeping this behavior.

Great!

&gt; &gt; The only thing that&apos;s different about frames[0].location.replace and
&gt; &gt; window.location.replace is that the former operates on frames[0] whereas the
&gt; &gt; latter operates on window.
&gt; 
&gt; Is there anything intrinsic to those methods that make them only able to
&gt; operate on the original object (that is to say - are they bound)?

No, I just meant in the way they&apos;re commonly used (i.e., called with |this| bound to frames[0].location).  You&apos;d get exactly the same results via window.location.replace.call(frames[0].location, ...).  That&apos;s, in fact, one of the ways to see that this approach is secure.  You never give a cross-origin script any objects that it didn&apos;t already have access to, which means you&apos;re not leaking anything dangerous.

&gt; This used
&gt; to be the case in Gecko, but we considered it a bug and I fixed it. You can
&gt; now call/apply any version of |replace| you find anywhere on any Location
&gt; object, cross-origin or not.

Great!

&gt; &gt; The way it works is just the way the following JavaScript
&gt; &gt; would work:
&gt; &gt; 
&gt; &gt; get location() {
&gt; &gt;   var activeWindow = %GetIncumbentWindow();
&gt; &gt;   if (%IsSameOrigin(this, activeWindow)) {
&gt; &gt;     // Return the same full-featured Location instance
&gt; &gt;     // to all same-origin viewers.
&gt; &gt;     return this._location;
&gt; &gt;   return new activeWindow.Location(this);
&gt; &gt; }
&gt; 
&gt; As David points out in the first paragraph of comment 67, this implies that
&gt; |xoWin.location != xoWin.location|, because you&apos;d get a new object each
&gt; time. I&apos;m quite sure this isn&apos;t true in Blink, both from my testing and from
&gt; my understanding of how Blink works. IIUC, you have a per-global (or
&gt; per-origin?) hash that maps from the C++ DOM object to the JS reflector.

The JS interface object minted in this way is never stored in the hash map.  It&apos;s possible the model I&apos;ve described in this thread doesn&apos;t match the implementation 100% precisely, but it&apos;s a model we&apos;d be happy to implement and is probably simpler to what Blink&apos;s implementation does currently.  For example, it&apos;s possible that we cache the minted Location objects, but that&apos;s not necessary.

&gt; &gt; Notice that all same-origin viewers get exactly the same instance of the
&gt; &gt; Location object
&gt; 
&gt; This would imply that the hash is per-origin. Is that correct?

Conceptually, the hash is static (meaning global for all frames).  We just don&apos;t query the hash in the cross-origin case.  Instead, we mint new objects.  (The reality is a bit more complex due to workers and a performance optimization that lets us avoid the hash lookup in some cases, but let&apos;s imagine a world without workers or observationally equivalent performance optimizations.)

&gt; &gt; and that object has a prototype chain that connects up with
&gt; &gt; it&apos;s window&apos;s prototypes.
&gt; 
&gt; Which prototypes, exactly? In the case of multiple same-origin windows
&gt; jointly observing a cross-origin Location object - do they share the same
&gt; instance?

Yes.  When I wrote the JavaScript &quot;return this._location&quot;, what that means in JavaScript is that they all get the same instance: the one that&apos;s stored in the (hidden) _location property of the Window object.

&gt; If so, where does the prototype chain lead? To the
&gt; Location.prototype of whoever touched it first?

No.  For same-origin viewers, sameOriginWindow.location.__proto__ === sameOriginWindow.Location.prototype, just as with sameOriginWindow.locationbar.

I feel like I keep repeating myself.  Here&apos;s where I wrote that before:

&quot;If they were same-origin, then the location property works the same way the locationbar property works, which is to say extremely normally.&quot;

&gt; &gt; &gt; despite the fact that presumably the window.location will compare equal.
&gt; &gt; 
&gt; &gt; There&apos;s no reason for the objects to compare equal.
&gt; 
&gt; And _this_ implies that the hash is per-global. Which is it?

I don&apos;t see how you&apos;ve arrived at that conclusion.

Really, this all works exactly the way the JavaScript snippet I keep writing works.  Same-origin callers of the location getter get identical objects---exactly the same sort of object they&apos;d get for the locationbar property.  Cross-origin callers of the location getter get minted new objects each time, as described in that snippet.  There&apos;s no magic.  Just normal JavaScript semantics as described by the normal JavaScript I wrote earlier.

I think the problem is that you&apos;re so used to magic being required here that you keep looking for the magic.  There is no magic.  Everything really is as simple as described by those 9 lines of JavaScript.

&gt; &gt; We can make the
&gt; &gt; comparison throw if you&apos;d like, but they&apos;re not the same object.
&gt; 
&gt; In terms of how the spec describes the DOM, they very much are the same
&gt; object. 

They don&apos;t need to be.  They&apos;re just different objects that both happen to navigate the same window.

&gt; &gt; Cross-origin viewers get minted fresh objects.  That&apos;s what makes it secure.
&gt; 
&gt; This is an implementation detail of Blink, as much as wrappers are an
&gt; implementation detail of Gecko.

No, that&apos;s the design!  That&apos;s what makes the design secure using normal JavaScript semantics.  Using fresh objects maintains the invariant that a given script only ever has references to JS objects that are associated with global objects associated with its origin (except the super-magic WindowProxy object, of course).

&gt; (In reply to Adam Barth from comment #66)
&gt; &gt; (In reply to Ian &apos;Hixie&apos; Hickson from comment #65)
&gt; &gt; What makes you say that it&apos;s the same object?  They&apos;re just accessing the
&gt; &gt; same getter, which is returning different objects at different times.  It&apos;s
&gt; &gt; easy to write in idiomatic JavaScript, and we do it all the time in the
&gt; &gt; platform.  For example, document.body.firstChild will return different
&gt; &gt; objects at different times.  That certainly isn&apos;t a bug.
&gt; 
&gt; Yes, but this generally doesn&apos;t change depending on the incumbent script.

So?  What&apos;s going on in both cases is that the property is implemented by a JavaScript getter, which returns different objects based on some internal state of the user agent.  In the case of Node#firstChild, the internal state is the state of the DOM tree.  In the case Window#location, the internal state is the JS runtime stack.

&gt; Conceptually, it&apos;s a difference between the binding layer (with JS reflector
&gt; objects) and the actual DOM. If the DOM changes (as in the firstChild case)
&gt; you should get a different result. If it doesn&apos;t, you should get the same
&gt; result.

That&apos;s a distinction without a difference.  If the user agent was implemented entirely in JavaScript, that distinction wouldn&apos;t exist.  Similarly, you can implement the proposal I&apos;ve described above by creating a new native Location object instead of just creating a new JS interface object to the same native Location object.  That&apos;s observationally equivalent.

&gt; I don&apos;t follow this part. As you noted, each origin gets a freshly-minted JS
&gt; object in Blink. Why can&apos;t those fresh ones be frozen while the canonical
&gt; one not be frozen?

We can freeze the objects if you like:

-  return new activeWindow.Location(this);
+  return Object.freeze(new activeWindow.Location(this));

Rather than saying the object &quot;acts as if&quot; it is frozen, we would say that this newly minted object *is* frozen.

&gt; &gt; I agree that interoperability is a good goal, but I don&apos;t see how to achieve
&gt; &gt; it in this case because it&apos;s too easy for script to figure out which
&gt; &gt; implementation approach is being used.
&gt; 
&gt; I don&apos;t agree. I believe that we can spec a compromise if the vendors come
&gt; together in good faith.

I believe I&apos;ve been clear about my requirements, but I&apos;ll restate them to avoid any doubt:

1) The design must be secure.
2) The design must not involve non-ECMAScript semantics.

I&apos;ve made a proposal that meets these requirements.  I&apos;ve explained the invariant that makes it secure.  I&apos;ve proved that it follows ECMAScript semantics by exhibiting an ECMAScript implementation of the proposal.  Is my proposal acceptable to you?  If not, would you be willing to make a counter proposal that meets these requirements?

&gt; &gt; They just behave differently. 
&gt; &gt; Trying to hide all the implementation details is going to end up being more
&gt; &gt; complicated than the entire security mechanism.
&gt; 
&gt; Are you really suggesting that we should cease our efforts to interoperate
&gt; on security behavior?

I&apos;m saying we shouldn&apos;t try to paper over the differences in our implementations by adding some complicated machinery because the machinery to paper over the differences will end up being more complicated than the security mechanism itself.

Instead, we should implement the same behavior using a similar approach.  That way the behavior really will be interoperable.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94617</commentid>
    <comment_count>70</comment_count>
    <who name="David Bruant">bruant.d</who>
    <bug_when>2013-10-12 17:45:15 +0000</bug_when>
    <thetext>(In reply to Adam Barth from comment #69)
&gt; &gt; &gt; I agree that interoperability is a good goal, but I don&apos;t see how to achieve
&gt; &gt; &gt; it in this case because it&apos;s too easy for script to figure out which
&gt; &gt; &gt; implementation approach is being used.
&gt; &gt; 
&gt; &gt; I don&apos;t agree. I believe that we can spec a compromise if the vendors come
&gt; &gt; together in good faith.
&gt; 
&gt; I believe I&apos;ve been clear about my requirements, but I&apos;ll restate them to
&gt; avoid any doubt:
&gt; 
&gt; 1) The design must be secure.
&gt; 2) The design must not involve non-ECMAScript semantics.
Everything I&apos;ve read about wrappers so far can be implemented in ECMAScript... 6 with proxies. (being able to create &quot;membranes&quot; was a design goal for proxies).
The proxies design is now very stable and has been agreed upon at the TC39 May 2013 meeting [1]. There is one detail that is not entirely sorted out yet about private state (like for Date or Map objects), but this detail doesn&apos;t affect what&apos;s being discussed here.
Note that one purpose of proxies and something that influence its design was closing the gap between platform objects and what can be done in pure ECMAScript. With ES6 proxies, you can implement live NodeList as well as WindowProxy with changing the underlying Window (modulo a few details about property non-configurability I raised about a year ago, but it&apos;s just a matter of adjusting HTML5/WebIDL to match ECMAScript semantics and its invariants in particular).

You&apos;ve been very clear on not wanting to implement wrappers, so I&apos;m not trying to convince you, just trying to clear out potential ambiguities. I imagine you refer to ES5 when you write &quot;ECMAScript semantics.&quot;?
But to me, it begs the question: when will ES6 semantics be ok?


[1] https://github.com/rwaldron/tc39-notes/blob/master/es6/2013-05/may-21.md#44-proxies</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94618</commentid>
    <comment_count>71</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-10-12 18:24:33 +0000</bug_when>
    <thetext>&gt; &gt; I believe I&apos;ve been clear about my requirements, but I&apos;ll restate them to
&gt; &gt; avoid any doubt:
&gt; &gt; 
&gt; &gt; 1) The design must be secure.
&gt; &gt; 2) The design must not involve non-ECMAScript semantics.
&gt;
&gt; Everything I&apos;ve read about wrappers so far can be implemented in
&gt; ECMAScript... 6 with proxies. (being able to create &quot;membranes&quot; was a design
&gt; goal for proxies).

Ok.  Let me be more precise:

2) The design must not involve non-ECMAScript5 semantics.

&gt; You&apos;ve been very clear on not wanting to implement wrappers, so I&apos;m not
&gt; trying to convince you, just trying to clear out potential ambiguities. I
&gt; imagine you refer to ES5 when you write &quot;ECMAScript semantics.&quot;?

Correct.

&gt; But to me, it begs the question: when will ES6 semantics be ok?

For security-critical semantics?  Probably never.  Proxies are much more complicated than necessary.  Complexity is the enemy of security.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94620</commentid>
    <comment_count>72</comment_count>
    <who name="David Bruant">bruant.d</who>
    <bug_when>2013-10-12 23:51:53 +0000</bug_when>
    <thetext>(In reply to Adam Barth from comment #71)
&gt; &gt; But to me, it begs the question: when will ES6 semantics be ok?
&gt; 
&gt; For security-critical semantics?  Probably never.  Proxies are much more
&gt; complicated than necessary.  Complexity is the enemy of security.
Interesting. The way I see it, some security properties of JS programs (like revocability) cannot be achieved without proxies. Anyway not really the topic at hand, but sheds an interesting light on the opposition in this thread.

Back to the topic, although it respects ES5 semantics, it really is awkward that the result of the getter (same or different object) depends on the caller context, especially as it creates garbage that could be otherwise (with wrappers) avoided. At the same time, this is such a stupid use case with few practical value for authors (from what I understand), that I don&apos;t feel too strongly about avoiding garbage.

Are there other cases than location? What&apos;s the strategy for these? Is this creating a precedent? Has this strategy a chance to be reused elsewhere where creating garbage would be less appropriate?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94623</commentid>
    <comment_count>73</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-10-13 05:00:01 +0000</bug_when>
    <thetext>&gt; Are there other cases than location?

Just |location| and a handful of functions (e.g., postMessage, location.replace).  There used to be |history|, but we managed to block accessing that across origins.  Well, there&apos;s Window, of course, but that&apos;s super magical in more ways.

&gt; What&apos;s the strategy for these?

The same approach works for all the cases I&apos;m aware.

&gt; Is this creating a precedent?

Everything is a precedent for something, but I don&apos;t think we&apos;re going to expose any more JS objects across origins.  Hopefully we&apos;ve learned our lesson.

&gt; Has this strategy a chance to be reused elsewhere
&gt; where creating garbage would be less appropriate?

I&apos;m not worried about that.  Exposing JS object across origins is an anti-pattern and we should avoid it in the future.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94625</commentid>
    <comment_count>74</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-10-13 05:16:19 +0000</bug_when>
    <thetext>(In reply to Adam Barth from comment #66)
&gt; &gt; I don&apos;t know how to reconcile that with the fact that this is true (in a
&gt; &gt; same-origin iframe):
&gt; &gt; 
&gt; &gt;    parent.document.appendChild.__proto__ !== document.appendChild.__proto__
&gt; &gt; 
&gt; &gt; Why do these two methods work differently?
&gt; 
&gt; Is |parent| same-origin with |window|?

Yes (as noted in the parenthetical above).

Assuming A and B are in the same origin, and C is a separate origin, and the script is running in B, then in Blink:

   A.document.appendChild.__proto__ !== B.document.appendChild.__proto__
   A.locationbar.__proto__ !== B.locationbar.__proto__
   A.locationbar.toString.__proto__ !== B.locationbar.toString.__proto__
   A.location.__proto__ !== B.location.__proto__
   A.location.toString.__proto__ !== B.location.toString.__proto__
   A.location.replace.__proto__ === B.location.replace.__proto__ // !
   A.location === A.location
   C.location === C.location
   C.location.replace.__proto__ === B.location.replace.__proto__ // !
   A.location instanceof A.Location
   !(A.location instanceof B.Location)
   !(C.location instanceof B.Location)

See: http://software.hixie.ch/utilities/js/live-dom-viewer/saved/2560

The two lines marked &quot;// !&quot; are the ones I find surprising. That, and the way that the second script in comment 65 operates:

   http://software.hixie.ch/utilities/js/live-dom-viewer/saved/2561

Or to put it another way, I think it&apos;s very odd that this prints true:

   http://damowmow.com/playground/demos/cross-window/001.html

...while this prints false:

   http://damowmow.com/playground/demos/cross-window/002.html

Same-origin, two different windows get hold of the same object (a Location) object, which is triple-equals whichever side you look at it from. But then you compare that object&apos;s method&apos;s prototype, and you get different results based on which window you read it from? This is very strange. And it&apos;s only true of the methods on Location, for some reason the methods on Object are different, e.g. compare assign (!==) and toString (===) on the same Location objects:

   http://damowmow.com/playground/demos/cross-window/003.html (assign)
   http://damowmow.com/playground/demos/cross-window/004.html (toString)

I don&apos;t have an opinion as to what the spec should require, other than wanting everyone to agree on something and implement it. But I do think that Blink&apos;s current behaviour isn&apos;t intuitive. An object&apos;s identity, heritage, etc, shouldn&apos;t change based merely on how that object is accessed, in a script-detectable fashion. So if the proposal is Blink&apos;s behaviour, I would prefer (maybe slight, I don&apos;t really know) modifications. A concrete proposal in the form of comment 56&apos;s would help a lot.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94629</commentid>
    <comment_count>75</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-10-13 08:00:52 +0000</bug_when>
    <thetext>(In reply to Adam Barth from comment #69)
&gt; 
&gt; &gt; This also means that as a cross-origin script, I get a different object
&gt; &gt; everytime I ask for the location object? (since no record is kept of which
&gt; &gt; activeWindow is being passed which Location instance)
&gt; 
&gt; Correct

&gt; The JS interface object minted in this way is never stored in the hash map. 
&gt; It&apos;s possible the model I&apos;ve described in this thread doesn&apos;t match the
&gt; implementation 100% precisely, but it&apos;s a model we&apos;d be happy to implement
&gt; and is probably simpler to what Blink&apos;s implementation does currently.  For
&gt; example, it&apos;s possible that we cache the minted Location objects, but that&apos;s
&gt; not necessary.

Ok. So you&apos;re proposing that xoWin.location != xoWin.location. This isn&apos;t what Blink does today (presumably due to your optimization), nor any other UA that I know if. It&apos;s not at all obvious to me that this would be web-compatible.

It&apos;s also contrary to the semantics of the web platform, because getters aren&apos;t supposed to mint a new JS value each time they&apos;re invoked (you&apos;re supposed to use a method if you want to do that).

&gt; &gt; Which prototypes, exactly? In the case of multiple same-origin windows
&gt; &gt; jointly observing a cross-origin Location object - do they share the same
&gt; &gt; instance?
&gt; 
&gt; Yes.  When I wrote the JavaScript &quot;return this._location&quot;, what that means
&gt; in JavaScript is that they all get the same instance: the one that&apos;s stored
&gt; in the (hidden) _location property of the Window object.
&gt;
&gt; I feel like I keep repeating myself.

Probably because you misread my comment. I was asking about the case where |A| and |B| are same-origin with each other but not same-origin with |C|. The Location object they&apos;re observing is cross-origin.

Anyway. Adam has now clarified that his proposal really is to mint a new JS object on each call to the location getter from a cross-origin script. This provides a clean answer to most of the prototype details, but has two glaring issues:
(1) The behavior with respect to identity comparisons is extremely unintuitive and un-web.
(2) Blink does not actually implement this behavior, and given the == issue, it very well may not be web-compatible.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94732</commentid>
    <comment_count>76</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-10-15 05:37:55 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #74)
&gt; (In reply to Adam Barth from comment #66)
&gt; &gt; &gt; I don&apos;t know how to reconcile that with the fact that this is true (in a
&gt; &gt; &gt; same-origin iframe):
&gt; &gt; &gt; 
&gt; &gt; &gt;    parent.document.appendChild.__proto__ !== document.appendChild.__proto__
&gt; &gt; &gt; 
&gt; &gt; &gt; Why do these two methods work differently?
&gt; &gt; 
&gt; &gt; Is |parent| same-origin with |window|?
&gt; 
&gt; Yes (as noted in the parenthetical above).

Sorry, then I gave you completely the wrong answer.  In the same-origin case, the |location| property works identically to the |locationbar| property.

&gt; Assuming A and B are in the same origin, and C is a separate origin, and the
&gt; script is running in B, then in Blink:
&gt; 
&gt;    A.document.appendChild.__proto__ !== B.document.appendChild.__proto__
&gt;    A.locationbar.__proto__ !== B.locationbar.__proto__
&gt;    A.locationbar.toString.__proto__ !== B.locationbar.toString.__proto__
&gt;    A.location.__proto__ !== B.location.__proto__
&gt;    A.location.toString.__proto__ !== B.location.toString.__proto__
&gt;    A.location.replace.__proto__ === B.location.replace.__proto__ // !

That&apos;s not the intended behavior.  The intended behavior is that these objects would be !==.

&gt;    A.location === A.location
&gt;    C.location === C.location
&gt;    C.location.replace.__proto__ === B.location.replace.__proto__ // !

This is the intended behavior.

&gt;    A.location instanceof A.Location
&gt;    !(A.location instanceof B.Location)
&gt;    !(C.location instanceof B.Location)
&gt; 
&gt; See: http://software.hixie.ch/utilities/js/live-dom-viewer/saved/2560
&gt;
&gt; The two lines marked &quot;// !&quot; are the ones I find surprising.

As noted, I find only one of them surprising.

&gt; Same-origin, two different windows get hold of the same object (a Location)
&gt; object, which is triple-equals whichever side you look at it from. But then
&gt; you compare that object&apos;s method&apos;s prototype, and you get different results
&gt; based on which window you read it from?

The intent is that the same-origin case works the same way for |location| and |locationbar|.  I&apos;m certainly willing to change the same-origin behavior to follow the normal rules for WebIDL interfaces.

However, in the cross-origin case, the second &quot;// !&quot; is expected and is essential to the security mechanism, as explained above.

&gt; I don&apos;t have an opinion as to what the spec should require, other than
&gt; wanting everyone to agree on something and implement it. But I do think that
&gt; Blink&apos;s current behaviour isn&apos;t intuitive. An object&apos;s identity, heritage,
&gt; etc, shouldn&apos;t change based merely on how that object is accessed, in a
&gt; script-detectable fashion. So if the proposal is Blink&apos;s behaviour, I would
&gt; prefer (maybe slight, I don&apos;t really know) modifications. A concrete
&gt; proposal in the form of comment 56&apos;s would help a lot.

I&apos;ve given a concrete proposal several times in the form of a JavaScript program.  I can re-write the JavaScript in prose if that would help.  My proposal in this thread doesn&apos;t match Blink&apos;s behavior exactly, but it meets the requirements I&apos;ve written above.  Currently, it&apos;s the only proposal on the table that meets those requirements.

&gt; Ok. So you&apos;re proposing that xoWin.location != xoWin.location. This isn&apos;t
&gt; what Blink does today (presumably due to your optimization), nor any other
&gt; UA that I know if. It&apos;s not at all obvious to me that this would be
&gt; web-compatible.

I assume you mean !== rather than !=.

&gt; It&apos;s also contrary to the semantics of the web platform, because getters
&gt; aren&apos;t supposed to mint a new JS value each time they&apos;re invoked (you&apos;re
&gt; supposed to use a method if you want to do that).

That sounds like an aesthetic issue.  All things being equal, I&apos;d prefer to follow web aesthetics, but the requirements I&apos;ve written about above are more important to me than aesthetics.  Do you have a more aesthetic counter-proposal that meets the above requirements?

&gt; &gt; &gt; Which prototypes, exactly? In the case of multiple same-origin windows
&gt; &gt; &gt; jointly observing a cross-origin Location object - do they share the same
&gt; &gt; &gt; instance?
&gt; &gt; 
&gt; &gt; Yes.  When I wrote the JavaScript &quot;return this._location&quot;, what that means
&gt; &gt; in JavaScript is that they all get the same instance: the one that&apos;s stored
&gt; &gt; in the (hidden) _location property of the Window object.
&gt; &gt;
&gt; &gt; I feel like I keep repeating myself.
&gt; 
&gt; Probably because you misread my comment. I was asking about the case where
&gt; |A| and |B| are same-origin with each other but not same-origin with |C|.
&gt; The Location object they&apos;re observing is cross-origin.

You&apos;ve trimmed too much context.  I&apos;m not sure what |A|, |B|, and |C| refer to.

&gt; Anyway. Adam has now clarified that his proposal really is to mint a new JS
&gt; object on each call to the location getter from a cross-origin script. This
&gt; provides a clean answer to most of the prototype details, but has two
&gt; glaring issues:
&gt; (1) The behavior with respect to identity comparisons is extremely
&gt; unintuitive and un-web.
&gt; (2) Blink does not actually implement this behavior, and given the == issue,
&gt; it very well may not be web-compatible.

I&apos;m open to other proposals that meet the requirements above.  Do you have one?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94739</commentid>
    <comment_count>77</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-10-15 09:40:01 +0000</bug_when>
    <thetext>(In reply to Adam Barth from comment #76)
&gt; &gt; Ok. So you&apos;re proposing that xoWin.location != xoWin.location. This isn&apos;t
&gt; &gt; what Blink does today (presumably due to your optimization), nor any other
&gt; &gt; UA that I know if. It&apos;s not at all obvious to me that this would be
&gt; &gt; web-compatible.
&gt; 
&gt; I assume you mean !== rather than !=.

Why would it make a difference? Both values are of type |object|, which means that we just do a pointer comparison (Step 1-f in http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3 ).

&gt; I&apos;m open to other proposals that meet the requirements above.  Do you have
&gt; one?

Yes. The original one Hixie proposed in comment 56. You claim that it requires wrappers to implement, but this seems mostly based around the usage of the phrase &quot;act as if&quot;, which carries no semantic value and can certainly be removed if it bothers you.

From what I understand, here&apos;s what it would take to implement it in Blink:
(1) For each origin that is not same-origin with the canonical Location object&apos;s document, create a separate (cached) AlienLocation object. This satisfies the requirement that the design be secure.
2) Make the cross-origin-accessible properties (|replace| and |href|) |own| properties of an AlienLocation object. Freeze the AlienLocation object, the |replace| method, and the |href| setter. Give them all null prototypes. These operations are all implementable in ES5, which satisfies Adam&apos;s second requirement.

(Note that AlienLocation object is purely a theoretical concept. |instanceof Location| will still work, even with the null prototype, because WebIDL overrides instanceof to operate on object branding for DOM objects)

I want to be very clear about two things:

(1) - This proposal explicitly seeks to avoid the need for wrappers. If there are concrete ways in which the proposal requires them in a script-observable way, I consider that a bug and would like them to be pointed out.

(2) - I am not in any way insisting on this proposal. I am totally willing to implement Adam&apos;s proposal, on the condition that the following three things happen:
(A) - We first sort out any bugs in the counter-proposal that would prevent Blink from easily implementing it.
(B) - The spec editors (Hixie, David, Anne, etc) prefer it.
(C) - Blink ships first, thereby doing the leg work of determining whether the proposal is web-compatible.

Adam&apos;s proposal has the advantage that it&apos;s simple to spec, since we don&apos;t have to mess around with freezing and nulling out prototypes and whatnot. This would be a pretty killer argument for it in my mind, except for the fact that we still need to figure out what to do about the prototype chains for cross-origin Windows and their methods/getters/setters. I understand that Adam feels that discussing Window is out-of-scope for this bug. However, we&apos;re eventually going to need to sort out the cross-origin prototype issue for that case as well. So if we go with Adam&apos;s proposal for Location, we should be very sure that we&apos;re not going to have to end up doing the same freeze/null dance for Window.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94740</commentid>
    <comment_count>78</comment_count>
    <who name="David Bruant">bruant.d</who>
    <bug_when>2013-10-15 09:59:06 +0000</bug_when>
    <thetext>(In reply to Adam Barth from comment #76)
&gt; &gt; I don&apos;t have an opinion as to what the spec should require, other than
&gt; &gt; wanting everyone to agree on something and implement it. But I do think that
&gt; &gt; Blink&apos;s current behaviour isn&apos;t intuitive. An object&apos;s identity, heritage,
&gt; &gt; etc, shouldn&apos;t change based merely on how that object is accessed, in a
&gt; &gt; script-detectable fashion. So if the proposal is Blink&apos;s behaviour, I would
&gt; &gt; prefer (maybe slight, I don&apos;t really know) modifications. A concrete
&gt; &gt; proposal in the form of comment 56&apos;s would help a lot.
&gt; 
&gt; I&apos;ve given a concrete proposal several times in the form of a JavaScript
&gt; program.  I can re-write the JavaScript in prose if that would help.  My
&gt; proposal in this thread doesn&apos;t match Blink&apos;s behavior exactly, but it meets
&gt; the requirements I&apos;ve written above.  Currently, it&apos;s the only proposal on
&gt; the table that meets those requirements.
Web-compatibility is an implicit requirement of any proposal and it hasn&apos;t been proven yet.


(In reply to Bobby Holley (:bholley) from comment #77)
&gt; (B) - The spec editors (Hixie, David, Anne, etc) prefer it.
Which David? me? I&apos;m not a spec editor. Just trying to follow along and sending responses mostly to understand what&apos;s going on :-) I care to understand enough in order to be able to document that on MDN (or wherever) eventually, but I don&apos;t think my opinion should be taken into account.


&gt; (C) - Blink ships first, thereby doing the leg work of determining whether
&gt; the proposal is web-compatible.
Yep. Looking forward to Blink feedback ;-)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94741</commentid>
    <comment_count>79</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-10-15 10:18:19 +0000</bug_when>
    <thetext>(In reply to David Bruant from comment #78)
&gt; &gt; (B) - The spec editors (Hixie, David, Anne, etc) prefer it.
&gt; Which David? me? I&apos;m not a spec editor.

Oh, for some reason I thought you were involved with TC39 stuff. Anyway, it doesn&apos;t really matter - I&apos;m just talking about the general community of people that thinks about these sorts of details and what they want it to look like. Adam and I both suffer from the unavoidable bias of living in a given implementation, so more neutral voices are helpful.

But yes, Hixie&apos;s opinion probably matters most. :-)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94744</commentid>
    <comment_count>80</comment_count>
    <who name="David Bruant">bruant.d</who>
    <bug_when>2013-10-15 10:47:56 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #79)
&gt; (In reply to David Bruant from comment #78)
&gt; &gt; &gt; (B) - The spec editors (Hixie, David, Anne, etc) prefer it.
&gt; &gt; Which David? me? I&apos;m not a spec editor.
&gt; 
&gt; Oh, for some reason I thought you were involved with TC39 stuff.
I participate a lot on es-discuss, but that&apos;s where it stops. Of course, after some time now, I&apos;m starting to get a sense of where TC39 is going to (hence my comment on proxies and ES6 and the goal to close the gap between ECMAScript expressiveness and what the platform needs to express).


&gt; Adam and I both suffer from the unavoidable bias of living in a
&gt; given implementation, so more neutral voices are helpful.
I noticed indeed :-) Whenever relevant/possible, I try to carry the voice and point of view of authors based on my experience (I&apos;ve been doing website/apps for the last couple of years now). In that instance, my opinion, as I wrote is:
&quot;this is such a stupid use case with few practical value for authors (from what I understand)&quot;. So, unless another author expresses a different opinion, the priority of constituency suggests that implementors are allowed to fight based on their bias :-)

I&apos;m usually vocal when I feel the needs of implementors is taken too much into account, but I don&apos;t feel this bug is such a case, so I keep it low profile.

But I keep watching just to be sure things don&apos;t leak where that would be inappropriate (for instance, I&apos;m keeping an eye open to see if the decision of this bug will leak to what happens for Window)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94797</commentid>
    <comment_count>81</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-10-15 22:19:32 +0000</bug_when>
    <thetext>I&apos;m happy to spec whatever is going to get implemented in multiple browsers, but I would definitely prefer it if it didn&apos;t have weird behaviour like, in a purely same-origin environment, a Location object having different behaviour for the __proto__ of .toString(), assign(), and replace().


I must admit to not understanding the JS code in comment 66 (the % stuff confuses me, in particular). Since the whole topic is something that is going somewhat over my head in the first place, the idea proposal for me would be one in spec terms, somewhat like the text in comment 56. Also, it would be ideal if the proposal could completely cover how Window works as well, so that we could put the whole topic of cross-origin JS stuff to rest all at once.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94801</commentid>
    <comment_count>82</comment_count>
    <who name="David Bruant">bruant.d</who>
    <bug_when>2013-10-15 22:34:38 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #81)
&gt; I must admit to not understanding the JS code in comment 66 (the % stuff
&gt; confuses me, in particular).
It&apos;s a browser-specific extension. I think V8 started it when self-hosting ECMAScript built-ins. I think it was mostly for performance purposes.
Example: http://code.google.com/p/v8/source/browse/trunk/src/array-iterator.js
At some point, SpiderMonkey started self-hosting too and reused that convention, but I can&apos;t find examples anymore, maybe they removed their use of %
%Something is a function that is only accessible to privileged code.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>94810</commentid>
    <comment_count>83</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-10-16 08:17:20 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #81)
&gt; I&apos;m happy to spec whatever is going to get implemented in multiple browsers

If possible, I want to get at least two proposals on the table that vendors will implement, so as to allow you to exercise some editorial control. Additionally, once Adam and I are satisfied, I&apos;d like to get some input from the Trident folks as well.

&gt; but I would definitely prefer it if it didn&apos;t have weird behaviour like, in
&gt; a purely same-origin environment, a Location object having different
&gt; behaviour for the __proto__ of .toString(), assign(), and replace().

Unless I misunderstand you, I don&apos;t think that proposal is on the table.

&gt; I must admit to not understanding the JS code in comment 66 (the % stuff
&gt; confuses me, in particular). Since the whole topic is something that is
&gt; going somewhat over my head in the first place, the idea proposal for me
&gt; would be one in spec terms, somewhat like the text in comment 56.

Adam&apos;s proposal is that cross-origin callers get a new, unique object from the location getter each time they call it. This solves all the prototype issues (since the object can be created in the scope of whoever did the call), but has the unfortunate behavior that |xoWin.location != xoWin.location|.

&gt; Also, it
&gt; would be ideal if the proposal could completely cover how Window works as
&gt; well, so that we could put the whole topic of cross-origin JS stuff to rest
&gt; all at once.

I absolutely agree.

Adam, can you tell us how you think cross-origin Window access should work? In particular, supposing |A| and |B| are Windows which are same-origin with each other and |C| is a cross-origin Window jointly observed by |A| and |B|, I&apos;m curious about the following things:

(1) Should |A| and |B| observe the same identity for |C|? I&apos;m assuming so, but I want to double-check.

(2) Should |A| and |B| observe the same prototype chain for |C|? If so, where does it lead? Possibilities include A.__proto__, B.__proto__, some unique object, or null.

(3) If the prototype chain isn&apos;t null, does it include the named properties object?

(4) When |A| and |B| grab |C.close|, do they get the same function? In either case, what does the prototype chain of the function look like?


Sorting this out should give us some helpful perspective on the Location issue.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>95405</commentid>
    <comment_count>84</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-10-27 13:50:32 +0000</bug_when>
    <thetext> Adam, do you have an estimate on when you&apos;ll be able to weigh in here? I&apos;d really like to sort this out before it goes stale in all of our heads.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96614</commentid>
    <comment_count>85</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-11-20 23:28:19 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #81)
&gt; I must admit to not understanding the JS code in comment 66 (the % stuff
&gt; confuses me, in particular). Since the whole topic is something that is
&gt; going somewhat over my head in the first place, the idea proposal for me
&gt; would be one in spec terms, somewhat like the text in comment 56.

Sorry, I can re-phrase in spec terms.

When the getter for the location property of a Window object |window| is invoked:

1) If the incumbent settings object specifies an effective script origin that is the same as the Window object&apos;s Document:
  a) Return the real |location| property of |window| and abort these steps.
2) Otherwise, let |activeWindow| be the Window object of the responsible browsing context of the incumbent settings object.
3) Let |location| be a fresh instance of the Location interface associated with |activeWindow|.
4) Associate |location| with |window| (e.g., make it so that setting the href property of |location| acts on |window| rather than on |activeWindow|---not sure what the right spec terminology is for this operation).
5) Return |location|.

(In reply to Bobby Holley (:bholley) from comment #83)
&gt; Adam&apos;s proposal is that cross-origin callers get a new, unique object from
&gt; the location getter each time they call it. This solves all the prototype
&gt; issues (since the object can be created in the scope of whoever did the
&gt; call), but has the unfortunate behavior that |xoWin.location !=
&gt; xoWin.location|.

Correct.  Each get of the location property will hit step (3) above, which means each will get a fresh instance of |activeWindow|&apos;s Location interface.

&gt; Adam, can you tell us how you think cross-origin Window access should work?
&gt; In particular, supposing |A| and |B| are Windows which are same-origin with
&gt; each other and |C| is a cross-origin Window jointly observed by |A| and |B|,
&gt; I&apos;m curious about the following things:
&gt; 
&gt; (1) Should |A| and |B| observe the same identity for |C|? I&apos;m assuming so,
&gt; but I want to double-check.

I don&apos;t really want to talk about Window objects.  They&apos;re a big can of worms.  I&apos;d much rather get the simpler Location object sorted out first.

To answer your question, I do think they should observe the same identity for |C|.

&gt; (2) Should |A| and |B| observe the same prototype chain for |C|? If so,
&gt; where does it lead? Possibilities include A.__proto__, B.__proto__, some
&gt; unique object, or null.

I think getting |C|&apos;s __proto__ property should throw, which means |A| and |B| can&apos;t observe the answer to this question.

&gt; (3) If the prototype chain isn&apos;t null, does it include the named properties
&gt; object?

There&apos;s no way to tell because you can&apos;t get the __proto__ property.

&gt; (4) When |A| and |B| grab |C.close|, do they get the same function?

No.

&gt; In either case, what does the prototype chain of the function look like?

Executing as |A|:

var closeFunc = C.close;
assert closeFunc.__proto__ === Function.prototype
assert closeFunc.__proto__ !== B.Function.prototype

Executing as |B|:

var closeFunc = C.close;
assert closeFunc.__proto__ === Function.prototype
assert closeFunc.__proto__ !== A.Function.prototype
assert A.closeFunc !== closeFunc

&gt; Sorting this out should give us some helpful perspective on the Location
&gt; issue.

I don&apos;t think the Location object should work the same way as the Window object.  The Window object is deeply magic because of WindowProxy.  The Location object, by contrast, doesn&apos;t need any magic for compatibility or security.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96615</commentid>
    <comment_count>86</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-11-20 23:31:53 +0000</bug_when>
    <thetext>I really don&apos;t like having otherWindow.location !== otherWindow.location , or having otherWindow.location !== x where x is otherWindow.location obtained from a script with a different global. That to me seems highly unintuitive and confusing.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96620</commentid>
    <comment_count>87</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-11-21 02:36:00 +0000</bug_when>
    <thetext>Thanks for the input, Adam.

Given the current bug title, both Location and Window are in-scope for discussion.

====== The Window Object ======

To summarize what Adam wants for the Window object:
* The identity of a cross-origin Window object is consistent among all same-origin observers.
* The prototype of a cross-origin Window object is unobservable.
* The functions returned from property look-ups on the Window object have prototype chains leading to the Function.prototype associated with the incumbent script performing the look-up.

This is roughly consistent with what Gecko does, which is great.

Adam, can you clarify the following points?
* Are all properties on a cross-origin Window object reported as |own|? Presumably they should be, if the prototype is unobservable.
* Can we just make the prototype of cross-origin Window objects null, or is it important for Blink that we actually throw? Naively, it seems like whatever code does the throwing could equally just lie to the caller and return null. We could probably do either in Gecko, so I&apos;d like to clarify which options are on the table.
* In the example from comment 83, what is the result of executing |C.close == C.close|? is the value cached, or minted afresh each time? We cache it in Gecko.


====== The Location Object ======

The Location object appears to be the bigger source of disagreement. In Gecko, we handle all cross-origin objects with the same code, so we&apos;d have the same behavior for Location as we&apos;d have for Window. This code is general, so it doesn&apos;t cost us anything extra.

In Blink, it sounds like it&apos;s a different story. The machinery there is specific to Window, and does not generalize as easily. This is why Adam wants to mint a new Location object on each access (so xoWin.location != xoWin.location). From here on, let&apos;s refer to Adam&apos;s proposal as &quot;Minting&quot;.

Here are the various stakes, as I see them:
* Implementing Location similarly to Window would be a lot of work in Blink.
* Implementing Location similarly to Window is the default in Gecko. Doing otherwise requires nontrivial work, though perhaps not as much as the aforementioned work in Blink.
* Given that we already have to spec Window, speccing Minting for Location does not simplify the spec. It complicates it, though not by very much, because Minting itself is simple to spec.
* Speccing Minting for the Location object leads to very confusing and potentially-foot-gun semantics, which Hixie outlines in comment 86.
* Blink does not currently implement Minting, nor does any other UA. So we don&apos;t know if it&apos;s web compatible. I&apos;m personally concerned that it may not be, given the breakage of equality comparisons.

Did I miss anything?

Hixie, what&apos;s the next step here? Should we get input from Microsoft? I know they don&apos;t participate in the WHATWG, but this is probably important enough that we should talk to them about it at some point.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96647</commentid>
    <comment_count>88</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-11-21 19:16:32 +0000</bug_when>
    <thetext>Getting input from Microsoft would be great; I didn&apos;t realise they weren&apos;t cc&apos;ed.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96651</commentid>
    <comment_count>89</comment_count>
    <who name="Travis Leithead [MSFT]">travil</who>
    <bug_when>2013-11-21 19:29:13 +0000</bug_when>
    <thetext>Oh man, thrown into the fire. I&apos;ll try to catch up and provide some useful feedback...</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96667</commentid>
    <comment_count>90</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-11-21 22:38:54 +0000</bug_when>
    <thetext>(In reply to Travis Leithead [MSFT] from comment #89)
&gt; Oh man, thrown into the fire. I&apos;ll try to catch up and provide some useful
&gt; feedback...

Yeah, reading this bug in its entirety is going to tie your brain into a pretzel. I&apos;d suggest starting with comment 87, and searching back for more context when necessary.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96683</commentid>
    <comment_count>91</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-11-22 02:02:32 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #87)
&gt; Adam, can you clarify the following points?
&gt; * Are all properties on a cross-origin Window object reported as |own|?
&gt; Presumably they should be, if the prototype is unobservable.

What APIs can to call to tell?  Without testing, I&apos;d recommend having any ways of observing the answer to that question throw exceptions.

&gt; * Can we just make the prototype of cross-origin Window objects null, or is
&gt; it important for Blink that we actually throw? Naively, it seems like
&gt; whatever code does the throwing could equally just lie to the caller and
&gt; return null. We could probably do either in Gecko, so I&apos;d like to clarify
&gt; which options are on the table.

What benefit is there in returning null?  If we return null, folks could start depending on that behavior.  If we throw, it&apos;s harder to add dependencies.  It&apos;s not impossible, of course, but it&apos;s harder.

&gt; * In the example from comment 83, what is the result of executing |C.close
&gt; == C.close|? is the value cached, or minted afresh each time? We cache it in
&gt; Gecko.

The value appears to be cached in Blink as well, but I couldn&apos;t find the mechanism that caches it, which makes me worry that there&apos;s some hidden detail I don&apos;t fully understand.

&gt; ====== The Location Object ======
&gt; 
&gt; The Location object appears to be the bigger source of disagreement. In
&gt; Gecko, we handle all cross-origin objects with the same code, so we&apos;d have
&gt; the same behavior for Location as we&apos;d have for Window. This code is
&gt; general, so it doesn&apos;t cost us anything extra.

You seem happy with the minting approach for |close|.  I&apos;m just suggesting that we use minting for |location| as well.  You seem to already be using both approaches in Gecko.  Is there some reason minting is ok for |close| but not for |location|?

&gt; In Blink, it sounds like it&apos;s a different story. The machinery there is
&gt; specific to Window, and does not generalize as easily.

It&apos;s just that there&apos;s a big pile of Window-specific machinery.

&gt; This is why Adam
&gt; wants to mint a new Location object on each access (so xoWin.location !=
&gt; xoWin.location). From here on, let&apos;s refer to Adam&apos;s proposal as &quot;Minting&quot;.

Do you agree that window.close also uses the &quot;minting&quot; approach?  Maybe there&apos;s some subtle distinction I&apos;m missing.

&gt; Here are the various stakes, as I see them:
&gt; * Implementing Location similarly to Window would be a lot of work in Blink.
&gt; * Implementing Location similarly to Window is the default in Gecko. Doing
&gt; otherwise requires nontrivial work, though perhaps not as much as the
&gt; aforementioned work in Blink.

Why does it require any more work than what you&apos;ve already implemented for window.close?

&gt; * Given that we already have to spec Window, speccing Minting for Location
&gt; does not simplify the spec. It complicates it, though not by very much,
&gt; because Minting itself is simple to spec.

Don&apos;t we need to spec minting already for |close|?

&gt; * Speccing Minting for the Location object leads to very confusing and
&gt; potentially-foot-gun semantics, which Hixie outlines in comment 86.

Why doesn&apos;t using minting for |close| cause the same confusion?

&gt; * Blink does not currently implement Minting, nor does any other UA. So we
&gt; don&apos;t know if it&apos;s web compatible. I&apos;m personally concerned that it may not
&gt; be, given the breakage of equality comparisons.

My proposal is what we do internally for Location.  We just throw a bunch of exceptions to try to make it hard to observe what we&apos;re doing.  We can spec throwing those exceptions if you want something that works exactly like an existing implementation.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96685</commentid>
    <comment_count>92</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-11-22 06:11:39 +0000</bug_when>
    <thetext>(In reply to Adam Barth from comment #91)
&gt; &gt; * Are all properties on a cross-origin Window object reported as |own|?
&gt; &gt; Presumably they should be, if the prototype is unobservable.
&gt; 
&gt; What APIs can to call to tell?  Without testing, I&apos;d recommend having any
&gt; ways of observing the answer to that question throw exceptions.

Object.getOwnPropertyDescriptor. Unless we want to declare war on TC39, that has to work.
 
&gt; &gt; * Can we just make the prototype of cross-origin Window objects null, or is
&gt; &gt; it important for Blink that we actually throw? Naively, it seems like
&gt; &gt; whatever code does the throwing could equally just lie to the caller and
&gt; &gt; return null. We could probably do either in Gecko, so I&apos;d like to clarify
&gt; &gt; which options are on the table.
&gt; 
&gt; What benefit is there in returning null?  If we return null, folks could
&gt; start depending on that behavior.  If we throw, it&apos;s harder to add
&gt; dependencies.  It&apos;s not impossible, of course, but it&apos;s harder.

The whole point of speccing it is to allow people to depend on it.

I don&apos;t really have an opinion on it. I just want to help Hixie clearly distinguish between actual implementor constraints with the aesthetic opinions of those implementors.

&gt; &gt; ====== The Location Object ======

&gt; You seem happy with the minting approach for |close|.  I&apos;m just suggesting
&gt; that we use minting for |location| as well.  You seem to already be using
&gt; both approaches in Gecko.  Is there some reason minting is ok for |close|
&gt; but not for |location|?

&gt; Do you agree that window.close also uses the &quot;minting&quot; approach?  Maybe
&gt; there&apos;s some subtle distinction I&apos;m missing.

Conceptually, I think functions and DOM objects are very different beasts. But more importantly, there _is_ a subtle distinction - whether or not the value is cached, and how that happens (i.e. whether window.close === window.close).

&gt; Why does it require any more work than what you&apos;ve already implemented for
&gt; window.close?

Because Gecko treats functions and WebIDL objects quite differently.

&gt; &gt; * Speccing Minting for the Location object leads to very confusing and
&gt; &gt; potentially-foot-gun semantics, which Hixie outlines in comment 86.
&gt; 
&gt; Why doesn&apos;t using minting for |close| cause the same confusion?

Because people are much less likely to do equality comparisons of window.close than they are to on window.location. Moreover: the caching issue.

&gt; &gt; * Blink does not currently implement Minting, nor does any other UA. So we
&gt; &gt; don&apos;t know if it&apos;s web compatible. I&apos;m personally concerned that it may not
&gt; &gt; be, given the breakage of equality comparisons.
&gt; 
&gt; My proposal is what we do internally for Location.  We just throw a bunch of
&gt; exceptions to try to make it hard to observe what we&apos;re doing.  We can spec
&gt; throwing those exceptions if you want something that works exactly like an
&gt; existing implementation.

No. My point is that, in Chrome today, |xoWin.location === xoWin.location|. Therefore, Chrome does not implement the most controversial aspect of Minting as it has been proposed.


So maybe we should modify the minting proposal for Location by adding caching? In particular, what if we specced that the |location| getter on cross-origin Window objects minted a brand new Location object, _but_ that object was cached for all incumbent scripts that share a given script settings object. This gets us |xoWin.location === xoWin.location|, even though two collaborating same-origin iframes could still detect that they receive different results.

I&apos;m not really wild about this proposal, but it seems like it&apos;s probably more likely to get us interop than anything that&apos;s been proposed so far. Indeed, I&apos;d guess that this is probably what Blink does today (even though the source of the caching is a bit of a mystery according to Adam).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96696</commentid>
    <comment_count>93</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-11-22 17:06:50 +0000</bug_when>
    <thetext>&gt; What APIs can to call to tell?

Object.getOwnPropertyDescriptor is the obvious one.

Object.defineProperty would be another, if there is ever a situation in which _setting_ a non-unforgeable property on a cross-origin window is allowed.  I&apos;m not sure whether there are such cases.

Object.getOwnPropertyNames is another one.

We may in fact be able to make these throw as desired, I suspect, if WindowProxy is very carefully specced as something akin to an ES proxy and all of its hooks are very carefully defined (e.g. the get() and set() hooks need to work even if getOwnPropertyDescriptor() throws).  I strongly suggest checking with the TC39 folks and the various JS engine implementors whether this sort of thing is possible.

The result would be pretty fragile, though, especially as changes happen to the ES specification in terms of how the MOP works.  It&apos;s also not obvious to me how web-compatible such a change would be at this point, unless UAs already throw for this stuff.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96700</commentid>
    <comment_count>94</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-11-22 18:02:05 +0000</bug_when>
    <thetext>FWIW, I really think we should maintain x.close === x.close (and x.close === y, where y is x.close from another same-origin or similar-origin context). The idea that you could, in one script, have two objects that don&apos;t have the same identity but that actually are the same object is really weird and unintuitive.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96702</commentid>
    <comment_count>95</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-11-22 18:06:34 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #94)
&gt; FWIW, I really think we should maintain x.close === x.close

Yes, this is covered by &quot;minting with caching&quot;.

&gt; (and x.close === y, where y is x.close from another same-origin or
&gt; similar-origin context).

This is not covered by minting with caching. Doing it correctly is going to be very hard (both for Gecko and Blink).

&gt; The idea that you could, in one script, have two objects that don&apos;t have the
&gt; same identity but that actually are the same object is really weird and
&gt; unintuitive.

Yes. But we have to consider the likelihood of confusion. I think at least  90% of the pain is covered by the |x.close === x.close| case as opposed to the |x.close === y| case.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96741</commentid>
    <comment_count>96</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-11-23 02:55:01 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #92)
&gt; Object.getOwnPropertyDescriptor. Unless we want to declare war on TC39, that
&gt; has to work.

Looks like Blink currently returns undefined, which seems like plausible solution.

&gt; &gt; What benefit is there in returning null?  If we return null, folks could
&gt; &gt; start depending on that behavior.  If we throw, it&apos;s harder to add
&gt; &gt; dependencies.  It&apos;s not impossible, of course, but it&apos;s harder.
&gt; 
&gt; The whole point of speccing it is to allow people to depend on it.

I don&apos;t want people to depend on it.  We might want to change it in the future.  The fewer dependencies people have on these crazy corner cases, the better.

&gt; I don&apos;t really have an opinion on it. I just want to help Hixie clearly
&gt; distinguish between actual implementor constraints with the aesthetic
&gt; opinions of those implementors.

This falls more into the aesthetic camp.

&gt; Conceptually, I think functions and DOM objects are very different beasts.

Why?  That seems like an odd distinction.  Maybe there&apos;s some implementation reason for that in Gecko, but in Blink they&apos;re just part-and-parcel.

&gt; But more importantly, there _is_ a subtle distinction - whether or not the
&gt; value is cached, and how that happens (i.e. whether window.close ===
&gt; window.close).

Ok, if caching is a big deal for you, we can add caching to the proposal.  We just need to make sure that everyone who gets the same object out of the cache is in the same origin.

&gt; &gt; Why does it require any more work than what you&apos;ve already implemented for
&gt; &gt; window.close?
&gt; 
&gt; Because Gecko treats functions and WebIDL objects quite differently.

That&apos;s unfortunate.  :(

&gt; &gt; &gt; * Speccing Minting for the Location object leads to very confusing and
&gt; &gt; &gt; potentially-foot-gun semantics, which Hixie outlines in comment 86.
&gt; &gt; 
&gt; &gt; Why doesn&apos;t using minting for |close| cause the same confusion?
&gt; 
&gt; Because people are much less likely to do equality comparisons of
&gt; window.close than they are to on window.location. Moreover: the caching
&gt; issue.

So, would minting+caching work for you as a solution?  We&apos;d still need to work out the details of when you get a cache hit and when you need to mint a new object, but if the general approach works for you, we can probably work out the details.

&gt; So maybe we should modify the minting proposal for Location by adding
&gt; caching?

Sure, I&apos;m happy to explore that idea.  My only hard requirement is the one I wrote above, which is that no single object is exposed to more than one origin.

Aesthetically, it would also be nice if the properties of the object you see aren&apos;t history-dependent.  For example, we&apos;d probably want to null out or throw when getting the __proto__ property so that the cached object doesn&apos;t have an obvious &quot;home&quot; global object.

Unlike in the proxy approach, these details aren&apos;t security-critical.  They&apos;re just for developer sanity.

&gt; In particular, what if we specced that the |location| getter on
&gt; cross-origin Window objects minted a brand new Location object, _but_ that
&gt; object was cached for all incumbent scripts that share a given script
&gt; settings object. This gets us |xoWin.location === xoWin.location|, even
&gt; though two collaborating same-origin iframes could still detect that they
&gt; receive different results.

That&apos;s fine, but I would like to make the design history-independent.  Specifically, if a script reads xoWin.location, there should be no observables which would let it determine that another script had previously read that same property.

&gt; I&apos;m not really wild about this proposal, but it seems like it&apos;s probably
&gt; more likely to get us interop than anything that&apos;s been proposed so far.

The best signs of a good compromise.  :)

&gt; Indeed, I&apos;d guess that this is probably what Blink does today (even though
&gt; the source of the caching is a bit of a mystery according to Adam).

It&apos;s more likely that we just lie about ===, but I&apos;d have to dig into the implementation to either find the === lie or the cache.  I haven&apos;t been able to find either yet.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96748</commentid>
    <comment_count>97</comment_count>
    <who name="David Bruant">bruant.d</who>
    <bug_when>2013-11-23 17:24:06 +0000</bug_when>
    <thetext>(In reply to Boris Zbarsky from comment #93)
&gt; &gt; What APIs can to call to tell?
&gt; 
&gt; Object.getOwnPropertyDescriptor is the obvious one.
&gt; 
&gt; Object.defineProperty would be another, if there is ever a situation in
&gt; which _setting_ a non-unforgeable property on a cross-origin window is
&gt; allowed.  I&apos;m not sure whether there are such cases.
&gt; 
&gt; Object.getOwnPropertyNames is another one.
&gt; 
&gt; We may in fact be able to make these throw as desired, I suspect, if
&gt; WindowProxy is very carefully specced as something akin to an ES proxy and
&gt; all of its hooks are very carefully defined (e.g. the get() and set() hooks
&gt; need to work even if getOwnPropertyDescriptor() throws).  I strongly suggest
&gt; checking with the TC39 folks and the various JS engine implementors whether
&gt; this sort of thing is possible.
I&apos;m not TC39 and don&apos;t carry an implementor POV, but from what I know of ES proxies, this is possible indeed. One thing to be extra careful about when spec&apos;ing the traps (which you call &quot;hooks&quot;) is respecting &quot;eternal invariants&quot;
https://mail.mozilla.org/pipermail/es-discuss/2011-May/014150.html
These are enforced by proxies at runtime by throwing errors. My personal recommendation to be sure to get that part right would be to write code first with ES proxies to see if what&apos;s planned as spec is actually something allowed in the language. To my knowledge, the most up-to-date implementation of ES proxies (&quot;direct proxies&quot;) is this library (by Tom Van Cutsem, one of the TC39-ers champion of ES proxies) https://github.com/tvcutsem/harmony-reflect


&gt; The result would be pretty fragile, though, especially as changes happen to
&gt; the ES specification in terms of how the MOP works.
I feel that spec&apos;ing ES proxies will freeze how the MOP works and changes there are very unlikely to happen. In lots of occasions, discussions of the ES proxies design led to MOP discussions (which I take as a sign that the MOP needed to be nailed down and robust before the freeze that proxies would cause). But that&apos;s just a feeling.

&gt; It&apos;s also not obvious
&gt; to me how web-compatible such a change would be at this point, unless UAs
&gt; already throw for this stuff.
Since IE8 is very much around, I doubt Object.getOwnPropertyDescriptor/defineProperty/getOwnPropertyNames are being used too much. But mobile web is rising and has these.
At the same time, web browsers have been very inconsistent in how they expose the global object, so I also doubt people are playing around too much with ES5 introspection function on the global object. The web may prove me wrong, of course.

(In reply to Adam Barth from comment #96)
&gt; (In reply to Bobby Holley (:bholley) from comment #92)
&gt; &gt; Object.getOwnPropertyDescriptor. Unless we want to declare war on TC39, that
&gt; &gt; has to work.
&gt; 
&gt; Looks like Blink currently returns undefined, which seems like plausible
&gt; solution.
I&apos;m willing to bet that *at least* one of these undefined breaks one of the &quot;eternal invariants&quot;. For why these invariants are important, either write to Mark Miller directly or ask on es-discuss.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96797</commentid>
    <comment_count>98</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-11-25 18:41:00 +0000</bug_when>
    <thetext>I don&apos;t understand why it has to be difficult to return the same object for the same attribute regardless of who gives it. Why can&apos;t we just have the attributes and methods and setters and getters check the identity of the script and act accordingly, rather than having multiple objects going around?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96804</commentid>
    <comment_count>99</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-11-25 19:45:27 +0000</bug_when>
    <thetext>(In reply to Adam Barth from comment #96)

&gt; Sure, I&apos;m happy to explore that idea.  My only hard requirement is the one I
&gt; wrote above, which is that no single object is exposed to more than one
&gt; origin.
&gt; 
&gt; Aesthetically, it would also be nice if the properties of the object you see
&gt; aren&apos;t history-dependent.  For example, we&apos;d probably want to null out or
&gt; throw when getting the __proto__ property so that the cached object doesn&apos;t
&gt; have an obvious &quot;home&quot; global object.

I don&apos;t understand the issue here. If the cache is per-incumbent-script-settings-object (per-global), the cached object very much has a &quot;home&quot; global object.

If the idea is that the cache is per-origin, and the particular global is unobservable due to null prototypes and whatnot, then this is starting to sound very much like the original &quot;alien object&quot; proposal.

&gt; That&apos;s fine, but I would like to make the design history-independent. 
&gt; Specifically, if a script reads xoWin.location, there should be no
&gt; observables which would let it determine that another script had previously
&gt; read that same property.

Yes, minting-with-caching has this property.

&gt; &gt; Indeed, I&apos;d guess that this is probably what Blink does today (even though
&gt; &gt; the source of the caching is a bit of a mystery according to Adam).
&gt; 
&gt; It&apos;s more likely that we just lie about ===, but I&apos;d have to dig into the
&gt; implementation to either find the === lie or the cache.  I haven&apos;t been able
&gt; to find either yet.

Oh, interesting. I don&apos;t think lying about === would be acceptable in Gecko, but if the spec can be implemented either way then that&apos;s fine too.

(In reply to Ian &apos;Hixie&apos; Hickson from comment #98)
&gt; I don&apos;t understand why it has to be difficult to return the same object for
&gt; the same attribute regardless of who gives it. Why can&apos;t we just have the
&gt; attributes and methods and setters and getters check the identity of the
&gt; script and act accordingly, rather than having multiple objects going around?

Are you referring to single-object-per-origin, or single-object-period?

The former requires neutering the object in such a way that its &quot;home&quot; global is unobservable (i.e. alien objects). The latter violates the &quot;hard requirement&quot; that Adam gives in comment 96.

The third option is minting-with-caching. We could probably do any of the three in Gecko with varying amounts of work, but I&apos;d want to do a final deep-dive before irrevocably signing off on any of them.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96849</commentid>
    <comment_count>100</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-11-26 20:14:17 +0000</bug_when>
    <thetext>&gt; Are you referring to single-object-per-origin, or single-object-period?

single-object-period.


&gt; The former requires neutering the object in such a way that its &quot;home&quot;
&gt; global is unobservable (i.e. alien objects).

Why? Can&apos;t we just return a different proto depending on who looks, just like we do for everything else?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96855</commentid>
    <comment_count>101</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-11-27 00:34:17 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #100)
&gt; &gt; Are you referring to single-object-per-origin, or single-object-period?
&gt; 
&gt; single-object-period.

Ok. I&apos;ll let you take that up with Adam then.

&gt; &gt; The former requires neutering the object in such a way that its &quot;home&quot;
&gt; &gt; global is unobservable (i.e. alien objects).
&gt; 
&gt; Why? Can&apos;t we just return a different proto depending on who looks, just
&gt; like we do for everything else?

What is &quot;everything else&quot; here?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>96894</commentid>
    <comment_count>102</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-11-27 23:51:31 +0000</bug_when>
    <thetext>&gt; &gt; Why? Can&apos;t we just return a different proto depending on who looks, just
&gt; &gt; like we do for everything else?
&gt; 
&gt; What is &quot;everything else&quot; here?

I meant just like we&apos;d return a different value (or throw instead of returning a value) for attributes and methods.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97134</commentid>
    <comment_count>103</comment_count>
    <who name="Adam Barth">w3c</who>
    <bug_when>2013-12-04 17:10:31 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #98)
&gt; I don&apos;t understand why it has to be difficult to return the same object for
&gt; the same attribute regardless of who gives it. Why can&apos;t we just have the
&gt; attributes and methods and setters and getters check the identity of the
&gt; script and act accordingly, rather than having multiple objects going around?

Because it&apos;s too difficult to implement that securely.  The bugs are subtle and when they occur, the result is universal XSS.  That&apos;s not a risk I&apos;m willing to take.

(In reply to Bobby Holley (:bholley) from comment #99)
&gt; I don&apos;t understand the issue here. If the cache is
&gt; per-incumbent-script-settings-object (per-global), the cached object very
&gt; much has a &quot;home&quot; global object.

Ok, we can make it per-global.

&gt; If the idea is that the cache is per-origin, and the particular global is
&gt; unobservable due to null prototypes and whatnot, then this is starting to
&gt; sound very much like the original &quot;alien object&quot; proposal.

The difference is that these tweaks aren&apos;t required for security.  They&apos;re just for aesthetics.  If we go with per-global, then we can skip them.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97192</commentid>
    <comment_count>104</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-12-05 18:21:39 +0000</bug_when>
    <thetext>Window already has the same object across origins, right?
Why is it ok for Window but not Location?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97225</commentid>
    <comment_count>105</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-12-06 00:21:51 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #104)
&gt; Window already has the same object across origins, right?
&gt; Why is it ok for Window but not Location?

Adam&apos;s claim is that Window is special-cased up the wazoo in Blink and he doesn&apos;t want to duplicate all the special-casing for Location.


(In reply to Adam Barth from comment #103)
&gt; &gt; this is starting to
&gt; &gt; sound very much like the original &quot;alien object&quot; proposal.
&gt; 
&gt; The difference is that these tweaks aren&apos;t required for security.  They&apos;re
&gt; just for aesthetics.

By &quot;aesthetics&quot;, do  you mean &quot;providing speccable behavior that doesn&apos;t depend on the order in which different scripts access different properties&quot;? If so, then those bits (in comment 56) were always for aesthetics.

Does clearing that up change your willingness to implement Alien Objects? If so, what are the important differences between Alien Objects and your proposal in comment 96?

&gt; If we go with per-global, then we can skip them.

Yes.

If I understand correctly, there are now two proposals on the table that Adam would consider implementing:

(1) One Location object per (accessing script origin, target Window) pair, with the appropriate bits neutered to make the &quot;home global&quot; of that Location object unobservable.

(2) One Location object per (accessing script global, target Window) pair. No neutering needs to be done.

Approach (2) makes identity issues observable, but only between same-origin scripts jointly observing a cross-origin Window. Approach (1) fixes the identity issues, at the cost of some amount of funky neutering.

Did I get all that right?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97265</commentid>
    <comment_count>106</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-12-06 18:57:09 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #105)
&gt; (In reply to Ian &apos;Hixie&apos; Hickson from comment #104)
&gt; &gt; Window already has the same object across origins, right?
&gt; &gt; Why is it ok for Window but not Location?
&gt; 
&gt; Adam&apos;s claim is that Window is special-cased up the wazoo in Blink and he
&gt; doesn&apos;t want to duplicate all the special-casing for Location.

If it&apos;s safe enough for Window, I don&apos;t understand why it wouldn&apos;t be safe enough for Location. This isn&apos;t a slippery slope, we&apos;re talking about exactly two objects here, down from four originally; we&apos;ve been trimming this down as much as possible. It&apos;s not like we&apos;ll ever add new objects. I understand that it probably wouldn&apos;t be pretty code.


&gt; (1) One Location object per (accessing script origin, target Window) pair,
&gt; with the appropriate bits neutered to make the &quot;home global&quot; of that
&gt; Location object unobservable.

So the &quot;===&quot; operator would return true? They either wouldn&apos;t have, or would share, custom properties? Prototypes on their members wouldn&apos;t be visible?

In what sense are they different objects, then, other than as an implementation detail? I&apos;m not really understanding this proposal in detail.


&gt; (2) One Location object per (accessing script global, target Window) pair.

Obviously I don&apos;t get a veto here, but if I did, I would want to veto anything that involves the accessing script global controlling the identity of objects returned from an attribute getter.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97267</commentid>
    <comment_count>107</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-12-06 20:34:18 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #106)
&gt; (In reply to Bobby Holley (:bholley) from comment #105)
&gt; &gt; (In reply to Ian &apos;Hixie&apos; Hickson from comment #104)
&gt; &gt; &gt; Window already has the same object across origins, right?
&gt; &gt; &gt; Why is it ok for Window but not Location?
&gt; &gt; 
&gt; &gt; Adam&apos;s claim is that Window is special-cased up the wazoo in Blink and he
&gt; &gt; doesn&apos;t want to duplicate all the special-casing for Location.
&gt; 
&gt; If it&apos;s safe enough for Window, I don&apos;t understand why it wouldn&apos;t be safe
&gt; enough for Location. This isn&apos;t a slippery slope, we&apos;re talking about
&gt; exactly two objects here, down from four originally; we&apos;ve been trimming
&gt; this down as much as possible. It&apos;s not like we&apos;ll ever add new objects. I
&gt; understand that it probably wouldn&apos;t be pretty code.

I&apos;ll leave that between you and Adam. It would be good to get Travis&apos; input too.

&gt; &gt; (1) One Location object per (accessing script origin, target Window) pair,
&gt; &gt; with the appropriate bits neutered to make the &quot;home global&quot; of that
&gt; &gt; Location object unobservable.
&gt; 
&gt; So the &quot;===&quot; operator would return true?

Yes. There would only be one object for any set of same-origin scripts. Though what would we do for document.domain?

&gt; They either wouldn&apos;t have, or would
&gt; share, custom properties? Prototypes on their members wouldn&apos;t be visible?
&gt; 
&gt; In what sense are they different objects, then, other than as an
&gt; implementation detail? I&apos;m not really understanding this proposal in detail.

I don&apos;t really grok what you mean by &quot;They&quot; here. The proposal is just to spec that there is a unique object per origin. The difference between this and &quot;one object&quot; isn&apos;t really observable modulo document.domain (and as noted, I&apos;m not sure what we would do there). In Gecko, we&apos;d implement this by just doing &quot;one object&quot; and giving cross-origin consumers XrayWrappers to it.

&gt; &gt; (2) One Location object per (accessing script global, target Window) pair.

&gt; Obviously I don&apos;t get a veto here, but if I did, I would want to veto
&gt; anything that involves the accessing script global controlling the identity
&gt; of objects returned from an attribute getter.

That&apos;s good to know.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97271</commentid>
    <comment_count>108</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-12-06 22:31:23 +0000</bug_when>
    <thetext>Oh, I see. I missed the difference between &quot;accessing script origin&quot; and &quot;accessing script global&quot;. Making it dependent on the accessing script _origin_ is something I think would be fine — as you say, it&apos;s not distinguishable from there being one object. Except, also as you say, with document.domain. But I&apos;m happy to throw document.domain under the bus here. I guess we&apos;d return a different object per effective script origin, such that:

   var L1 = location;
   document.domain = slightlyDifferentDomain;
   var L2 = location;
   // L1 !== L2

Assuming that&apos;s not Web-incompatible, I&apos;m fine with it.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97280</commentid>
    <comment_count>109</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-12-07 02:06:42 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #108)
&gt; Oh, I see. I missed the difference between &quot;accessing script origin&quot; and
&gt; &quot;accessing script global&quot;. Making it dependent on the accessing script
&gt; _origin_ is something I think would be fine — as you say, it&apos;s not
&gt; distinguishable from there being one object. Except, also as you say, with
&gt; document.domain. But I&apos;m happy to throw document.domain under the bus here.
&gt; I guess we&apos;d return a different object per effective script origin, such
&gt; that:
&gt; 
&gt;    var L1 = location;
&gt;    document.domain = slightlyDifferentDomain;
&gt;    var L2 = location;
&gt;    // L1 !== L2

Well, that&apos;s the kicker. In Gecko, we&apos;d actually be implementing Location just like Window (as you suggest, in comment 104), since the difference is (almost) unobservable. So in the document.domain case, they&apos;d compare equal for us. We don&apos;t have a good way of making them compare not equal.

If we go with this approach, the location-identity-after-document-domain issue is going to be as maddening to solve (for whoever lands on the wrong side of the spec) as it is silly.

So in short, I would not be ok with speccing L1 !== L2 as you propose. Whether that scuttles this whole proposal, I don&apos;t know.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97343</commentid>
    <comment_count>110</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-12-09 18:28:42 +0000</bug_when>
    <thetext>Doesn&apos;t Gecko&apos;s security model mean you couldn&apos;t actually compare L1 and L2 anyway? I thought you were ignoring the spec&apos;s model and using a different one where document.domain prevents you from accessing objects from earlier or something.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97344</commentid>
    <comment_count>111</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2013-12-09 18:32:02 +0000</bug_when>
    <thetext>We revoke no-longer-same-origin objects, so that basically all MOP operations on them throw.

But == and === don&apos;t invoke a MOP operation when comparing objects; they&apos;re done directly without asking the object anything.  So they can still be performed, even on objects you otherwise have no access to, as long as you have a reference to them.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97347</commentid>
    <comment_count>112</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-12-09 19:23:37 +0000</bug_when>
    <thetext>What Boris says is true. But the issue is actually deeper than that.

Suppose we have the following scopes:
A: a.foo.com
B: b.foo.com
C: bar.org

Imagine that A and B both grab a reference to C.location, which is a cross-origin Location object. Then, they each set document.domain to |foo.com| so that they can collaborate with each other. They each have independent and valid cross-origin references to C.location. At this point, the identity issue becomes observable.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97348</commentid>
    <comment_count>113</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-12-09 20:59:21 +0000</bug_when>
    <thetext>So the problem is that you (Gecko) want to return the same object, rather than one per origin? Why not just return one per origin?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97352</commentid>
    <comment_count>114</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-12-09 21:11:46 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #113)
&gt; So the problem is that you (Gecko) want to return the same object, rather
&gt; than one per origin? Why not just return one per origin?

Because then we have to deal with the nastiness of where that object actually lives - i.e. in which global&apos;s scope. Creating a special global per-origin to hold this thing is a non-starter memory-wise. And if we just put it in the scope of whichever global happens to access it first, we have to figure out what to do if _that_ global&apos;s script does document.domain. Yuck.

My top preference would be for us to just continue using one Location object, like we do now. Whether we spec that explicitly or just spec something that allows us to do that under the hood isn&apos;t so much of a concern for me.

If we can&apos;t do that, the only remaining option that I can think of is to have the identity of a cross-origin Location object depend on the incumbent global when the access happens (the idea that you said merited your veto).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97536</commentid>
    <comment_count>115</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2013-12-12 21:20:52 +0000</bug_when>
    <thetext>If we can get the one-object and multiple-object cases to be indistinguishable (notwithstanding document.domain), then let&apos;s go with that. It seems to be the option that everyone can implement. (Or at least, everyone who&apos;s commented.)

Anyone want to try to describe that in the style of comment 56?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97551</commentid>
    <comment_count>116</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-12-12 23:29:39 +0000</bug_when>
    <thetext>Just spoke with Ian and Adam. We&apos;re going to meet up at Google SF next friday (the 20th) to hash this out. If anyone wants to join or has any input before then, please speak up.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97571</commentid>
    <comment_count>117</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-12-13 03:08:29 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #115)
&gt; If we can get the one-object and multiple-object cases to be
&gt; indistinguishable (notwithstanding document.domain), then let&apos;s go with
&gt; that. It seems to be the option that everyone can implement. (Or at least,
&gt; everyone who&apos;s commented.)

I just got some feedback from Boris about this, and he&apos;s very skeptical of trying to make the home global of methods unobservable. His points:

(1) Nulling out prototypes means that you lose apply(), bind(), call(), toString(), etc, unless we manually copy all of those down, which is more work.

(2) This approach, in his view, is doomed by TC39&apos;s realm work, in which mechanisms to access the Realm of an object are quickly proliferating. It would basically result in a game of spec whack-a-mole in which HTML5 would need to enumerate all the things that would have to throw for alien objects. All in all, very fragile.

(3) This approach wouldn&apos;t work for window, because you can just invoke a window method with an undefined |this|, and it will operate on its global, at which point it&apos;s generally possible to exfiltrate information.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>97572</commentid>
    <comment_count>118</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2013-12-13 03:10:13 +0000</bug_when>
    <thetext>Also, we should make every effort to get some idea of Trident&apos;s setup before next friday. Travis, can you describe your setup a bit? It would be massively beneficial.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>98036</commentid>
    <comment_count>119</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-01-06 19:29:46 +0000</bug_when>
    <thetext>Here&apos;s what we concluded at the meeting, based on my notes:

- Window and Location objects represent a concept. In the case of Window it&apos;s
  the set of APIs associated with a Document in a browsing context; in the case
  of Location it&apos;s the set of APIs relating to that document&apos;s URL and
  navigating that document&apos;s browsing context.

- When a script from one origin tries to get a Window or Location object
  representing a concept from another origin, it gets an instance of that object 
  that is specially minted for that origin. If that origin is not the same 
  origin as the origin of the Document for which the underlying concept exists, 
  then the object is known as a &quot;non-native object&quot;.

- The === operator, when applied to two Window or Location objects representing 
  the same underlying concept, returns true.

- Location object properties defined in WebIDL cannot be changed.

- Non-native Window and Location objects refuse new properties (maybe they are 
  frozen? We weren&apos;t quite sure what that implied.)

- Object.getPrototypeOf() when applied to non-native Window and Location objects
  returns null.

- Non-native objects&apos; properties fall into two buckets, whitelisted and not 
  whitelisted (the lists are in the spec today).

- When you get a property on a non-native object that is not whitelisted, it 
  throws a SecurityError.

- When you get a property on a non-native object that is a function, it returns
  a Function object that is specially minted for that origin, object, and 
  property.

- When you get a property on a non-native object that is not a function, it
  returns a primitive value.

bholley and I also discussed something to do with own properties on Window, but I forget the details and apparently didn&apos;t write it down. :-(</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>98037</commentid>
    <comment_count>120</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2014-01-06 19:45:54 +0000</bug_when>
    <thetext>&gt; - When you get a property

This needs to be defined more carefully.  Really, what you need to do is to define what the various things in the table in http://people.mozilla.org/~jorendorff/es6-draft.html#sec-object-internal-methods-and-internal-slots do.  The proposal here defines [[GetPrototypeOf]] explicitly and presumably defines [[SetPrototypeOf]], [[IsExtensible]], [[Set]], [[Delete]], [[DefineOwnProperty]] implicitly by freezeing the object.  What remain to be defined are [[GetOwnProperty]], [[Enumerate]], and [[OwnPropertyKeys]].  

&gt;- When you get a property on a non-native object that is not a function, it
&gt;  returns a primitive value.

Is that web-compatible?  I thought the web allowed indexed/named access into even cross-origin windows, returning child frames...  Bobby?

&gt;- The === operator, when applied to two Window or Location objects representing 
&gt;  the same underlying concept, returns true.

This needs either an ES6 spec change or we&apos;re claiming that it&apos;s impossible to detect through black-box testing that two things that are testing === in this sense are actually different objects, right?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>98041</commentid>
    <comment_count>121</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-01-06 21:02:46 +0000</bug_when>
    <thetext>&gt; Is that web-compatible?  I thought the web allowed indexed/named access into
&gt; even cross-origin windows, returning child frames...  Bobby?

Oops, yeah, sorry, for Window there&apos;s a few exceptions around returning other Windows or Location objects.


&gt; This needs either an ES6 spec change or we&apos;re claiming that it&apos;s impossible
&gt; to detect through black-box testing that two things that are testing === in
&gt; this sense are actually different objects, right?

I don&apos;t know; this was something that bholley and abarth seemed to think was the less controversial of the points here...</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>98058</commentid>
    <comment_count>122</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-01-07 00:45:00 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #119)

&gt; - When you get a property on a non-native object that is a function, it
&gt; returns
&gt;   a Function object that is specially minted for that origin, object, and 
&gt;   property.

I&apos;m pretty sure this isn&apos;t quite right. I believe it was per (incumbent script, object, property).

Basically, we wanted the following to be true in the scope of A:

C.close !== B.eval(&quot;C.close&quot;)

Otherwise, the weirdness becomes observable with document.domain.

(In reply to Boris Zbarsky from comment #120)&gt; 
&gt; &gt;- The === operator, when applied to two Window or Location objects representing 
&gt; &gt;  the same underlying concept, returns true.
&gt; 
&gt; This needs either an ES6 spec change or we&apos;re claiming that it&apos;s impossible
&gt; to detect through black-box testing that two things that are testing === in
&gt; this sense are actually different objects, right?

I believe that the idea was that it would be impossible to differentiate them, even with document.domain. The prototypes are unobservable, and the properties change depending on who accesses them.

Basically, Gecko&apos;s current implementation should more or less implement what we discussed, modulo potentially a bit of tweaking for the proto hiding.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>98725</commentid>
    <comment_count>123</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-01-17 22:12:54 +0000</bug_when>
    <thetext>I&apos;ve been looking into what this is going to take, at the spec level.

The biggest problem I see so far is that the assumption that there&apos;s just one Window object per Document is baked really deep into the spec. There&apos;s 900+ mentions of Window in the spec, every one of which would have to be audited and probably significantly edited.

One option is to just mention this problem in the Security section, but that&apos;s pretty awful.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>98730</commentid>
    <comment_count>124</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-01-17 23:48:43 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #123)
&gt; I&apos;ve been looking into what this is going to take, at the spec level.
&gt; 
&gt; The biggest problem I see so far is that the assumption that there&apos;s just
&gt; one Window object per Document is baked really deep into the spec. There&apos;s
&gt; 900+ mentions of Window in the spec, every one of which would have to be
&gt; audited and probably significantly edited.
&gt; 
&gt; One option is to just mention this problem in the Security section, but
&gt; that&apos;s pretty awful.

I&apos;m not convinced it&apos;s such a big change. Can&apos;t we just let &quot;a Window Object&quot; continue to refer to what it means now, and introduce the terminology of &quot;a non-native Window Object&quot;?

Anyway, before doing any massive surgery on the spec, it seems like we should first:

(1) Come up with a very clear a concise plan of what we&apos;re proposing (similar to comment 119, but with all subsequent feedback addressed, especially comment 122). If we don&apos;t want to keep pasting this in the bug, we could put it in a wiki or etherpad somewhere.

(2) Make sure that it matches the memory of the 3 people who were in the room.

(3) Get feedback/signoff from Travis (MSFT), who is now back from vacation and want to know what the status is here. Feedback from Apple would be good too.

(4) Write tests in some sort of easily-sharable format.

(5) Have the implementors take a look at the tests and what it will take to pass them. If the proposal is as I remember, I&apos;m pretty sure I can make Gecko pass those with pretty quick turnaround.

(6) Once we&apos;ve ironed out any kinks, figure out how to make it all fit elegantly into the spec.

Does that sound ok? If so, Hixie, can you do (1)?

What&apos;s the best way to do (3)?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>98773</commentid>
    <comment_count>125</comment_count>
    <who name="Simon Pieters">zcorpan</who>
    <bug_when>2014-01-20 13:37:27 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #124)
&gt; (4) Write tests in some sort of easily-sharable format.

web-platform-tests (testharness.js + wpt-serve) seems like a good fit.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>98784</commentid>
    <comment_count>126</comment_count>
    <who name="Travis Leithead [MSFT]">travil</who>
    <bug_when>2014-01-20 19:03:19 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #124)
&gt; (3) Get feedback/signoff from Travis (MSFT), who is now back from vacation
&gt; and want to know what the status is here. Feedback from Apple would be good
&gt; too.

I&apos;m watching this thread (more closely now then I was in the past months...), so we can continue with this dialog here in the bug. I would like to see a comprehensive summary though, to avoid having to piece it together based on the comment history :-)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>98980</commentid>
    <comment_count>127</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-01-24 06:17:21 +0000</bug_when>
    <thetext>I&apos;m working on a detailed writeup and comprehensive web-platform-tests. Stay tuned.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99068</commentid>
    <comment_count>128</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-01-25 01:34:35 +0000</bug_when>
    <thetext>Alright, so I&apos;ve defined this stuff in pretty excruciating detail, largely in terms of ES Internal Methods. Here&apos;s my work-in-progress. Please comment! Doing so directly in the Etherpad is fine by me.

https://etherpad.mozilla.org/html5-cross-origin-objects

I&apos;ve also written thorough w3c tests for everything above. No UA passes them at present. Before publishing them, I want to take a brief crack at getting Firefox to pass them, which will hopefully reveal any bugs in the tests before other people spend time trying to pass them.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99091</commentid>
    <comment_count>129</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-01-25 21:38:02 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #128)
&gt; Before publishing them, I want to take a brief crack at getting
&gt; Firefox to pass them, which will hopefully reveal any bugs in the tests
&gt; before other people spend time trying to pass them.

To clarify, I plan to post them very soon, probably early next week. The issue is just that there are some large portions of various tests that currently never run at all on any of the UAs I have installed, because they fail some basic sanity checks (i.e. being able to access cross-origin properties with Object.getOwnPropertyDescriptor). I can fix most of these very easily in Gecko, and doing so has the potential to reveal bugs (i.e. misspelled variables) that occur later in the tests.

Put another way, the tests are 90% done, and I just didn&apos;t have the time or energy to finish them on friday evening. ;-)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99369</commentid>
    <comment_count>130</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-01-28 23:34:58 +0000</bug_when>
    <thetext>Sounds good.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99384</commentid>
    <comment_count>131</comment_count>
      <attachid>1433</attachid>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-01-29 03:35:17 +0000</bug_when>
    <thetext>Created attachment 1433
Tests. v1

OK, here&apos;s a reasonable first pass at the tests. It&apos;ll still take some work to support the behavior in Firefox, so I want to make sure we have a tentative consensus here.

David Bruant promised to review these - David, do you have time to take a look?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99388</commentid>
    <comment_count>132</comment_count>
    <who name="David Bruant">bruant.d</who>
    <bug_when>2014-01-29 09:03:50 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #131)
&gt; David Bruant promised to review these - David, do you have time to take a
&gt; look?
No later than today. This morning (Paris time) even maybe :-)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99414</commentid>
    <comment_count>133</comment_count>
    <who name="David Bruant">bruant.d</who>
    <bug_when>2014-01-29 14:58:04 +0000</bug_when>
    <thetext>(yet another long comment in this thread, yay!)
I&apos;m mostly verifying coherence with the ES6 object model.
I lack proper experience understanding if this is web-compatible. Someone else will have to check that part.
I didn&apos;t run the tests, only read the code.

In the first part, I talk about test content and things that will affect conformance. In the second part I touch on more cosmetic aspects.

## Content

* Whitelist behavior
=&gt; What if inside the iframe, I do &quot;window.postMessage = {}&quot;? What do I see in the parent?
=&gt; is a test missing for location prop === &apos;href&apos;? For symetry, whitelistedLocationProps might help

* getPrototypeOf/[[GetOwnProperty]]
=&gt; To tell a coherent story from an ES point of view, all whitelisted properties (and location.replace) must be own properties. Is it the case? (not all whitelisted properties are tested)
=&gt; Since tests below show Function.prototype for C.close, why forcing null and not Object.prototype for instance?

* [[SetPrototypeOf]]
=&gt; maybe add tests for Object.setPrototypeOf if present.
=&gt; From an ES point of view, throwing on [[SetPrototypeOf]], [[PreventExtensions]], etc. is only possible if location is an ES6 proxy (since it&apos;s reported as extensible).

* checkPropertyDescriptor
=&gt; it expects properties to be non-enumerable. If they are not enumerable, they won&apos;t appear in the whitelist test behavior since props are traversed with for-in. Unless enumerability changes with cross-origin-ness?
=&gt; configurable === false is a very strong commitment (see eternal invariants from [1]) from an ES perspective for a WindowProxy. It means, for instance, that the postMessage instance will remain even if the underlying Window instance changes.
Although awkward, to respect the invariants, we can have configurable=true with some of the expected behavior of configurable=false (throw on defineProperty, etc.)

* checkDefine function
=&gt; copy/paste error, valueDesc used twice in assert_throws, accessorDesc not used (change error message accordingly too)

* [[OwnPropertyKeys]]
=&gt; Not sure about toSource. Is it standard? Can it be relied on?
I think test harness has methods for array values equality.

* &quot;Cross-origin functions get local Function.prototype&quot; &amp; &quot;Cross-origin Window accessors get local Function.prototype&quot;
=&gt; This is possible only if getting C.close returns a ES6 Proxy (at least if the cross-origin context sees a proxy) as well as if the target of this proxy remains extensible. If this is a story everyone is comfortable with, some tests should be added to nail it down (decide of what happens when inside the iframe Object.preventExtensions(close) is attempted).

* assert_true(close != C.close, &apos;cross-origin Window functions get their own object&apos;);
=&gt; Is it specific to cross-origin windows?
this is true also for B, also, no? close !== B.close?

* assert_true(close_B != C.close, &apos;different Window functions per-incumbent script settings object&apos;);
=&gt;  maybe rename close_B with C_close_from_B
So if I followed well, that was the part that was mostly controversial in this thread?
a test for close !== close_B is lacking I feel. Or is it implicitely tested via the [[Prototype]] tests with Function.prototype and B.Function.prototype?

* doDocumentDomainTest
=&gt; Just to be sure I&apos;m not missing something, this is testing 2 things:
1) references within the iframe remain consistent after changing origin
2) references from outside the iframe remain consistent after changing origin
Is it enough? I have a gut feeling that no, but can&apos;t find something relevant to add yet.
Maybe that some cross-origin restrictions have been removed (like the inability to [[delete]] a property)?
Follow-up from above, if D.close is a proxy in the cross-origin case, it can&apos;t be === to D.close after the origin changed. Is it the intended behavior?



## Cosmetic

* instead of frameElement.uriToLoad, use data attributes (and dataList?)

* for (var p in whitelistedWindowProps)
whitelistedWindowProps is an array. Traverse with forEach, map and friends (for-in is for objects used as key-&gt;value maps).

* Be careful with typeof x === &apos;object&apos; as it returns true for null. Does the test harness have an isObject helper function?
Object(x) === x is otherwise a safer test.

* [[Enumerate]]
=&gt; &quot;assert_true(false, (...)&quot;
isn&apos;t there an assert_fail?

* checkFunction
=&gt; Not sure f.name can be relied on with DOM built-in on different browsers. To be tested or the function can be changed to accept a label like checkPropertyDescriptor

* I worry about how these tests are run. They rely on top being the main test file. If they&apos;re run as iframes, they may fail in subtle ways. Maybe add a comment at the top of the test file to explain the proper conditions in which this test should be run as we&apos;re in one of the rare cases where it really matters.

* // The document.domain test is unavoidably side-effect-y, so we do it last.
=&gt; Maybe they belong in their own file?

* is the E iframe used somewhere?
* Maybe add an F that is @sandbox=&quot;allow-scripts&quot; (different origin)
* Maybe add a G that is @sandbox=&quot;allow-scripts allow-same-origin&quot;


[1] https://mail.mozilla.org/pipermail/es-discuss/2011-May/014150.html</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99542</commentid>
    <comment_count>134</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-01-31 18:39:59 +0000</bug_when>
    <thetext>(In reply to David Bruant from comment #133)
&gt; 
&gt; * Whitelist behavior
&gt; =&gt; What if inside the iframe, I do &quot;window.postMessage = {}&quot;? What do I see
&gt; in the parent?

Assuming they&apos;re same-origin, you see {}.

If they&apos;re cross-origin, setting it on the non-native object should throw, because it&apos;s not configurable, and setting it on the native Window should have no effect on the cross-origin Window, since they&apos;re not the same object.


&gt; * getPrototypeOf/[[GetOwnProperty]]
&gt; =&gt; To tell a coherent story from an ES point of view, all whitelisted
&gt; properties (and location.replace) must be own properties. Is it the case?
&gt; (not all whitelisted properties are tested)

Also, how does this work for the frame names?


I&apos;ll let bholley and abarth respond to the rest, but I have to say, I still don&apos;t really understand why we&apos;re trying so hard to fit Window, WindowProxy, and Location into obeying the language invariants. I don&apos;t understand what negative consequences there are to making these specific highly magical objects be so magical that ES can&apos;t describe them generically.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99543</commentid>
    <comment_count>135</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2014-01-31 18:53:08 +0000</bug_when>
    <thetext>&gt; I still don&apos;t really understand why we&apos;re trying so hard to fit Window,
&gt; WindowProxy, and Location into obeying the language invariants.

Two reasons off the top of my head:

1)  A bunch of ES spec algorithms depend on these invariants and will go completely off the rails if applied to objects for which the invariants do not hold.

2)  Things like Caja depend on these invariants and will end up with security bugs if the invariants do not hold.

For both cases, it&apos;s better to lie and say things are configurable if they _might_ change even if in practice they never do than to lie and say things are not configurable and then have them change out from under code that doesn&apos;t expect them to.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99544</commentid>
    <comment_count>136</comment_count>
    <who name="David Bruant">bruant.d</who>
    <bug_when>2014-01-31 18:55:58 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #134)
&gt; (In reply to David Bruant from comment #133)
&gt; &gt; 
&gt; &gt; * Whitelist behavior
&gt; &gt; =&gt; What if inside the iframe, I do &quot;window.postMessage = {}&quot;? What do I see
&gt; &gt; in the parent?
&gt; 
&gt; If they&apos;re cross-origin, setting it on the non-native object should throw,
&gt; because it&apos;s not configurable, and setting it on the native Window should
&gt; have no effect on the cross-origin Window, since they&apos;re not the same object.
It looks like against the semantics of Bobby&apos;s document-domain tests (references don&apos;t change after an iframe becomes same-origin)


&gt; I still don&apos;t really understand why we&apos;re trying so hard to fit Window,
&gt; WindowProxy, and Location into obeying the language invariants.
&gt; I don&apos;t understand what negative consequences there are to making these
&gt; specific highly magical objects be so magical that ES can&apos;t describe them generically.
Among the reasons I care about it enables self-hostability. If browsers don&apos;t care about implementing things partly in JS, it gives authors an opportunity to fix a non-compliant browser. We&apos;ve been needed that. Granted, this is much less a problem than it used to be, but who knows about future browsers.
Self-hostability also allow for faithful confinement via Caja or else (without having to rewrite the JS code or prevent the use of iframes).

The invariants allow for defensive code. They guarantee that when you succesfully freeze an object, new properties won&apos;t magically pop up creating a new communication channel among parties that shouldn&apos;t be talking to one another, etc.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99549</commentid>
    <comment_count>137</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-01-31 21:34:24 +0000</bug_when>
    <thetext>Can you elaborate on #1? What algorithms will fail? Last time we talked about this, I don&apos;t recall we came up with any that actually fail in a meaningful way.

As far as Caja goes, if you&apos;re handing Caja code a WindowProxy or Location object, you&apos;ve already lost so hard it&apos;s not even worth talking about. I don&apos;t see how this is relevant here.

Nobody&apos;s going to be able to patch cross-domain Window behaviour in a useful way regardless of whether we do all this with the precise invariants followed or not. I really don&apos;t see what that would concretely look like. Can you give an example of useful code that would be possible with these invariants met but not if these invariants are subtly broken for Window/WindowProxy and Location?

(In reply to David Bruant from comment #136)
&gt; It looks like against the semantics of Bobby&apos;s document-domain tests
&gt; (references don&apos;t change after an iframe becomes same-origin)

Can you elaborate on this? References to what, when what about an iframe changes origin? (There&apos;s about 6 possible origins involved with an iframe. :-) )</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99551</commentid>
    <comment_count>138</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2014-01-31 22:03:20 +0000</bug_when>
    <thetext>&gt; What algorithms will fail? 

I&apos;m pretty sure correct functioning of Proxy relies on the target object enforcing the invariants....</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99557</commentid>
    <comment_count>139</comment_count>
    <who name="David Bruant">bruant.d</who>
    <bug_when>2014-01-31 23:26:06 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #137)
&gt; As far as Caja goes, if you&apos;re handing Caja code a WindowProxy or Location
&gt; object, you&apos;ve already lost so hard it&apos;s not even worth talking about.
How so? In the current state of affairs, I agree, but if they comply to Bholley&apos;s tests (modulo a few tweaks), &quot;cajoled&quot; (confined) code won&apos;t be able to do anything harmful with them.

&gt; I don&apos;t see how this is relevant here.
I was more thinking that if WindowProxy can be expressed in ES semantics, Caja can provide a compliant emulation of it to cajoled code even if the browser doesn&apos;t comply itself.


&gt; Nobody&apos;s going to be able to patch cross-domain Window behaviour in a useful
&gt; way regardless of whether we do all this with the precise invariants
&gt; followed or not. I really don&apos;t see what that would concretely look like.
&gt; Can you give an example of useful code that would be possible with these
&gt; invariants met but not if these invariants are subtly broken for
&gt; Window/WindowProxy and Location?
In our case, the postMessage instance, described as non-configurable on a WindowProxy can change over time if the underlying Window changes. In ES code, it&apos;s expected that the value of a non-configurable data property doesn&apos;t change, so that the thing you get from window.postMessage once remains the same value.
You may have a WeakMap using &quot;someIframe.contentWindow.postMessage&quot; as key, expecting it won&apos;t change over time.
You may have written Object.freeze(someIframe.contentWindow.postMessage) at some point. Given postMessage is exposed as non-configurable, you would expect that the thing you acquire from &quot;someIframe.contentWindow.postMessage&quot; will always be frozen from this point on. Since the postMessage function can change over time, it&apos;s not the case.

Granted, these examples aren&apos;t very concrete. But they all relate to the idea of defensive code.
Some signals have been added to ES5 to basically say &quot;if you do x and it doesn&apos;t throw or observe y, you&apos;re guaranteed of z&quot;. They&apos;re all related to non-configurability and non-extensibilty.
I wasn&apos;t there at the time, but from what I understand, they&apos;ve been added after the experience of Caja trying to make JavaScript a securable language (note the &quot;-able&quot;) without having to rewrite the source code to add runtime checks (which they did to secure ES3 code). That&apos;s actually fairly minimal, but that&apos;s what they need to write defensive code. Since the release of ES5, they haven&apos;t reported they missed a primitive to secure without rewriting.


&gt; (In reply to David Bruant from comment #136)
&gt; &gt; It looks like against the semantics of Bobby&apos;s document-domain tests
&gt; &gt; (references don&apos;t change after an iframe becomes same-origin)
&gt; 
&gt; Can you elaborate on this? References to what, when what about an iframe
&gt; changes origin? (There&apos;s about 6 possible origins involved with an iframe.
&gt; :-) )
Bobby&apos;s tests do the following at the end:
1) inside a cross-domain iframe, save all indexed references of the parent.
2) in both parent and iframe, set document.domain to the same valid domain.
3) The checkWindowReferences makes sure that the indexed references after 2) === the ones saved at 1)
From this test, we can infer that all the WindowProxy objects remain the same objects whether they&apos;re found same or different origin. 
My understanding of your message is that you were saying the opposite. Did I misunderstand?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99561</commentid>
    <comment_count>140</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-02-01 00:21:27 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #134)
&gt; &gt; * getPrototypeOf/[[GetOwnProperty]]
&gt; &gt; =&gt; To tell a coherent story from an ES point of view, all whitelisted
&gt; &gt; properties (and location.replace) must be own properties. Is it the case?
&gt; &gt; (not all whitelisted properties are tested)
&gt; 
&gt; Also, how does this work for the frame names?

Yeah, since these appear and disappear, presumably we have to claim that these properties are configurable (this is also why we have to claim that cross-origin objects are extensible). In fact, given that we return different property descriptors to different same-origin callers, their properties probably _always_ need to be reported as configurable (and we can just throw if somebody tries to actually configure them). I&apos;ll make a note to fix that.

&gt; I&apos;ll let bholley and abarth respond to the rest, but I have to say, I still
&gt; don&apos;t really understand why we&apos;re trying so hard to fit Window, WindowProxy,
&gt; and Location into obeying the language invariants.

Caja stuff aside, I think this is hugely important for the feasibility of implementation. Different JS engines do different things, and we want to be as sure as possible that everyone can implement what we come up with. SpiderMonkey (and I&apos;m sure V8 as well) is steadily aligning its API and internal semantics with ES, and so those are the hooks that I (as an embedder) have available to implement custom behavior.

We&apos;re kind of cheating with the post-document-domain identity stuff - it either requires overriding operator===, or having a security membrane (though the latter is arguably describable in ES). But it&apos;s a corner-case, and was the best that the three of us could come up with - so we&apos;re going to have to live with it. But for the 99%, it seems like we should use the ES object model to describe ES objects.

&gt; I don&apos;t understand what
&gt; negative consequences there are to making these specific highly magical
&gt; objects be so magical that ES can&apos;t describe them generically.

Precisely describing something more magical than ES is a pretty tall order. Even if you can manage to specify everything that happens to be observable in current browsers, it&apos;ll all come tumbling down as soon as TC39 adds another Object.getSomeFancyThing method.

There are a lot of smart people who&apos;ve spent an eternity coming up with a way to specify ES object behavior. I think it&apos;s pretty foolish to fork that work.

I&apos;m out of time tonight, but will respond to the rest of the specific feedback here next week.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99639</commentid>
    <comment_count>141</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-02-03 20:20:04 +0000</bug_when>
    <thetext>Consider the same-origin case. You have a frame A, containing an iframe B. B is navigated to page X, then navigated to page Y. While it&apos;s at page X, the page in A gets a reference to the WindowProxy for X&apos;s Window object, and it grabs a reference to postMessage&apos;s Function object on X. Then B navigates to page Y, and A does the same again. Those two references won&apos;t be ===, right? But they can be manipulated like any other Function object (they&apos;re same-origin, after all).

Then introduce page Z, which is cross-origin. B is navigated to Z. The same WindowProxy object now has to defer to Z&apos;s Window. Regardless of what else is going on, Z&apos;s Window&apos;s postMessage function isn&apos;t the same one as the one from X or the one from Y, right?

But you can still navigate back to Y or X, and then the same WindowProxy object had better return the same-origin stuff from X and Y.

I don&apos;t see how we can ever make WindowProxy sane. It just points to whatever the &quot;current&quot; Window is, and that will go from being a same-origin Window object with one behaviour to a cross-origin Window object with another wildly different behaviour.

I&apos;m not objecting to it being defined in a way that fits ES semantics. It seems like a lost cause to me, and the gains seem minimal, but if it&apos;s possible...</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99669</commentid>
    <comment_count>142</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-02-04 19:17:20 +0000</bug_when>
    <thetext>(In reply to David Bruant from comment #139)
&gt; Bobby&apos;s tests do the following at the end:
&gt; 1) inside a cross-domain iframe, save all indexed references of the parent.
&gt; 2) in both parent and iframe, set document.domain to the same valid domain.
&gt; 3) The checkWindowReferences makes sure that the indexed references after 2)
&gt; === the ones saved at 1)
&gt; From this test, we can infer that all the WindowProxy objects remain the
&gt; same objects whether they&apos;re found same or different origin. 

The document.domain identity issues are definitely where we come closest to violating ES language invariants, I think. In the spec, we have &quot;The === operator, when applied to two objects representing the same underlying concept, returns true (even after document.domain)&quot;, which obviously isn&apos;t ES-kosher. Gecko implements this with a membrane layer, FWIW. But nobody really wants to spend that much time worrying about document.domain. I&apos;m somewhat willing to say &quot;you don&apos;t get ES language invariants if you use document.domain&quot;, though I haven&apos;t really thought through all the implications of that.

(In reply to Ian &apos;Hixie&apos; Hickson from comment #141)
&gt; But you can still navigate back to Y or X, and then the same WindowProxy
&gt; object had better return the same-origin stuff from X and Y.
&gt; 
&gt; I don&apos;t see how we can ever make WindowProxy sane.

So far I don&apos;t see any problem. The WindowProxy is just a proxy whose referent changes. As long as it always reports itself as extensible and never reports a non-configurable property, this is totally kosher.

It&apos;s possible that the weird semantics of WindowProxy will eventually require some changes on the ES side. But I think we should make an honest effort to respect the language invariants, and raise issues with TC39 where we can&apos;t.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99705</commentid>
    <comment_count>143</comment_count>
    <who name="David Bruant">bruant.d</who>
    <bug_when>2014-02-04 23:22:27 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #142)
&gt; (In reply to David Bruant from comment #139)
&gt; &gt; Bobby&apos;s tests do the following at the end:
&gt; &gt; 1) inside a cross-domain iframe, save all indexed references of the parent.
&gt; &gt; 2) in both parent and iframe, set document.domain to the same valid domain.
&gt; &gt; 3) The checkWindowReferences makes sure that the indexed references after 2)
&gt; &gt; === the ones saved at 1)
&gt; &gt; From this test, we can infer that all the WindowProxy objects remain the
&gt; &gt; same objects whether they&apos;re found same or different origin. 
&gt; 
&gt; The document.domain identity issues are definitely where we come closest to
&gt; violating ES language invariants, I think. In the spec, we have &quot;The ===
&gt; operator, when applied to two objects representing the same underlying
&gt; concept, returns true (even after document.domain)&quot;
oooooh.... I think I see it now... Trying to explain it with my own words:
* a script in the parent see their global object.
* a script in a different origin see the same object as their &quot;parent&quot;.
* the fact that it&apos;s the &quot;same&quot; object can be observed via === after setting document.domain on both sides.
* However *before* setting document.domain, both context actually observe different objects (the iframe see a version with only whitelisted properties for instance)
For instance, both side would Object.getOwnPropertyDescriptor the same object, send one another their list via postMessage and notice the difference of what they observe.

I don&apos;t think there are tests for this behavior currently?

&gt; which obviously isn&apos;t ES-kosher. Gecko implements this with a membrane layer, FWIW.
Alright... Crazy time now to demonstrate that the observed behavior may actually be expressible in ES6. Buckle up!
It&apos;s technically possible to implement transparent membranes in ES with proxies. Among other things, it&apos;s possible to implement wet/dry membranes [1] (some scripts only see wet objects, other scripts only see dry objects, but they can communicate via function calls, object properties, etc. transparently as if the membranes weren&apos;t here)
We can say the parent is dry, the iframe is wet (note: with the WindowProxy, it&apos;s two layers of proxies before the Window :-) #Composability). From this setup, we have the following:
* inside the parent, references are self-consistent (respecting tests in for loop in doDocumentDomainTest)
* inside the iframe, references are self consistent (respecting checkWindowReferences tests)
* The WindowProxy objects both context can look at are effectively !== but neither side can ever observe it, because each is &quot;locked&quot; in its side of the membrane.

To have the &quot;same&quot; WindowProxy object that look differently from the parent and from the iframe, the handler to WindowProxy objects isn&apos;t simply a transparent dry/wet handler; it enforces the rules that are being attempted to be codified in this bug (property whitelist, throw otherwise, etc.) on one side of the membrane only.
On document.domain being set to the same thing on both side, the handler changes its behavior to just be a transparent dry/wet membrane.

So I think the chosen semantics is expressible in pure ES terms (granted, with quite an overhead and elaborate design).
That was obviously just a thought exercise. I don&apos;t recommend standardizing nor ever implementing it like that (though from &quot;Gecko implements this with a membrane layer&quot;, it looks Gecko already did implement it like that in a way...).
Standardizing and implementing invoking magic (&quot;wilful violations&quot;) works as far as I&apos;m concerned.


[1] see slide 27 of https://docs.google.com/file/d/0B9iYRsLxmdqUd1RsdHZtazliWmc/edit for the super-short version</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99707</commentid>
    <comment_count>144</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-02-05 00:20:20 +0000</bug_when>
    <thetext>Finally found some time to go through and address David&apos;s feedback. Sorry for the delay here.

(In reply to David Bruant from comment #133)
&gt; * Whitelist behavior
&gt; =&gt; What if inside the iframe, I do &quot;window.postMessage = {}&quot;? What do I see
&gt; in the parent?

Good catch. It depends on whether the iframe is same-origin or not. I&apos;ve updated the etherpad spec to reflect that, and added tests.

&gt; =&gt; is a test missing for location prop === &apos;href&apos;?

It&apos;s true that we don&apos;t test invoking the setter. But doing that makes the tests complicated, because it causes us to navigate. I didn&apos;t see anything really crucial in there that wouldn&apos;t be covered by other stuff.

&gt; For symetry, whitelistedLocationProps might help

It doesn&apos;t really make sense, because |replace| is the only cross-origin readable property, and |href| is the only cross-origin writable property. So we kinda jus have to special

&gt; * getPrototypeOf/[[GetOwnProperty]]
&gt; =&gt; To tell a coherent story from an ES point of view, all whitelisted
&gt; properties (and location.replace) must be own properties. Is it the case?

Yes.

&gt; (not all whitelisted properties are tested)

Which ones?

&gt; =&gt; Since tests below show Function.prototype for C.close, why forcing null
&gt; and not Object.prototype for instance?

Because the functions are just regular functions, and have different identities depending on who is accessing them. There&apos;s no identity relationship between the value the caller gets for |C.postMessage|, the value B sees for |parent.C.postMessage|, and the value C sees for |window.postMessage|. |Window| and |Location| have to compare equal (especially between same-origin observers)
 
&gt; * [[SetPrototypeOf]]
&gt; =&gt; maybe add tests for Object.setPrototypeOf if present.

Added (though untested at present).

&gt; =&gt; From an ES point of view, throwing on [[SetPrototypeOf]],
&gt; [[PreventExtensions]], etc. is only possible if location is an ES6 proxy
&gt; (since it&apos;s reported as extensible).

Is there any meaningful reason this has to be the case?

&gt; * checkPropertyDescriptor
&gt; =&gt; it expects properties to be non-enumerable. If they are not enumerable,
&gt; they won&apos;t appear in the whitelist test behavior since props are traversed
&gt; with for-in. Unless enumerability changes with cross-origin-ness?

Yep, that&apos;s the reason. This stuff is normally enumerable, but we decided to make it non-enumerable for cross-origin objects. We still have to list them for [[GetOwnPropertyKeys]] though, so we could also just make them enumerable. It doesn&apos;t matter much.

&gt; =&gt; configurable === false is a very strong commitment (see eternal
&gt; invariants from [1]) from an ES perspective for a WindowProxy. It means, for
&gt; instance, that the postMessage instance will remain even if the underlying
&gt; Window instance changes.
&gt; Although awkward, to respect the invariants, we can have configurable=true
&gt; with some of the expected behavior of configurable=false (throw on
&gt; defineProperty, etc.)

Totally agree. We really can&apos;t enforce configurable=false on any sort of WindowProxy, cross-origin or not. Updated the spec.

&gt; * checkDefine function
&gt; =&gt; copy/paste error, valueDesc used twice in assert_throws, accessorDesc not
&gt; used (change error message accordingly too)

Good catch. Fixed.
 
&gt; * [[OwnPropertyKeys]]
&gt; =&gt; Not sure about toSource. Is it standard? Can it be relied on?
&gt; I think test harness has methods for array values equality.

Sorry, bad habit from writing Gecko tests. Fixed.
 
&gt; * &quot;Cross-origin functions get local Function.prototype&quot; &amp; &quot;Cross-origin
&gt; Window accessors get local Function.prototype&quot;
&gt; =&gt; This is possible only if getting C.close returns a ES6 Proxy (at least if
&gt; the cross-origin context sees a proxy) as well as if the target of this
&gt; proxy remains extensible.

Hm, I&apos;m not sure I agree. |C| has to be proxy-like, but |close| is just a regular function.

&gt; * assert_true(close != C.close, &apos;cross-origin Window functions get their own
&gt; object&apos;);
&gt; =&gt; Is it specific to cross-origin windows?
&gt; this is true also for B, also, no? close !== B.close?

Sure. I just wasn&apos;t testing the latter. I can add one.

&gt; * assert_true(close_B != C.close, &apos;different Window functions per-incumbent
&gt; script settings object&apos;);
&gt; =&gt;  maybe rename close_B with C_close_from_B

Honestly it seems like there&apos;s too much relevant information to encode in the variables names. :-(

&gt; So if I followed well, that was the part that was mostly controversial in
&gt; this thread?

Bingo. I&apos;m impressed. :-)

&gt; a test for close !== close_B is lacking I feel. Or is it implicitely tested
&gt; via the [[Prototype]] tests with Function.prototype and B.Function.prototype?

I can add one.
 
&gt; * instead of frameElement.uriToLoad, use data attributes (and dataList?)

I need to generate the URIs programatically, at which point I don&apos;t know if there&apos;s a functional difference between expandos and data attributes.
 
&gt; * for (var p in whitelistedWindowProps)
&gt; whitelistedWindowProps is an array. Traverse with forEach, map and friends
&gt; (for-in is for objects used as key-&gt;value maps).

ok.

&gt; * Be careful with typeof x === &apos;object&apos; as it returns true for null. Does
&gt; the test harness have an isObject helper function?
&gt; Object(x) === x is otherwise a safer test.

It does not have one, but I&apos;ll add one locally in the form that you suggest.
 
&gt; * [[Enumerate]]
&gt; =&gt; &quot;assert_true(false, (...)&quot;
&gt; isn&apos;t there an assert_fail?

I don&apos;t see one.

&gt; * checkFunction
&gt; =&gt; Not sure f.name can be relied on with DOM built-in on different browsers.
&gt; To be tested or the function can be changed to accept a label like
&gt; checkPropertyDescriptor

Eh, it&apos;s just cosmetic for the error message. I&apos;ll just do:

var name = f.name || &apos;&lt;missing name&gt;&apos;;
 
&gt; * I worry about how these tests are run. They rely on top being the main
&gt; test file. If they&apos;re run as iframes, they may fail in subtle ways. Maybe
&gt; add a comment at the top of the test file to explain the proper conditions
&gt; in which this test should be run as we&apos;re in one of the rare cases where it
&gt; really matters.

Ok, Added a comment.
 
&gt; * // The document.domain test is unavoidably side-effect-y, so we do it last.
&gt; =&gt; Maybe they belong in their own file?

Maybe. We can do that later or something.
 
&gt; * is the E iframe used somewhere?

See the comment: &quot;The last two are only used for the document.domain tests, in which D ceases to be same-origin with E and becomes same-origin with B.&quot;


&gt; * Maybe add an F that is @sandbox=&quot;allow-scripts&quot; (different origin)
&gt; * Maybe add a G that is @sandbox=&quot;allow-scripts allow-same-origin&quot;

We can add this at some point, but it feels out of scope to me right now.

From the etherpad:

&gt; I call this a &quot;reflected&quot; property, since it reflects back its identity
&gt; to the caller :)

IMO reflected is too overloaded of a term to use here. ;-)

&gt;&gt; If the property is a value-prop and whitelisted for reading,
&gt;&gt; return a property descriptor with |configurable| set to true,
&gt;&gt;|enumerable| set to false, |writable| set to false, and |value|
&gt;&gt; to a Caller-Appropriate Representation of the value.
&gt; whos internal [[Prototype]] is Object.prototype of the incumbant script?) 

not really - it&apos;ll either be another cross-origin object (for which the prototype is null), or a same-origin object with normal prototype semantics.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99713</commentid>
    <comment_count>145</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-02-05 00:34:59 +0000</bug_when>
    <thetext>Alright, I&apos;ve updated the tests.

Tests are here:
https://github.com/bholley/web-platform-tests/compare/submission;bholley

Proposed spec is here:
https://etherpad.mozilla.org/html5-cross-origin-objects

To make progress here, there are a few things that I want to leave out of scope for now:

(1) The finer points of speccing this wrt document.domain (I think that&apos;s likely to be a massive distraction)
(2) The intricacies of cross-origin named subframe access (since I think the ideal behavior here is still evolving, per [1]).

Hixie and David - Putting those things aside, do you think this is in a state that we can ask Microsoft and WebKit for feedback? Do you have any outstanding concerns?

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=916945</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99775</commentid>
    <comment_count>146</comment_count>
    <who name="Simon Pieters">zcorpan</who>
    <bug_when>2014-02-05 12:07:34 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #145)
&gt; Alright, I&apos;ve updated the tests.
&gt; 
&gt; Tests are here:
&gt; https://github.com/bholley/web-platform-tests/compare/submission;bholley

It seems this isn&apos;t a pull request yet, right? Can you make it so, please?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99777</commentid>
    <comment_count>147</comment_count>
    <who name="David Bruant">bruant.d</who>
    <bug_when>2014-02-05 12:29:54 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #144)
&gt; &gt; * getPrototypeOf/[[GetOwnProperty]]
&gt; &gt; =&gt; To tell a coherent story from an ES point of view, all whitelisted
&gt; &gt; properties (and location.replace) must be own properties. Is it the case?
&gt; 
&gt; Yes.
&gt; 
&gt; &gt; (not all whitelisted properties are tested)
&gt; 
&gt; Which ones?
I was referring to the [[GetOwnProperty]] tests where only C.close and C.top are being verified (for Window). But it&apos;s tested in the very first test :
assert_true(Object.prototype.hasOwnProperty.call(C, prop), &quot;hasOwnProperty for &quot; + prop)
My mistake.

&gt; &gt; =&gt; Since tests below show Function.prototype for C.close, why forcing null
&gt; &gt; and not Object.prototype for instance?
&gt; 
&gt; Because the functions are just regular functions, and have different
&gt; identities depending on who is accessing them. There&apos;s no identity
&gt; relationship between the value the caller gets for |C.postMessage|, the
&gt; value B sees for |parent.C.postMessage|, and the value C sees for
&gt; |window.postMessage|.
This is magic (especially that C.postMessage !== parent.C.postMessage given C === parent.C).
In &quot;naïve&quot; ES terms, a consequence of &quot;The === operator, when applied to two objects representing  the same underlying concept, returns true&quot; is that all parties seeing a concept also see the same functions (same object identity) for all the methods and objects attached to the concept.
Now that I think about it, I think starting a sentence with &quot;The === operator, when applied to...&quot; is dangerous because it can question everything that comes with object equality.
A less foot-gunny option would be to use the phrase &quot;are the same objects&quot;. And that&apos;s an assertion that cannot change in time regardless of whatever happens in the runtime. It obviously comes with consequences when it comes to object properties.

Another option is to buy the dry/wet membranes thing (now that I think about it, pretty much every scenario of object in/equality can be explained via dry/wet membranes).


&gt; &gt; * [[SetPrototypeOf]]
&gt; &gt; =&gt; maybe add tests for Object.setPrototypeOf if present.
&gt; 
&gt; Added (though untested at present).
There is some activity in bug 885788; might arrive soon in Firefox. I think it&apos;s already in V8.

&gt; &gt; =&gt; From an ES point of view, throwing on [[SetPrototypeOf]],
&gt; &gt; [[PreventExtensions]], etc. is only possible if location is an ES6 proxy
&gt; &gt; (since it&apos;s reported as extensible).
&gt; 
&gt; Is there any meaningful reason this has to be the case?
ES objects cannot choose their behavior to built-ins. ES6 objects internal operations are regulated by specific semantics
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-ordinary-object-internal-methods-and-internal-slots
Exception exists and are codified in the ES spec (Array [[GetOwnProperty]] for instance).
There used to be a place for &quot;host objects&quot; that could do literally everything they wanted (and that was the hole the whole DOM and browser APIs were fitting into). In ES6, host objects are gone. The only way to do something different from the ordinary objects semantics is to use proxies. And proxies are codified by the ES spec to respect a couple of constraints (ES invariants).

The meaningful reason is to keep everything exposed to an ECMAScript environment saner than what host objects have historically been. In a way it relates to your argument to &quot;why care about ES-expressibility&quot; about implementation feasability and hooks to JS engines.

From an author perspective, I think it&apos;s good if specs state clearly that some object is a proxy. If I read a spec and it doesn&apos;t say the object is a proxy, I know exactly what to expect from its internal operations and the algorithms that use these internal operations (Object.* functions, but also Array.prototype.* methods, JSON.stringify, soon promises with their thenable shit, etc.).
If the spec says an object is a proxy, then I can look at the details to understand how the object differs from ES ordinary objects semantics.

To be honest, when compared to no spec or host-object-magic-land, proxies in spec doesn&apos;t sound so bad. We might need WebIDL ways to express proxies.


&gt; &gt; * checkPropertyDescriptor
&gt; &gt; =&gt; it expects properties to be non-enumerable. If they are not enumerable,
&gt; &gt; they won&apos;t appear in the whitelist test behavior since props are traversed
&gt; &gt; with for-in. Unless enumerability changes with cross-origin-ness?
&gt; 
&gt; Yep, that&apos;s the reason. This stuff is normally enumerable, but we decided to
&gt; make it non-enumerable for cross-origin objects. We still have to list them
&gt; for [[GetOwnPropertyKeys]] though, so we could also just make them
&gt; enumerable. It doesn&apos;t matter much.
Agreed. Enumerability is pretty much a dead feature anyway.
https://mail.mozilla.org/pipermail/es-discuss/2014-January/035638.html
It&apos;s only used to control for-in. And for-in will die in a world with for-of.
Control over enumerability was added in ES5 only to give authors the same level of control over properties that the JS engine internals have.
Note also that there are no ES invariants related to enumerability.


&gt; &gt; * &quot;Cross-origin functions get local Function.prototype&quot; &amp; &quot;Cross-origin
&gt; &gt; Window accessors get local Function.prototype&quot;
&gt; &gt; =&gt; This is possible only if getting C.close returns a ES6 Proxy (at least if
&gt; &gt; the cross-origin context sees a proxy) as well as if the target of this
&gt; &gt; proxy remains extensible.
&gt; 
&gt; Hm, I&apos;m not sure I agree. |C| has to be proxy-like, but |close| is just a
&gt; regular function.
This is the same thing than postMessage above. C is the iframe global seen from the parent (so it === the window inside the iframe). Both inside and outside the iframe should see the same object when getting &apos;C.close&apos;/&apos;window.close&apos;(outside/inside resp.) and Object.getPrototypeOf can only return a single value, so it has to be the Function.prototype from only one of the contexts.
I was &quot;wrong&quot; when suggesting proxies since it would lead to close being two objects depending on where it&apos;s obtained seen from (in cross-origin case).
Unless the behavior is explained via dry/wet membranes when thinking in ES terms and wilful violations in WHATWG spec.


&gt; &gt; * assert_true(close_B != C.close, &apos;different Window functions per-incumbent
&gt; &gt; script settings object&apos;);
&gt; &gt; =&gt;  maybe rename close_B with C_close_from_B
&gt; 
&gt; Honestly it seems like there&apos;s too much relevant information to encode in
&gt; the variables names. :-(
Yeah... I made a suggestion, but was aware that even that was lacking info.
I was just confused by &quot;close_B&quot;, because it gave me the impression it was a close function from B (just reading at the variable name of course).

(In reply to Bobby Holley (:bholley) from comment #145)
&gt; Hixie and David - Putting those things aside, do you think this is in a
&gt; state that we can ask Microsoft and WebKit for feedback? Do you have any
&gt; outstanding concerns?
Nothing major stands out. I think it&apos;s a right time to ask for feedback. Thanks a lot for the work on the tests, it does help a lot understanding the intended behavior!</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99793</commentid>
    <comment_count>148</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-02-05 17:00:01 +0000</bug_when>
    <thetext>(In reply to Simon Pieters from comment #146)
&gt; (In reply to Bobby Holley (:bholley) from comment #145)
&gt; &gt; Tests are here:
&gt; &gt; https://github.com/bholley/web-platform-tests/compare/submission;bholley
&gt; 
&gt; It seems this isn&apos;t a pull request yet, right? Can you make it so, please?

It seems like we shouldn&apos;t land the tests until the behavior they&apos;re testing actually ends up in the spec, right?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99795</commentid>
    <comment_count>149</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-02-05 17:16:35 +0000</bug_when>
    <thetext>(In reply to David Bruant from comment #147) 
&gt; Now that I think about it, I think starting a sentence with &quot;The ===
&gt; operator, when applied to...&quot; is dangerous because it can question
&gt; everything that comes with object equality.
&gt; A less foot-gunny option would be to use the phrase &quot;are the same objects&quot;.
&gt; And that&apos;s an assertion that cannot change in time regardless of whatever
&gt; happens in the runtime. It obviously comes with consequences when it comes
&gt; to object properties.

That the spec can be implemented with entirely separate objects is very important to abarth. During our meeting, we agreed to the principle that &quot;No object is ever exposed to code running from a different origin&quot;.

So even if the observables end up being the same, I think it&apos;s important that we spec it this way, at least for now. If, down the line, we can find a way to spec it with proxies/membranes that maintain the same observables, so much the better.

 
&gt; &gt; &gt; =&gt; From an ES point of view, throwing on [[SetPrototypeOf]],
&gt; &gt; &gt; [[PreventExtensions]], etc. is only possible if location is an ES6 proxy
&gt; &gt; &gt; (since it&apos;s reported as extensible).
&gt; &gt; 
&gt; &gt; Is there any meaningful reason this has to be the case?

&gt; From an author perspective, I think it&apos;s good if specs state clearly that
&gt; some object is a proxy.

Ok, sure. I&apos;ve added a note to the spec indicating that these things should be considered to be proxies.

&gt; &gt; Hm, I&apos;m not sure I agree. |C| has to be proxy-like, but |close| is just a
&gt; &gt; regular function.
&gt; This is the same thing than postMessage above. C is the iframe global seen
&gt; from the parent (so it === the window inside the iframe). Both inside and
&gt; outside the iframe should see the same objectwhen getting
&gt; &apos;C.close&apos;/&apos;window.close&apos;(outside/inside resp.) and Object.getPrototypeOf can
&gt; only return a single value, so it has to be the Function.prototype from only
&gt; one of the contexts.

Er, the whole basis of this proposal is that different callers get different results. Assuming we make sure to mark these properties as non-configurable, how does this violate ES language invariants?

&gt; (In reply to Bobby Holley (:bholley) from comment #145)
&gt; &gt; Hixie and David - Putting those things aside, do you think this is in a
&gt; &gt; state that we can ask Microsoft and WebKit for feedback? Do you have any
&gt; &gt; outstanding concerns?
&gt; Nothing major stands out. I think it&apos;s a right time to ask for feedback.
&gt; Thanks a lot for the work on the tests, it does help a lot understanding the
&gt; intended behavior!

Ok, great! Thanks for your feedback :-)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99811</commentid>
    <comment_count>150</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-02-05 19:26:12 +0000</bug_when>
    <thetext>Looks fine to me, insofar as I understand it. :-)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99835</commentid>
    <comment_count>151</comment_count>
    <who name="Travis Leithead [MSFT]">travil</who>
    <bug_when>2014-02-05 22:22:52 +0000</bug_when>
    <thetext>Some bugs in your tests (couldn’t comment on github directly for some reason, so playing back my findings here):

Line 164: href should not be in the cross-domain allowable check—that’s why all the browser are failing that test.

Line 181: delete this line, you already have &quot;prop&quot; defined.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99837</commentid>
    <comment_count>152</comment_count>
    <who name="Travis Leithead [MSFT]">travil</who>
    <bug_when>2014-02-05 22:31:23 +0000</bug_when>
    <thetext>Chrome/IE throw on attempted enumeration of the cross-domain window, either via for..in, getOwnPropertyNames() or keys().

Is there a reason why this should be allowed? Seems to make life more complicated given that allowing this might lead a developer to expect to use for..of and apply an iterator (for what scenario or purpose I cannot imagine)...</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99842</commentid>
    <comment_count>153</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-02-05 22:45:45 +0000</bug_when>
    <thetext>(In reply to Travis Leithead [MSFT] from comment #151)
&gt; (couldn’t comment on github directly for some
&gt; reason, so playing back my findings here):

That&apos;s probably better anyway, since github stuff tends to be ephemeral.
 
&gt; Line 164: href should not be in the cross-domain allowable check—that’s why
&gt; all the browser are failing that test.

It&apos;s an accessor prop, right? It has a getter and a setter. Invoking the getter should throw, but I don&apos;t see any reason why looking up the property descriptor should throw.

&gt; Line 181: delete this line, you already have &quot;prop&quot; defined.

Good catch! I&apos;ll fix that.

(In reply to Travis Leithead [MSFT] from comment #152)
&gt; Chrome/IE throw on attempted enumeration of the cross-domain window, either
&gt; via for..in, getOwnPropertyNames() or keys().
&gt; 
&gt; Is there a reason why this should be allowed? Seems to make life more
&gt; complicated given that allowing this might lead a developer to expect to use
&gt; for..of and apply an iterator (for what scenario or purpose I cannot
&gt; imagine)...

The basic issue here is that throwing makes it a lot harder to write tests that verify that everything is kosher, because the tests will always get tripped up by the minefield of exceptions that tend to be subtly different between UAs. Removing various knee-jerk exceptions in my own attempt to get these tests to pass in Gecko revealed various subtle issues that I wouldn&apos;t have otherwise noticed.

UAs have historically been exception-happy on this stuff because it was underdefined and they wanted to be safe. We&apos;re defining it now (very carefully), and part of that is going to require making it possible to inspect these objects in predictable ways.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99845</commentid>
    <comment_count>154</comment_count>
    <who name="Travis Leithead [MSFT]">travil</who>
    <bug_when>2014-02-05 22:58:08 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #153)
&gt; (In reply to Travis Leithead [MSFT] from comment #151)
&gt; &gt; (couldn’t comment on github directly for some
&gt; &gt; reason, so playing back my findings here):
&gt; 
&gt; That&apos;s probably better anyway, since github stuff tends to be ephemeral.
&gt;  
&gt; &gt; Line 164: href should not be in the cross-domain allowable check—that’s why
&gt; &gt; all the browser are failing that test.
&gt; 
&gt; It&apos;s an accessor prop, right? It has a getter and a setter. Invoking the
&gt; getter should throw, but I don&apos;t see any reason why looking up the property
&gt; descriptor should throw.

But you assert on line 85 that non-cross-domain accessible properties throw when requesting their property descriptors...</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99848</commentid>
    <comment_count>155</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-02-05 23:07:54 +0000</bug_when>
    <thetext>(In reply to Travis Leithead [MSFT] from comment #154)
&gt; &gt; It&apos;s an accessor prop, right? It has a getter and a setter. Invoking the
&gt; &gt; getter should throw, but I don&apos;t see any reason why looking up the property
&gt; &gt; descriptor should throw.
&gt; 
&gt; But you assert on line 85 that non-cross-domain accessible properties throw
&gt; when requesting their property descriptors...

Good point.

Thinking about it again, I think the correct reasoning is that cross-origin callers do have a legitimate reason to lookup the |href| property descriptor, because they&apos;re allowed to call the setter.

So I think in this case Object.getOwnPropertyDescriptor(xoWin.location, &apos;href&apos;) should succeed, and that it should have a setter, but no getter. If that doesn&apos;t work for some reason, I guess the next-best thing would be to have the getter throw. But the former seems better.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99912</commentid>
    <comment_count>156</comment_count>
    <who name="Simon Pieters">zcorpan</who>
    <bug_when>2014-02-06 14:34:04 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #148)
&gt; It seems like we shouldn&apos;t land the tests until the behavior they&apos;re testing
&gt; actually ends up in the spec, right?

Right, but making a pull request is not landing.

When you make a pull request, a critic review will be created automatically where people can put their comments. You can still make changes to the branch in response to comments.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>99963</commentid>
    <comment_count>157</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-02-06 23:11:25 +0000</bug_when>
    <thetext>(In reply to Simon Pieters from comment #156)
&gt; When you make a pull request, a critic review will be created automatically
&gt; where people can put their comments. You can still make changes to the
&gt; branch in response to comments.

Ok. Opened a PR.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>101141</commentid>
    <comment_count>158</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-02-21 21:06:56 +0000</bug_when>
    <thetext>How are things going? Are we going ahead with the proposal?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>101142</commentid>
    <comment_count>159</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-02-21 21:08:35 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #158)
&gt; How are things going? Are we going ahead with the proposal?

Adam said he was going to take a look a couple of weeks ago - not sure what the status on that is.

Travis, do you have any other feedback here? Does the proposal sound workable?

No word from WebKit.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>101152</commentid>
    <comment_count>160</comment_count>
    <who name="Travis Leithead [MSFT]">travil</who>
    <bug_when>2014-02-21 22:05:11 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #159)
&gt; (In reply to Ian &apos;Hixie&apos; Hickson from comment #158)
&gt; &gt; How are things going? Are we going ahead with the proposal?
&gt; 
&gt; Travis, do you have any other feedback here? Does the proposal sound
&gt; workable?

If the test suite represents what is in the proposal, than I believe I am on board. Separately, I ran through the test suite and identified the 6 or so bugs that IE needs to fix in order to pass the test suite--and each of the issues seem like legitimate things we either 1) already knew about and just have in our backlog or 2) are gaps where the spec&apos;d behavior makes sense conceptually and we shouldn&apos;t have a problem implementing. (Of course, I reserve the right to have more feedback once we do start implementing, but from what I see right now, things look fine.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>101183</commentid>
    <comment_count>161</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-02-22 00:30:00 +0000</bug_when>
    <thetext>(In reply to Travis Leithead [MSFT] from comment #160)
&gt; If the test suite represents what is in the proposal, than I believe I am on
&gt; board.

That&apos;s great to hear!

&gt; Separately, I ran through the test suite and identified the 6 or so
&gt; bugs that IE needs to fix in order to pass the test suite--and each of the
&gt; issues seem like legitimate things we either 1) already knew about and just
&gt; have in our backlog or 2) are gaps where the spec&apos;d behavior makes sense
&gt; conceptually and we shouldn&apos;t have a problem implementing. (Of course, I
&gt; reserve the right to have more feedback once we do start implementing, but
&gt; from what I see right now, things look fine.

Same story on the Gecko side. I&apos;ve got patches that get us most of the way there, but I can&apos;t pass all the tests until we land a rewrite of our Window bindings, which should happen before the end of March. On a high level though, I think this is something we can do efficiently and securely.

Hixie - I sent mail a while back to Sam Weinig from WebKit, but never heard back. Any thoughts as to next steps?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>101251</commentid>
    <comment_count>162</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-02-24 18:39:46 +0000</bug_when>
    <thetext>I guess we should try shipping it, see if anything breaks.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>101256</commentid>
    <comment_count>163</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-02-24 19:19:31 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #162)
&gt; I guess we should try shipping it, see if anything breaks.

Yes. Though ideally, we&apos;d have some preliminary consensus before doing that. Though given Travis&apos; support, and assuming Adam&apos;s still on board with what we discussed in SF, we&apos;re in relatively good shape here.

If there&apos;s no schedule slippage, this should land in Gecko around the end of Q1 (once we land the new WebIDL bindings for Window and Location). The bug to track is https://bugzilla.mozilla.org/show_bug.cgi?id=965898</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108920</commentid>
    <comment_count>164</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-07-14 21:07:55 +0000</bug_when>
    <thetext>The relevant deps for this finally landed in Gecko (sorry it took way longer than predicted). I&apos;ll get on this in the next couple of days.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>110015</commentid>
    <comment_count>165</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-08-07 04:42:08 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #164)
&gt; The relevant deps for this finally landed in Gecko (sorry it took way longer
&gt; than predicted). I&apos;ll get on this in the next couple of days.

This landed in Gecko a few weeks ago, and should ship in Firefox 34.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>111455</commentid>
    <comment_count>166</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-09-12 18:26:36 +0000</bug_when>
    <thetext>bholley: what&apos;s the verdict? Any compat issues?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>111457</commentid>
    <comment_count>167</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-09-12 18:32:14 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #166)
&gt; bholley: what&apos;s the verdict? Any compat issues?

None yet. It&apos;s currently shipping on Aurora, and should hit release on November 24th.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>111464</commentid>
    <comment_count>168</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-09-13 00:50:18 +0000</bug_when>
    <thetext>(In reply to Bobby Holley (:bholley) from comment #167)
&gt; (In reply to Ian &apos;Hixie&apos; Hickson from comment #166)
&gt; &gt; bholley: what&apos;s the verdict? Any compat issues?
&gt; 
&gt; None yet. It&apos;s currently shipping on Aurora, and should hit release on
&gt; November 24th.

Needless to say, I&apos;m pretty confident that the code is going to ship without difficulty. If you have time to start polishing up the spec, I don&apos;t think it would be premature to do so.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>111544</commentid>
    <comment_count>169</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-09-15 21:57:07 +0000</bug_when>
    <thetext>Given the importance and subtlety of this issue, I&apos;m going to wait until it&apos;s been shipping for a few days before making any spec changes.

Do you have a description of what it is you ended up shipping?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>111585</commentid>
    <comment_count>170</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-09-16 10:41:02 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #169)
&gt; Given the importance and subtlety of this issue, I&apos;m going to wait until
&gt; it&apos;s been shipping for a few days before making any spec changes.

Ok.
 
&gt; Do you have a description of what it is you ended up shipping?

See https://bugzilla.mozilla.org/show_bug.cgi?id=965898#c1 .</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>115588</commentid>
    <comment_count>171</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-11-27 01:25:02 +0000</bug_when>
    <thetext>This is now shipping. \o/

Ball is now in Hixie&apos;s court to update the spec.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>115640</commentid>
    <comment_count>172</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-11-28 04:18:48 +0000</bug_when>
    <thetext>Nice, this is shipping and there&apos;s no sign that the world has ended?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>115647</commentid>
    <comment_count>173</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2014-11-28 07:02:24 +0000</bug_when>
    <thetext>(In reply to Ian &apos;Hixie&apos; Hickson from comment #172)
&gt; Nice, this is shipping and there&apos;s no sign that the world has ended?

Correct.

Exhaustive tests are also in web-platform-tests: https://github.com/w3c/web-platform-tests/tree/master/html/browsers/origin/cross-origin-objects</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>115747</commentid>
    <comment_count>174</comment_count>
    <who name="Ian &apos;Hixie&apos; Hickson">ian</who>
    <bug_when>2014-12-01 18:57:55 +0000</bug_when>
    <thetext>Alright! Let&apos;s move this back to my &quot;active&quot; list!</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>121413</commentid>
    <comment_count>175</comment_count>
      <attachid>1433</attachid>
    <who name="Kiks soto">Kikaayala12</who>
    <bug_when>2015-06-22 04:32:54 +0000</bug_when>
    <thetext>Comment on attachment 1433
Tests. v1

https://www.w3.org/Bugs/Public/attachment.cgi?id=1433</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>121414</commentid>
    <comment_count>176</comment_count>
      <attachid>1433</attachid>
    <who name="Kiks soto">Kikaayala12</who>
    <bug_when>2015-06-22 04:33:03 +0000</bug_when>
    <thetext>Comment on attachment 1433
Tests. v1

https://www.w3.org/Bugs/Public/attachment.cgi?id=1433</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>121415</commentid>
    <comment_count>177</comment_count>
      <attachid>1433</attachid>
    <who name="Kiks soto">Kikaayala12</who>
    <bug_when>2015-06-22 04:33:35 +0000</bug_when>
    <thetext>Comment on attachment 1433
Tests. v1

https://www.w3.org/Bugs/Public/attachment.cgi?id=1433</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>121416</commentid>
    <comment_count>178</comment_count>
      <attachid>1433</attachid>
    <who name="Kiks soto">Kikaayala12</who>
    <bug_when>2015-06-22 04:34:37 +0000</bug_when>
    <thetext>Comment on attachment 1433
Tests. v1

# HG changeset patch
# User Bobby Holley &lt;bobbyholley@gmail.com&gt;

Cross-origin object behavior.


diff --git a/html/browsers/origin/cross-origin-objects/MANIFEST b/html/browsers/origin/cross-origin-objects/MANIFEST
new file mode 100644
index 0000000..8c9039e
--- /dev/null
+++ b/html/browsers/origin/cross-origin-objects/MANIFEST
@@ -0,0 +1 @@
+cross-origin-objects.html
diff --git a/html/browsers/origin/cross-origin-objects/cross-origin-objects.html b/html/browsers/origin/cross-origin-objects/cross-origin-objects.html
new file mode 100644
index 0000000..320a7be
--- /dev/null
+++ b/html/browsers/origin/cross-origin-objects/cross-origin-objects.html
@@ -0,0 +1,329 @@
+&lt;!doctype html&gt;
+&lt;meta charset=utf-8&gt;
+&lt;title&gt;Cross-origin behavior of Window and Location&lt;/title&gt;
+&lt;link rel=&quot;author&quot; title=&quot;Bobby Holley (:bholley)&quot; href=&quot;bobbyholley@gmail.com&quot;&gt;
+&lt;link rel=&quot;help&quot; href=&quot;http://www.whatwg.org/specs/web-apps/current-work/#security-window&quot;&gt;
+&lt;link rel=&quot;help&quot; href=&quot;http://www.whatwg.org/specs/web-apps/current-work/#security-location&quot;&gt;
+&lt;script src=&quot;/resources/testharness.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;/resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
+&lt;div id=log&gt;&lt;/div&gt;
+&lt;iframe name=&quot;B&quot;&gt;&lt;/iframe&gt;
+&lt;iframe name=&quot;C&quot;&gt;&lt;/iframe&gt;
+&lt;iframe name=&quot;D&quot;&gt;&lt;/iframe&gt;
+&lt;iframe name=&quot;E&quot;&gt;&lt;/iframe&gt;
+&lt;script&gt;
+
+/*
+ * Setup boilerplate. This gives us a same-origin window &quot;B&quot; and a cross-origin
+ * window &quot;C&quot;.
+ */
+
+setup({explicit_done: true});
+path = location.pathname.substring(0, location.pathname.lastIndexOf(&apos;/&apos;)) + &apos;/frame.html&apos;;
+B.frameElement.uriToLoad = path;
+C.frameElement.uriToLoad = &apos;http://www1.web-platform.test:&apos; + location.port + path;
+
+// The last two are only used for the document.domain tests, in which D ceases to
+// be same-origin with E and becomes same-origin with B.
+D.frameElement.uriToLoad = &apos;http://www2.web-platform.test:&apos; + location.port + path;
+E.frameElement.uriToLoad = &apos;http://www2.web-platform.test:&apos; + location.port + path;
+
+function reloadSubframes(cb) {
+  var iframes = document.getElementsByTagName(&apos;iframe&apos;);
+  iframes.forEach = Array.prototype.forEach;
+  var count = 0;
+  function frameLoaded() {
+    if (++count == iframes.length) {
+      iframes.forEach(function(ifr) { ifr.onload = null; });
+      cb();
+    }
+  }
+  iframes.forEach(function(ifr) { ifr.onload = frameLoaded; ifr.setAttribute(&apos;src&apos;, ifr.uriToLoad); });
+}
+
+/*
+ * Note: we eschew assert_equals in a lot of these tests, since the harness ends
+ * up throwing when it tries to format a message involving a cross-origin object.
+ */
+
+var testList = [];
+function addTest(fun, desc) { testList.push([fun, desc]); }
+
+
+/*
+ * Basic sanity testing.
+ */
+
+addTest(function() {
+  assert_equals(location.host, &apos;web-platform.test:8000&apos;, &apos;Need to run the top-level test from web-platform.test:8000&apos;);
+  assert_equals(B.parent, window, &quot;window.parent works same-origin&quot;);
+  assert_equals(C.parent, window, &quot;window.parent works cross-origin&quot;);
+  assert_equals(B.location.pathname, path, &quot;location.href works same-origin&quot;);
+  assert_throws(null, function() { C.location.pathname; }, &quot;location.pathname throws cross-origin&quot;);
+}, &quot;Basic sanity-checking&quot;);
+
+/*
+ * Whitelist behavior.
+ *
+ * Also tests for [[GetOwnProperty]] and [[HasOwnProperty]] behavior.
+ */
+
+var whitelistedWindowProps = [&apos;location&apos;, &apos;postMessage&apos;, &apos;window&apos;, &apos;frames&apos;, &apos;self&apos;, &apos;top&apos;, &apos;parent&apos;,
+                              &apos;opener&apos;, &apos;closed&apos;, &apos;close&apos;, &apos;blur&apos;, &apos;focus&apos;, &apos;length&apos;];
+addTest(function() {
+    for (var prop in window) {
+      if (whitelistedWindowProps.indexOf(prop) != -1) {
+        C[prop]; // Shouldn&apos;t throw.
+        Object.getOwnPropertyDescriptor(C, prop); // Shouldn&apos;t throw.
+        assert_true(Object.prototype.hasOwnProperty.call(C, prop), &quot;hasOwnProperty for &quot; + prop);
+      } else {
+        assert_throws(null, function() { C[prop]; }, &quot;Should throw when accessing &quot; + prop + &quot; on Window&quot;);
+        assert_throws(null, function() { Object.getOwnPropertyDescriptor(C, prop); },
+                      &quot;Should throw when accessing property descriptor for &quot; + prop + &quot; on Window&quot;);
+        assert_throws(null, function() { Object.prototype.hasOwnProperty.call(C, prop); },
+                      &quot;Should throw when invoking hasOwnProperty for &quot; + prop + &quot; on Window&quot;);
+      }
+      if (prop != &apos;location&apos;)
+        assert_throws(null, function() { C[prop] = undefined; }, &quot;Should throw when writing to &quot; + prop + &quot; on Window&quot;);
+    }
+    for (var prop in location) {
+      if (prop == &apos;replace&apos;) {
+        C.location[prop]; // Shouldn&apos;t throw.
+        Object.getOwnPropertyDescriptor(C.location, prop); // Shouldn&apos;t throw.
+        assert_true(Object.prototype.hasOwnProperty.call(C.location, prop), &quot;hasOwnProperty for &quot; + prop);
+      }
+      else {
+        assert_throws(null, function() { C[prop]; }, &quot;Should throw when accessing &quot; + prop + &quot; on Location&quot;);
+        assert_throws(null, function() { Object.getOwnPropertyDescriptor(C, prop); },
+                      &quot;Should throw when accessing property descriptor for &quot; + prop + &quot; on Location&quot;);
+        assert_throws(null, function() { Object.prototype.hasOwnProperty.call(C, prop); },
+                      &quot;Should throw when invoking hasOwnProperty for &quot; + prop + &quot; on Location&quot;);
+      }
+      if (prop != &apos;href&apos;)
+        assert_throws(null, function() { C[prop] = undefined; }, &quot;Should throw when writing to &quot; + prop + &quot; on Location&quot;);
+    }
+}, &quot;Only whitelisted properties are accessible cross-origin&quot;);
+
+/*
+ * ES Internal Methods.
+ */
+
+/*
+ * [[GetPrototypeOf]]
+ */
+addTest(function() {
+  assert_true(Object.getPrototypeOf(C) === null, &quot;cross-origin Window proto is null&quot;);
+  assert_true(Object.getPrototypeOf(C.location) === null, &quot;cross-origin Location proto is null&quot;);
+}, &quot;[[GetPrototypeOf]] should return null&quot;);
+
+/*
+ * [[SetPrototypeOf]]
+ */
+addTest(function() {
+  assert_throws(null, function() { C.__proto__ = new Object(); }, &quot;proto set on cross-origin Window&quot;);
+  assert_throws(null, function() { C.location.__proto__ = new Object(); }, &quot;proto set on cross-origin Location&quot;);
+  var protoSetter = Object.getOwnPropertyDescriptor(Object.prototype, &apos;__proto__&apos;).set;
+  assert_throws(null, function() { protoSetter.call(C, new Object()); }, &quot;proto setter |call| on cross-origin Window&quot;);
+  assert_throws(null, function() { protoSetter.call(C.location, new Object()); }, &quot;proto setter |call| on cross-origin Location&quot;);
+}, &quot;[[SetPrototypeOf]] should throw&quot;);
+
+/*
+ * [[IsExtensible]]
+ */
+addTest(function() {
+  assert_true(Object.isExtensible(C), &quot;cross-origin Window should be extensible&quot;);
+  assert_true(Object.isExtensible(C.location), &quot;cross-origin Location should be extensible&quot;);
+}, &quot;[[IsExtensible]] should return true for cross-origin objects&quot;);
+
+/*
+ * [[PreventExtensions]]
+ */
+addTest(function() {
+  assert_throws(null, function() { Object.preventExtensions(C) },
+                &quot;preventExtensions on cross-origin Window should throw&quot;);
+  assert_throws(null, function() { Object.preventExtensions(C.location) },
+                &quot;preventExtensions on cross-origin Location should throw&quot;);
+}, &quot;[[PreventExtensions]] should throw for cross-origin objects&quot;);
+
+/*
+ * [[GetOwnProperty]]
+ */
+
+addTest(function() {
+  assert_true(typeof Object.getOwnPropertyDescriptor(C, &apos;close&apos;) == &apos;object&apos;, &quot;C.close is |own|&quot;);
+  assert_true(typeof Object.getOwnPropertyDescriptor(C, &apos;top&apos;) == &apos;object&apos;, &quot;C.top is |own|&quot;);
+  assert_true(typeof Object.getOwnPropertyDescriptor(C.location, &apos;href&apos;) == &apos;object&apos;, &quot;C.location.href is |own|&quot;);
+  assert_true(typeof Object.getOwnPropertyDescriptor(C.location, &apos;replace&apos;) == &apos;object&apos;, &quot;C.location.replace is |own|&quot;);
+}, &quot;[[GetOwnProperty]] - Properties on cross-origin objects should be reported |own|&quot;);
+
+function checkPropertyDescriptor(desc, propName, expectWritable) {
+  assert_equals(typeof desc, &apos;object&apos;, &quot;property descriptor for &quot; + propName + &quot; should exist&quot;);
+  assert_equals(desc.enumerable, false, &quot;property descriptor for &quot; + propName + &quot; should be non-enumerable&quot;);
+  assert_equals(desc.configurable, false, &quot;property descriptor for &quot; + propName + &quot; should be non-configurable&quot;);
+  if (&apos;value&apos; in desc)
+    assert_equals(desc.writable, expectWritable, &quot;property descriptor for &quot; + propName + &quot; should have writable: &quot; + expectWritable);
+  else
+    assert_equals(&apos;set&apos; in desc, expectWritable,
+                  &quot;property descriptor for &quot; + propName + &quot; should &quot; + (expectWritable ? &quot;&quot; : &quot;not &quot;) + &quot;have setter&quot;);
+}
+
+addTest(function() {
+    for (var p in whitelistedWindowProps) {
+      var prop = whitelistedWindowProps[p];
+      var desc = Object.getOwnPropertyDescriptor(C, prop);
+      checkPropertyDescriptor(desc, prop, prop == &apos;location&apos;);
+    }
+    checkPropertyDescriptor(Object.getOwnPropertyDescriptor(C.location, &apos;replace&apos;), &apos;replace&apos;, false);
+    checkPropertyDescriptor(Object.getOwnPropertyDescriptor(C.location, &apos;href&apos;), &apos;href&apos;, true);
+    assertFalse(&apos;get&apos; in Object.getOwnPropertyDescriptor(C.location, &apos;href&apos;), &quot;Cross-origin location should have no href getter&quot;);
+}, &quot;[[GetOwnProperty]] - Property descriptors for cross-origin properties should be set up correctly&quot;);
+
+/*
+ * [[Delete]]
+ */
+addTest(function() {
+    assert_throws(null, function() { delete C.location; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.parent; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.length; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.document; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.foopy; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.location.href; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.location.replace; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.location.port; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.location.foopy; }, &quot;Can&apos;t delete cross-origin property&quot;);
+}, &quot;[[Delete]] Should throw on cross-origin objects&quot;);
+
+/*
+ * [[DefineOwnProperty]]
+ */
+function checkDefine(obj, prop) {
+  var valueDesc = { configurable: false, enumerable: false, writable: false, value: 2 };
+  var accessorDesc = { configurable: false, enumerable: false, get: function() {} };
+  assert_throws(null, function() { Object.defineProperty(obj, prop, valueDesc); }, &quot;Can&apos;t define cross-origin property &quot; + prop);
+  assert_throws(null, function() { Object.defineProperty(obj, prop, valueDesc); }, &quot;Can&apos;t define cross-origin property &quot; + prop);
+}
+addTest(function() {
+    checkDefine(C, &apos;length&apos;);
+    checkDefine(C, &apos;parent&apos;);
+    checkDefine(C, &apos;location&apos;);
+    checkDefine(C, &apos;document&apos;);
+    checkDefine(C, &apos;foopy&apos;);
+    checkDefine(C.location, &apos;href&apos;);
+    checkDefine(C.location, &apos;replace&apos;);
+    checkDefine(C.location, &apos;port&apos;);
+    checkDefine(C.location, &apos;foopy&apos;);
+}, &quot;[[DefineOwnProperty]] Should throw for cross-origin objects&quot;);
+
+/*
+ * [[Enumerate]]
+ */
+
+addTest(function() {
+    for (var prop in C)
+      assert_true(false, &quot;Shouldn&apos;t have been able to enumerate &quot; + prop + &quot; on cross-origin Window&quot;);
+    for (var prop in C.location)
+      assert_true(false, &quot;Shouldn&apos;t have been able to enumerate &quot; + prop + &quot; on cross-origin Location&quot;);
+}, &quot;[[Enumerate]] should return an empty iterator&quot;);
+
+/*
+ * [[OwnPropertyKeys]]
+ */
+
+addTest(function() {
+  assert_equals(whitelistedWindowProps.sort().toSource(), Object.getOwnPropertyNames(C).sort().toSource(),
+                &quot;Object.getOwnPropertyNames() gives the right answer for cross-origin Window&quot;);
+  assert_equals([&apos;href&apos;, &apos;replace&apos;].toSource(), Object.getOwnPropertyNames(C.location).sort().toSource(),
+                &quot;Object.getOwnPropertyNames() gives the right answer for cross-origin Location&quot;);
+}, &quot;[[OwnPropertyKeys]] should return all properties from cross-origin objects&quot;);
+
+addTest(function() {
+  assert_true(B.eval(&apos;parent.C&apos;) === C, &quot;A and B observe the same identity for C&apos;s Window&quot;);
+  assert_true(B.eval(&apos;parent.C.location&apos;) === C.location, &quot;A and B observe the same identity for C&apos;s Location&quot;);
+}, &quot;A and B jointly observe the same identity for cross-origin Window and Location&quot;);
+
+function checkFunction(f, proto) {
+  assert_equals(typeof f, &apos;function&apos;, f.name + &quot; is a function&quot;);
+  assert_equals(Object.getPrototypeOf(f), proto, f.name + &quot; has the right prototype&quot;);
+}
+
+addTest(function() {
+  checkFunction(C.close, Function.prototype);
+  checkFunction(C.location.replace, Function.prototype);
+}, &quot;Cross-origin functions get local Function.prototype&quot;);
+
+addTest(function() {
+  assert_equals(typeof Object.getOwnPropertyDescriptor(C, &apos;top&apos;), &apos;object&apos;,
+                &quot;Need to be able to use Object.getOwnPropertyDescriptor do this test&quot;);
+  checkFunction(Object.getOwnPropertyDescriptor(C, &apos;top&apos;).get, Function.prototype);
+  checkFunction(Object.getOwnPropertyDescriptor(C.location, &apos;href&apos;).set, Function.prototype);
+}, &quot;Cross-origin Window accessors get local Function.prototype&quot;);
+
+addTest(function() {
+  checkFunction(close, Function.prototype);
+  assert_true(close != C.close, &apos;cross-origin Window functions get their own object&apos;);
+  var close_B = B.eval(&apos;top.C.close&apos;);
+  assert_true(close_B != C.close, &apos;different Window functions per-incumbent script settings object&apos;);
+  checkFunction(close_B, B.Function.prototype);
+
+  checkFunction(location.replace, Function.prototype);
+  assert_true(location.replace != C.location.replace, &quot;cross-origin Location functions get their own object&quot;);
+  var replace_B = B.eval(&apos;top.C.location.replace&apos;);
+  assert_true(replace_B != C.location.replace, &apos;different Location functions per-incumbent script settings object&apos;);
+  checkFunction(replace_B, B.Function.prototype);
+}, &quot;Same-origin observers get different functions for cross-origin objects&quot;);
+
+addTest(function() {
+  assert_equals(typeof Object.getOwnPropertyDescriptor(C, &apos;parent&apos;), &apos;object&apos;,
+                &quot;Need to be able to use Object.getOwnPropertyDescriptor do this test&quot;);
+  var get_self_parent = Object.getOwnPropertyDescriptor(window, &apos;parent&apos;).get;
+  var get_parent_A = Object.getOwnPropertyDescriptor(C, &apos;parent&apos;).get;
+  var get_parent_B = B.eval(&apos;Object.getOwnPropertyDescriptor(top.C, &quot;parent&quot;).get&apos;);
+  assert_true(get_self_parent != get_parent_A, &apos;different Window accessors per-incumbent script settings object&apos;);
+  assert_true(get_parent_A != get_parent_B, &apos;different Window accessors per-incumbent script settings object&apos;);
+  checkFunction(get_self_parent, Function.prototype);
+  checkFunction(get_parent_A, Function.prototype);
+  checkFunction(get_parent_B, B.Function.prototype);
+
+  var set_self_href = Object.getOwnPropertyDescriptor(window.location, &apos;href&apos;).set;
+  var set_href_A = Object.getOwnPropertyDescriptor(C.location, &apos;href&apos;).set;
+  var set_href_B = B.eval(&apos;Object.getOwnPropertyDescriptor(top.C.location, &quot;href&quot;).set&apos;);
+  assert_true(set_self_href != set_href_A, &apos;different Location accessors per-incumbent script settings object&apos;);
+  assert_true(set_href_A != set_href_B, &apos;different Location accessors per-incumbent script settings object&apos;);
+  checkFunction(set_self_href, Function.prototype);
+  checkFunction(set_href_A, Function.prototype);
+  checkFunction(set_href_B, B.Function.prototype);
+}, &quot;Same-origin observers get different accessors for cross-origin objects&quot;);
+
+// The document.domain test is unavoidably side-effect-y, so we do it last.
+function doDocumentDomainTest(cb) {
+    window.onmessage = function() {
+      test(function() {
+        assert_true(D.checkWindowReferences(), &quot;D&apos;s Window references are still self-consistent after document.domain&quot;);
+        for (var i = 0; i &lt; window.length; ++i) {
+          assert_true(window[i] === D.windowReferences[i],
+                      &quot;Window reference &quot; + i + &quot; consistent between globals after document.domain&quot;);
+          assert_true(window[i].location === D.locationReferences[i],
+                      &quot;Location reference &quot; + i + &quot; consistent between globals after document.domain&quot;);
+        }
+      }, &quot;Cross-origin object identity preserved across document.domain&quot;);
+      cb();
+    }
+    B.document.domain = B.document.domain;
+    document.domain = document.domain;
+    D.postMessage(&apos;&apos;, &apos;*&apos;);
+}
+
+// We do a fresh load of the subframes for each test to minimize side-effects.
+// It would be nice to reload ourselves as well, but we can&apos;t do that without
+// disrupting the test harness.
+function runNextTest() {
+  var entry = testList.shift();
+  test(entry[0], entry[1]);
+  if (testList.length != 0)
+    reloadSubframes(runNextTest);
+  else
+    doDocumentDomainTest(done); // Side-effect-y. Do it last.
+}
+reloadSubframes(runNextTest);
+
+&lt;/script&gt;
diff --git a/html/browsers/origin/cross-origin-objects/frame.html b/html/browsers/origin/cross-origin-objects/frame.html
new file mode 100644
index 0000000..c84a245
--- /dev/null
+++ b/html/browsers/origin/cross-origin-objects/frame.html
@@ -0,0 +1,31 @@
+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script&gt;
+  // If we get a postMessage, we grab references to everything and set
+  // document.domain to trim off our topmost subdomain.
+  window.onmessage = function(evt) {
+    window.windowReferences = [];
+    window.locationReferences = [];
+    for (var i = 0; i &lt; parent.length; ++i) {
+      windowReferences.push(parent[i]);
+      locationReferences.push(parent[i].location);
+    }
+    document.domain = document.domain.substring(document.domain.indexOf(&apos;.&apos;) + 1);
+    evt.source.postMessage(&apos;&apos;, &apos;*&apos;);
+  }
+
+  function checkWindowReferences() {
+    for (var i = 0; i &lt; parent.length; ++i) {
+      if (windowReferences[i] != parent[i])
+        throw new Error(&quot;Window references don&apos;t match for &quot; + i + &quot; after document.domain&quot;);
+      if (locationReferences[i] != parent[i].location)
+        throw new Error(&quot;Location references don&apos;t match for &quot; + i + &quot; after document.domain&quot;);
+    }
+    return true;
+  }
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;/body&gt;
+&lt;/html&gt;
-- 
1.8.4.3</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>121417</commentid>
    <comment_count>179</comment_count>
      <attachid>1433</attachid>
    <who name="Kiks soto">Kikaayala12</who>
    <bug_when>2015-06-22 04:35:07 +0000</bug_when>
    <thetext>Comment on attachment 1433
Tests. v1

# HG changeset patch
# User Bobby Holley &lt;bobbyholley@gmail.com&gt;

Cross-origin object behavior.


diff --git a/html/browsers/origin/cross-origin-objects/MANIFEST b/html/browsers/origin/cross-origin-objects/MANIFEST
new file mode 100644
index 0000000..8c9039e
--- /dev/null
+++ b/html/browsers/origin/cross-origin-objects/MANIFEST
@@ -0,0 +1 @@
+cross-origin-objects.html
diff --git a/html/browsers/origin/cross-origin-objects/cross-origin-objects.html b/html/browsers/origin/cross-origin-objects/cross-origin-objects.html
new file mode 100644
index 0000000..320a7be
--- /dev/null
+++ b/html/browsers/origin/cross-origin-objects/cross-origin-objects.html
@@ -0,0 +1,329 @@
+&lt;!doctype html&gt;
+&lt;meta charset=utf-8&gt;
+&lt;title&gt;Cross-origin behavior of Window and Location&lt;/title&gt;
+&lt;link rel=&quot;author&quot; title=&quot;Bobby Holley (:bholley)&quot; href=&quot;bobbyholley@gmail.com&quot;&gt;
+&lt;link rel=&quot;help&quot; href=&quot;http://www.whatwg.org/specs/web-apps/current-work/#security-window&quot;&gt;
+&lt;link rel=&quot;help&quot; href=&quot;http://www.whatwg.org/specs/web-apps/current-work/#security-location&quot;&gt;
+&lt;script src=&quot;/resources/testharness.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;/resources/testharnessreport.js&quot;&gt;&lt;/script&gt;
+&lt;div id=log&gt;&lt;/div&gt;
+&lt;iframe name=&quot;B&quot;&gt;&lt;/iframe&gt;
+&lt;iframe name=&quot;C&quot;&gt;&lt;/iframe&gt;
+&lt;iframe name=&quot;D&quot;&gt;&lt;/iframe&gt;
+&lt;iframe name=&quot;E&quot;&gt;&lt;/iframe&gt;
+&lt;script&gt;
+
+/*
+ * Setup boilerplate. This gives us a same-origin window &quot;B&quot; and a cross-origin
+ * window &quot;C&quot;.
+ */
+
+setup({explicit_done: true});
+path = location.pathname.substring(0, location.pathname.lastIndexOf(&apos;/&apos;)) + &apos;/frame.html&apos;;
+B.frameElement.uriToLoad = path;
+C.frameElement.uriToLoad = &apos;http://www1.web-platform.test:&apos; + location.port + path;
+
+// The last two are only used for the document.domain tests, in which D ceases to
+// be same-origin with E and becomes same-origin with B.
+D.frameElement.uriToLoad = &apos;http://www2.web-platform.test:&apos; + location.port + path;
+E.frameElement.uriToLoad = &apos;http://www2.web-platform.test:&apos; + location.port + path;
+
+function reloadSubframes(cb) {
+  var iframes = document.getElementsByTagName(&apos;iframe&apos;);
+  iframes.forEach = Array.prototype.forEach;
+  var count = 0;
+  function frameLoaded() {
+    if (++count == iframes.length) {
+      iframes.forEach(function(ifr) { ifr.onload = null; });
+      cb();
+    }
+  }
+  iframes.forEach(function(ifr) { ifr.onload = frameLoaded; ifr.setAttribute(&apos;src&apos;, ifr.uriToLoad); });
+}
+
+/*
+ * Note: we eschew assert_equals in a lot of these tests, since the harness ends
+ * up throwing when it tries to format a message involving a cross-origin object.
+ */
+
+var testList = [];
+function addTest(fun, desc) { testList.push([fun, desc]); }
+
+
+/*
+ * Basic sanity testing.
+ */
+
+addTest(function() {
+  assert_equals(location.host, &apos;web-platform.test:8000&apos;, &apos;Need to run the top-level test from web-platform.test:8000&apos;);
+  assert_equals(B.parent, window, &quot;window.parent works same-origin&quot;);
+  assert_equals(C.parent, window, &quot;window.parent works cross-origin&quot;);
+  assert_equals(B.location.pathname, path, &quot;location.href works same-origin&quot;);
+  assert_throws(null, function() { C.location.pathname; }, &quot;location.pathname throws cross-origin&quot;);
+}, &quot;Basic sanity-checking&quot;);
+
+/*
+ * Whitelist behavior.
+ *
+ * Also tests for [[GetOwnProperty]] and [[HasOwnProperty]] behavior.
+ */
+
+var whitelistedWindowProps = [&apos;location&apos;, &apos;postMessage&apos;, &apos;window&apos;, &apos;frames&apos;, &apos;self&apos;, &apos;top&apos;, &apos;parent&apos;,
+                              &apos;opener&apos;, &apos;closed&apos;, &apos;close&apos;, &apos;blur&apos;, &apos;focus&apos;, &apos;length&apos;];
+addTest(function() {
+    for (var prop in window) {
+      if (whitelistedWindowProps.indexOf(prop) != -1) {
+        C[prop]; // Shouldn&apos;t throw.
+        Object.getOwnPropertyDescriptor(C, prop); // Shouldn&apos;t throw.
+        assert_true(Object.prototype.hasOwnProperty.call(C, prop), &quot;hasOwnProperty for &quot; + prop);
+      } else {
+        assert_throws(null, function() { C[prop]; }, &quot;Should throw when accessing &quot; + prop + &quot; on Window&quot;);
+        assert_throws(null, function() { Object.getOwnPropertyDescriptor(C, prop); },
+                      &quot;Should throw when accessing property descriptor for &quot; + prop + &quot; on Window&quot;);
+        assert_throws(null, function() { Object.prototype.hasOwnProperty.call(C, prop); },
+                      &quot;Should throw when invoking hasOwnProperty for &quot; + prop + &quot; on Window&quot;);
+      }
+      if (prop != &apos;location&apos;)
+        assert_throws(null, function() { C[prop] = undefined; }, &quot;Should throw when writing to &quot; + prop + &quot; on Window&quot;);
+    }
+    for (var prop in location) {
+      if (prop == &apos;replace&apos;) {
+        C.location[prop]; // Shouldn&apos;t throw.
+        Object.getOwnPropertyDescriptor(C.location, prop); // Shouldn&apos;t throw.
+        assert_true(Object.prototype.hasOwnProperty.call(C.location, prop), &quot;hasOwnProperty for &quot; + prop);
+      }
+      else {
+        assert_throws(null, function() { C[prop]; }, &quot;Should throw when accessing &quot; + prop + &quot; on Location&quot;);
+        assert_throws(null, function() { Object.getOwnPropertyDescriptor(C, prop); },
+                      &quot;Should throw when accessing property descriptor for &quot; + prop + &quot; on Location&quot;);
+        assert_throws(null, function() { Object.prototype.hasOwnProperty.call(C, prop); },
+                      &quot;Should throw when invoking hasOwnProperty for &quot; + prop + &quot; on Location&quot;);
+      }
+      if (prop != &apos;href&apos;)
+        assert_throws(null, function() { C[prop] = undefined; }, &quot;Should throw when writing to &quot; + prop + &quot; on Location&quot;);
+    }
+}, &quot;Only whitelisted properties are accessible cross-origin&quot;);
+
+/*
+ * ES Internal Methods.
+ */
+
+/*
+ * [[GetPrototypeOf]]
+ */
+addTest(function() {
+  assert_true(Object.getPrototypeOf(C) === null, &quot;cross-origin Window proto is null&quot;);
+  assert_true(Object.getPrototypeOf(C.location) === null, &quot;cross-origin Location proto is null&quot;);
+}, &quot;[[GetPrototypeOf]] should return null&quot;);
+
+/*
+ * [[SetPrototypeOf]]
+ */
+addTest(function() {
+  assert_throws(null, function() { C.__proto__ = new Object(); }, &quot;proto set on cross-origin Window&quot;);
+  assert_throws(null, function() { C.location.__proto__ = new Object(); }, &quot;proto set on cross-origin Location&quot;);
+  var protoSetter = Object.getOwnPropertyDescriptor(Object.prototype, &apos;__proto__&apos;).set;
+  assert_throws(null, function() { protoSetter.call(C, new Object()); }, &quot;proto setter |call| on cross-origin Window&quot;);
+  assert_throws(null, function() { protoSetter.call(C.location, new Object()); }, &quot;proto setter |call| on cross-origin Location&quot;);
+}, &quot;[[SetPrototypeOf]] should throw&quot;);
+
+/*
+ * [[IsExtensible]]
+ */
+addTest(function() {
+  assert_true(Object.isExtensible(C), &quot;cross-origin Window should be extensible&quot;);
+  assert_true(Object.isExtensible(C.location), &quot;cross-origin Location should be extensible&quot;);
+}, &quot;[[IsExtensible]] should return true for cross-origin objects&quot;);
+
+/*
+ * [[PreventExtensions]]
+ */
+addTest(function() {
+  assert_throws(null, function() { Object.preventExtensions(C) },
+                &quot;preventExtensions on cross-origin Window should throw&quot;);
+  assert_throws(null, function() { Object.preventExtensions(C.location) },
+                &quot;preventExtensions on cross-origin Location should throw&quot;);
+}, &quot;[[PreventExtensions]] should throw for cross-origin objects&quot;);
+
+/*
+ * [[GetOwnProperty]]
+ */
+
+addTest(function() {
+  assert_true(typeof Object.getOwnPropertyDescriptor(C, &apos;close&apos;) == &apos;object&apos;, &quot;C.close is |own|&quot;);
+  assert_true(typeof Object.getOwnPropertyDescriptor(C, &apos;top&apos;) == &apos;object&apos;, &quot;C.top is |own|&quot;);
+  assert_true(typeof Object.getOwnPropertyDescriptor(C.location, &apos;href&apos;) == &apos;object&apos;, &quot;C.location.href is |own|&quot;);
+  assert_true(typeof Object.getOwnPropertyDescriptor(C.location, &apos;replace&apos;) == &apos;object&apos;, &quot;C.location.replace is |own|&quot;);
+}, &quot;[[GetOwnProperty]] - Properties on cross-origin objects should be reported |own|&quot;);
+
+function checkPropertyDescriptor(desc, propName, expectWritable) {
+  assert_equals(typeof desc, &apos;object&apos;, &quot;property descriptor for &quot; + propName + &quot; should exist&quot;);
+  assert_equals(desc.enumerable, false, &quot;property descriptor for &quot; + propName + &quot; should be non-enumerable&quot;);
+  assert_equals(desc.configurable, false, &quot;property descriptor for &quot; + propName + &quot; should be non-configurable&quot;);
+  if (&apos;value&apos; in desc)
+    assert_equals(desc.writable, expectWritable, &quot;property descriptor for &quot; + propName + &quot; should have writable: &quot; + expectWritable);
+  else
+    assert_equals(&apos;set&apos; in desc, expectWritable,
+                  &quot;property descriptor for &quot; + propName + &quot; should &quot; + (expectWritable ? &quot;&quot; : &quot;not &quot;) + &quot;have setter&quot;);
+}
+
+addTest(function() {
+    for (var p in whitelistedWindowProps) {
+      var prop = whitelistedWindowProps[p];
+      var desc = Object.getOwnPropertyDescriptor(C, prop);
+      checkPropertyDescriptor(desc, prop, prop == &apos;location&apos;);
+    }
+    checkPropertyDescriptor(Object.getOwnPropertyDescriptor(C.location, &apos;replace&apos;), &apos;replace&apos;, false);
+    checkPropertyDescriptor(Object.getOwnPropertyDescriptor(C.location, &apos;href&apos;), &apos;href&apos;, true);
+    assertFalse(&apos;get&apos; in Object.getOwnPropertyDescriptor(C.location, &apos;href&apos;), &quot;Cross-origin location should have no href getter&quot;);
+}, &quot;[[GetOwnProperty]] - Property descriptors for cross-origin properties should be set up correctly&quot;);
+
+/*
+ * [[Delete]]
+ */
+addTest(function() {
+    assert_throws(null, function() { delete C.location; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.parent; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.length; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.document; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.foopy; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.location.href; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.location.replace; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.location.port; }, &quot;Can&apos;t delete cross-origin property&quot;);
+    assert_throws(null, function() { delete C.location.foopy; }, &quot;Can&apos;t delete cross-origin property&quot;);
+}, &quot;[[Delete]] Should throw on cross-origin objects&quot;);
+
+/*
+ * [[DefineOwnProperty]]
+ */
+function checkDefine(obj, prop) {
+  var valueDesc = { configurable: false, enumerable: false, writable: false, value: 2 };
+  var accessorDesc = { configurable: false, enumerable: false, get: function() {} };
+  assert_throws(null, function() { Object.defineProperty(obj, prop, valueDesc); }, &quot;Can&apos;t define cross-origin property &quot; + prop);
+  assert_throws(null, function() { Object.defineProperty(obj, prop, valueDesc); }, &quot;Can&apos;t define cross-origin property &quot; + prop);
+}
+addTest(function() {
+    checkDefine(C, &apos;length&apos;);
+    checkDefine(C, &apos;parent&apos;);
+    checkDefine(C, &apos;location&apos;);
+    checkDefine(C, &apos;document&apos;);
+    checkDefine(C, &apos;foopy&apos;);
+    checkDefine(C.location, &apos;href&apos;);
+    checkDefine(C.location, &apos;replace&apos;);
+    checkDefine(C.location, &apos;port&apos;);
+    checkDefine(C.location, &apos;foopy&apos;);
+}, &quot;[[DefineOwnProperty]] Should throw for cross-origin objects&quot;);
+
+/*
+ * [[Enumerate]]
+ */
+
+addTest(function() {
+    for (var prop in C)
+      assert_true(false, &quot;Shouldn&apos;t have been able to enumerate &quot; + prop + &quot; on cross-origin Window&quot;);
+    for (var prop in C.location)
+      assert_true(false, &quot;Shouldn&apos;t have been able to enumerate &quot; + prop + &quot; on cross-origin Location&quot;);
+}, &quot;[[Enumerate]] should return an empty iterator&quot;);
+
+/*
+ * [[OwnPropertyKeys]]
+ */
+
+addTest(function() {
+  assert_equals(whitelistedWindowProps.sort().toSource(), Object.getOwnPropertyNames(C).sort().toSource(),
+                &quot;Object.getOwnPropertyNames() gives the right answer for cross-origin Window&quot;);
+  assert_equals([&apos;href&apos;, &apos;replace&apos;].toSource(), Object.getOwnPropertyNames(C.location).sort().toSource(),
+                &quot;Object.getOwnPropertyNames() gives the right answer for cross-origin Location&quot;);
+}, &quot;[[OwnPropertyKeys]] should return all properties from cross-origin objects&quot;);
+
+addTest(function() {
+  assert_true(B.eval(&apos;parent.C&apos;) === C, &quot;A and B observe the same identity for C&apos;s Window&quot;);
+  assert_true(B.eval(&apos;parent.C.location&apos;) === C.location, &quot;A and B observe the same identity for C&apos;s Location&quot;);
+}, &quot;A and B jointly observe the same identity for cross-origin Window and Location&quot;);
+
+function checkFunction(f, proto) {
+  assert_equals(typeof f, &apos;function&apos;, f.name + &quot; is a function&quot;);
+  assert_equals(Object.getPrototypeOf(f), proto, f.name + &quot; has the right prototype&quot;);
+}
+
+addTest(function() {
+  checkFunction(C.close, Function.prototype);
+  checkFunction(C.location.replace, Function.prototype);
+}, &quot;Cross-origin functions get local Function.prototype&quot;);
+
+addTest(function() {
+  assert_equals(typeof Object.getOwnPropertyDescriptor(C, &apos;top&apos;), &apos;object&apos;,
+                &quot;Need to be able to use Object.getOwnPropertyDescriptor do this test&quot;);
+  checkFunction(Object.getOwnPropertyDescriptor(C, &apos;top&apos;).get, Function.prototype);
+  checkFunction(Object.getOwnPropertyDescriptor(C.location, &apos;href&apos;).set, Function.prototype);
+}, &quot;Cross-origin Window accessors get local Function.prototype&quot;);
+
+addTest(function() {
+  checkFunction(close, Function.prototype);
+  assert_true(close != C.close, &apos;cross-origin Window functions get their own object&apos;);
+  var close_B = B.eval(&apos;top.C.close&apos;);
+  assert_true(close_B != C.close, &apos;different Window functions per-incumbent script settings object&apos;);
+  checkFunction(close_B, B.Function.prototype);
+
+  checkFunction(location.replace, Function.prototype);
+  assert_true(location.replace != C.location.replace, &quot;cross-origin Location functions get their own object&quot;);
+  var replace_B = B.eval(&apos;top.C.location.replace&apos;);
+  assert_true(replace_B != C.location.replace, &apos;different Location functions per-incumbent script settings object&apos;);
+  checkFunction(replace_B, B.Function.prototype);
+}, &quot;Same-origin observers get different functions for cross-origin objects&quot;);
+
+addTest(function() {
+  assert_equals(typeof Object.getOwnPropertyDescriptor(C, &apos;parent&apos;), &apos;object&apos;,
+                &quot;Need to be able to use Object.getOwnPropertyDescriptor do this test&quot;);
+  var get_self_parent = Object.getOwnPropertyDescriptor(window, &apos;parent&apos;).get;
+  var get_parent_A = Object.getOwnPropertyDescriptor(C, &apos;parent&apos;).get;
+  var get_parent_B = B.eval(&apos;Object.getOwnPropertyDescriptor(top.C, &quot;parent&quot;).get&apos;);
+  assert_true(get_self_parent != get_parent_A, &apos;different Window accessors per-incumbent script settings object&apos;);
+  assert_true(get_parent_A != get_parent_B, &apos;different Window accessors per-incumbent script settings object&apos;);
+  checkFunction(get_self_parent, Function.prototype);
+  checkFunction(get_parent_A, Function.prototype);
+  checkFunction(get_parent_B, B.Function.prototype);
+
+  var set_self_href = Object.getOwnPropertyDescriptor(window.location, &apos;href&apos;).set;
+  var set_href_A = Object.getOwnPropertyDescriptor(C.location, &apos;href&apos;).set;
+  var set_href_B = B.eval(&apos;Object.getOwnPropertyDescriptor(top.C.location, &quot;href&quot;).set&apos;);
+  assert_true(set_self_href != set_href_A, &apos;different Location accessors per-incumbent script settings object&apos;);
+  assert_true(set_href_A != set_href_B, &apos;different Location accessors per-incumbent script settings object&apos;);
+  checkFunction(set_self_href, Function.prototype);
+  checkFunction(set_href_A, Function.prototype);
+  checkFunction(set_href_B, B.Function.prototype);
+}, &quot;Same-origin observers get different accessors for cross-origin objects&quot;);
+
+// The document.domain test is unavoidably side-effect-y, so we do it last.
+function doDocumentDomainTest(cb) {
+    window.onmessage = function() {
+      test(function() {
+        assert_true(D.checkWindowReferences(), &quot;D&apos;s Window references are still self-consistent after document.domain&quot;);
+        for (var i = 0; i &lt; window.length; ++i) {
+          assert_true(window[i] === D.windowReferences[i],
+                      &quot;Window reference &quot; + i + &quot; consistent between globals after document.domain&quot;);
+          assert_true(window[i].location === D.locationReferences[i],
+                      &quot;Location reference &quot; + i + &quot; consistent between globals after document.domain&quot;);
+        }
+      }, &quot;Cross-origin object identity preserved across document.domain&quot;);
+      cb();
+    }
+    B.document.domain = B.document.domain;
+    document.domain = document.domain;
+    D.postMessage(&apos;&apos;, &apos;*&apos;);
+}
+
+// We do a fresh load of the subframes for each test to minimize side-effects.
+// It would be nice to reload ourselves as well, but we can&apos;t do that without
+// disrupting the test harness.
+function runNextTest() {
+  var entry = testList.shift();
+  test(entry[0], entry[1]);
+  if (testList.length != 0)
+    reloadSubframes(runNextTest);
+  else
+    doDocumentDomainTest(done); // Side-effect-y. Do it last.
+}
+reloadSubframes(runNextTest);
+
+&lt;/script&gt;
diff --git a/html/browsers/origin/cross-origin-objects/frame.html b/html/browsers/origin/cross-origin-objects/frame.html
new file mode 100644
index 0000000..c84a245
--- /dev/null
+++ b/html/browsers/origin/cross-origin-objects/frame.html
@@ -0,0 +1,31 @@
+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script&gt;
+  // If we get a postMessage, we grab references to everything and set
+  // document.domain to trim off our topmost subdomain.
+  window.onmessage = function(evt) {
+    window.windowReferences = [];
+    window.locationReferences = [];
+    for (var i = 0; i &lt; parent.length; ++i) {
+      windowReferences.push(parent[i]);
+      locationReferences.push(parent[i].location);
+    }
+    document.domain = document.domain.substring(document.domain.indexOf(&apos;.&apos;) + 1);
+    evt.source.postMessage(&apos;&apos;, &apos;*&apos;);
+  }
+
+  function checkWindowReferences() {
+    for (var i = 0; i &lt; parent.length; ++i) {
+      if (windowReferences[i] != parent[i])
+        throw new Error(&quot;Window references don&apos;t match for &quot; + i + &quot; after document.domain&quot;);
+      if (locationReferences[i] != parent[i].location)
+        throw new Error(&quot;Location references don&apos;t match for &quot; + i + &quot; after document.domain&quot;);
+    }
+    return true;
+  }
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;/body&gt;
+&lt;/html&gt;
-- 
1.8.4.3</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>121595</commentid>
    <comment_count>180</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2015-07-03 19:29:26 +0000</bug_when>
    <thetext>It&apos;s been 7 months since comment 174 - any update here, Hixie?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>122822</commentid>
    <comment_count>181</comment_count>
    <who name="Anne">annevk</who>
    <bug_when>2015-08-28 07:26:43 +0000</bug_when>
    <thetext>Okay, so the state of the art here is:

https://etherpad.mozilla.org/html5-cross-origin-objects
https://github.com/w3c/web-platform-tests/tree/master/html/browsers/origin/cross-origin-objects

Bobby, is there anything else we would need to study to fix this? Is there any chance you would be willing to provide a pull request for the specification?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>123197</commentid>
    <comment_count>182</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2015-09-14 22:29:29 +0000</bug_when>
    <thetext>(In reply to Anne from comment #181)
&gt; Okay, so the state of the art here is:
&gt; 
&gt; https://etherpad.mozilla.org/html5-cross-origin-objects
&gt; https://github.com/w3c/web-platform-tests/tree/master/html/browsers/origin/
&gt; cross-origin-objects
&gt; 
&gt; Bobby, is there anything else we would need to study to fix this?

Nope, each of those should be independently enough to generate prose (though it would be much, much easier to generate prose from the first)

&gt; Is there
&gt; any chance you would be willing to provide a pull request for the
&gt; specification?

I think it would make more sense for somebody accustomed to writing standards prose to write it, and for me to review it (rather than the converse).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>123198</commentid>
    <comment_count>183</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2015-09-14 22:30:01 +0000</bug_when>
    <thetext>(Sorry for the lag there, was on PTO)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>123730</commentid>
    <comment_count>184</comment_count>
    <who name="Anne">annevk</who>
    <bug_when>2015-10-16 09:24:38 +0000</bug_when>
    <thetext>https://bugzilla.mozilla.org/show_bug.cgi?id=1214375 suggests we also need to retain security checks for same-origin objects. https://lists.w3.org/Archives/Public/www-archive/2015Oct/thread.html#msg9 has some related discussion on what to do here.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>123743</commentid>
    <comment_count>185</comment_count>
    <who name="Bobby Holley (:bholley)">bobbyholley</who>
    <bug_when>2015-10-16 18:27:15 +0000</bug_when>
    <thetext>(In reply to Anne from comment #184)
&gt; https://bugzilla.mozilla.org/show_bug.cgi?id=1214375 suggests we also need
&gt; to retain security checks for same-origin objects.

To be clear, this applies only to Location, not Window.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>124682</commentid>
    <comment_count>186</comment_count>
      <attachid>1633</attachid>
    <who name="">jen1.6.15m</who>
    <bug_when>2016-01-23 09:44:45 +0000</bug_when>
    <thetext>Created attachment 1633
it is a crowdflower extention from crowdflower.com to do tasks with.

I need this attatchment for google chrome. pls fix it!</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>124980</commentid>
    <comment_count>187</comment_count>
    <who name="Anne">annevk</who>
    <bug_when>2016-02-11 16:17:47 +0000</bug_when>
    <thetext>https://github.com/whatwg/html/pull/638</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="1"
              isprivate="0"
          >
            <attachid>1433</attachid>
            <date>2014-01-29 03:35:17 +0000</date>
            <delta_ts>2014-01-29 03:35:17 +0000</delta_ts>
            <desc>Tests. v1</desc>
            <filename>0001-Cross-origin-object-behavior.-v1.patch</filename>
            <type>text/plain</type>
            <size>18228</size>
            <attacher name="Bobby Holley (:bholley)">bobbyholley</attacher>
            
              <data encoding="base64">IyBIRyBjaGFuZ2VzZXQgcGF0Y2gKIyBVc2VyIEJvYmJ5IEhvbGxleSA8Ym9iYnlob2xsZXlAZ21h
aWwuY29tPgoKQ3Jvc3Mtb3JpZ2luIG9iamVjdCBiZWhhdmlvci4KCgpkaWZmIC0tZ2l0IGEvaHRt
bC9icm93c2Vycy9vcmlnaW4vY3Jvc3Mtb3JpZ2luLW9iamVjdHMvTUFOSUZFU1QgYi9odG1sL2Jy
b3dzZXJzL29yaWdpbi9jcm9zcy1vcmlnaW4tb2JqZWN0cy9NQU5JRkVTVApuZXcgZmlsZSBtb2Rl
IDEwMDY0NAppbmRleCAwMDAwMDAwLi44YzkwMzllCi0tLSAvZGV2L251bGwKKysrIGIvaHRtbC9i
cm93c2Vycy9vcmlnaW4vY3Jvc3Mtb3JpZ2luLW9iamVjdHMvTUFOSUZFU1QKQEAgLTAsMCArMSBA
QAorY3Jvc3Mtb3JpZ2luLW9iamVjdHMuaHRtbApkaWZmIC0tZ2l0IGEvaHRtbC9icm93c2Vycy9v
cmlnaW4vY3Jvc3Mtb3JpZ2luLW9iamVjdHMvY3Jvc3Mtb3JpZ2luLW9iamVjdHMuaHRtbCBiL2h0
bWwvYnJvd3NlcnMvb3JpZ2luL2Nyb3NzLW9yaWdpbi1vYmplY3RzL2Nyb3NzLW9yaWdpbi1vYmpl
Y3RzLmh0bWwKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uMzIwYTdiZQotLS0g
L2Rldi9udWxsCisrKyBiL2h0bWwvYnJvd3NlcnMvb3JpZ2luL2Nyb3NzLW9yaWdpbi1vYmplY3Rz
L2Nyb3NzLW9yaWdpbi1vYmplY3RzLmh0bWwKQEAgLTAsMCArMSwzMjkgQEAKKzwhZG9jdHlwZSBo
dG1sPgorPG1ldGEgY2hhcnNldD11dGYtOD4KKzx0aXRsZT5Dcm9zcy1vcmlnaW4gYmVoYXZpb3Ig
b2YgV2luZG93IGFuZCBMb2NhdGlvbjwvdGl0bGU+Cis8bGluayByZWw9ImF1dGhvciIgdGl0bGU9
IkJvYmJ5IEhvbGxleSAoOmJob2xsZXkpIiBocmVmPSJib2JieWhvbGxleUBnbWFpbC5jb20iPgor
PGxpbmsgcmVsPSJoZWxwIiBocmVmPSJodHRwOi8vd3d3LndoYXR3Zy5vcmcvc3BlY3Mvd2ViLWFw
cHMvY3VycmVudC13b3JrLyNzZWN1cml0eS13aW5kb3ciPgorPGxpbmsgcmVsPSJoZWxwIiBocmVm
PSJodHRwOi8vd3d3LndoYXR3Zy5vcmcvc3BlY3Mvd2ViLWFwcHMvY3VycmVudC13b3JrLyNzZWN1
cml0eS1sb2NhdGlvbiI+Cis8c2NyaXB0IHNyYz0iL3Jlc291cmNlcy90ZXN0aGFybmVzcy5qcyI+
PC9zY3JpcHQ+Cis8c2NyaXB0IHNyYz0iL3Jlc291cmNlcy90ZXN0aGFybmVzc3JlcG9ydC5qcyI+
PC9zY3JpcHQ+Cis8ZGl2IGlkPWxvZz48L2Rpdj4KKzxpZnJhbWUgbmFtZT0iQiI+PC9pZnJhbWU+
Cis8aWZyYW1lIG5hbWU9IkMiPjwvaWZyYW1lPgorPGlmcmFtZSBuYW1lPSJEIj48L2lmcmFtZT4K
KzxpZnJhbWUgbmFtZT0iRSI+PC9pZnJhbWU+Cis8c2NyaXB0PgorCisvKgorICogU2V0dXAgYm9p
bGVycGxhdGUuIFRoaXMgZ2l2ZXMgdXMgYSBzYW1lLW9yaWdpbiB3aW5kb3cgIkIiIGFuZCBhIGNy
b3NzLW9yaWdpbgorICogd2luZG93ICJDIi4KKyAqLworCitzZXR1cCh7ZXhwbGljaXRfZG9uZTog
dHJ1ZX0pOworcGF0aCA9IGxvY2F0aW9uLnBhdGhuYW1lLnN1YnN0cmluZygwLCBsb2NhdGlvbi5w
YXRobmFtZS5sYXN0SW5kZXhPZignLycpKSArICcvZnJhbWUuaHRtbCc7CitCLmZyYW1lRWxlbWVu
dC51cmlUb0xvYWQgPSBwYXRoOworQy5mcmFtZUVsZW1lbnQudXJpVG9Mb2FkID0gJ2h0dHA6Ly93
d3cxLndlYi1wbGF0Zm9ybS50ZXN0OicgKyBsb2NhdGlvbi5wb3J0ICsgcGF0aDsKKworLy8gVGhl
IGxhc3QgdHdvIGFyZSBvbmx5IHVzZWQgZm9yIHRoZSBkb2N1bWVudC5kb21haW4gdGVzdHMsIGlu
IHdoaWNoIEQgY2Vhc2VzIHRvCisvLyBiZSBzYW1lLW9yaWdpbiB3aXRoIEUgYW5kIGJlY29tZXMg
c2FtZS1vcmlnaW4gd2l0aCBCLgorRC5mcmFtZUVsZW1lbnQudXJpVG9Mb2FkID0gJ2h0dHA6Ly93
d3cyLndlYi1wbGF0Zm9ybS50ZXN0OicgKyBsb2NhdGlvbi5wb3J0ICsgcGF0aDsKK0UuZnJhbWVF
bGVtZW50LnVyaVRvTG9hZCA9ICdodHRwOi8vd3d3Mi53ZWItcGxhdGZvcm0udGVzdDonICsgbG9j
YXRpb24ucG9ydCArIHBhdGg7CisKK2Z1bmN0aW9uIHJlbG9hZFN1YmZyYW1lcyhjYikgeworICB2
YXIgaWZyYW1lcyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdpZnJhbWUnKTsKKyAg
aWZyYW1lcy5mb3JFYWNoID0gQXJyYXkucHJvdG90eXBlLmZvckVhY2g7CisgIHZhciBjb3VudCA9
IDA7CisgIGZ1bmN0aW9uIGZyYW1lTG9hZGVkKCkgeworICAgIGlmICgrK2NvdW50ID09IGlmcmFt
ZXMubGVuZ3RoKSB7CisgICAgICBpZnJhbWVzLmZvckVhY2goZnVuY3Rpb24oaWZyKSB7IGlmci5v
bmxvYWQgPSBudWxsOyB9KTsKKyAgICAgIGNiKCk7CisgICAgfQorICB9CisgIGlmcmFtZXMuZm9y
RWFjaChmdW5jdGlvbihpZnIpIHsgaWZyLm9ubG9hZCA9IGZyYW1lTG9hZGVkOyBpZnIuc2V0QXR0
cmlidXRlKCdzcmMnLCBpZnIudXJpVG9Mb2FkKTsgfSk7Cit9CisKKy8qCisgKiBOb3RlOiB3ZSBl
c2NoZXcgYXNzZXJ0X2VxdWFscyBpbiBhIGxvdCBvZiB0aGVzZSB0ZXN0cywgc2luY2UgdGhlIGhh
cm5lc3MgZW5kcworICogdXAgdGhyb3dpbmcgd2hlbiBpdCB0cmllcyB0byBmb3JtYXQgYSBtZXNz
YWdlIGludm9sdmluZyBhIGNyb3NzLW9yaWdpbiBvYmplY3QuCisgKi8KKwordmFyIHRlc3RMaXN0
ID0gW107CitmdW5jdGlvbiBhZGRUZXN0KGZ1biwgZGVzYykgeyB0ZXN0TGlzdC5wdXNoKFtmdW4s
IGRlc2NdKTsgfQorCisKKy8qCisgKiBCYXNpYyBzYW5pdHkgdGVzdGluZy4KKyAqLworCithZGRU
ZXN0KGZ1bmN0aW9uKCkgeworICBhc3NlcnRfZXF1YWxzKGxvY2F0aW9uLmhvc3QsICd3ZWItcGxh
dGZvcm0udGVzdDo4MDAwJywgJ05lZWQgdG8gcnVuIHRoZSB0b3AtbGV2ZWwgdGVzdCBmcm9tIHdl
Yi1wbGF0Zm9ybS50ZXN0OjgwMDAnKTsKKyAgYXNzZXJ0X2VxdWFscyhCLnBhcmVudCwgd2luZG93
LCAid2luZG93LnBhcmVudCB3b3JrcyBzYW1lLW9yaWdpbiIpOworICBhc3NlcnRfZXF1YWxzKEMu
cGFyZW50LCB3aW5kb3csICJ3aW5kb3cucGFyZW50IHdvcmtzIGNyb3NzLW9yaWdpbiIpOworICBh
c3NlcnRfZXF1YWxzKEIubG9jYXRpb24ucGF0aG5hbWUsIHBhdGgsICJsb2NhdGlvbi5ocmVmIHdv
cmtzIHNhbWUtb3JpZ2luIik7CisgIGFzc2VydF90aHJvd3MobnVsbCwgZnVuY3Rpb24oKSB7IEMu
bG9jYXRpb24ucGF0aG5hbWU7IH0sICJsb2NhdGlvbi5wYXRobmFtZSB0aHJvd3MgY3Jvc3Mtb3Jp
Z2luIik7Cit9LCAiQmFzaWMgc2FuaXR5LWNoZWNraW5nIik7CisKKy8qCisgKiBXaGl0ZWxpc3Qg
YmVoYXZpb3IuCisgKgorICogQWxzbyB0ZXN0cyBmb3IgW1tHZXRPd25Qcm9wZXJ0eV1dIGFuZCBb
W0hhc093blByb3BlcnR5XV0gYmVoYXZpb3IuCisgKi8KKwordmFyIHdoaXRlbGlzdGVkV2luZG93
UHJvcHMgPSBbJ2xvY2F0aW9uJywgJ3Bvc3RNZXNzYWdlJywgJ3dpbmRvdycsICdmcmFtZXMnLCAn
c2VsZicsICd0b3AnLCAncGFyZW50JywKKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdv
cGVuZXInLCAnY2xvc2VkJywgJ2Nsb3NlJywgJ2JsdXInLCAnZm9jdXMnLCAnbGVuZ3RoJ107Cith
ZGRUZXN0KGZ1bmN0aW9uKCkgeworICAgIGZvciAodmFyIHByb3AgaW4gd2luZG93KSB7CisgICAg
ICBpZiAod2hpdGVsaXN0ZWRXaW5kb3dQcm9wcy5pbmRleE9mKHByb3ApICE9IC0xKSB7CisgICAg
ICAgIENbcHJvcF07IC8vIFNob3VsZG4ndCB0aHJvdy4KKyAgICAgICAgT2JqZWN0LmdldE93blBy
b3BlcnR5RGVzY3JpcHRvcihDLCBwcm9wKTsgLy8gU2hvdWxkbid0IHRocm93LgorICAgICAgICBh
c3NlcnRfdHJ1ZShPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoQywgcHJvcCks
ICJoYXNPd25Qcm9wZXJ0eSBmb3IgIiArIHByb3ApOworICAgICAgfSBlbHNlIHsKKyAgICAgICAg
YXNzZXJ0X3Rocm93cyhudWxsLCBmdW5jdGlvbigpIHsgQ1twcm9wXTsgfSwgIlNob3VsZCB0aHJv
dyB3aGVuIGFjY2Vzc2luZyAiICsgcHJvcCArICIgb24gV2luZG93Iik7CisgICAgICAgIGFzc2Vy
dF90aHJvd3MobnVsbCwgZnVuY3Rpb24oKSB7IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0
b3IoQywgcHJvcCk7IH0sCisgICAgICAgICAgICAgICAgICAgICAgIlNob3VsZCB0aHJvdyB3aGVu
IGFjY2Vzc2luZyBwcm9wZXJ0eSBkZXNjcmlwdG9yIGZvciAiICsgcHJvcCArICIgb24gV2luZG93
Iik7CisgICAgICAgIGFzc2VydF90aHJvd3MobnVsbCwgZnVuY3Rpb24oKSB7IE9iamVjdC5wcm90
b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChDLCBwcm9wKTsgfSwKKyAgICAgICAgICAgICAgICAg
ICAgICAiU2hvdWxkIHRocm93IHdoZW4gaW52b2tpbmcgaGFzT3duUHJvcGVydHkgZm9yICIgKyBw
cm9wICsgIiBvbiBXaW5kb3ciKTsKKyAgICAgIH0KKyAgICAgIGlmIChwcm9wICE9ICdsb2NhdGlv
bicpCisgICAgICAgIGFzc2VydF90aHJvd3MobnVsbCwgZnVuY3Rpb24oKSB7IENbcHJvcF0gPSB1
bmRlZmluZWQ7IH0sICJTaG91bGQgdGhyb3cgd2hlbiB3cml0aW5nIHRvICIgKyBwcm9wICsgIiBv
biBXaW5kb3ciKTsKKyAgICB9CisgICAgZm9yICh2YXIgcHJvcCBpbiBsb2NhdGlvbikgeworICAg
ICAgaWYgKHByb3AgPT0gJ3JlcGxhY2UnKSB7CisgICAgICAgIEMubG9jYXRpb25bcHJvcF07IC8v
IFNob3VsZG4ndCB0aHJvdy4KKyAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRv
cihDLmxvY2F0aW9uLCBwcm9wKTsgLy8gU2hvdWxkbid0IHRocm93LgorICAgICAgICBhc3NlcnRf
dHJ1ZShPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoQy5sb2NhdGlvbiwgcHJv
cCksICJoYXNPd25Qcm9wZXJ0eSBmb3IgIiArIHByb3ApOworICAgICAgfQorICAgICAgZWxzZSB7
CisgICAgICAgIGFzc2VydF90aHJvd3MobnVsbCwgZnVuY3Rpb24oKSB7IENbcHJvcF07IH0sICJT
aG91bGQgdGhyb3cgd2hlbiBhY2Nlc3NpbmcgIiArIHByb3AgKyAiIG9uIExvY2F0aW9uIik7Cisg
ICAgICAgIGFzc2VydF90aHJvd3MobnVsbCwgZnVuY3Rpb24oKSB7IE9iamVjdC5nZXRPd25Qcm9w
ZXJ0eURlc2NyaXB0b3IoQywgcHJvcCk7IH0sCisgICAgICAgICAgICAgICAgICAgICAgIlNob3Vs
ZCB0aHJvdyB3aGVuIGFjY2Vzc2luZyBwcm9wZXJ0eSBkZXNjcmlwdG9yIGZvciAiICsgcHJvcCAr
ICIgb24gTG9jYXRpb24iKTsKKyAgICAgICAgYXNzZXJ0X3Rocm93cyhudWxsLCBmdW5jdGlvbigp
IHsgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKEMsIHByb3ApOyB9LAorICAg
ICAgICAgICAgICAgICAgICAgICJTaG91bGQgdGhyb3cgd2hlbiBpbnZva2luZyBoYXNPd25Qcm9w
ZXJ0eSBmb3IgIiArIHByb3AgKyAiIG9uIExvY2F0aW9uIik7CisgICAgICB9CisgICAgICBpZiAo
cHJvcCAhPSAnaHJlZicpCisgICAgICAgIGFzc2VydF90aHJvd3MobnVsbCwgZnVuY3Rpb24oKSB7
IENbcHJvcF0gPSB1bmRlZmluZWQ7IH0sICJTaG91bGQgdGhyb3cgd2hlbiB3cml0aW5nIHRvICIg
KyBwcm9wICsgIiBvbiBMb2NhdGlvbiIpOworICAgIH0KK30sICJPbmx5IHdoaXRlbGlzdGVkIHBy
b3BlcnRpZXMgYXJlIGFjY2Vzc2libGUgY3Jvc3Mtb3JpZ2luIik7CisKKy8qCisgKiBFUyBJbnRl
cm5hbCBNZXRob2RzLgorICovCisKKy8qCisgKiBbW0dldFByb3RvdHlwZU9mXV0KKyAqLworYWRk
VGVzdChmdW5jdGlvbigpIHsKKyAgYXNzZXJ0X3RydWUoT2JqZWN0LmdldFByb3RvdHlwZU9mKEMp
ID09PSBudWxsLCAiY3Jvc3Mtb3JpZ2luIFdpbmRvdyBwcm90byBpcyBudWxsIik7CisgIGFzc2Vy
dF90cnVlKE9iamVjdC5nZXRQcm90b3R5cGVPZihDLmxvY2F0aW9uKSA9PT0gbnVsbCwgImNyb3Nz
LW9yaWdpbiBMb2NhdGlvbiBwcm90byBpcyBudWxsIik7Cit9LCAiW1tHZXRQcm90b3R5cGVPZl1d
IHNob3VsZCByZXR1cm4gbnVsbCIpOworCisvKgorICogW1tTZXRQcm90b3R5cGVPZl1dCisgKi8K
K2FkZFRlc3QoZnVuY3Rpb24oKSB7CisgIGFzc2VydF90aHJvd3MobnVsbCwgZnVuY3Rpb24oKSB7
IEMuX19wcm90b19fID0gbmV3IE9iamVjdCgpOyB9LCAicHJvdG8gc2V0IG9uIGNyb3NzLW9yaWdp
biBXaW5kb3ciKTsKKyAgYXNzZXJ0X3Rocm93cyhudWxsLCBmdW5jdGlvbigpIHsgQy5sb2NhdGlv
bi5fX3Byb3RvX18gPSBuZXcgT2JqZWN0KCk7IH0sICJwcm90byBzZXQgb24gY3Jvc3Mtb3JpZ2lu
IExvY2F0aW9uIik7CisgIHZhciBwcm90b1NldHRlciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURl
c2NyaXB0b3IoT2JqZWN0LnByb3RvdHlwZSwgJ19fcHJvdG9fXycpLnNldDsKKyAgYXNzZXJ0X3Ro
cm93cyhudWxsLCBmdW5jdGlvbigpIHsgcHJvdG9TZXR0ZXIuY2FsbChDLCBuZXcgT2JqZWN0KCkp
OyB9LCAicHJvdG8gc2V0dGVyIHxjYWxsfCBvbiBjcm9zcy1vcmlnaW4gV2luZG93Iik7CisgIGFz
c2VydF90aHJvd3MobnVsbCwgZnVuY3Rpb24oKSB7IHByb3RvU2V0dGVyLmNhbGwoQy5sb2NhdGlv
biwgbmV3IE9iamVjdCgpKTsgfSwgInByb3RvIHNldHRlciB8Y2FsbHwgb24gY3Jvc3Mtb3JpZ2lu
IExvY2F0aW9uIik7Cit9LCAiW1tTZXRQcm90b3R5cGVPZl1dIHNob3VsZCB0aHJvdyIpOworCisv
KgorICogW1tJc0V4dGVuc2libGVdXQorICovCithZGRUZXN0KGZ1bmN0aW9uKCkgeworICBhc3Nl
cnRfdHJ1ZShPYmplY3QuaXNFeHRlbnNpYmxlKEMpLCAiY3Jvc3Mtb3JpZ2luIFdpbmRvdyBzaG91
bGQgYmUgZXh0ZW5zaWJsZSIpOworICBhc3NlcnRfdHJ1ZShPYmplY3QuaXNFeHRlbnNpYmxlKEMu
bG9jYXRpb24pLCAiY3Jvc3Mtb3JpZ2luIExvY2F0aW9uIHNob3VsZCBiZSBleHRlbnNpYmxlIik7
Cit9LCAiW1tJc0V4dGVuc2libGVdXSBzaG91bGQgcmV0dXJuIHRydWUgZm9yIGNyb3NzLW9yaWdp
biBvYmplY3RzIik7CisKKy8qCisgKiBbW1ByZXZlbnRFeHRlbnNpb25zXV0KKyAqLworYWRkVGVz
dChmdW5jdGlvbigpIHsKKyAgYXNzZXJ0X3Rocm93cyhudWxsLCBmdW5jdGlvbigpIHsgT2JqZWN0
LnByZXZlbnRFeHRlbnNpb25zKEMpIH0sCisgICAgICAgICAgICAgICAgInByZXZlbnRFeHRlbnNp
b25zIG9uIGNyb3NzLW9yaWdpbiBXaW5kb3cgc2hvdWxkIHRocm93Iik7CisgIGFzc2VydF90aHJv
d3MobnVsbCwgZnVuY3Rpb24oKSB7IE9iamVjdC5wcmV2ZW50RXh0ZW5zaW9ucyhDLmxvY2F0aW9u
KSB9LAorICAgICAgICAgICAgICAgICJwcmV2ZW50RXh0ZW5zaW9ucyBvbiBjcm9zcy1vcmlnaW4g
TG9jYXRpb24gc2hvdWxkIHRocm93Iik7Cit9LCAiW1tQcmV2ZW50RXh0ZW5zaW9uc11dIHNob3Vs
ZCB0aHJvdyBmb3IgY3Jvc3Mtb3JpZ2luIG9iamVjdHMiKTsKKworLyoKKyAqIFtbR2V0T3duUHJv
cGVydHldXQorICovCisKK2FkZFRlc3QoZnVuY3Rpb24oKSB7CisgIGFzc2VydF90cnVlKHR5cGVv
ZiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKEMsICdjbG9zZScpID09ICdvYmplY3Qn
LCAiQy5jbG9zZSBpcyB8b3dufCIpOworICBhc3NlcnRfdHJ1ZSh0eXBlb2YgT2JqZWN0LmdldE93
blByb3BlcnR5RGVzY3JpcHRvcihDLCAndG9wJykgPT0gJ29iamVjdCcsICJDLnRvcCBpcyB8b3du
fCIpOworICBhc3NlcnRfdHJ1ZSh0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRv
cihDLmxvY2F0aW9uLCAnaHJlZicpID09ICdvYmplY3QnLCAiQy5sb2NhdGlvbi5ocmVmIGlzIHxv
d258Iik7CisgIGFzc2VydF90cnVlKHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlw
dG9yKEMubG9jYXRpb24sICdyZXBsYWNlJykgPT0gJ29iamVjdCcsICJDLmxvY2F0aW9uLnJlcGxh
Y2UgaXMgfG93bnwiKTsKK30sICJbW0dldE93blByb3BlcnR5XV0gLSBQcm9wZXJ0aWVzIG9uIGNy
b3NzLW9yaWdpbiBvYmplY3RzIHNob3VsZCBiZSByZXBvcnRlZCB8b3dufCIpOworCitmdW5jdGlv
biBjaGVja1Byb3BlcnR5RGVzY3JpcHRvcihkZXNjLCBwcm9wTmFtZSwgZXhwZWN0V3JpdGFibGUp
IHsKKyAgYXNzZXJ0X2VxdWFscyh0eXBlb2YgZGVzYywgJ29iamVjdCcsICJwcm9wZXJ0eSBkZXNj
cmlwdG9yIGZvciAiICsgcHJvcE5hbWUgKyAiIHNob3VsZCBleGlzdCIpOworICBhc3NlcnRfZXF1
YWxzKGRlc2MuZW51bWVyYWJsZSwgZmFsc2UsICJwcm9wZXJ0eSBkZXNjcmlwdG9yIGZvciAiICsg
cHJvcE5hbWUgKyAiIHNob3VsZCBiZSBub24tZW51bWVyYWJsZSIpOworICBhc3NlcnRfZXF1YWxz
KGRlc2MuY29uZmlndXJhYmxlLCBmYWxzZSwgInByb3BlcnR5IGRlc2NyaXB0b3IgZm9yICIgKyBw
cm9wTmFtZSArICIgc2hvdWxkIGJlIG5vbi1jb25maWd1cmFibGUiKTsKKyAgaWYgKCd2YWx1ZScg
aW4gZGVzYykKKyAgICBhc3NlcnRfZXF1YWxzKGRlc2Mud3JpdGFibGUsIGV4cGVjdFdyaXRhYmxl
LCAicHJvcGVydHkgZGVzY3JpcHRvciBmb3IgIiArIHByb3BOYW1lICsgIiBzaG91bGQgaGF2ZSB3
cml0YWJsZTogIiArIGV4cGVjdFdyaXRhYmxlKTsKKyAgZWxzZQorICAgIGFzc2VydF9lcXVhbHMo
J3NldCcgaW4gZGVzYywgZXhwZWN0V3JpdGFibGUsCisgICAgICAgICAgICAgICAgICAicHJvcGVy
dHkgZGVzY3JpcHRvciBmb3IgIiArIHByb3BOYW1lICsgIiBzaG91bGQgIiArIChleHBlY3RXcml0
YWJsZSA/ICIiIDogIm5vdCAiKSArICJoYXZlIHNldHRlciIpOworfQorCithZGRUZXN0KGZ1bmN0
aW9uKCkgeworICAgIGZvciAodmFyIHAgaW4gd2hpdGVsaXN0ZWRXaW5kb3dQcm9wcykgeworICAg
ICAgdmFyIHByb3AgPSB3aGl0ZWxpc3RlZFdpbmRvd1Byb3BzW3BdOworICAgICAgdmFyIGRlc2Mg
PSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKEMsIHByb3ApOworICAgICAgY2hlY2tQ
cm9wZXJ0eURlc2NyaXB0b3IoZGVzYywgcHJvcCwgcHJvcCA9PSAnbG9jYXRpb24nKTsKKyAgICB9
CisgICAgY2hlY2tQcm9wZXJ0eURlc2NyaXB0b3IoT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3Jp
cHRvcihDLmxvY2F0aW9uLCAncmVwbGFjZScpLCAncmVwbGFjZScsIGZhbHNlKTsKKyAgICBjaGVj
a1Byb3BlcnR5RGVzY3JpcHRvcihPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKEMubG9j
YXRpb24sICdocmVmJyksICdocmVmJywgdHJ1ZSk7CisgICAgYXNzZXJ0RmFsc2UoJ2dldCcgaW4g
T2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihDLmxvY2F0aW9uLCAnaHJlZicpLCAiQ3Jv
c3Mtb3JpZ2luIGxvY2F0aW9uIHNob3VsZCBoYXZlIG5vIGhyZWYgZ2V0dGVyIik7Cit9LCAiW1tH
ZXRPd25Qcm9wZXJ0eV1dIC0gUHJvcGVydHkgZGVzY3JpcHRvcnMgZm9yIGNyb3NzLW9yaWdpbiBw
cm9wZXJ0aWVzIHNob3VsZCBiZSBzZXQgdXAgY29ycmVjdGx5Iik7CisKKy8qCisgKiBbW0RlbGV0
ZV1dCisgKi8KK2FkZFRlc3QoZnVuY3Rpb24oKSB7CisgICAgYXNzZXJ0X3Rocm93cyhudWxsLCBm
dW5jdGlvbigpIHsgZGVsZXRlIEMubG9jYXRpb247IH0sICJDYW4ndCBkZWxldGUgY3Jvc3Mtb3Jp
Z2luIHByb3BlcnR5Iik7CisgICAgYXNzZXJ0X3Rocm93cyhudWxsLCBmdW5jdGlvbigpIHsgZGVs
ZXRlIEMucGFyZW50OyB9LCAiQ2FuJ3QgZGVsZXRlIGNyb3NzLW9yaWdpbiBwcm9wZXJ0eSIpOwor
ICAgIGFzc2VydF90aHJvd3MobnVsbCwgZnVuY3Rpb24oKSB7IGRlbGV0ZSBDLmxlbmd0aDsgfSwg
IkNhbid0IGRlbGV0ZSBjcm9zcy1vcmlnaW4gcHJvcGVydHkiKTsKKyAgICBhc3NlcnRfdGhyb3dz
KG51bGwsIGZ1bmN0aW9uKCkgeyBkZWxldGUgQy5kb2N1bWVudDsgfSwgIkNhbid0IGRlbGV0ZSBj
cm9zcy1vcmlnaW4gcHJvcGVydHkiKTsKKyAgICBhc3NlcnRfdGhyb3dzKG51bGwsIGZ1bmN0aW9u
KCkgeyBkZWxldGUgQy5mb29weTsgfSwgIkNhbid0IGRlbGV0ZSBjcm9zcy1vcmlnaW4gcHJvcGVy
dHkiKTsKKyAgICBhc3NlcnRfdGhyb3dzKG51bGwsIGZ1bmN0aW9uKCkgeyBkZWxldGUgQy5sb2Nh
dGlvbi5ocmVmOyB9LCAiQ2FuJ3QgZGVsZXRlIGNyb3NzLW9yaWdpbiBwcm9wZXJ0eSIpOworICAg
IGFzc2VydF90aHJvd3MobnVsbCwgZnVuY3Rpb24oKSB7IGRlbGV0ZSBDLmxvY2F0aW9uLnJlcGxh
Y2U7IH0sICJDYW4ndCBkZWxldGUgY3Jvc3Mtb3JpZ2luIHByb3BlcnR5Iik7CisgICAgYXNzZXJ0
X3Rocm93cyhudWxsLCBmdW5jdGlvbigpIHsgZGVsZXRlIEMubG9jYXRpb24ucG9ydDsgfSwgIkNh
bid0IGRlbGV0ZSBjcm9zcy1vcmlnaW4gcHJvcGVydHkiKTsKKyAgICBhc3NlcnRfdGhyb3dzKG51
bGwsIGZ1bmN0aW9uKCkgeyBkZWxldGUgQy5sb2NhdGlvbi5mb29weTsgfSwgIkNhbid0IGRlbGV0
ZSBjcm9zcy1vcmlnaW4gcHJvcGVydHkiKTsKK30sICJbW0RlbGV0ZV1dIFNob3VsZCB0aHJvdyBv
biBjcm9zcy1vcmlnaW4gb2JqZWN0cyIpOworCisvKgorICogW1tEZWZpbmVPd25Qcm9wZXJ0eV1d
CisgKi8KK2Z1bmN0aW9uIGNoZWNrRGVmaW5lKG9iaiwgcHJvcCkgeworICB2YXIgdmFsdWVEZXNj
ID0geyBjb25maWd1cmFibGU6IGZhbHNlLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IGZh
bHNlLCB2YWx1ZTogMiB9OworICB2YXIgYWNjZXNzb3JEZXNjID0geyBjb25maWd1cmFibGU6IGZh
bHNlLCBlbnVtZXJhYmxlOiBmYWxzZSwgZ2V0OiBmdW5jdGlvbigpIHt9IH07CisgIGFzc2VydF90
aHJvd3MobnVsbCwgZnVuY3Rpb24oKSB7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIHByb3As
IHZhbHVlRGVzYyk7IH0sICJDYW4ndCBkZWZpbmUgY3Jvc3Mtb3JpZ2luIHByb3BlcnR5ICIgKyBw
cm9wKTsKKyAgYXNzZXJ0X3Rocm93cyhudWxsLCBmdW5jdGlvbigpIHsgT2JqZWN0LmRlZmluZVBy
b3BlcnR5KG9iaiwgcHJvcCwgdmFsdWVEZXNjKTsgfSwgIkNhbid0IGRlZmluZSBjcm9zcy1vcmln
aW4gcHJvcGVydHkgIiArIHByb3ApOworfQorYWRkVGVzdChmdW5jdGlvbigpIHsKKyAgICBjaGVj
a0RlZmluZShDLCAnbGVuZ3RoJyk7CisgICAgY2hlY2tEZWZpbmUoQywgJ3BhcmVudCcpOworICAg
IGNoZWNrRGVmaW5lKEMsICdsb2NhdGlvbicpOworICAgIGNoZWNrRGVmaW5lKEMsICdkb2N1bWVu
dCcpOworICAgIGNoZWNrRGVmaW5lKEMsICdmb29weScpOworICAgIGNoZWNrRGVmaW5lKEMubG9j
YXRpb24sICdocmVmJyk7CisgICAgY2hlY2tEZWZpbmUoQy5sb2NhdGlvbiwgJ3JlcGxhY2UnKTsK
KyAgICBjaGVja0RlZmluZShDLmxvY2F0aW9uLCAncG9ydCcpOworICAgIGNoZWNrRGVmaW5lKEMu
bG9jYXRpb24sICdmb29weScpOworfSwgIltbRGVmaW5lT3duUHJvcGVydHldXSBTaG91bGQgdGhy
b3cgZm9yIGNyb3NzLW9yaWdpbiBvYmplY3RzIik7CisKKy8qCisgKiBbW0VudW1lcmF0ZV1dCisg
Ki8KKworYWRkVGVzdChmdW5jdGlvbigpIHsKKyAgICBmb3IgKHZhciBwcm9wIGluIEMpCisgICAg
ICBhc3NlcnRfdHJ1ZShmYWxzZSwgIlNob3VsZG4ndCBoYXZlIGJlZW4gYWJsZSB0byBlbnVtZXJh
dGUgIiArIHByb3AgKyAiIG9uIGNyb3NzLW9yaWdpbiBXaW5kb3ciKTsKKyAgICBmb3IgKHZhciBw
cm9wIGluIEMubG9jYXRpb24pCisgICAgICBhc3NlcnRfdHJ1ZShmYWxzZSwgIlNob3VsZG4ndCBo
YXZlIGJlZW4gYWJsZSB0byBlbnVtZXJhdGUgIiArIHByb3AgKyAiIG9uIGNyb3NzLW9yaWdpbiBM
b2NhdGlvbiIpOworfSwgIltbRW51bWVyYXRlXV0gc2hvdWxkIHJldHVybiBhbiBlbXB0eSBpdGVy
YXRvciIpOworCisvKgorICogW1tPd25Qcm9wZXJ0eUtleXNdXQorICovCisKK2FkZFRlc3QoZnVu
Y3Rpb24oKSB7CisgIGFzc2VydF9lcXVhbHMod2hpdGVsaXN0ZWRXaW5kb3dQcm9wcy5zb3J0KCku
dG9Tb3VyY2UoKSwgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoQykuc29ydCgpLnRvU291cmNl
KCksCisgICAgICAgICAgICAgICAgIk9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKCkgZ2l2ZXMg
dGhlIHJpZ2h0IGFuc3dlciBmb3IgY3Jvc3Mtb3JpZ2luIFdpbmRvdyIpOworICBhc3NlcnRfZXF1
YWxzKFsnaHJlZicsICdyZXBsYWNlJ10udG9Tb3VyY2UoKSwgT2JqZWN0LmdldE93blByb3BlcnR5
TmFtZXMoQy5sb2NhdGlvbikuc29ydCgpLnRvU291cmNlKCksCisgICAgICAgICAgICAgICAgIk9i
amVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKCkgZ2l2ZXMgdGhlIHJpZ2h0IGFuc3dlciBmb3IgY3Jv
c3Mtb3JpZ2luIExvY2F0aW9uIik7Cit9LCAiW1tPd25Qcm9wZXJ0eUtleXNdXSBzaG91bGQgcmV0
dXJuIGFsbCBwcm9wZXJ0aWVzIGZyb20gY3Jvc3Mtb3JpZ2luIG9iamVjdHMiKTsKKworYWRkVGVz
dChmdW5jdGlvbigpIHsKKyAgYXNzZXJ0X3RydWUoQi5ldmFsKCdwYXJlbnQuQycpID09PSBDLCAi
QSBhbmQgQiBvYnNlcnZlIHRoZSBzYW1lIGlkZW50aXR5IGZvciBDJ3MgV2luZG93Iik7CisgIGFz
c2VydF90cnVlKEIuZXZhbCgncGFyZW50LkMubG9jYXRpb24nKSA9PT0gQy5sb2NhdGlvbiwgIkEg
YW5kIEIgb2JzZXJ2ZSB0aGUgc2FtZSBpZGVudGl0eSBmb3IgQydzIExvY2F0aW9uIik7Cit9LCAi
QSBhbmQgQiBqb2ludGx5IG9ic2VydmUgdGhlIHNhbWUgaWRlbnRpdHkgZm9yIGNyb3NzLW9yaWdp
biBXaW5kb3cgYW5kIExvY2F0aW9uIik7CisKK2Z1bmN0aW9uIGNoZWNrRnVuY3Rpb24oZiwgcHJv
dG8pIHsKKyAgYXNzZXJ0X2VxdWFscyh0eXBlb2YgZiwgJ2Z1bmN0aW9uJywgZi5uYW1lICsgIiBp
cyBhIGZ1bmN0aW9uIik7CisgIGFzc2VydF9lcXVhbHMoT2JqZWN0LmdldFByb3RvdHlwZU9mKGYp
LCBwcm90bywgZi5uYW1lICsgIiBoYXMgdGhlIHJpZ2h0IHByb3RvdHlwZSIpOworfQorCithZGRU
ZXN0KGZ1bmN0aW9uKCkgeworICBjaGVja0Z1bmN0aW9uKEMuY2xvc2UsIEZ1bmN0aW9uLnByb3Rv
dHlwZSk7CisgIGNoZWNrRnVuY3Rpb24oQy5sb2NhdGlvbi5yZXBsYWNlLCBGdW5jdGlvbi5wcm90
b3R5cGUpOworfSwgIkNyb3NzLW9yaWdpbiBmdW5jdGlvbnMgZ2V0IGxvY2FsIEZ1bmN0aW9uLnBy
b3RvdHlwZSIpOworCithZGRUZXN0KGZ1bmN0aW9uKCkgeworICBhc3NlcnRfZXF1YWxzKHR5cGVv
ZiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKEMsICd0b3AnKSwgJ29iamVjdCcsCisg
ICAgICAgICAgICAgICAgIk5lZWQgdG8gYmUgYWJsZSB0byB1c2UgT2JqZWN0LmdldE93blByb3Bl
cnR5RGVzY3JpcHRvciBkbyB0aGlzIHRlc3QiKTsKKyAgY2hlY2tGdW5jdGlvbihPYmplY3QuZ2V0
T3duUHJvcGVydHlEZXNjcmlwdG9yKEMsICd0b3AnKS5nZXQsIEZ1bmN0aW9uLnByb3RvdHlwZSk7
CisgIGNoZWNrRnVuY3Rpb24oT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihDLmxvY2F0
aW9uLCAnaHJlZicpLnNldCwgRnVuY3Rpb24ucHJvdG90eXBlKTsKK30sICJDcm9zcy1vcmlnaW4g
V2luZG93IGFjY2Vzc29ycyBnZXQgbG9jYWwgRnVuY3Rpb24ucHJvdG90eXBlIik7CisKK2FkZFRl
c3QoZnVuY3Rpb24oKSB7CisgIGNoZWNrRnVuY3Rpb24oY2xvc2UsIEZ1bmN0aW9uLnByb3RvdHlw
ZSk7CisgIGFzc2VydF90cnVlKGNsb3NlICE9IEMuY2xvc2UsICdjcm9zcy1vcmlnaW4gV2luZG93
IGZ1bmN0aW9ucyBnZXQgdGhlaXIgb3duIG9iamVjdCcpOworICB2YXIgY2xvc2VfQiA9IEIuZXZh
bCgndG9wLkMuY2xvc2UnKTsKKyAgYXNzZXJ0X3RydWUoY2xvc2VfQiAhPSBDLmNsb3NlLCAnZGlm
ZmVyZW50IFdpbmRvdyBmdW5jdGlvbnMgcGVyLWluY3VtYmVudCBzY3JpcHQgc2V0dGluZ3Mgb2Jq
ZWN0Jyk7CisgIGNoZWNrRnVuY3Rpb24oY2xvc2VfQiwgQi5GdW5jdGlvbi5wcm90b3R5cGUpOwor
CisgIGNoZWNrRnVuY3Rpb24obG9jYXRpb24ucmVwbGFjZSwgRnVuY3Rpb24ucHJvdG90eXBlKTsK
KyAgYXNzZXJ0X3RydWUobG9jYXRpb24ucmVwbGFjZSAhPSBDLmxvY2F0aW9uLnJlcGxhY2UsICJj
cm9zcy1vcmlnaW4gTG9jYXRpb24gZnVuY3Rpb25zIGdldCB0aGVpciBvd24gb2JqZWN0Iik7Cisg
IHZhciByZXBsYWNlX0IgPSBCLmV2YWwoJ3RvcC5DLmxvY2F0aW9uLnJlcGxhY2UnKTsKKyAgYXNz
ZXJ0X3RydWUocmVwbGFjZV9CICE9IEMubG9jYXRpb24ucmVwbGFjZSwgJ2RpZmZlcmVudCBMb2Nh
dGlvbiBmdW5jdGlvbnMgcGVyLWluY3VtYmVudCBzY3JpcHQgc2V0dGluZ3Mgb2JqZWN0Jyk7Cisg
IGNoZWNrRnVuY3Rpb24ocmVwbGFjZV9CLCBCLkZ1bmN0aW9uLnByb3RvdHlwZSk7Cit9LCAiU2Ft
ZS1vcmlnaW4gb2JzZXJ2ZXJzIGdldCBkaWZmZXJlbnQgZnVuY3Rpb25zIGZvciBjcm9zcy1vcmln
aW4gb2JqZWN0cyIpOworCithZGRUZXN0KGZ1bmN0aW9uKCkgeworICBhc3NlcnRfZXF1YWxzKHR5
cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKEMsICdwYXJlbnQnKSwgJ29iamVj
dCcsCisgICAgICAgICAgICAgICAgIk5lZWQgdG8gYmUgYWJsZSB0byB1c2UgT2JqZWN0LmdldE93
blByb3BlcnR5RGVzY3JpcHRvciBkbyB0aGlzIHRlc3QiKTsKKyAgdmFyIGdldF9zZWxmX3BhcmVu
dCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iod2luZG93LCAncGFyZW50JykuZ2V0
OworICB2YXIgZ2V0X3BhcmVudF9BID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihD
LCAncGFyZW50JykuZ2V0OworICB2YXIgZ2V0X3BhcmVudF9CID0gQi5ldmFsKCdPYmplY3QuZ2V0
T3duUHJvcGVydHlEZXNjcmlwdG9yKHRvcC5DLCAicGFyZW50IikuZ2V0Jyk7CisgIGFzc2VydF90
cnVlKGdldF9zZWxmX3BhcmVudCAhPSBnZXRfcGFyZW50X0EsICdkaWZmZXJlbnQgV2luZG93IGFj
Y2Vzc29ycyBwZXItaW5jdW1iZW50IHNjcmlwdCBzZXR0aW5ncyBvYmplY3QnKTsKKyAgYXNzZXJ0
X3RydWUoZ2V0X3BhcmVudF9BICE9IGdldF9wYXJlbnRfQiwgJ2RpZmZlcmVudCBXaW5kb3cgYWNj
ZXNzb3JzIHBlci1pbmN1bWJlbnQgc2NyaXB0IHNldHRpbmdzIG9iamVjdCcpOworICBjaGVja0Z1
bmN0aW9uKGdldF9zZWxmX3BhcmVudCwgRnVuY3Rpb24ucHJvdG90eXBlKTsKKyAgY2hlY2tGdW5j
dGlvbihnZXRfcGFyZW50X0EsIEZ1bmN0aW9uLnByb3RvdHlwZSk7CisgIGNoZWNrRnVuY3Rpb24o
Z2V0X3BhcmVudF9CLCBCLkZ1bmN0aW9uLnByb3RvdHlwZSk7CisKKyAgdmFyIHNldF9zZWxmX2hy
ZWYgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHdpbmRvdy5sb2NhdGlvbiwgJ2hy
ZWYnKS5zZXQ7CisgIHZhciBzZXRfaHJlZl9BID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3Jp
cHRvcihDLmxvY2F0aW9uLCAnaHJlZicpLnNldDsKKyAgdmFyIHNldF9ocmVmX0IgPSBCLmV2YWwo
J09iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodG9wLkMubG9jYXRpb24sICJocmVmIiku
c2V0Jyk7CisgIGFzc2VydF90cnVlKHNldF9zZWxmX2hyZWYgIT0gc2V0X2hyZWZfQSwgJ2RpZmZl
cmVudCBMb2NhdGlvbiBhY2Nlc3NvcnMgcGVyLWluY3VtYmVudCBzY3JpcHQgc2V0dGluZ3Mgb2Jq
ZWN0Jyk7CisgIGFzc2VydF90cnVlKHNldF9ocmVmX0EgIT0gc2V0X2hyZWZfQiwgJ2RpZmZlcmVu
dCBMb2NhdGlvbiBhY2Nlc3NvcnMgcGVyLWluY3VtYmVudCBzY3JpcHQgc2V0dGluZ3Mgb2JqZWN0
Jyk7CisgIGNoZWNrRnVuY3Rpb24oc2V0X3NlbGZfaHJlZiwgRnVuY3Rpb24ucHJvdG90eXBlKTsK
KyAgY2hlY2tGdW5jdGlvbihzZXRfaHJlZl9BLCBGdW5jdGlvbi5wcm90b3R5cGUpOworICBjaGVj
a0Z1bmN0aW9uKHNldF9ocmVmX0IsIEIuRnVuY3Rpb24ucHJvdG90eXBlKTsKK30sICJTYW1lLW9y
aWdpbiBvYnNlcnZlcnMgZ2V0IGRpZmZlcmVudCBhY2Nlc3NvcnMgZm9yIGNyb3NzLW9yaWdpbiBv
YmplY3RzIik7CisKKy8vIFRoZSBkb2N1bWVudC5kb21haW4gdGVzdCBpcyB1bmF2b2lkYWJseSBz
aWRlLWVmZmVjdC15LCBzbyB3ZSBkbyBpdCBsYXN0LgorZnVuY3Rpb24gZG9Eb2N1bWVudERvbWFp
blRlc3QoY2IpIHsKKyAgICB3aW5kb3cub25tZXNzYWdlID0gZnVuY3Rpb24oKSB7CisgICAgICB0
ZXN0KGZ1bmN0aW9uKCkgeworICAgICAgICBhc3NlcnRfdHJ1ZShELmNoZWNrV2luZG93UmVmZXJl
bmNlcygpLCAiRCdzIFdpbmRvdyByZWZlcmVuY2VzIGFyZSBzdGlsbCBzZWxmLWNvbnNpc3RlbnQg
YWZ0ZXIgZG9jdW1lbnQuZG9tYWluIik7CisgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgd2lu
ZG93Lmxlbmd0aDsgKytpKSB7CisgICAgICAgICAgYXNzZXJ0X3RydWUod2luZG93W2ldID09PSBE
LndpbmRvd1JlZmVyZW5jZXNbaV0sCisgICAgICAgICAgICAgICAgICAgICAgIldpbmRvdyByZWZl
cmVuY2UgIiArIGkgKyAiIGNvbnNpc3RlbnQgYmV0d2VlbiBnbG9iYWxzIGFmdGVyIGRvY3VtZW50
LmRvbWFpbiIpOworICAgICAgICAgIGFzc2VydF90cnVlKHdpbmRvd1tpXS5sb2NhdGlvbiA9PT0g
RC5sb2NhdGlvblJlZmVyZW5jZXNbaV0sCisgICAgICAgICAgICAgICAgICAgICAgIkxvY2F0aW9u
IHJlZmVyZW5jZSAiICsgaSArICIgY29uc2lzdGVudCBiZXR3ZWVuIGdsb2JhbHMgYWZ0ZXIgZG9j
dW1lbnQuZG9tYWluIik7CisgICAgICAgIH0KKyAgICAgIH0sICJDcm9zcy1vcmlnaW4gb2JqZWN0
IGlkZW50aXR5IHByZXNlcnZlZCBhY3Jvc3MgZG9jdW1lbnQuZG9tYWluIik7CisgICAgICBjYigp
OworICAgIH0KKyAgICBCLmRvY3VtZW50LmRvbWFpbiA9IEIuZG9jdW1lbnQuZG9tYWluOworICAg
IGRvY3VtZW50LmRvbWFpbiA9IGRvY3VtZW50LmRvbWFpbjsKKyAgICBELnBvc3RNZXNzYWdlKCcn
LCAnKicpOworfQorCisvLyBXZSBkbyBhIGZyZXNoIGxvYWQgb2YgdGhlIHN1YmZyYW1lcyBmb3Ig
ZWFjaCB0ZXN0IHRvIG1pbmltaXplIHNpZGUtZWZmZWN0cy4KKy8vIEl0IHdvdWxkIGJlIG5pY2Ug
dG8gcmVsb2FkIG91cnNlbHZlcyBhcyB3ZWxsLCBidXQgd2UgY2FuJ3QgZG8gdGhhdCB3aXRob3V0
CisvLyBkaXNydXB0aW5nIHRoZSB0ZXN0IGhhcm5lc3MuCitmdW5jdGlvbiBydW5OZXh0VGVzdCgp
IHsKKyAgdmFyIGVudHJ5ID0gdGVzdExpc3Quc2hpZnQoKTsKKyAgdGVzdChlbnRyeVswXSwgZW50
cnlbMV0pOworICBpZiAodGVzdExpc3QubGVuZ3RoICE9IDApCisgICAgcmVsb2FkU3ViZnJhbWVz
KHJ1bk5leHRUZXN0KTsKKyAgZWxzZQorICAgIGRvRG9jdW1lbnREb21haW5UZXN0KGRvbmUpOyAv
LyBTaWRlLWVmZmVjdC15LiBEbyBpdCBsYXN0LgorfQorcmVsb2FkU3ViZnJhbWVzKHJ1bk5leHRU
ZXN0KTsKKworPC9zY3JpcHQ+CmRpZmYgLS1naXQgYS9odG1sL2Jyb3dzZXJzL29yaWdpbi9jcm9z
cy1vcmlnaW4tb2JqZWN0cy9mcmFtZS5odG1sIGIvaHRtbC9icm93c2Vycy9vcmlnaW4vY3Jvc3Mt
b3JpZ2luLW9iamVjdHMvZnJhbWUuaHRtbApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAw
MDAwLi5jODRhMjQ1Ci0tLSAvZGV2L251bGwKKysrIGIvaHRtbC9icm93c2Vycy9vcmlnaW4vY3Jv
c3Mtb3JpZ2luLW9iamVjdHMvZnJhbWUuaHRtbApAQCAtMCwwICsxLDMxIEBACis8IWRvY3R5cGUg
aHRtbD4KKzxodG1sPgorPGhlYWQ+Cis8c2NyaXB0PgorICAvLyBJZiB3ZSBnZXQgYSBwb3N0TWVz
c2FnZSwgd2UgZ3JhYiByZWZlcmVuY2VzIHRvIGV2ZXJ5dGhpbmcgYW5kIHNldAorICAvLyBkb2N1
bWVudC5kb21haW4gdG8gdHJpbSBvZmYgb3VyIHRvcG1vc3Qgc3ViZG9tYWluLgorICB3aW5kb3cu
b25tZXNzYWdlID0gZnVuY3Rpb24oZXZ0KSB7CisgICAgd2luZG93LndpbmRvd1JlZmVyZW5jZXMg
PSBbXTsKKyAgICB3aW5kb3cubG9jYXRpb25SZWZlcmVuY2VzID0gW107CisgICAgZm9yICh2YXIg
aSA9IDA7IGkgPCBwYXJlbnQubGVuZ3RoOyArK2kpIHsKKyAgICAgIHdpbmRvd1JlZmVyZW5jZXMu
cHVzaChwYXJlbnRbaV0pOworICAgICAgbG9jYXRpb25SZWZlcmVuY2VzLnB1c2gocGFyZW50W2ld
LmxvY2F0aW9uKTsKKyAgICB9CisgICAgZG9jdW1lbnQuZG9tYWluID0gZG9jdW1lbnQuZG9tYWlu
LnN1YnN0cmluZyhkb2N1bWVudC5kb21haW4uaW5kZXhPZignLicpICsgMSk7CisgICAgZXZ0LnNv
dXJjZS5wb3N0TWVzc2FnZSgnJywgJyonKTsKKyAgfQorCisgIGZ1bmN0aW9uIGNoZWNrV2luZG93
UmVmZXJlbmNlcygpIHsKKyAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcmVudC5sZW5ndGg7ICsr
aSkgeworICAgICAgaWYgKHdpbmRvd1JlZmVyZW5jZXNbaV0gIT0gcGFyZW50W2ldKQorICAgICAg
ICB0aHJvdyBuZXcgRXJyb3IoIldpbmRvdyByZWZlcmVuY2VzIGRvbid0IG1hdGNoIGZvciAiICsg
aSArICIgYWZ0ZXIgZG9jdW1lbnQuZG9tYWluIik7CisgICAgICBpZiAobG9jYXRpb25SZWZlcmVu
Y2VzW2ldICE9IHBhcmVudFtpXS5sb2NhdGlvbikKKyAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJM
b2NhdGlvbiByZWZlcmVuY2VzIGRvbid0IG1hdGNoIGZvciAiICsgaSArICIgYWZ0ZXIgZG9jdW1l
bnQuZG9tYWluIik7CisgICAgfQorICAgIHJldHVybiB0cnVlOworICB9Cis8L3NjcmlwdD4KKzwv
aGVhZD4KKzxib2R5PgorPC9ib2R5PgorPC9odG1sPgotLSAKMS44LjQuMwoK
</data>

          </attachment>
          <attachment
              isobsolete="0"
              ispatch="0"
              isprivate="0"
          >
            <attachid>1633</attachid>
            <date>2016-01-23 09:44:45 +0000</date>
            <delta_ts>2016-01-23 09:44:45 +0000</delta_ts>
            <desc>it is a crowdflower extention from crowdflower.com to do tasks with.</desc>
            <filename>file_20701.txt</filename>
            <type>text/plain</type>
            <size>196</size>
            <attacher>jen1.6.15m</attacher>
            
              <data encoding="base64">QzpcUHJvZ3JhbSBGaWxlcyAoeDg2KVxHb29nbGVcQ2hyb21lXEFwcEM6XFByb2dyYW0gRmlsZXMg
KHg4NilcR29vZ2xlXENocm9tZVxBcHBsaWNhdGlvblw0Ny4wLjI1MjYuMTExXEV4dGVuc2lvbnNc
ZXh0ZXJuYWxfZXh0ZW5zaW9ucy5qc29ubGljYXRpb25cNDcuMC4yNTI2LjExMVxFeHRlbnNpb25z
XGV4dGVybmFsX2V4dGVuc2lvbnMuanNvbg==
</data>

          </attachment>
      

    </bug>

</bugzilla>