Skip to content

Latest commit

 

History

History
115 lines (80 loc) · 3.72 KB

CONTRIBUTING.md

File metadata and controls

115 lines (80 loc) · 3.72 KB

Contributing

You can directly create a PR if the change is small. Otherwise, please open an issue first to discuss the change.

Getting Started

This project uses pnpm for package management. Please make sure you have it installed before proceeding.

  1. Fork and clone the repo
  2. Check out a new branch: git checkout -b some-feature
  3. Install dependencies: pnpm install
  4. Test your changes in the playground: pnpm dev

Attach a Debugger

Press F5 in VSCode to build the project and launch the debugger. Choose any of these launch configurations:

  • Launch playground: runs a dev server in the background and opens the playground in your browser.

    debug-playground.mp4
  • Deobfuscate tmp file: runs the CLI locally.

    1. Create the file packages/webcrack/tmp/test.js and paste your code
    2. The output will be saved in tmp/webcrack-out

Tests

Run the tests with pnpm test.

.toMatchInlineSnapshot() for new tests will automatically generate the expected output when saved, no need to write it manually.

If the snapshots are outdated, make sure the changes are correct and update them: failed snapshot

The tests can also be debugged by installing the Vitest extension and right-clicking on the play icon: vitest debug

Linting and Formatting

pnpm lint:fix && pnpm format

Create a new Transform

The easiest way to create a new transform is to copy an existing one and modify it.

Performance Optimizations

Named Visitor Keys

{
- exit(path) { if (path.isIdentifier()) { ... } }
+ Identifier: { exit(path) { ... } }
}

noScope Visitors

May not work in some cases (accessing path.scope when the scope hasn't been crawled before).

{
  Identifier(path) { ... },
+ noScope: true,
}

Merging Visitors

To only traverse the AST once and avoid missing nodes based on the order of visitors.

- applyTransform(ast, transformA);
- applyTransform(ast, transformB);
+ applyTransforms(ast, [transformA, transformB]);

Renaming Bindings (variables, functions, ...)

This also avoids conflicts by first renaming bindings with the name b to something else.

- path.scope.rename('a', 'b');
+ const binding = path.scope.getBinding('a')!;
+ renameFast(binding, 'b');

Following References instead of Traversing the AST

For example finding calls to a function foo (provided that you already have foo's NodePath):

const matcher = m.callExpression(m.identifier('foo'));
- traverse(ast, {
-   CallExpression(path) {
-     if (matcher.match(path.node)) { ... }
-   }
- });
+ const binding = fooPath.scope.getBinding('foo')!;
+ for (const reference of binding.referencePaths) {
+   if (matcher.match(reference.parent)) { ... }
+ }

Resources