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

What is the URL of a CSSStyleSheet created via the constructor? #10

Closed
bzbarsky opened this issue Feb 6, 2018 · 21 comments
Closed

What is the URL of a CSSStyleSheet created via the constructor? #10

bzbarsky opened this issue Feb 6, 2018 · 21 comments
Labels
needs resolution Needs consensus/resolution before shipping

Comments

@bzbarsky
Copy link

bzbarsky commented Feb 6, 2018

This matters for base URL bits in the CSS and some DOM APIs. In general, need to define https://drafts.csswg.org/cssom/#concept-css-style-sheet-location

@TakayoshiKochi
Copy link
Member

The CSSOM spec says location is specified when created, but naively I thought it can be deferred until it is added to somewhere (e.g. .moreStyleSheets). But in that case at least resource fetching for @import and url() would not work until the location becomes clear, which is not ideal.

Is there any situation that copying document base URL becomes problematic?

@calebdwilliams
Copy link

Given the discussion in #23 I think it would make sense to treat using the document base URL as a security feature. That might also have some impact on #26 as well, but that's getting beyond my pay grade.

@TakayoshiKochi
Copy link
Member

A naive solution would be to use the document URL that the current running inline script belongs to (I don't think anyone except Blink cares about HTML imports, but in that case document.currentScript.ownerDocument.baseURI), for classic external scripts its base URL, and for module scripts, import.meta.url.

At this moment a CSSStyleSheet is constructed from string, I think the above is a reasonable default.

@bzbarsky
Copy link
Author

Why would there necessarily be a running inline script?

<div onclick="var sheet = new CSSStyleSheet(stuff)">Click me</div>

@calebdwilliams
Copy link

calebdwilliams commented Apr 25, 2018

@bzbarsky I would assume in that case it would be HTMLElement.ownerDocument.baseURI based on the comments above.

@bzbarsky
Copy link
Author

Of which HTMLElement? The one the event handler is on? Is that also what happens if the event handler was assigned via .onclick to some function?

The simplest thing, of course, is to use the base url of the document of the constructor's Realm global (which is a Window, presumably). Still have to decide whether it gets copied or aliased, of course.

@TakayoshiKochi
Copy link
Member

Why would there necessarily be a running inline script?

@bzbarsky I might have misused the term, I meant <script> without src= attribute.

Let's decide on using document base url of the constructor's Realm global. Let me scratch import.meta.url I mentioned above.

Any objections / opinions?

@bzbarsky
Copy link
Author

@bzbarsky I might have misused the term, I meant <script> without src= attribute.

The term is correct for that, but in my example above there is no <script> involved at all.

Let's decide on using document base url of the constructor's Realm global.

Is that aliased, or snapshotted at the point when the constructor is called?

@TakayoshiKochi
Copy link
Member

Let's decide on using document base url of the constructor's Realm global.
Is that aliased, or snapshotted at the point when the constructor is called?

As far as I imagine I'd go with snapshot when the constructor is called, but my imagination can be very small-scoped. What's the case when aliasing is useful...? In other words, does dynamic change of a document's base url happen so often, or even if it is rare, can following the change by aliasing be useful?

@bzbarsky
Copy link
Author

What's the case when aliasing is useful...?

I'm not sure there's an obvious case, but what do inline stylesheets end up doing? We should probably at least consider matching them here.

does dynamic change of a document's base url happen so often

Often enough, with pushState and single-page apps....

@TakayoshiKochi
Copy link
Member

I'm not sure there's an obvious case, but what do inline stylesheets end up doing? We should probably at least consider matching them here.

Hmm, interesting, so if pushState() changes the document's URL, and delayed loading of @import or url() may have non deterministic behavior when UA aliases the URL. Let me dig into what the spec says and what browser behaves.

@TakayoshiKochi
Copy link
Member

I think this is the latest reference
https://drafts.csswg.org/css-values-4/#relative-urls

the base URL is that of the style sheet itself, not that of the styled source document.
Style sheets embedded within a document have the base URL associated with their container.

@TakayoshiKochi
Copy link
Member

Found a note below the part that I quoted above:
https://drafts.csswg.org/css-values-4/#local-urls

What “browser eccentricities”?
Theoretically, browsers should re-resolve any relative URLs, including fragment-only URLs, whenever the document’s base URL changes (such as through mutation of the base element, or calling pushState()). In many cases they don’t, however, and so without special handling, fragment-only URLs will suddenly become cross-document references (pointing at the previous base URL) and break in many of the places they’re used.

So... in many cases browser don't recalculate url() whenever base URL changes :(

Related to #2, maybe we should hang the factory method under Document so that the URL association to the document is clear, but still needs to clarify the case for standalone constructor. Let me work on spec update.

@calebdwilliams
Copy link

I think the constructor is only useful if there’s an instance method to parse style sheets asynchronously. That’s only useful if the spec for custom element styles proposal allows modification of the style sheet after the element has been defined which so far they seem opposed to despite my push back. Ultimately there might not be any real use case for the constructor.

@TakayoshiKochi
Copy link
Member

Maybe my last comment was not clear, but rather than

StyleSheet.createFromString(text)

, hanging the API on document

document.createCSSStyleSheet(text)

can make it clear about the association of the constructed stylesheet with the document (much like <style> or <link rel=stylesheet>), then how url() is resolved becomes more obvious.

@rakina
Copy link
Member

rakina commented Sep 12, 2018

#35 resolves this - We use the Document's base URL.

@pygy
Copy link

pygy commented Feb 2, 2020

Couldn't a blob: URI be a nice fit WRT both synchronous @import usage (assuming @import would be restricted to blobs in constructed sheets) and CSP?

@bzbarsky
Copy link
Author

bzbarsky commented Feb 2, 2020

How, exactly? blob: URL loads are most definitely not synchronous.

@pygy
Copy link

pygy commented Feb 2, 2020

The blob: URI could be used as a key in a hash map (when used by @import), to get to the actual CSSStyleSheet object synchronously, bypassing the streaming protocol.

There are obviously more efficient ways of passing the dependency (through a JS API), I'm just trying to find a way to reuse pre-existing concepts.

@import feels like a natural way to manage dependencies, and blob: URIs provide unique ids to local data.

@bzbarsky
Copy link
Author

bzbarsky commented Feb 2, 2020

The blob: URI could be used as a key in a hash map (when used by @import)

Browsers already do this, for all URIs, if the URI has been parsed into a sheet.

and blob: URIs provide unique ids to local data.

Thinking of blob: as "local data" can be misleading: it can be stored on disk, and retrieving it might then be slower than getting something off the network, depending on the disk and the network.

@pygy
Copy link

pygy commented Feb 2, 2020

it can be stored on disk, and retrieving it might then be slow[...]

This is true of blobs in general, but in this case we're not fetching the blob, but the CSSStyleSheet directly.

If it has been paged out, setting up the dependency will be slow, no matter how the dep is defined (through @import or through JS).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs resolution Needs consensus/resolution before shipping
Projects
None yet
Development

No branches or pull requests

5 participants