-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Add support for JS macros #9299
Conversation
Benchmark ResultsKitchen Sink ✅
Timings
Cold Bundles
Cached Bundles
React HackerNews ✅
Timings
Cold Bundles
Cached Bundles
AtlasKit Editor ✅
Timings
Cold Bundles
Cached Bundles
Three.js ✅
Timings
Cold BundlesNo bundle changes detected. Cached BundlesNo bundle changes detected. |
This comment was marked as resolved.
This comment was marked as resolved.
Another API question here is how to control caching. In your example that's not a problem but a useful macro would be getting the current git commit, current date, .... |
Added a few new features:
The question about caching is a good one. Right now the code for the macro or the code calling the macro would need to change for it to be invalidated (like a normal dev dependency). Perhaps the macro context ( |
Would it be unexpected for the results of macros to be hoisted out as constants? For example if a macro returned a function/object, we know that value will never change, and cannot depend on inputs since it was evaluated statically. Might be nice to hoist it to allow things like react to optimize re-renders because the value isn't re-created each time. However, this is different from the normal semantics of JS, so maybe it would be unexpected? |
Probably yes. Especially if you mutate the result (like array and objects) of the macro call which would break with hoisting. However, if the return value is indeed an immutable "primitive" value (so everything except object/array), then it should be possible to hoist (ignoring that you can of course assign properties to functions). We could also have two modes for the macro expansion, without and with hoisting.
Yeah, could it just be all of the invalidations we already have on |
Looks like |
let b = await bundle(path.join(dir, '/index.js'), { | ||
inputFS: overlayFS, | ||
mode: 'production', | ||
}); | ||
|
||
let res = await overlayFS.readFile(b.getBundles()[0].filePath, 'utf8'); | ||
assert(res.includes('output=3')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
haha nice. updated them to use a string hash function instead.
Added functions to the macro context to control caching. This also resulted in |
export function test(a, b) { | ||
return a + b; | ||
} | ||
import { hashString as foo } from "@parcel/rust" with { type: "macro" }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice that you can import any package here, I wouldn't have thought of trying that 👍
* upstream/v2: (22 commits) Add source map support to the inline-require optimizer (#9511) [Web Extension] Add content script world property to manifest schema validation (#9510) feat: add getCurrentPackageManager (#9505) Default Bundler Contributor Notes (#9488) rename parentAsset to root for msb config and remove unstable (#9486) Macro errors -> v2 (#9501) Statically evaluate constants referenced by macros (#9487) Multiple css bundles in Entry bundle groups issue (#9023) Fix macro issues (#9485) Bump follow-redirects from 1.14.7 to 1.15.4 (#9475) Revert more CI changes to centos job (#9472) Use lightningcss to implement CSS packager (#8492) Fixup CI again (#9471) Clippy and use napi's Either3 (#9047) Upgrade to eslint 8 (#8580) Add support for JS macros (#9299) Fixup REPL CI (#9467) Drop per-pipeline transformation cache (#9459) Upgrade some CI actions (#9466) REPL (#9365) ...
This adds support for importing and executing JS macros during the build. It follows the same API as implemented in Bun, using import attributes to determine which modules are macros.
These are then evaluated inside the JS transformer by calling back from Rust into JS, requiring the dependency, and running the function. Arguments are statically evaluated, then serialized to napi values.
Macros return JS values which are then converted back into an AST and inserted where the call was. The output of the above code would be:
The dependency is not included in the final bundle. This is useful for computing values during the build that might be expensive in terms of bundle size to do at runtime, or to insert values beyond simple environment variables. Macros also run before the dead code eliminator, so if the result of a macro is used in an if statement the dead branch can be removed.
To do