@barefootjs/mojolicious 0.18.7 → 0.19.0

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.
@@ -1001,7 +1001,7 @@ function collectBooleanTypedProps(ir) {
1001
1001
  return new Set(ir.metadata.propsParams.filter((prop) => prop.type?.primitive === "boolean" || prop.type?.raw === "boolean").map((prop) => prop.name));
1002
1002
  }
1003
1003
  function collectNullableOptionalProps(ir) {
1004
- return new Set(ir.metadata.propsParams.filter((p) => p.defaultValue === undefined && !p.isRest && p.type?.kind !== "primitive").map((p) => p.name));
1004
+ return new Set(ir.metadata.propsParams.filter((p) => p.defaultValue === undefined && !p.isRest && (p.type?.kind !== "primitive" || p.optional)).map((p) => p.name));
1005
1005
  }
1006
1006
  function collectStringValueNames(ir) {
1007
1007
  const names = new Set;
@@ -30,11 +30,10 @@ export declare function collectBooleanTypedProps(ir: ComponentIR): Set<string>;
30
30
  * resolved `interface{}` field type; here it is the absence of a default (the
31
31
  * analyzer reports `rows` — a `TextareaHTMLAttributes` member destructured
32
32
  * without a default — as no-default, `type.kind: 'unknown'`).
33
- * Excludes concrete-primitive types (`string`/`number`/`boolean`) to match
34
- * the Go adapter's scope, which guards only `interface{}` (nillable) fields
35
- * and leaves concrete fields unconditional. So a required, no-default
36
- * `string` prop still emits `attr=""` like Hono, and only nillable
37
- * (`unknown`/object/array) no-default props guard.
33
+ * A REQUIRED concrete-primitive prop (`string`/`number`/`boolean`) is
34
+ * excluded — the caller always supplies it, so it emits `attr=""` like Hono
35
+ * but an OPTIONAL primitive is presence-uncertain and stays guarded
36
+ * (#2259).
38
37
  */
39
38
  export declare function collectNullableOptionalProps(ir: ComponentIR): Set<string>;
40
39
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"prop-classes.d.ts","sourceRoot":"","sources":["../../../src/adapter/props/prop-classes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAyB,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGzE;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAMrE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAMrE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAWzE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAepE"}
1
+ {"version":3,"file":"prop-classes.d.ts","sourceRoot":"","sources":["../../../src/adapter/props/prop-classes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAyB,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGzE;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAMrE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAMrE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAWzE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAepE"}
package/dist/build.js CHANGED
@@ -1001,7 +1001,7 @@ function collectBooleanTypedProps(ir) {
1001
1001
  return new Set(ir.metadata.propsParams.filter((prop) => prop.type?.primitive === "boolean" || prop.type?.raw === "boolean").map((prop) => prop.name));
1002
1002
  }
1003
1003
  function collectNullableOptionalProps(ir) {
1004
- return new Set(ir.metadata.propsParams.filter((p) => p.defaultValue === undefined && !p.isRest && p.type?.kind !== "primitive").map((p) => p.name));
1004
+ return new Set(ir.metadata.propsParams.filter((p) => p.defaultValue === undefined && !p.isRest && (p.type?.kind !== "primitive" || p.optional)).map((p) => p.name));
1005
1005
  }
1006
1006
  function collectStringValueNames(ir) {
1007
1007
  const names = new Set;
package/dist/index.js CHANGED
@@ -1001,7 +1001,7 @@ function collectBooleanTypedProps(ir) {
1001
1001
  return new Set(ir.metadata.propsParams.filter((prop) => prop.type?.primitive === "boolean" || prop.type?.raw === "boolean").map((prop) => prop.name));
1002
1002
  }
1003
1003
  function collectNullableOptionalProps(ir) {
1004
- return new Set(ir.metadata.propsParams.filter((p) => p.defaultValue === undefined && !p.isRest && p.type?.kind !== "primitive").map((p) => p.name));
1004
+ return new Set(ir.metadata.propsParams.filter((p) => p.defaultValue === undefined && !p.isRest && (p.type?.kind !== "primitive" || p.optional)).map((p) => p.name));
1005
1005
  }
1006
1006
  function collectStringValueNames(ir) {
1007
1007
  const names = new Set;
@@ -1,5 +1,5 @@
1
1
  package BarefootJS::Backend::Mojo;
2
- our $VERSION = "0.18.5";
2
+ our $VERSION = "0.18.7";
3
3
  use Mojo::Base -base, -signatures;
4
4
 
5
5
  use Mojo::ByteStream qw(b);
@@ -1,5 +1,5 @@
1
1
  package Mojolicious::Plugin::BarefootJS::DevReload;
2
- our $VERSION = "0.18.5";
2
+ our $VERSION = "0.18.7";
3
3
  use Mojo::Base 'Mojolicious::Plugin', -signatures;
4
4
 
5
5
  =head1 NAME
@@ -1,5 +1,5 @@
1
1
  package Mojolicious::Plugin::BarefootJS;
2
- our $VERSION = "0.18.5";
2
+ our $VERSION = "0.18.7";
3
3
  use Mojo::Base 'Mojolicious::Plugin', -signatures;
4
4
 
5
5
  use Mojo::File qw(path);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/mojolicious",
3
- "version": "0.18.7",
3
+ "version": "0.19.0",
4
4
  "description": "Mojolicious EP template adapter for BarefootJS - generates .html.ep files from IR",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -52,7 +52,7 @@
52
52
  "directory": "packages/adapter-mojolicious"
53
53
  },
54
54
  "dependencies": {
55
- "@barefootjs/shared": "0.18.7"
55
+ "@barefootjs/shared": "0.19.0"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "@barefootjs/jsx": ">=0.2.0",
@@ -60,6 +60,6 @@
60
60
  },
61
61
  "devDependencies": {
62
62
  "@barefootjs/adapter-tests": "0.1.0",
63
- "@barefootjs/jsx": "0.18.7"
63
+ "@barefootjs/jsx": "0.19.0"
64
64
  }
65
65
  }
@@ -59,6 +59,28 @@ runAdapterConformanceTests({
59
59
  // #1467 Phase 2e: same `/* @client */` keyed-map elision (data-table).
60
60
  'data-table',
61
61
  ]),
62
+ skipDataPoints: new Set<string>([
63
+ // #2255 — Perl length() counts codepoints under utf8; JS counts
64
+ // UTF-16 code units, so a surrogate-pair character is 2 in JS, 1 here.
65
+ 'string-length-text:astral',
66
+ // #2260 — controlled boolean props: the SSR seed evaluates only the
67
+ // static fallback of `props.X ?? internal()` chains.
68
+ 'toggle:gen:pressed:true',
69
+ 'switch:gen:checked:true',
70
+ 'checkbox:gen:checked:true',
71
+ // #2261 — invalid dynamic CSS value kept (escaped) where the oracle
72
+ // drops the property.
73
+ 'style-object-dynamic:gen:color:markup',
74
+ // #2262 — dynamic `.flat` depth 0/negative violates the documented
75
+ // shallow-copy contract.
76
+ 'array-flat-dynamic-depth:gen:depth:zero',
77
+ 'array-flat-dynamic-depth:gen:depth:negative',
78
+ // #2266 — asChild=true with plain-text children breaks the Slot
79
+ // rendering path (same class as the Go Slot define; observed on the
80
+ // real-Perl CI run).
81
+ 'button:gen:asChild:true',
82
+ 'kbd:gen:asChild:true',
83
+ ]),
62
84
  onRenderError: (err, id) => {
63
85
  if (err instanceof PerlNotAvailableError) {
64
86
  console.log(`Skipping [${id}]: ${err.message}`)
@@ -47,11 +47,10 @@ export function collectBooleanTypedProps(ir: ComponentIR): Set<string> {
47
47
  * resolved `interface{}` field type; here it is the absence of a default (the
48
48
  * analyzer reports `rows` — a `TextareaHTMLAttributes` member destructured
49
49
  * without a default — as no-default, `type.kind: 'unknown'`).
50
- * Excludes concrete-primitive types (`string`/`number`/`boolean`) to match
51
- * the Go adapter's scope, which guards only `interface{}` (nillable) fields
52
- * and leaves concrete fields unconditional. So a required, no-default
53
- * `string` prop still emits `attr=""` like Hono, and only nillable
54
- * (`unknown`/object/array) no-default props guard.
50
+ * A REQUIRED concrete-primitive prop (`string`/`number`/`boolean`) is
51
+ * excluded — the caller always supplies it, so it emits `attr=""` like Hono
52
+ * but an OPTIONAL primitive is presence-uncertain and stays guarded
53
+ * (#2259).
55
54
  */
56
55
  export function collectNullableOptionalProps(ir: ComponentIR): Set<string> {
57
56
  return new Set(
@@ -60,7 +59,7 @@ export function collectNullableOptionalProps(ir: ComponentIR): Set<string> {
60
59
  p =>
61
60
  p.defaultValue === undefined &&
62
61
  !p.isRest &&
63
- p.type?.kind !== 'primitive',
62
+ (p.type?.kind !== 'primitive' || p.optional),
64
63
  )
65
64
  .map(p => p.name),
66
65
  )
@@ -583,7 +583,15 @@ function buildPerlProps(
583
583
  if (props) {
584
584
  for (const [key, value] of Object.entries(props)) {
585
585
  if (routedKeys.has(key)) continue
586
- if (typeof value === 'string') {
586
+ if (value === null) {
587
+ // An explicit-null prop must still DECLARE the template var —
588
+ // `typeof null === 'object'` fails every branch below, so the key
589
+ // emitted nothing and `Mojo::Template`'s `vars => 1` never ran
590
+ // `my $user`, tripping Perl's strict-mode "Global symbol requires
591
+ // explicit package name" before the `//` fallback could apply
592
+ // (data-point conformance, optional-chaining-prop:null-user).
593
+ entries.push(`${key} => undef`)
594
+ } else if (typeof value === 'string') {
587
595
  entries.push(`${key} => '${value.replace(/'/g, "\\'")}'`)
588
596
  } else if (typeof value === 'number') {
589
597
  entries.push(`${key} => ${value}`)