@solidjs/babel-plugin 2.0.0-rc.16 → 2.0.0-rc.17

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.
@@ -7,4 +7,4 @@ src/shared/transform.ts -> src/dom/element.ts -> src/universal/element.ts -> src
7
7
  src/shared/transform.ts -> src/ssr/element.ts -> src/shared/transform.ts
8
8
  src/shared/transform.ts -> src/shared/component.ts -> src/shared/transform.ts
9
9
  src/shared/transform.ts -> src/shared/fragment.ts -> src/shared/transform.ts
10
- created index.js in 3.3s
10
+ created index.js in 2.3s
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @solidjs/babel-plugin
2
2
 
3
+ ## 2.0.0-rc.17
4
+
5
+ ### Patch Changes
6
+
7
+ - 3e72783: The removed Solid 1.x attribute forms are now compile errors on native elements in the `dom` and `ssr` generates (#4187). `on:`, `oncapture:`, `attr:`, `bool:`, `use:` and `classList` used to compile silently into literal attributes (`<div use:tip="() => {}">`, `classlist="[object Object]"`). Both compilers now reject them with the same message, which names the 2.0 replacement: a camelCase handler or a `ref` callback for `on:`, a plain attribute for `attr:`, a boolean value for `bool:`, a `ref` directive factory for `use:`, and an object or array `class` for `classList`. Components, the universal generate, `prop:` and the XML namespaces (`xlink:`, `xml:`, `xmlns:`) are unaffected. The check runs only at compile time and adds no runtime code.
8
+ - 6cca8b5: Dev builds now warn with `UNCOMMITTED_INPUT_OVERWRITTEN` (#4186) when a stateful DOM property binding (`value`/`checked` on an input, `value` on a textarea, `value`/`selected` on an option, `muted` on media) is about to re-write the value it wrote last time over an edit the user never committed to the bound signal — e.g. `value={props.name} onChange={commit}` with no draft signal, when another dynamic attribute in the same template changes. Runtime behavior is unchanged: the write still happens, once per element and property the warning names the fix (write the signal from `onInput`, use `defaultValue`/`defaultChecked` for an uncontrolled element, or write a rejected edit back with `e.currentTarget.value = next`).
9
+
10
+ Production output is unchanged byte for byte. In dev DOM output both compilers write stateful properties through a new `setStatefulProperty(el, name, value)` helper instead of the inline `el.name = value`; hydratable output keeps `setProperty`, and `spread`/`assign` check in the runtime. The check lives only in `@solidjs/web`'s dev build; the production entry carries a plain `node[name] = value` stub that no production-compiled module imports, so it tree-shakes away.
11
+
12
+ The "Form inputs" section of the DOM RFC, the cheatsheet and the solid-2.0 skill now say that a change to any other dynamic attribute in the same template re-runs a stateful binding, link the new code, and drop `equals: false` as a way to reject input (it is what the warning reports); write the accepted value back with `e.currentTarget.value = next` instead.
13
+
14
+ - 2ba1c4a: A valueless `prop:` attribute (`<el prop:active />`) now compiles as `prop:active={true}`, matching bare plain attributes, instead of being dropped silently (#4180).
15
+
3
16
  ## 2.0.0-rc.16
4
17
 
5
18
  ### Patch Changes
package/index.js CHANGED
@@ -2321,11 +2321,6 @@ value,
2321
2321
  );
2322
2322
  }
2323
2323
 
2324
- const assignment = t$1.assignmentExpression(
2325
- "=",
2326
- t$1.memberExpression(elem, t$1.identifier(name)),
2327
- value
2328
- );
2329
2324
  if (
2330
2325
  (name === "value" || name === "defaultValue") && (
2331
2326
  tagName === "input" || tagName === "textarea") &&
@@ -2334,13 +2329,20 @@ value,
2334
2329
  {
2335
2330
  // prevents undefined on text input/textarea.value/defaultValue, fallback
2336
2331
  // to empty string (#2957)
2337
- return t$1.assignmentExpression(
2338
- "=",
2339
- t$1.memberExpression(elem, t$1.identifier(name)),
2340
- t$1.logicalExpression("??", value, t$1.stringLiteral(""))
2332
+ value = t$1.logicalExpression("??", value, t$1.stringLiteral(""));
2333
+ }
2334
+ // Dev DOM output writes stateful properties (value/checked/selected/
2335
+ // muted) through `setStatefulProperty` — the same `elem[name] = value`,
2336
+ // preceded in the dev runtime by the UNCOMMITTED_INPUT_OVERWRITTEN check
2337
+ // (#4186). Production output keeps the inline assignment, byte for byte.
2338
+ if (config.dev && config.generate === "dom" && isStatefulDOMProperty(tagName, name)) {
2339
+ return t$1.callExpression(registerImportMethod(path, "setStatefulProperty"), [
2340
+ elem,
2341
+ t$1.stringLiteral(name),
2342
+ value]
2341
2343
  );
2342
2344
  }
2343
- return assignment;
2345
+ return t$1.assignmentExpression("=", t$1.memberExpression(elem, t$1.identifier(name)), value);
2344
2346
  }
2345
2347
 
2346
2348
  const ns = name.indexOf(":") > -1 && Namespaces[name.split(":")[0]];
@@ -2877,7 +2879,9 @@ results)
2877
2879
  reservedNameSpace &&
2878
2880
  !t$1.isJSXExpressionContainer(value))
2879
2881
  {
2880
- node.value = value = t$1.jsxExpressionContainer(value || t$1.jsxEmptyExpression());
2882
+ // A valueless `prop:x` means `prop:x={true}`, like a bare plain
2883
+ // attribute (#4180).
2884
+ node.value = value = t$1.jsxExpressionContainer(value || t$1.booleanLiteral(true));
2881
2885
  }
2882
2886
  if (
2883
2887
  t$1.isJSXExpressionContainer(value) && (
@@ -6586,6 +6590,63 @@ config)
6586
6590
  results.exprs.push(childNodes.length === 1 ? childNodes[0] : t__namespace.arrayExpression(childNodes));
6587
6591
  }
6588
6592
 
6593
+ /**
6594
+ * Solid 1.x attribute forms that 2.0 removed (#4187). Left alone they
6595
+ * compile into literal attributes (`<div use:tip="() => {}">`,
6596
+ * `classlist="[object Object]"`) with no diagnostic, so on native elements
6597
+ * of the web generates (`dom` / `ssr`) they are a compile error that names
6598
+ * the 2.0 replacement. Components are untouched (their props are
6599
+ * user-defined names with no compiler semantics), as is the universal
6600
+ * generate (a custom renderer's `setProp` owns its own naming), and every
6601
+ * other namespace — `prop:`, `xlink:`, `xml:`, `xmlns:`, `svg:`, … — still
6602
+ * compiles as before. The message text is mirrored in the native compiler
6603
+ * (`packages/compiler/src/shared/removed.rs`); keep the two in sync.
6604
+ */
6605
+ function removedAttributeMessage(tagName, key) {
6606
+ if (key === "classList") {
6607
+ return (
6608
+ `\`classList\` on <${tagName}> was removed in Solid 2.0. ` +
6609
+ "Use `class` with an object or array instead: `class={{ active: isActive() }}` " +
6610
+ 'or `class={["base", { active: isActive() }]}`.');
6611
+
6612
+ }
6613
+ const colon = key.indexOf(":");
6614
+ if (colon < 0) return;
6615
+ const namespace = key.slice(0, colon);
6616
+ const name = key.slice(colon + 1);
6617
+ const removed = `\`${key}\` on <${tagName}> uses the \`${namespace}:\` namespace, which was removed in Solid 2.0.`;
6618
+ switch (namespace) {
6619
+ case "on":
6620
+ case "oncapture":
6621
+ return (
6622
+ `${removed} Use a camelCase handler such as \`onClick={handler}\` for Solid events, ` +
6623
+ "or a `ref` callback that calls `addEventListener` for listener options or custom event names.");
6624
+
6625
+ case "attr":
6626
+ return `${removed} Attributes are the default in 2.0: write \`${name}={value}\` (or \`prop:${name}\` to set a DOM property).`;
6627
+ case "bool":
6628
+ return `${removed} Boolean values add or remove the attribute in 2.0: write \`${name}={condition}\`.`;
6629
+ case "use":
6630
+ return (
6631
+ `${removed} Use a \`ref\` directive factory instead: \`ref={${name}(options)}\`, ` +
6632
+ `or \`ref={${name}}\` without options; arrays compose (\`ref={[a, b]}\`).`);
6633
+
6634
+ }
6635
+ }
6636
+
6637
+ /** Throws a code-frame error at the first removed 1.x attribute form. */
6638
+ function assertNoRemovedAttributes(path, tagName) {
6639
+ for (const attribute of path.get("openingElement").get("attributes")) {
6640
+ if (!attribute.isJSXAttribute()) continue;
6641
+ const name = attribute.node.name;
6642
+ const key = t__namespace.isJSXNamespacedName(name) ?
6643
+ `${name.namespace.name}:${name.name.name}` :
6644
+ name.name;
6645
+ const message = removedAttributeMessage(tagName, key);
6646
+ if (message) throw attribute.buildCodeFrameError(message);
6647
+ }
6648
+ }
6649
+
6589
6650
  function isTransformConditionStatements(
6590
6651
  expr)
6591
6652
  {
@@ -6866,11 +6927,13 @@ info = {})
6866
6927
  );
6867
6928
 
6868
6929
  if (tagRenderer?.name === "dom" || getConfig(path).generate === "dom") {
6930
+ assertNoRemovedAttributes(path, tagName);
6869
6931
  renameElementKey(path, false);
6870
6932
  return transformElement$2(path, info);
6871
6933
  }
6872
6934
 
6873
6935
  if (getConfig(path).generate === "ssr") {
6936
+ assertNoRemovedAttributes(path, tagName);
6874
6937
  renameElementKey(path, true);
6875
6938
  return transformElement$1(path, info);
6876
6939
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@solidjs/babel-plugin",
3
3
  "description": "Babel compiler plugin for Solid templates",
4
- "version": "2.0.0-rc.16",
4
+ "version": "2.0.0-rc.17",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",
7
7
  "repository": {