Skip to content
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

fix(compartment-mapper): Defer all importHook errors when importing a… #2610

Merged
merged 6 commits into from
Nov 5, 2024

Conversation

naugtur
Copy link
Member

@naugtur naugtur commented Oct 23, 2024

… dependency if they're intended to be deferred

Description

When importHook is used to load dependencies, they might be coming from imports that were identified by a parser that uses heuristics to find them. (e.g. cjs parser implementation uses a lexer to find all require calls even if they're not the require function but a local require function)
In such cases we want to defer loading errors to runtime, so the error doesn't happen until actual require is actually called to get it.

That was true for loading known dependency, but exit modules (via exitModuleImportHook) were not covered.

Security Considerations

no changes security-wise

Scaling Considerations

The way this is currently implemented - one big try-catch instead of returning the deferred error without throwing and catching, might be less performant. Should we consider trading aesthetics for a tiny performance gain here?
Note this only makes a difference for cases where non-dynamic require is called on a specifier that causes an error.

Documentation Considerations

It's a fix of unintended behavior. No changes to what needs to be documented.

Testing Considerations

Fix was added test-first

Compatibility Considerations

Compatibility is improved. Packages can now do:

try {
  require('my-dev-dependency')
  } catch(){}

to silently attempt to load something that is only useful in their own development process. (typescript does that)

Upgrade Considerations

While it's a fix, not a breaking change, it does change one specific behavior - an error resulting from calling exitModuleImportHook (the importHook passed to compartment-mapper, not the one in Compartment options) is now thrown at runtime, not during loading, which could be noteworthy for the Archive use-case.

(insert mandatory xkcd about breaking changes)

… dependency if they're intended to be deferred
return deferError(
moduleSpecifier,
Error(
throw Error(
Copy link
Member Author

Choose a reason for hiding this comment

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

returning instead of throwing could be slightly more performant

@@ -502,89 +502,88 @@ export const makeImportHookMaker = (
// for lint rule
await null;
Copy link
Member Author

Choose a reason for hiding this comment

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

This diff looks much better with whitespace hidden

Screenshot_2024-10-23_22-54-18

Comment on lines +577 to +586
throw Error(
`Cannot find file for internal module ${q(
moduleSpecifier,
)} (with candidates ${candidates
.map(x => q(x))
.join(', ')}) in package ${packageLocation}`,
),
);
);
} catch (error) {
return deferError(moduleSpecifier, error);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO this should probably just return the deferError instead of throwing and catching it immediately, but if there's a good reason for doing this then ok.

Copy link
Member Author

Choose a reason for hiding this comment

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

no good reason, just being DRY/consistent. Didn't feel good doing it.

Copy link
Member

@kriskowal kriskowal left a comment

Choose a reason for hiding this comment

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

Given that this would cause missing exits to be discovered much later, I would like this to be enabled with an option. Otherwise, this is well-motivated and I’m in favor.

@boneskull
Copy link
Contributor

@kriskowal Reconsider? This looks like a bugfix to me.

@boneskull boneskull requested a review from kriskowal October 25, 2024 20:16
boneskull added a commit that referenced this pull request Oct 30, 2024
For CJS compat, the top-level `this` must be equal to `module.exports` (which must be equal to `exports`).

This implementation changes the CJS parsers to call the wrapper `functor` using the context of `module.exports`.

(This PR targets #2610)
boneskull added a commit that referenced this pull request Oct 30, 2024
For CJS compat, the top-level `this` must be equal to `module.exports` (which must be equal to `exports`).

This implementation changes the CJS parsers to call the wrapper `functor` using the context of `module.exports`.

(This PR targets #2610)
Copy link
Member

@kriskowal kriskowal left a comment

Choose a reason for hiding this comment

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

I see it now, thanks. More errors are caught, but those are released again for non-heuristic parsers. This only changes behavior for heuristic parsers.

@kriskowal
Copy link
Member

Consider adding to NEWS.

@boneskull boneskull added the bug Something isn't working label Nov 1, 2024
boneskull added a commit that referenced this pull request Nov 4, 2024
For CJS compat, the top-level `this` must be equal to `module.exports` (which must be equal to `exports`).

This implementation changes the CJS parsers to call the wrapper `functor` using the context of `module.exports`.

(This PR targets #2610)
# By Turadg Aleahmad (11) and others
# Via GitHub (4) and Kris Kowal (1)
* master:
  docs(ses): Finish embracing permits terminology
  fix(ses): Clarify lockdown types
  feat(ses): Lockdown reporting option
  chore(deps): yarn dedupe
  chore(types): fix import tags
  lint: enable jsdoc/recommended-typescript-flavor
  chore: rm dup config key
  chore(deps): bump eslint-plugin-jsdoc
  build(deps): bump typescript (patch)
  chore(types): conform to verbatimModuleSyntax
  ci: enable verbatimModuleSyntax
  style: prettier
  chore(deps): bump prettier
  build(deps): bump yarn to 4.5.1
  feat(compartment-mapper): Collect unretained module descriptors
  test(compartment-mapper): Mark and sweep unused module descriptors
  feat(ses): permit Promise.prototype.try (#2609)

# Conflicts:
#	packages/compartment-mapper/NEWS.md
boneskull added a commit that referenced this pull request Nov 4, 2024
For CJS compat, the top-level `this` must be equal to `module.exports` (which must be equal to `exports`).

This implementation changes the CJS parsers to call the wrapper `functor` using the context of `module.exports`.

(This PR targets #2610)
@boneskull
Copy link
Contributor

I've updated and added a blurb to NEWS.md.

Copy link
Member

@kriskowal kriskowal left a comment

Choose a reason for hiding this comment

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

With request for qualification in NEWS.

packages/compartment-mapper/NEWS.md Outdated Show resolved Hide resolved
boneskull added a commit that referenced this pull request Nov 4, 2024
For CJS compat, the top-level `this` must be equal to `module.exports` (which must be equal to `exports`).

This implementation changes the CJS parsers to call the wrapper `functor` using the context of `module.exports`.

(This PR targets #2610)
@boneskull boneskull merged commit 28999e8 into master Nov 5, 2024
15 checks passed
@boneskull boneskull deleted the naugtur/fix-defering-errors branch November 5, 2024 00:31
boneskull added a commit that referenced this pull request Nov 5, 2024
For CJS compat, the top-level `this` must be equal to `module.exports` (which must be equal to `exports`).

This implementation changes the CJS parsers to call the wrapper `functor` using the context of `module.exports`.

(This PR targets #2610)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants