-
Notifications
You must be signed in to change notification settings - Fork 386
[babel-plugin] Hoist stylex.create definitions and nested objects within functions #1137
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
Conversation
workflow: benchmarks/perfComparison of performance test results, measured in operations per second. Larger is better.
|
workflow: benchmarks/sizeComparison of minified (terser) and compressed (brotli) size results, measured in bytes. Smaller is better.
|
packages/@stylexjs/babel-plugin/__tests__/transform-stylex-create-test.js
Show resolved
Hide resolved
packages/@stylexjs/babel-plugin/__tests__/validation-stylex-create-test.js
Outdated
Show resolved
Hide resolved
| return true; | ||
| } | ||
|
|
||
| export function getProgramStatement(path: NodePath<>): NodePath<> { |
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.
i think we need to check programPath.isStatement() here too. but please double check
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.
I don't think so. Everything is in a program and if not we want to return the top level anyway. Otherwise, things will break.
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.
don't we call insertBefore later on the node returned by getProgramStatement? if that ever returns a non-Statement then Babel will throw
this doesn't affect this PR specifically because we only call it from CallExpression paths but since this is a general purpose util it could break things in the future
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.
A program can never have a non statement child anyway afaik. Is there an edge-case where that's not true?
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.
babel workings... yes correct
necolas
left a comment
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.
Please could we break this down into different PRs? It would be good if we could fix the deopt for dynamic styles separately from a big change that might no longer require create calls at the top level. We should also talk about whether that should be limited to nesting within TS vs being allowed for arbitrary functions or blocks
packages/@stylexjs/babel-plugin/__tests__/evaluation-import-test.js
Outdated
Show resolved
Hide resolved
| const { code, metadata } = transform(` | ||
| import * as stylex from '@stylexjs/stylex'; | ||
| function fooBar() { | ||
| const styles = stylex.create({ |
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.
We should probably have a discussion about the pros and cons of allowing create within arbitrary functions. It might set incorrect expectations for users that create can be used dynamically
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.
I should’ve marked this PR as a draft as it’s mostly a POC right now and the actual design needs discussion.
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.
OK. I've made changes now. The important thing here is that there is no change to the actual API. The ESLint rule should still error when using stylex.create not at the top level.
However, I've added these tests for two reasons:
- Flow doesn't support namespaces and our tests aren't set up for TS syntax
- To make the transformation more reliable when used with various bundlers and transformations. It's not uncommon for various bundlers to wrap each module in a self-executing function or something like that. Today StyleX tends to break if things aren't just right. Making it work in more scenarios should help make the babel plugin more reliable.
432e37b to
4ee92dc
Compare
What changed / motivation ?
Today all StyleX transformation happens in-place. This usually works fine, but there are edge cases where this breaks down a bit.
stylex.createwithin Typescript namespaces doesn't workTo solve these issues, this PR refactors and add AST utilities for hoisting expressions to the top level of a file and provide an identifier reference to it instead.
As of right now this is only used for two use-cases:
stylex.createcan now be defined within blocks such as functions. The compiler will define the actual object at the top level of the file, and use a stable reference where it is defined.Tests have been added and updated to show these changes.