feat: add polyfills build option to enable or disable polyfills - #496
Merged
Conversation
Polyfills were previously selected entirely by `compilerOptions.target`,
with `Latest` disabling all of them and every other target enabling
whichever ones matched. The new `polyfills` build option overrides that
per polyfill:
polyfills: { importMeta: false }
A boolean enables or disables all of them. Anything left unspecified
still resolves from the target.
This also fixes denoland#471. The `import.meta` call sites are rewritten by a
TypeScript compiler transform in `lib/compiler_transforms.ts` rather than
by the Rust transform, and that rewrite was not gated on the target at
all. Setting `target: "Latest"` therefore dropped the polyfill file while
still emitting calls into it, producing output that threw at runtime. The
rewrite is now gated on the same resolved decision as the polyfill file.
Disabling the `importMeta` polyfill requires `scriptModule: false` since
`import.meta` is a syntax error in CommonJS; it errors otherwise instead
of emitting invalid output.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #471
Polyfills were previously selected entirely by
compilerOptions.target:Latestdisabled all of them and every other target enabled whichever ones matched. There was no way to keep a target and opt out of an individual polyfill.This adds a
polyfillsbuild option that overrides the target per polyfill:A bare
true/falseenables or disables all of them. Anything left unspecified still resolves from the target, sopolyfillsoverrides the target rather than replacing it.Supported names:
arrayFindLast,arrayFromAsync,errorCause,importMeta,objectHasOwn,promiseWithResolvers,stringReplaceAll.The
import.metabugThis also fixes the runtime error reported in #471, which turned out to be a separate pre-existing bug.
The
import.metacall sites are rewritten by a TypeScript compiler transform inlib/compiler_transforms.ts, not by the Rust transform, and that rewrite was never gated on the target. Settingtarget: "Latest"dropped the polyfill file (via theLatestearly-return inpolyfills_for_target) while still emittingglobalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta)calls into it — so the output threw at runtime. The rewrite is now gated on the same resolved decision as the polyfill file.Disabling the
importMetapolyfill requiresscriptModule: false, sinceimport.metais a syntax error in CommonJS. It errors with an explanation rather than emitting invalid output.Implementation
Polyfillgainsfn name(&self) -> &'static str, andpolyfills_for_targettakes an overrides map. TheLatestearly-return moves into the filter so an explicit override can turn a polyfill back on atLatest; defaults are unchanged.polyfillsis threaded throughTransformOptionsinrs-lib,wasm, andtransform.ts.lib/polyfills.tsholds the option resolution and theimport.metadecision, and errors on unknown polyfill names for JS callers (TS callers get it from thePolyfillNameunion).Note on types
The polyfill scripts carry the ambient
declare globaldeclarations for the features they polyfill, so opting out of one means relying oncompilerOptions.libfor those declarations instead. This is documented in the README. It's worth being aware of because users will hit a type error before a runtime one — e.g.polyfills: falseon a project usingObject.hasOwnneedslib: ["ESNext"], andimport.meta.mainis a Deno-ism that exists in no TS lib, so it stops type checking entirely withimportMeta: false.Tests
Latest, and an override affecting only the named polyfill.lib/polyfills.test.tsunit tests for option resolution and theimport.metadecision.import.metaleft intact for an ESM-only build with the polyfill off, the script-module error, andpolyfills: falseemitting no polyfill file.deno test -A(111 passed),cargo test --workspace(83 passed),deno fmt/deno lint/cargo fmtall clean.