Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define when navigator and location objects are replaced #2545

Open
foolip opened this issue Apr 18, 2017 · 19 comments
Open

Define when navigator and location objects are replaced #2545

foolip opened this issue Apr 18, 2017 · 19 comments
Labels
interop Implementations are not interoperable with each other topic: navigation

Comments

@foolip
Copy link
Member

foolip commented Apr 18, 2017

The document attribute returns the associated Document and the history attribute is defined in terms of that as well.

For navigator and location, there isn't anything to suggest that these objects are replaced when navigating an iframe.

https://jsbin.com/jagiruh/edit?html,output is a test that passes in Chrome, Firefox and Safari, showing that a bunch of objects are replaced when navigating an iframe. It fails with "Permission denied" in Edge.

@foolip
Copy link
Member Author

foolip commented Apr 18, 2017

Is this all entangled with the reasons that WindowProxy exist, perhaps?

@foolip
Copy link
Member Author

foolip commented Apr 18, 2017

This came up in https://codereview.chromium.org/2805763004 where I wanted to propose something like an "is active" check for the navigator object.

@annevk
Copy link
Member

annevk commented Apr 18, 2017

Yeah, WindowProxy typically persists, but its underlying Window object definitely changes upon navigation (unless initial about:blank).

@domenic
Copy link
Member

domenic commented Apr 18, 2017

The spec here is pretty bad for Navigator:

The navigator attribute of the Window interface must return an instance of the Navigator interface, which represents...

It could be any instance! The entire browser could share a single instance!! Ugh.

For Location it's much better:

Each Window object is associated with a unique instance of a Location object, allocated when the Window object is created.

and Window objects are created explicitly during navigation and other scenarios.

@annevk
Copy link
Member

annevk commented Apr 20, 2017

I wrote this test:

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<iframe></iframe>
<script>
async_test(t => {
  const frameLocation = self[0].location,
        frameNavigator = self[0].navigator,
        frameHistory = self[0].history
  self[0].frameElement.onload = t.step_func_done(() => {
    assert_equals(self[0].location, frameLocation)
    assert_equals(self[0].navigator, frameNavigator)
    assert_equals(self[0].history, frameHistory)
  })
  self[0].location.href = "/common/blank.html"
})
</script>

Note that History objects are technically associated with documents, so it should change here, but in Firefox it does not and it passes the test. However, in Chrome and Safari I get

assert_equals: expected [stringifying object threw TypeError: Cannot convert object to primitive value with type object] but got object "http://web-platform.test:8000/common/blank.html"

which I'm not sure what to do with.

@annevk
Copy link
Member

annevk commented Apr 20, 2017

@foolip @cdumez any clues why the above test throws a TypeError? It looks perfectly reasonable to me.

@cdumez
Copy link

cdumez commented Apr 20, 2017

It looks like the exception is thrown when test harness tries to construct a string for the error message from frameLocation. All those assertions fail in WebKit, we do not return the same objects after the navigation. Therefore, frameLocation is in a state where it throws when trying to do whatever the test harness does.

@annevk
Copy link
Member

annevk commented Apr 21, 2017

That seems like a bug in itself as everything is same-origin and nothing would end up throwing like that (it seems to simply try to ToString it). And not returning the same object is a bug too. I guess all this is even less interoperable than I thought.

@cdumez
Copy link

cdumez commented Apr 21, 2017

I believe our location object relies on having a frame to be useful. However, after the navigation, it seems we create a new Location object and the old one ends up being frameless.

@annevk
Copy link
Member

annevk commented Apr 24, 2017

If I reduce my above test to just Navigator objects I get different objects in Chrome and Safari, I get "Permission denied" in Edge, and I get a pass in Firefox.

I think what Firefox does makes the most sense, unless we really want to tie all these objects to Document objects while they are accessed from the Window object...

@annevk
Copy link
Member

annevk commented May 4, 2017

Created a test for window.location with @domenic's excellent per-global framework: web-platform-tests/wpt#5778. All browsers are different. 🎉

Once we make progress there I'd propose we make History and Navigator per-global as well.

@foolip
Copy link
Member Author

foolip commented May 4, 2017

Wow, thanks for the excellent research! I've merged web-platform-tests/wpt#5778, do you think we should wait for that to be sorted out implementation-side before doing anything further here?

@annevk
Copy link
Member

annevk commented May 4, 2017

Yeah, I'm wondering whether Chromium and WebKit have architectural reasons for having almost everything associated with Document objects. If they're okay with moving some things to the global object I think we're good, but if not, we probably want to reconsider a couple of things before pushing this further.

@foolip
Copy link
Member Author

foolip commented May 4, 2017

I'm not sure either. A change like this might end up with @tkent-google to ponder, WDYT?

@tkent-google
Copy link
Collaborator

I guess fixing this is not easy due to out-of-process iframe.

@annevk
Copy link
Member

annevk commented May 8, 2017

I'm actually now confused how it can work securely to associate things with the global object. If you grab a reference to this associated thing and then navigate the initial about:blank frame cross-origin, what happens? @bzbarsky how does Firefox handle that?

@bzbarsky
Copy link
Contributor

bzbarsky commented May 8, 2017

If you grab a reference to this associated thing and then navigate the initial about:blank frame cross-origin, what happens?

The same thing that happens when you navigate any other page cross-origin. You get a new global object, with a different origin from the old global object. The things you were holding on to are still referencing the old global object. Do you have a specific scenario or API you're concerned about?

@annevk
Copy link
Member

annevk commented May 10, 2017

Thanks, I had just missed that replacement only happens same-origin. @tkent-google so what exactly is the issue with out-of-process child documents then?

@tkent-google
Copy link
Collaborator

I don't have an idea of exact technical issues at this moment. It's just a guess, and I don't think fixing it is impossible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interop Implementations are not interoperable with each other topic: navigation
Development

No branches or pull requests

7 participants