Repository navigation
📦🔧:survive minifiers that rename properties - #135
Merged
Merged
Conversation
Compiled with Closure Compiler's ADVANCED mode, which renames every property it has no declaration for, the packages broke in two ways. UnicodeEscapes was a TypeScript enum, which compiles to quoted writes read back unquoted. Only the reads were renamed, so curlyQuote and ellipsify, and every error message that quotes a name with them, printed "undefined". It is a plain object again, as in 1.x, with a type of the same name, and erasableSyntaxOnly now keeps enums, namespaces and parameter properties out; three tests used the last. isRawJSON, isNativeError and the isTemporal* guards probe the host for JSON.isRawJSON, Error.isError, process and Temporal, none of which Closure declares. Renamed, each probe found nothing: the guards said false for every value, and isNativeError fell back to a check that a forged prototype fools. They are now read by name, like the globals the brand checks already read that way. util-object also declared an unused module-local Object, which tsickle turned into an extern that erased Closure's type for Object. Signed-off-by: Derek Lewis <DerekNonGeneric@inf.is> Assisted-by: Claude-Code:claude-opus-5
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.
Requested by DerekNonGeneric · project thread
The SDK was put through Google Closure Compiler v20261021 (SIMPLE and ADVANCED), both on the built ESM output and on tsickle's output from the TypeScript sources. It compiles in both modes, but ADVANCED, which renames every property it has no declaration for, broke four things at runtime. A differential run (each of the 221 exported
is*/has*/can*guards on about 90 values, Closure output compared with plain Node.js, with and without--harmony-temporal) found 19 guards that answered differently before this change and none after.UnicodeEscapes: it was a TypeScript enum, which compiles to quoted writes read back unquoted. Only the reads were renamed, socurlyQuote('x')returnedundefinedxundefined,ellipsifydid the same, and so did every error message that quotes a name with them. It is a plainas constobject again, the shape it had in 1.x, plus a type of the same name.erasableSyntaxOnlyintsconfig.base.jsonnow keeps enums, namespaces and parameter properties out. Three tests used parameter properties and now declare the field instead.isRawJSON,isNativeError,isTemporal*: they probeJSON.isRawJSON,Error.isError,process.getBuiltinModuleandTemporal, and Closure has no declaration for any of them. Once renamed, each probe found nothing.isRawJSONand all eight Temporal guards saidfalsefor every value, andisNativeErroraccepted anObject.create(Error.prototype)that carries a tag. These are now read by quoted key, like theglobals['WeakRef']reads the same file already does.declare let Object: this module-local declaration was never used. tsickle turned it into an externvar Objecttyped?, which erased Closure's type forObject.Left alone, because they are limits of the tools rather than problems in the SDK:
#privateclass fields, so gh-file-importer only compiles when downleveled to ES2021.@categoryand@param a.btags as bad JSDoc. These are warnings and can be silenced with--extra_annotation_name._as private, which flags the_tagTester-style helpers the packages deliberately share.Object.hasOwn(obj, number), for example).Temporal/isWellFormed,esModuleInteropoff andimportHelperson. All of its ~290 warnings are types it can't translate (intersections, mapped and conditional types).Assertdecorator and guard expectations put in their messages. Any minifier does this.GhFileImportercheckshasOwn(options, 'destDir')and then readsoptions.destDir. Under ADVANCED that always throwsMissingOptionError, and tsickle doesn't help. It is left alone because the own-property check keeps a pollutedObject.prototype.destDirfrom choosing where files are written, and a Node-only class that writes files isn't a realistic ADVANCED target.Checked locally on Node 24: build,
pnpm test(1331 tests, 0 failures), lint, lint:types, knip, format, md, spelling, examples, packages, docs:check and lint:commits.Summary by CodeRabbit