Skip to content

Unmangle a switch variable for Closure #7136

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

Merged
merged 1 commit into from
Mar 21, 2023
Merged

Unmangle a switch variable for Closure #7136

merged 1 commit into from
Mar 21, 2023

Conversation

hsubox76
Copy link
Contributor

There is a bug where Closure has trouble handling scope in a switch statement. The mangler reuses a name in the switch statement body that was previously declared outside the switch scope and used inside the switch condition. If we don't mangle the outer variable, there can't be a name collision.

@changeset-bot
Copy link

changeset-bot bot commented Mar 20, 2023

⚠️ No Changeset found

Latest commit: 5232c8a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@google-oss-bot
Copy link
Contributor

Size Report 1

Affected Products

  • @firebase/firestore

    TypeBase (b516abd)Merge (3d16603)Diff
    browser278 kB278 kB+68 B (+0.0%)
    module278 kB278 kB+68 B (+0.0%)
    react-native278 kB278 kB+68 B (+0.0%)
  • firebase

    TypeBase (b516abd)Merge (3d16603)Diff
    firebase-compat.js749 kB750 kB+66 B (+0.0%)
    firebase-firestore-compat.js323 kB323 kB+66 B (+0.0%)

Test Logs

  1. https://storage.googleapis.com/firebase-sdk-metric-reports/WqZJXdow5s.html

@google-oss-bot
Copy link
Contributor

@hsubox76 hsubox76 marked this pull request as ready for review March 20, 2023 18:55
@hsubox76 hsubox76 requested a review from dwyfrequency as a code owner March 20, 2023 18:55
@hsubox76 hsubox76 requested a review from dconeybe March 20, 2023 19:06
@@ -150,8 +150,10 @@ const manglePrivatePropertiesOptions = {
// This can be removed if the problem in the downstream library is fixed
// or if terser's mangler provides an option to avoid mangling everything
// that isn't a property.
// `lastReasonableEscapeIndex` was causing problems in a switch statement
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a link to a buganizer ticket or the "closure bug" for additional context? On its own it's unclear what bug this fixes. Also, why is this the only property that happens to be affected by this "bug"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: b/124161650

The issue seems to be that if you declare a variable outside the switch block, then reference it in the switch condition (the parens), and then declare a new variable with the same name inside the switch block (in one of the cases), Closure thinks that the variable inside the switch condition is referencing the variable in the case, which hasn't been declared yet, instead of realizing it's the variable declared before the switch block.

The mangling around this bit of code:

causes lastReasonableEscapeIndex to have the same mangled single-letter name as currentPiece (and the entire if block gets moved into the switch condition as part of tree-shaking/minifiication) which triggers this Closure problem. If we prevent lastReasonableEscapeIndex from being mangled, it can't have a doppelganger variable inside the switch block.

This is a very hacky fix but the only robust alternative I can think of is to generate an additional un-mangled version of Firestore exclusively to be used by the CDN build script (the prod version of @firebase/firestore will continue to be mangled, for size savings). This way it won't be mangled twice. Unfortunately that's one more Firestore build which will make build time longer.

Without the change, this is the code that is generated for packages/firestore/dist/index.esm2017.js:

        const n = e - 2, s = [];
    let i = "";
    for (let r = 0; r < e; ) {
        // The last two characters of a valid encoded path must be a separator, so
        // there must be an end to this segment.
        const e = t.indexOf("�", r);
        (e < 0 || e > n) && $();
        switch (t.charAt(e + 1)) {
          case "�":
            const n = t.substring(r, e);

where n is the problem variable. With this fix, the first n is replaced with __PRIVATE_lastReasonableEscapeIndex (the _PRIVATE gets appended by another Firestore build task which I'm not sure if it's worth trying to work around right now) and the problem goes away.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fantastic explanation!

Copy link
Contributor

@dwyfrequency dwyfrequency left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@hsubox76 hsubox76 merged commit 480d7d5 into master Mar 21, 2023
@hsubox76 hsubox76 deleted the ch-g3-2 branch March 21, 2023 20:03
renkelvin pushed a commit that referenced this pull request Mar 21, 2023
@firebase firebase locked and limited conversation to collaborators Apr 21, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants