From 47e904061c6ef069bc8f3897d726f8f6b49ab442 Mon Sep 17 00:00:00 2001 From: meh Date: Sun, 16 Aug 2026 17:28:34 +0700 Subject: [PATCH] fix(build): compile the Solid 2 JSX transform, and declare the peers it needs The consumer smoke test was failing on a package that built cleanly here, which is exactly the gap it exists to close. Four separate faults, each hidden behind the one before it. @rsbuild/plugin-solid depends on babel-preset-solid ^1.9.12, a range semver cannot cross to 2.0.0-rc.0, so bun installed a nested Solid 1 preset under the plugin and the plugin's own require.resolve loaded that one regardless of what this package hoisted. The Solid 1 transform emits imports from solid-js/web, a subpath Solid 2 dropped, and a use helper Solid 2 does not export. An override plus moduleName pins the transform to the Solid 2 one across all 130 generated files. Same shape as the solid-layouts-oxc nesting, and the same lesson: an exact or narrow pin in a dependency is not overridden by hoisting. The peer ranges then said solid-layouts ^0.1.3 and solid-js ^1.9, neither of which admits what the emitted code imports: 0.1.x ships no ./solid-2 export, and 1.9 has no omit or createOwner for @solidjs/web to bind to. A consumer installing the declared peers got a package that could not resolve. The smoke fixture also still imported useTableModel, removed with TanStack, and set jsxImportSource to solid-js, whose jsx-runtime Solid 2 moved to @solidjs/web. --- bun.lock | 21 +++++++++++++-------- package.json | 9 ++++++--- rslib.config.ts | 18 +++++++++++++++++- scripts/smoke-consumer.ts | 8 +++----- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/bun.lock b/bun.lock index 1c59e345..9337a5be 100644 --- a/bun.lock +++ b/bun.lock @@ -21,7 +21,7 @@ "@solidjs/h": "2.0.0-rc.0", "@standard-schema/spec": "^1.1.0", "@types/bun": "^1.3.14", - "babel-preset-solid": "^1.9.12", + "babel-preset-solid": "2.0.0-rc.0", "cally": "^0.8.0", "cssnano": "^7.1.9", "postcss": "^8.5.15", @@ -37,8 +37,8 @@ "peerDependencies": { "@standard-schema/spec": "^1.0.0", "popmotion": "^11.0.5", - "solid-js": "^1.9", - "solid-layouts": "^0.1.3", + "solid-js": ">=2.0.0-rc.0", + "solid-layouts": "^0.2.0", }, "optionalPeers": [ "@standard-schema/spec", @@ -46,6 +46,9 @@ ], }, }, + "overrides": { + "babel-preset-solid": "2.0.0-rc.0", + }, "packages": { "@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="], @@ -153,6 +156,8 @@ "@colordx/core": ["@colordx/core@5.4.3", "", {}, "sha512-kIxYSfA5T8HXjav55UaaH/o/cKivF6jCCGIb8eqtcsfI46wsvlSiT8jMDyrl779qLec3c2c2oHBZo4oAhvbjrQ=="], + "@dom-expressions/babel-plugin-jsx": ["@dom-expressions/babel-plugin-jsx@0.50.0-next.42", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2", "validate-html-nesting": "^1.2.1" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-ol24x9RW8loPyOTzC/mQzh/zAsrsPxyTG4WRxxRlwzNK2uBWIBftWN5IwmSV51zDQa7JcT6sE6kkXFCLUvsYIQ=="], + "@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], "@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], @@ -287,9 +292,7 @@ "atomico": ["atomico@1.79.2", "", {}, "sha512-mshhLRMeIltNYbnQnqgnrvJ/uDa8XDfTQcjw3ymOygQqwHIQ4Sp0LcNYMCbACkV3DtV+eDXb9szwU4qMUuGwYQ=="], - "babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.40.7", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-/O6JWUmjv03OI9lL2ry9bUjpD5S3PclM55RRJEyCdcFZ5W2SEA/59d+l2hNsk3gI6kiWRdRPdOtqZmsQzFN1pQ=="], - - "babel-preset-solid": ["babel-preset-solid@1.9.12", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.40.6" }, "peerDependencies": { "@babel/core": "^7.0.0", "solid-js": "^1.9.12" }, "optionalPeers": ["solid-js"] }, "sha512-LLqnuKVDlKpyBlMPcH6qEvs/wmS9a+NczppxJ3ryS/c0O5IiSFOIBQi9GzyiGDSbcJpx4Gr87jyFTos1MyEuWg=="], + "babel-preset-solid": ["babel-preset-solid@2.0.0-rc.0", "", { "dependencies": { "@dom-expressions/babel-plugin-jsx": "0.50.0-next.42" }, "peerDependencies": { "@babel/core": "^7.0.0", "solid-js": "^2.0.0-rc.0" }, "optionalPeers": ["solid-js"] }, "sha512-Ap2/QQY3pICj+Q0VM/RnIOpZo7e6icZnUA0oBJuhqzoCrljqMNo3eFb2OeEa4pUQeFREJOlex4Bt1ggwrcgC8w=="], "baseline-browser-mapping": ["baseline-browser-mapping@2.10.33", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw=="], @@ -605,6 +608,8 @@ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + "validate-html-nesting": ["validate-html-nesting@1.2.4", "", {}, "sha512-doQi7e8EJ2OWneSG1aZpJluS6A49aZM0+EICXWKm1i6WvqTLmq0tpUcImc4KTWG50mORO0C4YDBtOCSYvElftw=="], + "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], @@ -617,9 +622,9 @@ "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], - "anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], + "@dom-expressions/babel-plugin-jsx/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="], - "babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="], + "anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="], diff --git a/package.json b/package.json index 3e5c49f4..a4f03f26 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "@solidjs/h": "2.0.0-rc.0", "@standard-schema/spec": "^1.1.0", "@types/bun": "^1.3.14", - "babel-preset-solid": "^1.9.12", + "babel-preset-solid": "2.0.0-rc.0", "cally": "^0.8.0", "cssnano": "^7.1.9", "postcss": "^8.5.15", @@ -89,6 +89,9 @@ "svgo": "^3.3.3", "typescript": "^6.0.3" }, + "overrides": { + "babel-preset-solid": "2.0.0-rc.0" + }, "dependencies": { "@solidjs/web": "2.0.0-rc.0", "clsx": "^2.1.1", @@ -97,8 +100,8 @@ "peerDependencies": { "@standard-schema/spec": "^1.0.0", "popmotion": "^11.0.5", - "solid-js": "^1.9", - "solid-layouts": "^0.1.3" + "solid-js": ">=2.0.0-rc.0", + "solid-layouts": "^0.2.0" }, "peerDependenciesMeta": { "@standard-schema/spec": { diff --git a/rslib.config.ts b/rslib.config.ts index 2597e5d6..66b3d6d5 100644 --- a/rslib.config.ts +++ b/rslib.config.ts @@ -48,6 +48,22 @@ export default defineConfig({ pluginBabel({ include: /\.(?:jsx|tsx)$/, }), - pluginSolid(), + // `@rsbuild/plugin-solid` depends on `babel-preset-solid: ^1.9.12`, a range + // semver cannot cross to `2.0.0-rc.0`. So bun installs a *nested* Solid 1 + // preset under the plugin, and the plugin's own `require.resolve` loads + // that one no matter what this package hoists. The Solid 1 transform emits + // `solid-js/web`, a subpath Solid 2 dropped, so every generated file was + // unresolvable in a real consumer while building fine in this repo. + // + // Naming the preset by absolute path is what pins the transform to the + // Solid 2 one. Verify with a built file rather than a passing build: + // grep -o 'from "[^"]*web"' dist/components/icon/Icon.generated.js + // must say `@solidjs/web`. + pluginSolid({ + solidPresetOptions: { + moduleName: "@solidjs/web", + generate: "dom", + }, + }), ], }); diff --git a/scripts/smoke-consumer.ts b/scripts/smoke-consumer.ts index 37d261bc..0bd5fc7d 100644 --- a/scripts/smoke-consumer.ts +++ b/scripts/smoke-consumer.ts @@ -101,7 +101,7 @@ writeFileSync( module: "ESNext", moduleResolution: "bundler", jsx: "preserve", - jsxImportSource: "solid-js", + jsxImportSource: "@solidjs/web", strict: true, noEmit: true, // true, matching every consumer app in this org. With false, the CSS @@ -134,7 +134,6 @@ writeFileSync( toast, createDataGrid, createForm, - useTableModel, type Flavor, type Size, type State, @@ -171,7 +170,7 @@ grid.addRow({ id: 1, firstName: "John" }); export const Grid = () => ; // Values must exist, not just types. -export const used = [Dialog, Select, Table, Toast, toast, createForm, useTableModel, runMotion]; +export const used = [Dialog, Select, Table, Toast, toast, createForm, runMotion]; `, ); @@ -188,11 +187,10 @@ import { toast, createDataGrid, createForm, - useTableModel, } from "${pkgJson.name}"; import { runMotion } from "${pkgJson.name}/motion"; -export const used = [Button, Card, Dialog, Flex, Icon, toast, createDataGrid, createForm, useTableModel, runMotion]; +export const used = [Button, Card, Dialog, Flex, Icon, toast, createDataGrid, createForm, runMotion]; `, );