Window
,
WindowProxy
,
and
Location
objects
This section describes features that apply most directly to Web browsers. Having said that, except where specified otherwise, the requirements defined in this section do apply to all user agents, whether they are Web browsers or not.
A
browsing
context
is
an
environment
in
which
Document
objects
are
presented
to
the
user.
A
tab
or
window
in
a
Web
browser
typically
contains
a
browsing
context
,
as
does
an
iframe
or
frame
s
in
a
frameset
.
A
browsing
context
has
a
corresponding
WindowProxy
object.
A browsing context has an opener browsing context , which is null or a browsing context . It is initially null.
A browsing context has a disowned boolean. It is initially false.
A browsing context has an is closing boolean. It is initially false.
A
browsing
context
has
a
session
history
,
which
lists
the
Document
objects
that
the
browsing
context
has
presented,
is
presenting,
or
will
present.
A
browsing
context
's
active
document
is
its
WindowProxy
object's
[[Window]]
internal
slot
value's
associated
Document
.
A
Document
's
browsing
context
is
the
browsing
context
whose
session
history
contains
the
Document
,
if
any
such
browsing
context
exists
and
has
not
been
discarded
,
and
null
otherwise.
In
general,
there
is
a
1-to-1
mapping
from
the
Window
object
to
the
Document
object,
as
long
as
the
Document
object
has
a
non-null
browsing
context
.
There
is
one
exception.
A
Window
can
be
reused
for
the
presentation
of
a
second
Document
in
the
same
browsing
context
,
such
that
the
mapping
is
then
1-to-2.
This
occurs
when
a
browsing
context
is
navigated
from
the
initial
about:blank
Document
to
another,
with
replacement
enabled
.
A
Document
does
not
necessarily
have
a
non-null
browsing
context
.
In
particular,
data
mining
tools
are
likely
to
never
instantiate
browsing
contexts.
A
Document
created
using
an
API
such
as
createDocument()
never
has
a
non-null
browsing
context
.
And
the
Document
originally
created
for
an
iframe
element,
which
has
since
been
removed
from
the
document
,
has
no
associated
browsing
context,
since
that
browsing
context
was
discarded
.
The following example illustrates the various possibilities of a browsing context . It can be disowned , is closing , neither, or both.
// Neither disowned nor is closing:
const popup1 = window.open();
// Disowned, but not is closing:
const popup2 = window.open();
popup2.opener = null;
// Not disowned, but is closing:
const popup3 = window.open();
popup3.close();
// Disowned, is closing:
const popup4 = window.open();
popup4.opener = null;
popup4.close();
To
set
the
active
document
of
a
browsing
context
browsingContext
to
a
Document
object
document
,
run
these
steps:
Let window be document 's relevant global object .
Per this standard document can be created before window , which does not make much sense. See issue #2688 .
Set
browsingContext
's
WindowProxy
object's
[[Window]]
internal
slot
value
to
window
.
Set
window
's
associated
Document
to
document
.
Set window 's relevant settings object 's execution ready flag .
A browsing context has an associated creator origin (null or returns an origin ), creator URL (null or returns a URL ), and creator base URL (null or returns a URL ). These are all initially null.
To determine the origin , given browsing context browsingContext , URL url , sandboxing flag set sandboxFlags , and two origins invocationOrigin and activeDocumentNavigationOrigin :
If sandboxFlags has its sandboxed origin browsing context flag set, then return a new opaque origin .
If url is null, then return a new opaque origin .
If
activeDocumentOrigin
is
not
null,
and
url
's
scheme
is
"
javascript
",
then
return
activeDocumentNavigationOrigin
.
If
invocationOrigin
is
non-null
and
url
is
about:blank
,
then
return
invocationOrigin
.
The
result
here
is
that
two
documents
end
up
with
the
same
underlying
origin
,
meaning
that
document.domain
affects
both.
If
url
is
about:srcdoc
,
then
return
the
origin
of
browsingContext
's
container
document
.
Return url 's origin .
To
create
a
new
browsing
context
,
given
null
or
a
Document
object
creator
,
null
or
an
element
embedder
,
and
a
browsing
context
group
group
,
run
these
steps:
Let browsingContext be a new browsing context .
If creator is non-null, then set browsingContext 's creator origin to return creator 's origin , browsingContext 's creator URL to return creator 's URL , and browsingContext 's creator base URL to return creator 's base URL .
Let sandboxFlags be the result of determining the creation sandboxing flags given browsingContext and embedder .
Let
origin
be
the
result
of
determining
the
origin
given
browsingContext
,
about:blank
,
sandboxFlags
,
browsingContext
's
creator
origin
,
and
null.
Let featurePolicy be the result of creating a feature policy given browsingContext and origin . [FEATUREPOLICY]
This needs to use embedder .
Let agent be the result of obtaining a similar-origin window agent given origin and group .
Let realm execution context be the result of creating a new JavaScript realm given agent and the following customizations:
For
the
global
object,
create
a
new
Window
object.
For
the
global
this
binding,
use
browsingContext
's
WindowProxy
object.
Let topLevelOrigin be origin if embedder is null; otherwise embedder 's relevant settings object 's top-level origin .
Let settingsObject be the result of setting up a window environment settings object given realm execution context and topLevelOrigin .
Let
document
be
a
new
Document
,
marked
as
an
HTML
document
in
quirks
mode
,
whose
content
type
is
"
text/html
",
origin
is
origin
,
active
sandboxing
flag
set
is
sandboxFlags
,
feature
policy
is
feature
policy
,
and
which
is
both
ready
for
post-load
tasks
and
completely
loaded
immediately.
Ensure
that
document
has
a
single
child
html
node,
which
itself
has
two
empty
child
nodes:
a
head
element,
and
a
body
element.
Set the active document of browsingContext to document .
If browsingContext 's creator URL is non-null, then set document 's referrer to the serialization of it.
If creator is non-null, then set document 's referrer policy to creator 's referrer policy .
If creator is non-null, then set document 's embedder policy to creator 's embedder policy .
Add document to browsingContext 's session history .
Return browsingContext .
To create a new top-level browsing context :
Let group be the result of creating a new browsing context group .
Return group 's browsing context set [0].
This creates a top-level browsing context .
To create a new auxiliary browsing context , given a browsing context opener :
Let group be opener 's top-level browsing context 's group
Assert: group is non-null, as navigating invokes this directly.
Let browsingContext be the result of creating a new browsing context with opener 's active document , null, and group .
Append browsingContext to group .
Set browsingContext 's opener browsing context to opener .
Assert: browsingContext 's creator origin is non-null.
If
browsingContext
's
creator
origin
is
same
origin
with
browsingContext
's
active
document
's
origin
,
then
copy
the
sessionStorage
storage
area
of
opener
into
browsingContext
's
set
of
session
storage
areas.
These
areas
must
be
considered
separate,
not
affecting
each
other
in
any
way.
Return browsingContext .
This creates a top-level browsing context that is also an auxiliary browsing context .
To create a new nested browsing context , given an element element :
Let group be element 's node document 's browsing context 's top-level browsing context 's group .
Let browsingContext be the result of creating a new browsing context with element 's node document , element , and group .
Set element 's nested browsing context to browsingContext .
If
element
has
a
name
attribute,
then
set
browsingContext
's
name
to
the
value
of
this
attribute.
Certain
elements
(for
example,
iframe
elements)
can
instantiate
further
browsing
contexts
.
These
elements
are
called
browsing
context
containers
.
Each browsing context container has a nested browsing context , which is either a browsing context or null. It is initially null.
The container of a browsing context bc is the browsing context container whose nested browsing context is bc , or null if there is no such element.
Each browsing context bc has a container document , which is the result of running these steps:
If bc 's container is null, then return null.
Return bc 's container 's node document .
This is equal to bc 's container 's shadow-including root as bc 's container has to be connected .
A browsing context child is said to be a child browsing context of another browsing context parent , if child 's container document is non-null and child 's container document 's browsing context is parent .
A browsing context child is a document-tree child browsing context of parent if child is a child browsing context and child 's container is in a document tree .
A browsing context child may have a parent browsing context . This is the unique browsing context that has child as a child browsing context , if any such browsing context exists. Otherwise, the browsing context has no parent browsing context .
A browsing context A is said to be an ancestor of a browsing context B if there exists a browsing context A' that is a child browsing context of A and that is itself an ancestor of B , or if the browsing context A is the parent browsing context of B .
A browsing context that has no parent browsing context is the top-level browsing context for itself and all of the browsing contexts for which it is an ancestor browsing context .
A top-level browsing context has an associated group (null or a browsing context group ). It is initially null.
It is possible to create new browsing contexts that are related to a top-level browsing context while their container is null. Such browsing contexts are called auxiliary browsing contexts . Auxiliary browsing contexts are always top-level browsing contexts .
The transitive closure of parent browsing contexts for a browsing context that is a child browsing context gives the list of ancestor browsing contexts .
The
list
of
the
descendant
browsing
contexts
of
a
Document
d
is
the
(ordered)
list
returned
by
the
following
algorithm:
Let list be an empty list .
For each browsing context container container , whose nested browsing context is non-null and whose shadow-including root is d , in shadow-including tree order :
Let nestedBC be container 's nested browsing context .
Append nestedBC to list .
Extend list with the list of the descendant browsing contexts of nestedBC 's active document .
Return list .
A
Document
d
is
said
to
be
fully
active
when
d
's
browsing
context
is
non-null,
d
's
browsing
context
's
active
document
is
d
,
and
either
d
's
browsing
context
is
a
top-level
browsing
context
,
or
d
's
container
document
is
fully
active
.
Because
they
are
associated
with
an
element,
child
browsing
contexts
are
always
tied
to
a
specific
Document
in
their
parent
browsing
context
.
User
agents
must
not
allow
the
user
to
interact
with
child
browsing
contexts
of
elements
that
are
in
Document
s
that
are
not
themselves
fully
active
.
The
following
example
illustrates
the
differences
between
active
and
fully
active
Document
objects.
Here
a.html
is
loaded
into
a
browser
window,
b-1.html
starts
out
loaded
into
an
iframe
as
shown,
and
b-2.html
and
c.html
are
omitted
(they
can
simply
be
an
empty
document).
<!-- a.html -->
<!DOCTYPE html>
<html lang="en">
<title>Browsing context A</title>
<iframe src="b-1.html"></iframe>
<button onclick="frames[0].location.href = 'b-2.html'">Click me</button>
<!-- b-1.html -->
<!DOCTYPE html>
<html lang="en">
<title>Browsing context B</title>
<iframe
src="c.html"></iframe>
At
this
point,
the
documents
given
by
a.html
,
b-1.html
,
and
c.html
are
all
the
active
documents
of
their
respective
browsing
contexts
.
They
are
also
all
fully
active
.
After
clicking
on
the
button
,
and
thus
loading
a
new
Document
from
b-2.html
into
browsing
context
B,
we
have
the
following
results:
The
a.html
Document
remains
both
the
active
document
of
browsing
context
A,
and
fully
active
.
The
b-1.html
Document
is
now
not
the
active
document
of
browsing
context
B.
As
such
it
is
also
not
fully
active
.
The
new
b-2.html
Document
is
now
the
active
document
of
browsing
context
B,
and
is
also
fully
active
.
The
c.html
Document
is
still
the
active
document
of
browsing
context
C.
However,
since
C's
container
document
is
the
b-1.html
Document
,
which
is
itself
not
fully
active
,
this
means
the
c.html
Document
is
now
not
fully
active
(even
though
it
is
active
).
For more explorations of the complexities involved here, especially as it impacts the session history , see A Model of Navigation History . [NAVMODEL]
A
child
browsing
context
can
be
put
into
a
delaying
load
events
mode
.
This
is
used
when
it
is
navigated
,
to
delay
the
load
event
of
its
container
before
the
new
Document
is
created.
The
document
family
of
a
browsing
context
consists
of
the
union
of
all
the
Document
objects
in
that
browsing
context
's
session
history
and
the
document
families
of
all
those
Document
objects.
The
document
family
of
a
Document
object
consists
of
the
union
of
all
the
document
families
of
the
browsing
contexts
in
the
list
of
the
descendant
browsing
contexts
of
the
Document
object.
The content document of a browsing context container container is the result of the following algorithm:
If container 's nested browsing context is null, then return null.
Let context be container 's nested browsing context .
Let document be context 's active document .
If document 's origin and container 's node document 's origin are not same origin-domain , then return null.
Return document .
top
Returns
the
WindowProxy
for
the
top-level
browsing
context
.
opener
[
=
value
]
Returns
the
WindowProxy
for
the
opener
browsing
context
.
Returns null if there isn't one or if it has been set to null.
Can be set to null.
parent
Returns
the
WindowProxy
for
the
parent
browsing
context
.
frameElement
Returns
the
Element
for
the
browsing
context
container
.
Returns null if there isn't one, and in cross-origin situations.
The
top
attribute's
getter
must
run
these
steps:
If
this
Window
object's
browsing
context
is
null,
then
return
null.
Return
this
Window
object's
browsing
context
's
top-level
browsing
context
's
WindowProxy
object.
The
opener
attribute's
getter
must
run
these
steps:
Let
current
be
this
Window
object's
browsing
context
.
If current is null, then return null.
If current 's disowned is true, then return null.
If current 's opener browsing context is null, then return null.
Return
current
's
opener
browsing
context
's
WindowProxy
object.
The
opener
attribute's
setter
must
run
these
steps:
If
the
given
value
is
null
and
this
Window
object's
browsing
context
is
non-null,
then
set
this
Window
object's
browsing
context
's
disowned
to
true.
If
the
given
value
is
non-null,
then
return
?
OrdinaryDefineOwnProperty
(this
Window
object,
"
opener
",
{
[[Value]]:
the
given
value,
[[Writable]]:
true,
[[Enumerable]]:
true,
[[Configurable]]:
true
}).
If
a
browsing
context
's
disowned
is
true,
its
window.opener
attribute
is
null.
That
prevents
scripts
in
the
browsing
context
from
changing
any
properties
of
its
opener
browsing
context
's
Window
object
(i.e.,
the
Window
object
from
which
the
browsing
context
was
created).
Otherwise,
if
a
browsing
context
's
disowned
is
false,
then
scripts
in
that
browsing
context
can
use
window.opener
to
change
properties
of
its
opener
browsing
context
's
Window
object.
For
example,
a
script
running
in
the
browsing
context
can
change
the
value
of
window.opener.location
,
causing
the
opener
browsing
context
to
navigate
to
a
completely
different
document.
The
parent
attribute's
getter
must
run
these
steps:
Let
current
be
this
Window
object's
browsing
context
.
If current is null, then return null.
If
current
is
a
child
browsing
context
of
another
browsing
context
parent
,
then
return
parent
's
WindowProxy
object.
Assert: current is a top-level browsing context .
Return
current
's
WindowProxy
object.
The
frameElement
attribute's
getter
must
run
these
steps:
Let
current
be
this
Window
object's
browsing
context
.
If current is null, then return null.
Let container be current 's container .
If container is null, then return null.
If container 's node document 's origin is not same origin-domain with the current settings object 's origin , then return null.
Return container .
An example of when these IDL attributes can return null is as follows:
<!DOCTYPE html>
<iframe></iframe>
<script>
"use strict";
const element = document.querySelector("iframe");
const iframeWindow = element.contentWindow;
element.remove();
console.assert(iframeWindow.top === null);
console.assert(iframeWindow.parent === null);
console.assert(iframeWindow.frameElement === null);
</script>
Here
the
browsing
context
corresponding
to
iframeWindow
was
discarded
when
element
was
removed
from
the
document.
A browsing context A is familiar with a second browsing context B if one of the following conditions is true:
A browsing context A is allowed to navigate a second browsing context B if the following algorithm returns true:
If A is not the same browsing context as B , and A is not one of the ancestor browsing contexts of B , and B is not a top-level browsing context , and A 's active document 's active sandboxing flag set has its sandboxed navigation browsing context flag set, then return false.
Otherwise, if B is a top-level browsing context , and is one of the ancestor browsing contexts of A , then:
If
A
's
WindowProxy
's
[[Window]]
value
has
transient
activation
and
A
's
active
document
's
active
sandboxing
flag
set
has
its
sandboxed
top-level
navigation
with
user
activation
browsing
context
flag
set,
then
return
false.
Otherwise,
if
A
's
WindowProxy
's
[[Window]]
value
does
not
have
transient
activation
and
A
's
active
document
's
active
sandboxing
flag
set
has
its
sandboxed
top-level
navigation
without
user
activation
browsing
context
flag
set,
then
return
false.
Otherwise,
if
B
is
a
top-level
browsing
context
,
and
is
neither
A
nor
one
of
the
ancestor
browsing
contexts
of
A
,
and
A
's
Document
's
active
sandboxing
flag
set
has
its
sandboxed
navigation
browsing
context
flag
set,
and
A
is
not
the
one
permitted
sandboxed
navigator
of
B
,
then
return
false.
Return true.
An
element
has
a
browsing
context
scope
origin
if
its
Document
's
browsing
context
is
a
top-level
browsing
context
or
if
all
of
its
Document
's
ancestor
browsing
contexts
all
have
active
documents
whose
origin
are
the
same
origin
as
the
element's
node
document
's
origin
.
If
an
element
has
a
browsing
context
scope
origin
,
then
its
value
is
the
origin
of
the
element's
node
document
.
A user agent holds a browsing context group set (a set of browsing context groups ).
A browsing context group holds a browsing context set (a set of top-level browsing contexts ).
A browsing context group has an associated agent cluster map (a weak map of agent cluster keys to agent clusters ). User agents are responsible for collecting agent clusters when it is deemed that nothing can access them anymore.
To create a new browsing context group , run these steps:
Let group be a new browsing context group .
Append group to the user agent's browsing context group set .
Let browsingContext be the result of creating a new browsing context with null, null, and group .
Append browsingContext to group .
Return group .
To append a top-level browsing context browsingContext to a browsing context group group , run these steps:
Append browsingContext to group 's browsing context set .
Set browsingContext 's group to group .
To remove a top-level browsing context browsingContext , run these steps:
Assert: browsingContext 's group is non-null, because a browsing context only gets discarded once.
Let group be browsingContext 's group .
Set browsingContext 's group to null.
Remove browsingContext from group 's browsing context set .
If group 's browsing context set is empty , then remove group from the user agent's browsing context group set .
Append and remove are primitive operations that help define the lifetime of a browsing context group . They are called from creating a new browsing context group , creating a new auxiliary browsing context , and discarding a browsing context .
The HTML Standard used to define "
" and " ". These have been removed as they were not adequate.Browsing contexts can have a browsing context name . Unless stated otherwise, it is the empty string.
A valid browsing context name is any string with at least one character that does not start with a U+005F LOW LINE character. (Names starting with an underscore are reserved for special keywords.)
A
valid
browsing
context
name
or
keyword
is
any
string
that
is
either
a
valid
browsing
context
name
or
that
is
an
ASCII
case-insensitive
match
for
one
of:
_blank
,
_self
,
_parent
,
or
_top
.
These
values
have
different
meanings
based
on
whether
the
page
is
sandboxed
or
not,
as
summarized
in
the
following
(non-normative)
table.
In
this
table,
"current"
means
the
browsing
context
that
the
link
or
script
is
in,
"parent"
means
the
parent
browsing
context
of
the
one
the
link
or
script
is
in,
"top"
means
the
top-level
browsing
context
of
the
one
the
link
or
script
is
in,
"new"
means
a
new
top-level
browsing
context
or
auxiliary
browsing
context
is
to
be
created,
subject
to
various
user
preferences
and
user
agent
policies,
"none"
means
that
nothing
will
happen,
and
"maybe
new"
means
the
same
as
"new"
if
the
"
allow-popups
"
keyword
is
also
specified
on
the
sandbox
attribute
(or
if
the
user
overrode
the
sandboxing),
and
the
same
as
"none"
otherwise.
Keyword | Ordinary effect |
Effect
in
an
iframe
with...
| |
---|---|---|---|
sandbox=""
|
sandbox="allow-top-navigation"
| ||
none specified, for links and form submissions | current | current | current |
empty string | current | current | current |
_blank
| new | maybe new | maybe new |
_self
| current | current | current |
_parent
if
there
isn't
a
parent
| current | current | current |
_parent
if
parent
is
also
top
| parent/top | none | parent/top |
_parent
if
there
is
one
and
it's
not
top
| parent | none | none |
_top
if
top
is
current
| current | current | current |
_top
if
top
is
not
current
| top | none | top |
name that doesn't exist | new | maybe new | maybe new |
name that exists and is a descendant | specified descendant | specified descendant | specified descendant |
name that exists and is current | current | current | current |
name that exists and is an ancestor that is top | specified ancestor | none | specified ancestor/top |
name that exists and is an ancestor that is not top | specified ancestor | none | none |
other name that exists with common top | specified | none | none |
name that exists with different top, if familiar and one permitted sandboxed navigator | specified | specified | specified |
name that exists with different top, if familiar but not one permitted sandboxed navigator | specified | none | none |
name that exists with different top, not familiar | new | maybe new | maybe new |
Most of the restrictions on sandboxed browsing contexts are applied by other algorithms, e.g. the navigation algorithm, not the rules for choosing a browsing context given below.
The rules for choosing a browsing context , given a browsing context name name , a browsing context current , and a boolean noopener are as follows:
Let chosen be null.
Let new be false.
Let sandboxingFlagSet be current 's active document 's active sandboxing flag set .
If
name
is
the
empty
string
or
an
ASCII
case-insensitive
match
for
"
_self
",
then
set
chosen
to
current
.
Otherwise,
if
name
is
an
ASCII
case-insensitive
match
for
"
_parent
",
set
chosen
to
current
's
parent
browsing
context
,
if
any,
and
current
otherwise.
Otherwise,
if
name
is
an
ASCII
case-insensitive
match
for
"
_top
",
set
chosen
to
current
's
top-level
browsing
context
,
if
any,
and
current
otherwise.
Otherwise,
if
name
is
not
an
ASCII
case-insensitive
match
for
"
_blank
",
there
exists
a
browsing
context
whose
name
is
the
same
as
name
,
current
is
familiar
with
that
browsing
context,
and
the
user
agent
determines
that
the
two
browsing
contexts
are
related
enough
that
it
is
ok
if
they
reach
each
other,
set
chosen
to
that
browsing
context.
If
there
are
multiple
matching
browsing
contexts,
the
user
agent
should
set
chosen
to
one
in
some
arbitrary
consistent
manner,
such
as
the
most
recently
opened,
most
recently
focused,
or
more
closely
related.
This will be made more precise in issue #313 .
Otherwise, a new browsing context is being requested, and what happens depends on the user agent's configuration and abilities — it is determined by the rules given for the first applicable option from the following list:
WindowProxy
's
[[Window]]
value
does
not
have
transient
activation
and
the
user
agent
has
been
configured
to
not
show
popups
(i.e.
the
user
agent
has
a
"popup
blocker"
enabled)
The user agent may inform the user that a popup has been blocked.
The user agent may offer the user one of:
Set chosen to the result of creating a new top-level browsing context and set new to true.
Set chosen to an existing top-level browsing context .
If this case occurs, it means that an author has explicitly sandboxed the document that is trying to open a link.
If the user declines or the user agent doesn't offer the above, the variables remain unchanged.
Set new to true.
If noopener is true, then set chosen to the result of creating a new top-level browsing context .
Otherwise:
Set chosen to the result of creating a new auxiliary browsing context with current .
If sandboxingFlagSet 's sandboxed navigation browsing context flag is set, then current must be set as chosen 's one permitted sandboxed navigator .
If sandboxingFlagSet 's sandbox propagates to auxiliary browsing contexts flag is set, then all the flags that are set in sandboxingFlagSet must be set in chosen 's popup sandboxing flag set .
If
name
is
not
an
ASCII
case-insensitive
match
for
"
_blank
",
then
set
chosen
's
name
to
name
.
If the newly created browsing context is immediately navigated , then the navigation will be done with replacement enabled .
Set chosen to current .
Do nothing.
User agents are encouraged to provide a way for users to configure the user agent to always reuse current .
Return chosen and new .
Window
,
WindowProxy
,
and
Location
objects
Although typically objects cannot be accessed across origins , the web platform would not be true to itself if it did not have some legacy exceptions to that rule that the web depends upon.
When perform a security check is invoked, with a platformObject , identifier , and type , run these steps:
If
platformObject
is
not
a
Window
or
Location
object,
then
return.
For each e of ! CrossOriginProperties ( platformObject ):
If SameValue ( e .[[Property]], identifier ) is true, then:
If
type
is
"
method
"
and
e
has
neither
[[NeedsGet]]
nor
[[NeedsSet]],
then
return.
Otherwise,
if
type
is
"
getter
"
and
e
.[[NeedsGet]]
is
true,
then
return.
Otherwise,
if
type
is
"
setter
"
and
e
.[[NeedsSet]]
is
true,
then
return.
If
!
IsPlatformObjectSameOrigin
(
platformObject
)
is
false,
then
throw
a
"
SecurityError
"
DOMException
.
Window
and
Location
objects
both
have
a
[[CrossOriginPropertyDescriptorMap]]
internal
slot,
whose
value
is
initially
an
empty
map.
The
[[CrossOriginPropertyDescriptorMap]]
internal
slot
contains
a
map
with
entries
whose
keys
are
(
currentGlobal
,
objectGlobal
,
propertyKey
)-tuples
and
values
are
property
descriptors,
as
a
memoization
of
what
is
visible
to
scripts
when
currentGlobal
inspects
a
Window
or
Location
object
from
objectGlobal
.
It
is
filled
lazily
by
CrossOriginGetOwnPropertyHelper
,
which
consults
it
on
future
lookups.
User agents should allow a value held in the map to be garbage collected along with its corresponding key when nothing holds a reference to any part of the value. That is, as long as garbage collection is not observable.
For
example,
with
const
href
=
Object.getOwnPropertyDescriptor(crossOriginLocation,
"href").set
the
value
and
its
corresponding
key
in
the
map
cannot
be
garbage
collected
as
that
would
be
observable.
User
agents
may
have
an
optimization
whereby
they
remove
key-value
pairs
from
the
map
when
document.domain
is
set.
This
is
not
observable
as
document.domain
cannot
revisit
an
earlier
value.
For
example,
setting
document.domain
to
"
example.com
"
on
www.example.com
means
user
agents
can
remove
all
key-value
pairs
from
the
map
where
part
of
the
key
is
www.example.com,
as
that
can
never
be
part
of
the
origin
again
and
therefore
the
corresponding
value
could
never
be
retrieved
from
the
map.
If
O
is
a
Location
object,
then
return
«
{
[[Property]]:
"
href
",
[[NeedsGet]]:
false,
[[NeedsSet]]:
true
},
{
[[Property]]:
"
replace
"
}
».
Return
«
{
[[Property]]:
"
window
",
[[NeedsGet]]:
true,
[[NeedsSet]]:
false
},
{
[[Property]]:
"
self
",
[[NeedsGet]]:
true,
[[NeedsSet]]:
false
},
{
[[Property]]:
"
location
",
[[NeedsGet]]:
true,
[[NeedsSet]]:
true
},
{
[[Property]]:
"
close
"
},
{
[[Property]]:
"
closed
",
[[NeedsGet]]:
true,
[[NeedsSet]]:
false
},
{
[[Property]]:
"
focus
"
},
{
[[Property]]:
"
blur
"
},
{
[[Property]]:
"
frames
",
[[NeedsGet]]:
true,
[[NeedsSet]]:
false
},
{
[[Property]]:
"
length
",
[[NeedsGet]]:
true,
[[NeedsSet]]:
false
},
{
[[Property]]:
"
top
",
[[NeedsGet]]:
true,
[[NeedsSet]]:
false
},
{
[[Property]]:
"
opener
",
[[NeedsGet]]:
true,
[[NeedsSet]]:
false
},
{
[[Property]]:
"
parent
",
[[NeedsGet]]:
true,
[[NeedsSet]]:
false
},
{
[[Property]]:
"
postMessage
"
}
».
Indexed
properties
do
not
need
to
be
safelisted
as
they
are
handled
directly
by
the
WindowProxy
object.
If
P
is
"
then
",
@@toStringTag
,
@@hasInstance
,
or
@@isConcatSpreadable
,
then
return
PropertyDescriptor
{
[[Value]]:
undefined,
[[Writable]]:
false,
[[Enumerable]]:
false,
[[Configurable]]:
true
}.
Throw
a
"
SecurityError
"
DOMException
.
Return true if the current settings object 's origin is same origin-domain with O 's relevant settings object 's origin , and false otherwise.
If
this
abstract
operation
returns
undefined
and
there
is
no
custom
behavior,
the
caller
needs
to
throw
a
"
SecurityError
"
DOMException
.
In
practice
this
is
handled
by
the
caller
calling
CrossOriginPropertyFallback
.
Let crossOriginKey be a tuple consisting of the current settings object , O 's relevant settings object , and P .
For each e of ! CrossOriginProperties ( O ):
If SameValue ( e .[[Property]], P ) is true, then:
If the value of the [[CrossOriginPropertyDescriptorMap]] internal slot of O contains an entry whose key is crossOriginKey , then return that entry's value.
Let originalDesc be OrdinaryGetOwnProperty ( O , P ).
Let crossOriginDesc be undefined.
If e .[[NeedsGet]] and e .[[NeedsSet]] are absent, then:
Let value be originalDesc .[[Value]].
If ! IsCallable ( value ) is true, then set value to an anonymous built-in function, created in the current Realm Record , that performs the same steps as the IDL operation P on object O .
Set crossOriginDesc to PropertyDescriptor { [[Value]]: value , [[Enumerable]]: false, [[Writable]]: false, [[Configurable]]: true }.
Otherwise:
Let crossOriginGet be undefined.
If e .[[NeedsGet]] is true, then set crossOriginGet to an anonymous built-in function, created in the current Realm Record , that performs the same steps as the getter of the IDL attribute P on object O .
Let crossOriginSet be undefined.
If e .[[NeedsSet]] is true, then set crossOriginSet to an anonymous built-in function, created in the current Realm Record , that performs the same steps as the setter of the IDL attribute P on object O .
Set crossOriginDesc to PropertyDescriptor { [[Get]]: crossOriginGet , [[Set]]: crossOriginSet , [[Enumerable]]: false, [[Configurable]]: true }.
Create an entry in the value of the [[CrossOriginPropertyDescriptorMap]] internal slot of O with key crossOriginKey and value crossOriginDesc .
Return crossOriginDesc .
Return undefined.
The reason that the property descriptors produced here are configurable is to preserve the invariants of the essential internal methods required by the JavaScript specification. In particular, since the value of the property can change as a consequence of navigation, it is required that the property be configurable. (However, see tc39/ecma262 issue #672 and references to it elsewhere in this specification for cases where we are not able to preserve these invariants, for compatibility with existing Web content.) [JAVASCRIPT]
The reason the property descriptors are non-enumerable, despite this mismatching the same-origin behavior, is for compatibility with existing Web content. See issue #3183 for details.
Let desc be ? O .[[GetOwnProperty]]( P ).
Assert: desc is not undefined.
If ! IsDataDescriptor ( desc ) is true, then return desc .[[Value]].
Assert: IsAccessorDescriptor ( desc ) is true.
Let getter be desc .[[Get]].
If
getter
is
undefined,
then
throw
a
"
SecurityError
"
DOMException
.
Return ? Call ( getter , Receiver ).
Let desc be ? O .[[GetOwnProperty]]( P ).
Assert: desc is not undefined.
If desc .[[Set]] is present and its value is not undefined, then:
Perform ? Call ( setter , Receiver , « V »).
Return true.
Throw
a
"
SecurityError
"
DOMException
.
Let keys be a new empty List .
For each e of ! CrossOriginProperties ( O ), append e .[[Property]] to keys .
Return
the
concatenation
of
keys
and
«
"
then
",
@@toStringTag
,
@@hasInstance
,
@@isConcatSpreadable
».