-
Notifications
You must be signed in to change notification settings - Fork 199
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
Preserve correctness of import.meta.url
in bundled modules.
#300
Conversation
…de corrected URL.
… lerna bootstrap needed to do after I added acorn-import-meta.
Fixes #294 |
const aUrl = analyzer.resolveUrl('a.js')!; | ||
const bUrl = analyzer.resolveUrl('subfolder/b.js')!; | ||
const cUrl = analyzer.resolveUrl('c.js')!; | ||
const dUrl = analyzer.resolveUrl('d.js')!; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is dUrl used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, thanks! I was adding another test case and then gave up; forgot that was there. Removed.
packages/bundler/src/es6-rewriter.ts
Outdated
moduleFile: babel.File, | ||
relativeUrl: FileRelativeUrl): babel.File { | ||
// Generate a stand-in for any local references to import.meta... | ||
// const __bundledImportMeta = {...__importMeta, url: __bundledImportURL}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is __importMeta
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I previously had a local variable stand-in just for import.meta that is now gone. Old comment. Fixed to import.meta! Thanks!
packages/bundler/src/es6-rewriter.ts
Outdated
traverse(newModuleFile, { | ||
noScope: true, | ||
MetaProperty: { | ||
enter(path: NodePath) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can avoid the cast below by doing: enter(page: NodePath<babel.MetaProperty>) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AH! Thanks! I have several of these in bundler code to fix! Will do now.
packages/bundler/src/es6-rewriter.ts
Outdated
// URL has changed as a result of bundling. | ||
const relativeUrl = | ||
ensureLeadingDot(this.bundler.analyzer.urlResolver.relative( | ||
this.bundle.url, id as ResolvedUrl)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the cast of id
needed? It looks like it's a ResolvedUrl already
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. Fixed.
packages/bundler/src/es6-rewriter.ts
Outdated
ensureLeadingDot(this.bundler.analyzer.urlResolver.relative( | ||
this.bundle.url, id as ResolvedUrl)); | ||
const newAst = this._rewriteImportMetaToBundleMeta( | ||
document.parsedDocument.ast as babel.File, relativeUrl); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could put this constraint into the type system if we added a type checking function that checks that document
is a Document<ParsedJavascriptDocument>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right and in fact this code probably should have more guarantees/verification of the type of document it is loading anyways. I'll add a TODO here for this.
packages/bundler/src/es6-rewriter.ts
Outdated
// Generate a stand-in for any local references to import.meta... | ||
// const __bundledImportMeta = {...__importMeta, url: __bundledImportURL}; | ||
const bundledImportMetaName = '__bundledImportMeta'; | ||
const bundledImportMetaDeclaration = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could maybe use the @babel/template ast
template string literal tag here instead of building it manually with the API? (Example: https://github.com/Polymer/tools/blob/master/packages/build/src/babel-plugin-dynamic-import-amd.ts#L64)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love this idea. I even made a personal TODO note earlier today "Look up to see if there's a template string builder that would make this code cleaner."
I would like to consider bringing that approach to all of the ast production in bundler, but I'm going to hold off on a separate PR to bring that machinery in here. Adding TODO. It's a great idea and would make this code a lot better.
I should note that as of right now though, Bundler does not have any babel parsing in it and relies purely on Analyzer. Use of the template literal stuff would essentially require ensuring I either find a nice way to clone the Analyzer's babel parsing stack or rebuild it locally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM
packages/bundler/src/es6-rewriter.ts
Outdated
babel.identifier('import'), babel.identifier('meta'))), | ||
babel.objectProperty( | ||
babel.identifier('url'), | ||
babel.newExpression( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to get the .href
property of this new url, as import.meta.url
is a string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DERP! Really good catch. Fixed.
…ter-the-fact casting.
…arsedJavascriptDocument> verification and add typings to its ast.
Awww nuts. Something probably in the package-lock has updated causing something to break during gulp-typescript... https://ci.appveyor.com/project/Polymer/tools/build/1.0.858#L127 |
Bunch of things like |
Ah this failure is unrelated to branch. Created a new PR to start to fix the TS errors related to updating package locks at #309 |
// Generate a stand-in for any local references to import.meta... | ||
// const __bundledImportMeta = {...import.meta, url: __bundledImportURL}; | ||
// TODO(usergenic): Consider migrating this AST production mishmash into the | ||
// `ast` tagged template literal available like this: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. Much easier to read and write.
// TODO(usergenic): Consider migrating this AST production mishmash into the | ||
// `ast` tagged template literal available like this: | ||
// https://github.com/Polymer/tools/blob/master/packages/build/src/babel-plugin-dynamic-import-amd.ts#L64 | ||
const bundledImportMetaName = '__bundledImportMeta'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should generate this name to be conflict free with identifiers at import.meta
use sites.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added issue. #310
babel.newExpression( | ||
babel.identifier('URL'), | ||
[ | ||
// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove? Or if it's for formatting, move to previous line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang-format went crazy so I put this in here to get it to behave. I can annotate further. This of course goes away after I switch to ast
template literal...
babel.identifier('href'))) | ||
])) | ||
]); | ||
const newModuleFile = clone(moduleFile); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you have to clone it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I modify in-place from document returned by analyzer and I'm trying to be a good citizen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. Modifying documents returned by analyzer will lead to the worst kind of weird bugs with spooky action at a distance.
packages/bundler/src/es6-rewriter.ts
Outdated
return; | ||
} | ||
const bundledImportMeta = babel.identifier(bundledImportMetaName); | ||
rewriteObject(metaProperty, bundledImportMeta); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use path.replaceWith
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. That makes sense here. Replace'd
babel.identifier('href'))) | ||
])) | ||
]); | ||
const newModuleFile = clone(moduleFile); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. Modifying documents returned by analyzer will lead to the worst kind of weird bugs with spooky action at a distance.
I'm seeing this transform present on the es6-bundled build output which doesn't make since it uses const bundledImportMeta = { ...import.meta,
url: new URL('...', import.meta.url).href
}; |
Note that in the case where an imported module's URL is identical to the bundle URL, no modification to the module code is needed before bundling it, but for all other cases where
import.meta
occurs somewhere in the document contents, we construct a module-scoped stand-in variable and swap other references to import.meta to use the stand-in, which is declared as an object-literal like{...import.meta, url: new URL(relativeUrlToModule, import.meta.url)}
.