@tsrx/solid 0.0.17 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +2 -2
  2. package/src/transform.js +26 -113
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Solid compiler built on @tsrx/core",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.0.17",
6
+ "version": "0.0.18",
7
7
  "type": "module",
8
8
  "publishConfig": {
9
9
  "access": "public"
@@ -22,7 +22,7 @@
22
22
  "dependencies": {
23
23
  "esrap": "^2.1.0",
24
24
  "zimmerframe": "^1.1.2",
25
- "@tsrx/core": "0.0.17"
25
+ "@tsrx/core": "0.0.18"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "solid-js": ">=1.8 || >=2.0.0-beta"
package/src/transform.js CHANGED
@@ -3,6 +3,9 @@
3
3
 
4
4
  import {
5
5
  createJsxTransform,
6
+ mergeDuplicateRefs,
7
+ toJsxAttribute,
8
+ validateAtMostOneRefAttribute,
6
9
  setLocation,
7
10
  applyLazyTransforms as apply_lazy_transforms,
8
11
  collectLazyBindingsFromComponent as collect_lazy_bindings_from_component,
@@ -71,6 +74,10 @@ const solid_platform = {
71
74
  jsx: {
72
75
  rewriteClassAttr: false,
73
76
  acceptedTsxKinds: ['solid'],
77
+ // Solid's runtime accepts an array of refs natively, so multiple
78
+ // `ref` attributes collapse to `ref={[a, b, ...]}` rather than
79
+ // going through a `mergeRefs` helper.
80
+ multiRefStrategy: 'array',
74
81
  },
75
82
  validation: {
76
83
  requireUseServerForAwait: true,
@@ -106,8 +113,12 @@ const solid_platform = {
106
113
  componentToFunction: (component, ctx) =>
107
114
  component_to_function_declaration(component, /** @type {any} */ (ctx)),
108
115
  injectImports: (program, ctx) => inject_solid_imports(program, /** @type {any} */ (ctx)),
109
- transformElementAttributes: (attrs, ctx, element) =>
110
- transform_element_attributes(attrs, is_composite_element(element), /** @type {any} */ (ctx)),
116
+ // `transformElementAttributes` is intentionally omitted: the
117
+ // `transformElement` hook below short-circuits core's element walker
118
+ // before `to_jsx_element` runs, so the dispatch path that would call
119
+ // `transformElementAttributes` is never reached for Solid. Attribute
120
+ // lowering happens in Solid's local `transform_element_attributes`,
121
+ // which `to_jsx_element` and `create_dynamic_jsx_element` call directly.
111
122
  transformElement: (inner, ctx, raw_children) =>
112
123
  to_jsx_element(/** @type {any} */ (inner), /** @type {any} */ (ctx), raw_children),
113
124
  },
@@ -1175,44 +1186,6 @@ function create_element_children(children, transform_context) {
1175
1186
  return children.map((/** @type {any} */ child) => to_jsx_child(child, transform_context));
1176
1187
  }
1177
1188
 
1178
- /**
1179
- * Attribute transform. Unlike React, Solid uses the native `class` attribute
1180
- * (not `className`). `RefAttribute` and `SpreadAttribute` nodes are handled
1181
- * at the element level by {@link transform_element_attributes} so this
1182
- * function only sees plain attributes.
1183
- *
1184
- * @param {any} attr
1185
- * @returns {any}
1186
- */
1187
- function to_jsx_attribute(attr) {
1188
- if (!attr) return attr;
1189
- if (attr.type === 'JSXAttribute' || attr.type === 'JSXSpreadAttribute') return attr;
1190
-
1191
- const attr_name = attr.name;
1192
- const name =
1193
- attr_name && attr_name.type === 'Identifier' ? identifier_to_jsx_name(attr_name) : attr_name;
1194
-
1195
- let value = attr.value;
1196
- if (value) {
1197
- if (value.type === 'Literal' && typeof value.value === 'string') {
1198
- // Keep string literal as attribute string.
1199
- } else if (value.type !== 'JSXExpressionContainer') {
1200
- value = to_jsx_expression_container(value);
1201
- }
1202
- }
1203
-
1204
- return set_loc(
1205
- /** @type {any} */ ({
1206
- type: 'JSXAttribute',
1207
- name,
1208
- value: value || null,
1209
- shorthand: false,
1210
- metadata: { path: [] },
1211
- }),
1212
- attr,
1213
- );
1214
- }
1215
-
1216
1189
  /**
1217
1190
  * Detect whether an `Element` node represents a composite component (tag
1218
1191
  * name starts with an uppercase letter, or is a member expression like
@@ -1254,26 +1227,17 @@ function has_text_content_attribute(attributes) {
1254
1227
  }
1255
1228
 
1256
1229
  /**
1257
- * Transform a list of raw attributes into JSX attributes, lifting
1258
- * `{ref expr}` handling to the element level.
1230
+ * Transform a list of raw attributes into JSX attributes.
1259
1231
  *
1260
- * `{ref expr}` compiles to `ref={expr}` on both DOM elements and composite
1261
- * components. On DOM elements, Solid's JSX transform takes over: if `expr`
1262
- * is a mutable `let`-declared identifier it assigns the element to the
1263
- * variable; if `expr` is a function (or other callable) it invokes it
1264
- * with the element. On composite components, `ref` is passed through as a
1265
- * regular prop; the receiving child can consume it explicitly as
1266
- * `props.ref` or spread `{...props}` onto a DOM element, where Solid's
1267
- * spread runtime automatically applies the `ref` entry. Solid's merge
1268
- * proxies drop Symbol keys, so the Symbol-based forwarding used by
1269
- * Ripple doesn't port; the Solid target relies on its native `ref` prop
1270
- * support instead.
1271
- *
1272
- * Multiple `{ref ...}` attributes on the same element are collected into
1273
- * a single `ref={[a, b, ...]}` array so every callback fires. Solid's
1274
- * ref/spread runtime (`applyRef`) already iterates array refs, so this
1275
- * works on both DOM elements and composite components (when the child
1276
- * spreads `props` or forwards `props.ref`).
1232
+ * Per-attribute conversion (RefAttribute `ref={expr}`, SpreadAttribute
1233
+ * `{...expr}`, plain Attribute → JSXAttribute, JSXAttribute pass-through)
1234
+ * is delegated to `@tsrx/core`'s shared {@link toJsxAttribute}. The list
1235
+ * is then run through {@link mergeDuplicateRefs} so multiple ref attributes
1236
+ * on the same element whether from `{ref expr}` or TSX-style `ref={expr}`
1237
+ * collapse to a single `ref={[a, b, ...]}` array (the strategy chosen by
1238
+ * Solid's `multiRefStrategy: 'array'`). Solid's runtime iterates array refs
1239
+ * natively, so this works on both DOM elements and composite components
1240
+ * (when the child spreads `props` or forwards `props.ref`).
1277
1241
  *
1278
1242
  * @param {any[]} raw_attrs
1279
1243
  * @param {boolean} is_composite
@@ -1282,66 +1246,15 @@ function has_text_content_attribute(attributes) {
1282
1246
  */
1283
1247
  function transform_element_attributes(raw_attrs, is_composite, transform_context) {
1284
1248
  void is_composite;
1285
- void transform_context;
1249
+ validateAtMostOneRefAttribute(raw_attrs);
1286
1250
  /** @type {any[]} */
1287
1251
  const result = [];
1288
- /** @type {any[]} */
1289
- const ref_attrs = [];
1290
1252
 
1291
1253
  for (const attr of raw_attrs) {
1292
1254
  if (!attr) continue;
1293
- if (attr.type === 'RefAttribute') {
1294
- ref_attrs.push(attr);
1295
- continue;
1296
- }
1297
- if (attr.type === 'SpreadAttribute') {
1298
- result.push(
1299
- set_loc(
1300
- /** @type {any} */ ({
1301
- type: 'JSXSpreadAttribute',
1302
- argument: attr.argument,
1303
- }),
1304
- attr,
1305
- ),
1306
- );
1307
- continue;
1308
- }
1309
- result.push(to_jsx_attribute(attr));
1310
- }
1311
-
1312
- if (ref_attrs.length === 1) {
1313
- result.push(build_ref_attribute(ref_attrs[0].argument, ref_attrs[0]));
1314
- } else if (ref_attrs.length > 1) {
1315
- const array_expr = /** @type {any} */ ({
1316
- type: 'ArrayExpression',
1317
- elements: ref_attrs.map((attr) => attr.argument),
1318
- metadata: { path: [] },
1319
- });
1320
- result.push(build_ref_attribute(array_expr, ref_attrs[0]));
1255
+ result.push(toJsxAttribute(attr, /** @type {any} */ (transform_context)));
1321
1256
  }
1322
-
1323
- return result;
1324
- }
1325
-
1326
- /**
1327
- * Build a `ref={expr}` JSX attribute, passing the expression through
1328
- * unchanged so Solid's JSX transform can apply its normal ref semantics.
1329
- *
1330
- * @param {any} argument
1331
- * @param {any} source_node
1332
- * @returns {any}
1333
- */
1334
- function build_ref_attribute(argument, source_node) {
1335
- return set_loc(
1336
- /** @type {any} */ ({
1337
- type: 'JSXAttribute',
1338
- name: { type: 'JSXIdentifier', name: 'ref', metadata: { path: [] } },
1339
- value: to_jsx_expression_container(argument),
1340
- shorthand: false,
1341
- metadata: { path: [] },
1342
- }),
1343
- source_node,
1344
- );
1257
+ return mergeDuplicateRefs(result, /** @type {any} */ (transform_context));
1345
1258
  }
1346
1259
 
1347
1260
  /**