Get document URL in esm-amd-loader#407
Conversation
aomarks
left a comment
There was a problem hiding this comment.
Thanks for the PR! Looks good overall.
| if (defined === false) { | ||
| pendingDefine = undefined; | ||
| const url = baseUrl + '#' + topLevelScriptIdx++ as NormalizedUrl; | ||
| const url = documentUrl + '#' + topLevelScriptIdx++ as NormalizedUrl; |
There was a problem hiding this comment.
I think you'll also need to update line 267 (url: (module.isTopLevel === true) ? baseUrl : module.url), because when a module is top-level, we currently just return the const document URL when meta is requested. To do it correctly you'll need to return this new module.url with the artificial # fragment we added stripped off.
There was a problem hiding this comment.
Good point, I've made the change.
| define: ((deps: string[], moduleBody: OnExecutedCallback) => void)&{ | ||
| _reset?: () => void; | ||
| }; | ||
| HTMLImports: { importForElement: (element: Element) => HTMLLinkElement | undefined } |
There was a problem hiding this comment.
HTMLImports?: ... since it might not be defined
| } else { | ||
| // On chrome's native implementation it's not possible to get a direct reference to the link element, | ||
| // create a new script and let the browser resolve the url. | ||
| const script = currentScript.ownerDocument.createElement('script'); |
There was a problem hiding this comment.
I'd use an a tag with an href instead of a script, just to be more consistent with what we do with normalizeUrl above.
| // On chrome's native implementation it's not possible to get a direct reference to the link element, | ||
| // create a new script and let the browser resolve the url. | ||
| const script = currentScript.ownerDocument.createElement('script'); | ||
| script.src = './'; |
There was a problem hiding this comment.
I think this needs to be '' instead of './', otherwise you'll get e.g. http://localhost/ instead of http://localhost/import.html.
There was a problem hiding this comment.
I didn't think '' would resolve to anything, but it did. It's better because it resolves to the filename.
| return baseUrl; | ||
| } | ||
| // Take the import href and strip off the filename | ||
| return htmlImport.href.substring(0, htmlImport.href.lastIndexOf('/') + 1); |
There was a problem hiding this comment.
I think we need to be a bit more careful here, e.g. this will return http:// if href is http://example.com. We handle this above with normalizeUrl (which ensures there is always a trailing slash), and getUrlBase (which handles some more cases).
There was a problem hiding this comment.
I'm not sure if the href will ever be http://example.com for a html import, won't it always need to be a specific file? But it turns out we can just return the href here, this is in line with what we're returning from the native implementation as well.
|
@aomarks I've made the changes and added tests. I couldn't get the tests to run from a html import, wct doesn't run suite() and test() created inside an import. I didn't want to introduce too much deviation from the current set up just for html imports. Creating the imports imperatively does the job pretty simply as well and keeps it in the same file. What do you think? I added the v1 webcomponents loader, as the v2 loader does not add html imports. |
…e/resolve-html-import-url
|
The tests run fine for me locally, but I'm not sure what's going wrong inside appveyor and travis? |
|
Looks good, just a few small more comments. Sorry for the delay! I'm also working on #441 so that we'll have this library running on Safari and IE11 in continuous integration. Have you tested manually on IE11 btw? |
| } | ||
|
|
||
| function testImport(href: string, expectedOrder: string[], done: () => void) { | ||
| // Each time and amd module in the chain is executed, it registers itself. |
| // Each time and amd module in the chain is executed, it registers itself. | ||
| // If we've reached the length of modules we are expecing to be loaded, | ||
| // we check if the right modules were loaded in the expected order | ||
| window.addExcutedForImport = (name: string) => { |
| "sourceMap": false, | ||
| "lib": [ | ||
| "es5", | ||
| "es2015", |
There was a problem hiding this comment.
Do you need this to be es2015? We need the tests to run in IE11 without adding polyfills so only having es5 helps make sure we aren't using APIs that won't be available.
There was a problem hiding this comment.
Sorry, I didn't mean to change that.
|
|
||
| test('import with meta', (done) => { | ||
| window.testImportMeta = (url) => { | ||
| assert.match(url, /https?:\/\/.+\/html-import\/meta/); |
There was a problem hiding this comment.
check that it ends exactly in html-import/meta/import-meta.html$
There was a problem hiding this comment.
You're right, made the change.
|
|
||
| <script> | ||
| define(['meta'], (meta) => { | ||
| window.testImportMeta(meta.url); |
There was a problem hiding this comment.
Might be a little nicer to have this set a global, and then check it inside testImport before you call done (or something like that) to ensure that the assertion is actually run. Right now if this module didn't execute at all for some reason, the test would still pass.
There was a problem hiding this comment.
I think this is already the case. In the start of the test we make a global function which is called from the import. If the module file fails to load or if the code fails to run, the function isn't called and thus done isn't called. This causes the test to fail.
|
@aomarks Made the changes. Also, I've run the tests on chrome, firefox, safari, edge and IE11. |
Currently the esm-amd-loader assumes that when it finds a top level module script, it's always a script in the index.html. When using HTML Imports (and possibility in the future HTML modules as well) this is not always the case.
Relative module import specified in HTML imports are resolved properly for es modules, but when transpiled to AMD they are always resolved relative to the index.html.
This PR makes it so that relative imports are resolved relative to the document (index or HTML import) that includes the script. It also makes it so that the correct import.meta.url is returned for these AMD modules.
I didn't change the tests yet, I first wanted to see if this was the right direction to fix HTML import - es module interop.
Fixes #391