@barefootjs/go-template 0.15.2 → 0.17.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.
- package/dist/adapter/analysis/component-tree.d.ts +23 -0
- package/dist/adapter/analysis/component-tree.d.ts.map +1 -0
- package/dist/adapter/emit-context.d.ts +53 -0
- package/dist/adapter/emit-context.d.ts.map +1 -0
- package/dist/adapter/expr/helper-inline.d.ts +31 -0
- package/dist/adapter/expr/helper-inline.d.ts.map +1 -0
- package/dist/adapter/expr/url-builder.d.ts +23 -0
- package/dist/adapter/expr/url-builder.d.ts.map +1 -0
- package/dist/adapter/go-template-adapter.d.ts +291 -1070
- package/dist/adapter/go-template-adapter.d.ts.map +1 -1
- package/dist/adapter/index.js +2859 -2618
- package/dist/adapter/lib/compile-state.d.ts +116 -0
- package/dist/adapter/lib/compile-state.d.ts.map +1 -0
- package/dist/adapter/lib/constants.d.ts +11 -0
- package/dist/adapter/lib/constants.d.ts.map +1 -0
- package/dist/adapter/lib/go-emit.d.ts +117 -0
- package/dist/adapter/lib/go-emit.d.ts.map +1 -0
- package/dist/adapter/lib/go-naming.d.ts +39 -0
- package/dist/adapter/lib/go-naming.d.ts.map +1 -0
- package/dist/adapter/lib/ir-scope.d.ts +13 -0
- package/dist/adapter/lib/ir-scope.d.ts.map +1 -0
- package/dist/adapter/lib/types.d.ts +165 -0
- package/dist/adapter/lib/types.d.ts.map +1 -0
- package/dist/adapter/memo/ctor-lowering.d.ts +39 -0
- package/dist/adapter/memo/ctor-lowering.d.ts.map +1 -0
- package/dist/adapter/memo/memo-compute.d.ts +124 -0
- package/dist/adapter/memo/memo-compute.d.ts.map +1 -0
- package/dist/adapter/memo/memo-type.d.ts +38 -0
- package/dist/adapter/memo/memo-type.d.ts.map +1 -0
- package/dist/adapter/memo/memo-value.d.ts +64 -0
- package/dist/adapter/memo/memo-value.d.ts.map +1 -0
- package/dist/adapter/memo/template-interp.d.ts +43 -0
- package/dist/adapter/memo/template-interp.d.ts.map +1 -0
- package/dist/adapter/props/prop-types.d.ts +31 -0
- package/dist/adapter/props/prop-types.d.ts.map +1 -0
- package/dist/adapter/spread/spread-codegen.d.ts +40 -0
- package/dist/adapter/spread/spread-codegen.d.ts.map +1 -0
- package/dist/adapter/type/type-codegen.d.ts +25 -0
- package/dist/adapter/type/type-codegen.d.ts.map +1 -0
- package/dist/adapter/value/parsed-literal-to-go.d.ts +17 -0
- package/dist/adapter/value/parsed-literal-to-go.d.ts.map +1 -0
- package/dist/adapter/value/value-lowering.d.ts +46 -0
- package/dist/adapter/value/value-lowering.d.ts.map +1 -0
- package/dist/build.js +2857 -2616
- package/dist/index.js +2859 -2618
- package/dist/test-render.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/derived-state-memo.test.ts +155 -84
- package/src/__tests__/go-template-adapter.test.ts +211 -60
- package/src/__tests__/lowering-plugin.test.ts +109 -0
- package/src/__tests__/query-href.test.ts +179 -0
- package/src/adapter/analysis/component-tree.ts +174 -0
- package/src/adapter/emit-context.ts +59 -0
- package/src/adapter/expr/helper-inline.ts +274 -0
- package/src/adapter/expr/url-builder.ts +123 -0
- package/src/adapter/go-template-adapter.ts +2100 -5316
- package/src/adapter/lib/compile-state.ts +150 -0
- package/src/adapter/lib/constants.ts +24 -0
- package/src/adapter/lib/go-emit.ts +289 -0
- package/src/adapter/lib/go-naming.ts +84 -0
- package/src/adapter/lib/ir-scope.ts +31 -0
- package/src/adapter/lib/types.ts +182 -0
- package/src/adapter/memo/ctor-lowering.ts +267 -0
- package/src/adapter/memo/memo-compute.ts +451 -0
- package/src/adapter/memo/memo-type.ts +74 -0
- package/src/adapter/memo/memo-value.ts +197 -0
- package/src/adapter/memo/template-interp.ts +246 -0
- package/src/adapter/props/prop-types.ts +84 -0
- package/src/adapter/spread/spread-codegen.ts +458 -0
- package/src/adapter/type/type-codegen.ts +95 -0
- package/src/adapter/value/parsed-literal-to-go.ts +94 -0
- package/src/adapter/value/value-lowering.ts +162 -0
- package/src/test-render.ts +2 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-render.d.ts","sourceRoot":"","sources":["../src/test-render.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"test-render.d.ts","sourceRoot":"","sources":["../src/test-render.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,iBAAiB,CAAA;AAUnE,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAgCD,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,8BAA8B;IAC9B,OAAO,EAAE,eAAe,CAAA;IACxB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACzC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAyVvF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/go-template",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Go html/template adapter for BarefootJS - generates Go template files from IR",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"directory": "packages/adapter-go-template"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@barefootjs/shared": "0.
|
|
52
|
+
"@barefootjs/shared": "0.17.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"@barefootjs/jsx": ">=0.2.0",
|
|
@@ -57,6 +57,6 @@
|
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@barefootjs/adapter-tests": "0.1.0",
|
|
60
|
-
"@barefootjs/jsx": "0.
|
|
60
|
+
"@barefootjs/jsx": "0.17.0"
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -22,10 +22,11 @@ function generate(src: string) {
|
|
|
22
22
|
describe('Capability A: object-returning searchParams memo → computed map field', () => {
|
|
23
23
|
const SRC = `
|
|
24
24
|
'use client'
|
|
25
|
-
import { createMemo,
|
|
25
|
+
import { createMemo, createSearchParams } from '@barefootjs/client'
|
|
26
26
|
const SORT_KEYS = ['date', 'title', 'tag']
|
|
27
27
|
const asSortKey = (raw) => (SORT_KEYS.includes(raw) ? raw : 'date')
|
|
28
28
|
export function P() {
|
|
29
|
+
const [searchParams] = createSearchParams()
|
|
29
30
|
const params = createMemo(() => {
|
|
30
31
|
const sp = searchParams()
|
|
31
32
|
return { sort: asSortKey(sp.get('sort')), tag: sp.get('tag') ?? '' }
|
|
@@ -74,8 +75,9 @@ export function P() {
|
|
|
74
75
|
test('string-valued ternary condition falls back to nil, never invalid Go', () => {
|
|
75
76
|
const src = `
|
|
76
77
|
'use client'
|
|
77
|
-
import { createMemo,
|
|
78
|
+
import { createMemo, createSearchParams } from '@barefootjs/client'
|
|
78
79
|
export function P() {
|
|
80
|
+
const [searchParams] = createSearchParams()
|
|
79
81
|
const params = createMemo(() => {
|
|
80
82
|
const sp = searchParams()
|
|
81
83
|
return { label: sp.get('tag') ? 'has' : 'none' }
|
|
@@ -95,8 +97,9 @@ export function P() {
|
|
|
95
97
|
test('block-body memo with control flow falls back to nil', () => {
|
|
96
98
|
const src = `
|
|
97
99
|
'use client'
|
|
98
|
-
import { createMemo,
|
|
100
|
+
import { createMemo, createSearchParams } from '@barefootjs/client'
|
|
99
101
|
export function P() {
|
|
102
|
+
const [searchParams] = createSearchParams()
|
|
100
103
|
const params = createMemo(() => {
|
|
101
104
|
const sp = searchParams()
|
|
102
105
|
if (sp.get('x')) return { sort: 'early' }
|
|
@@ -115,10 +118,11 @@ describe('Capability B: inline local pure helper calls at attribute call sites',
|
|
|
115
118
|
test('sortClass(k) inlines to a conditional, not a .SortClass method call', () => {
|
|
116
119
|
const src = `
|
|
117
120
|
'use client'
|
|
118
|
-
import { createMemo,
|
|
121
|
+
import { createMemo, createSearchParams } from '@barefootjs/client'
|
|
119
122
|
const SORT_KEYS = ['date', 'title', 'tag']
|
|
120
123
|
const asSortKey = (raw) => (SORT_KEYS.includes(raw) ? raw : 'date')
|
|
121
124
|
export function P() {
|
|
125
|
+
const [searchParams] = createSearchParams()
|
|
122
126
|
const params = createMemo(() => {
|
|
123
127
|
const sp = searchParams()
|
|
124
128
|
return { sort: asSortKey(sp.get('sort')), tag: sp.get('tag') ?? '' }
|
|
@@ -139,8 +143,9 @@ export function P() {
|
|
|
139
143
|
test('tagClass(t) inlines inside a loop, resolving the loop var and root memo', () => {
|
|
140
144
|
const src = `
|
|
141
145
|
'use client'
|
|
142
|
-
import { createMemo,
|
|
146
|
+
import { createMemo, createSearchParams } from '@barefootjs/client'
|
|
143
147
|
export function P(props: { tags: string[] }) {
|
|
148
|
+
const [searchParams] = createSearchParams()
|
|
144
149
|
const params = createMemo(() => {
|
|
145
150
|
const sp = searchParams()
|
|
146
151
|
return { tag: sp.get('tag') ?? '' }
|
|
@@ -214,51 +219,22 @@ export function P(props: { xs: string[] }) {
|
|
|
214
219
|
})
|
|
215
220
|
})
|
|
216
221
|
|
|
217
|
-
describe('
|
|
218
|
-
|
|
222
|
+
describe('Derived string-const → computed Go struct field (#1945)', () => {
|
|
223
|
+
// The trailing-slash strip `(props.base ?? '').replace(/\/+$/, '')` lowers in
|
|
224
|
+
// the `NewXxxProps` constructor to `strings.TrimRight`, and `base || '/'`
|
|
225
|
+
// becomes a computed `Root` field referenced by the template. (The former
|
|
226
|
+
// `URLSearchParams` href-builder recognizer that shared this fixture was
|
|
227
|
+
// retired in #2042 once `queryHref` replaced it.)
|
|
228
|
+
test('derived `root` const (trailing-slash strip) becomes a computed Root field', () => {
|
|
229
|
+
const src = `
|
|
219
230
|
'use client'
|
|
220
|
-
import { createMemo, searchParams } from '@barefootjs/client'
|
|
221
231
|
export function P(props: { base: string }) {
|
|
222
|
-
const params = createMemo(() => {
|
|
223
|
-
const sp = searchParams()
|
|
224
|
-
return { sort: sp.get('sort') ?? '', tag: sp.get('tag') ?? '' }
|
|
225
|
-
})
|
|
226
232
|
const base = (props.base ?? '').replace(/\\/+$/, '')
|
|
227
233
|
const root = base || '/'
|
|
228
|
-
|
|
229
|
-
const u = new URLSearchParams()
|
|
230
|
-
if (sort !== 'date') u.set('sort', sort)
|
|
231
|
-
if (tag) u.set('tag', tag)
|
|
232
|
-
const s = u.toString()
|
|
233
|
-
return s ? \`\${root}?\${s}\` : root
|
|
234
|
-
}
|
|
235
|
-
const sortHref = (k) => hrefFor(k, params().tag)
|
|
236
|
-
const tagHref = (t) => hrefFor(params().sort, t)
|
|
237
|
-
return (
|
|
238
|
-
<div>
|
|
239
|
-
<a href={sortHref('title')}>s</a>
|
|
240
|
-
{props.base ? <a href={tagHref('go')}>t</a> : null}
|
|
241
|
-
</div>
|
|
242
|
-
)
|
|
234
|
+
return <a href={root}>home</a>
|
|
243
235
|
}
|
|
244
236
|
`
|
|
245
|
-
|
|
246
|
-
test('sortHref/tagHref lower to bf_query, not a .SortHref method call', () => {
|
|
247
|
-
const { template } = generate(SRC)
|
|
248
|
-
expect(template).not.toContain('.SortHref')
|
|
249
|
-
expect(template).not.toContain('.TagHref')
|
|
250
|
-
expect(template).toContain('bf_query .Root')
|
|
251
|
-
})
|
|
252
|
-
|
|
253
|
-
test('guarded set() calls become bool include triples', () => {
|
|
254
|
-
const { template } = generate(SRC)
|
|
255
|
-
// sort !== 'date' guard (runtime sort case via tagHref) + tag truthiness.
|
|
256
|
-
expect(template).toContain('(ne (bf_string .Params.Sort) "date") "sort"')
|
|
257
|
-
expect(template).toContain('(ne .Params.Tag "") "tag"')
|
|
258
|
-
})
|
|
259
|
-
|
|
260
|
-
test('derived `root` const becomes a computed Root field', () => {
|
|
261
|
-
const { types } = generate(SRC)
|
|
237
|
+
const { types } = generate(src)
|
|
262
238
|
expect(types).toContain('Root string `json:"-"`')
|
|
263
239
|
expect(types).toContain(
|
|
264
240
|
'Root: func() string { v := strings.TrimRight(in.Base, "/"); if v != "" { return v }; return "/" }(),',
|
|
@@ -266,45 +242,6 @@ export function P(props: { base: string }) {
|
|
|
266
242
|
expect(types).toContain('"strings"')
|
|
267
243
|
})
|
|
268
244
|
|
|
269
|
-
// A `&&` guard is NOT a Go bool (Go's `and` returns an operand); it must be
|
|
270
|
-
// truthiness-wrapped so `bf_query`'s `include` receives a real bool (#1945 review).
|
|
271
|
-
test('a && guard is wrapped to a bool, not passed as bare `and`', () => {
|
|
272
|
-
const src = `
|
|
273
|
-
'use client'
|
|
274
|
-
import { createMemo, searchParams } from '@barefootjs/client'
|
|
275
|
-
export function P(props: { base: string }) {
|
|
276
|
-
const params = createMemo(() => { const sp = searchParams(); return { tag: sp.get('tag') ?? '' } })
|
|
277
|
-
const root = (props.base ?? '') || '/'
|
|
278
|
-
const hrefFor = (sort: string, tag: string) => {
|
|
279
|
-
const u = new URLSearchParams()
|
|
280
|
-
if (sort && tag) u.set('both', sort)
|
|
281
|
-
return u.toString() ? \`\${root}?\${u}\` : root
|
|
282
|
-
}
|
|
283
|
-
const h = (k) => hrefFor(k, params().tag)
|
|
284
|
-
return <a href={h('x')}>x</a>
|
|
285
|
-
}
|
|
286
|
-
`
|
|
287
|
-
const { template } = generate(src)
|
|
288
|
-
expect(template).toContain('(ne (and "x" .Params.Tag) "")')
|
|
289
|
-
})
|
|
290
|
-
|
|
291
|
-
// A URL-builder helper whose return isn't the conditional with-query/base
|
|
292
|
-
// shape must not be lowered to bf_query (#1945 review) — it falls back to the
|
|
293
|
-
// method-call form.
|
|
294
|
-
test('a builder returning a non-conditional shape is not lowered to bf_query', () => {
|
|
295
|
-
const src = `
|
|
296
|
-
'use client'
|
|
297
|
-
import { searchParams } from '@barefootjs/client'
|
|
298
|
-
export function P() {
|
|
299
|
-
const bad = (sort: string) => { const u = new URLSearchParams(); u.set('s', sort); return u.toString() }
|
|
300
|
-
return <a href={bad('x')}>x</a>
|
|
301
|
-
}
|
|
302
|
-
`
|
|
303
|
-
const { template } = generate(src)
|
|
304
|
-
expect(template).not.toContain('bf_query')
|
|
305
|
-
expect(template).toContain('.Bad')
|
|
306
|
-
})
|
|
307
|
-
|
|
308
245
|
// A non-string derived const referenced by the template must not be emitted
|
|
309
246
|
// as a `string` field with a non-string initializer (#1945 review).
|
|
310
247
|
test('a numeric derived const is not emitted as a string field', () => {
|
|
@@ -338,9 +275,10 @@ describe('Capability D: array-memo .length → handler-filled loop slice count',
|
|
|
338
275
|
test('visible().length lowers to len .<Slice>, not the nil memo field', () => {
|
|
339
276
|
const src = `
|
|
340
277
|
'use client'
|
|
341
|
-
import { createMemo,
|
|
278
|
+
import { createMemo, createSearchParams } from '@barefootjs/client'
|
|
342
279
|
import { Row } from './Row'
|
|
343
280
|
export function P(props: { items: { id: string }[] }) {
|
|
281
|
+
const [searchParams] = createSearchParams()
|
|
344
282
|
const params = createMemo(() => {
|
|
345
283
|
const sp = searchParams()
|
|
346
284
|
return { tag: sp.get('tag') ?? '' }
|
|
@@ -369,3 +307,136 @@ export function P(props: { items: { id: string }[] }) {
|
|
|
369
307
|
expect(template).toContain('len .Items')
|
|
370
308
|
})
|
|
371
309
|
})
|
|
310
|
+
|
|
311
|
+
describe('typed memo bodies parse from the type-stripped computation (#1976 review)', () => {
|
|
312
|
+
const mk = (body: string) => `
|
|
313
|
+
"use client"
|
|
314
|
+
import { createSignal, createMemo } from '@barefootjs/client'
|
|
315
|
+
export function T() {
|
|
316
|
+
const [count, setCount] = createSignal(3)
|
|
317
|
+
const doubled = createMemo(() => ${body})
|
|
318
|
+
return <div>{doubled()}</div>
|
|
319
|
+
}`
|
|
320
|
+
|
|
321
|
+
// `MemoInfo.parsed` is parsed from the type-STRIPPED body (`ctx.getJS`), not
|
|
322
|
+
// the raw source — otherwise TypeScript-only syntax (`as T`, `!`, satisfies)
|
|
323
|
+
// would make `parseExpression` bail, `parsed` would be undefined, and the
|
|
324
|
+
// adapter would lose the arithmetic shape it used to match on the stripped
|
|
325
|
+
// `computation` (changing the SSR default).
|
|
326
|
+
test('a TS-annotated memo body yields the same SSR as the untyped form', () => {
|
|
327
|
+
const typed = generate(mk('(count() as number) * 2'))
|
|
328
|
+
const untyped = generate(mk('count() * 2'))
|
|
329
|
+
expect(typed.types).toContain('Doubled: 3 * 2,')
|
|
330
|
+
expect(typed.types).toBe(untyped.types)
|
|
331
|
+
})
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
// #2040 PR-B: guard-and-return-const block memos lower via the analyzer fold
|
|
335
|
+
// (`MemoInfo.parsed`), with a tolerant `parsedBlock` fallback for blocks the
|
|
336
|
+
// fold refuses (so the SSR const bake never regresses vs. the old statement
|
|
337
|
+
// walker).
|
|
338
|
+
describe('Capability C: guard-const block memo via fold (#2040 PR-B)', () => {
|
|
339
|
+
test('folded guard memo bakes the module-const array (not nil)', () => {
|
|
340
|
+
const { types } = generate(`
|
|
341
|
+
"use client"
|
|
342
|
+
import { createSignal, createMemo } from "@barefootjs/client"
|
|
343
|
+
const ALL = ['a', 'b', 'c']
|
|
344
|
+
export function Tags() {
|
|
345
|
+
const [sel, setSel] = createSignal<string | null>(null)
|
|
346
|
+
const visible = createMemo(() => {
|
|
347
|
+
const k = sel()
|
|
348
|
+
if (!k) return ALL
|
|
349
|
+
return ALL.filter(t => t === k)
|
|
350
|
+
})
|
|
351
|
+
return <ul>{visible().map(t => (<li key={t}>{t}</li>))}</ul>
|
|
352
|
+
}
|
|
353
|
+
`)
|
|
354
|
+
expect(types).toContain(`[]interface{}{"a", "b", "c"}`)
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
test('guard memo with an impure tail binding still bakes the const (fallback path)', () => {
|
|
358
|
+
// `const n = ext()` is impure (not a reactive getter) and used more than
|
|
359
|
+
// once in the tail, so `foldBlockToExpr` refuses → `parsed` is unset. The
|
|
360
|
+
// tolerant `parsedBlock` fallback must still bake `ALL`; otherwise the first
|
|
361
|
+
// server render is an empty list (regression vs. main). (PR #2053 review #1)
|
|
362
|
+
const { types } = generate(`
|
|
363
|
+
"use client"
|
|
364
|
+
import { createSignal, createMemo } from "@barefootjs/client"
|
|
365
|
+
const ALL = ['a', 'b', 'c']
|
|
366
|
+
function ext() { return 1 }
|
|
367
|
+
export function Tags() {
|
|
368
|
+
const [sel, setSel] = createSignal<string | null>(null)
|
|
369
|
+
const visible = createMemo(() => {
|
|
370
|
+
const k = sel()
|
|
371
|
+
const n = ext()
|
|
372
|
+
if (!k) return ALL
|
|
373
|
+
return ALL.filter(t => t.length === n).concat(ALL.slice(n))
|
|
374
|
+
})
|
|
375
|
+
return <ul>{visible().map(t => (<li key={t}>{t}</li>))}</ul>
|
|
376
|
+
}
|
|
377
|
+
`)
|
|
378
|
+
expect(types).toContain(`[]interface{}{"a", "b", "c"}`)
|
|
379
|
+
})
|
|
380
|
+
|
|
381
|
+
test('early-return string-const block memo bakes the initial branch (#2040 scope)', () => {
|
|
382
|
+
// `() => { if (vert()) return A; return B }` folds to `vert() ? A : B`; with
|
|
383
|
+
// `vert` starting false the SSR value is B. Now lowered via the general
|
|
384
|
+
// `memoInitialFromParsedBody` conditional path. (PR #2053 review #2)
|
|
385
|
+
const { types } = generate(`
|
|
386
|
+
"use client"
|
|
387
|
+
import { createSignal, createMemo } from "@barefootjs/client"
|
|
388
|
+
const A = 'flex-col'
|
|
389
|
+
const B = 'flex'
|
|
390
|
+
export function Box() {
|
|
391
|
+
const [vert, setVert] = createSignal(false)
|
|
392
|
+
const cls = createMemo(() => {
|
|
393
|
+
if (vert()) return A
|
|
394
|
+
return B
|
|
395
|
+
})
|
|
396
|
+
return <div className={cls()}>x</div>
|
|
397
|
+
}
|
|
398
|
+
`)
|
|
399
|
+
expect(types).toContain('"flex"')
|
|
400
|
+
})
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
// #2040 PR-C: the object-returning searchParams memo lowers via the general
|
|
404
|
+
// fold (`foldBlockToExpr` with `searchParams` treated as a pure idempotent
|
|
405
|
+
// read), not a bespoke statement walk.
|
|
406
|
+
describe('Capability D: searchParams object memo via fold (#2040 PR-C)', () => {
|
|
407
|
+
test('object memo using searchParams() directly (no const binding) lowers', () => {
|
|
408
|
+
// The old statement walk required a `const sp = searchParams()` binding to
|
|
409
|
+
// populate its env; the fold inlines any binding, so a direct
|
|
410
|
+
// `searchParams().get('k')` in the returned object now lowers too.
|
|
411
|
+
const { types } = generate(`
|
|
412
|
+
"use client"
|
|
413
|
+
import { createMemo, createSearchParams } from "@barefootjs/client"
|
|
414
|
+
export function PostList() {
|
|
415
|
+
const [searchParams] = createSearchParams()
|
|
416
|
+
const params = createMemo(() => {
|
|
417
|
+
return { tag: searchParams().get('tag') ?? '' }
|
|
418
|
+
})
|
|
419
|
+
return <div>{params().tag}</div>
|
|
420
|
+
}
|
|
421
|
+
`)
|
|
422
|
+
expect(types).toContain('map[string]interface{}{')
|
|
423
|
+
expect(types).toContain('"Tag":')
|
|
424
|
+
expect(types).toContain('in.SearchParams.Get("tag")')
|
|
425
|
+
})
|
|
426
|
+
|
|
427
|
+
test('aliased env-signal getter still lowers (local-name oracle)', () => {
|
|
428
|
+
const { types } = generate(`
|
|
429
|
+
"use client"
|
|
430
|
+
import { createMemo, createSearchParams } from "@barefootjs/client"
|
|
431
|
+
export function PostList() {
|
|
432
|
+
const [sp] = createSearchParams()
|
|
433
|
+
const params = createMemo(() => {
|
|
434
|
+
const q = sp()
|
|
435
|
+
return { tag: q.get('tag') ?? '' }
|
|
436
|
+
})
|
|
437
|
+
return <div>{params().tag}</div>
|
|
438
|
+
}
|
|
439
|
+
`)
|
|
440
|
+
expect(types).toContain('in.SearchParams.Get("tag")')
|
|
441
|
+
})
|
|
442
|
+
})
|