Skip to content

Commit

Permalink
fix code gen issues due to new BIND CHILD and COMPONENT enums both ne…
Browse files Browse the repository at this point in the history
…ed compose
  • Loading branch information
martypdx committed Mar 29, 2024
1 parent 64b81d4 commit aff268f
Show file tree
Hide file tree
Showing 14 changed files with 277 additions and 192 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"eslint": "^8.57.0",
"globals": "^14.0.0",
"happy-dom": "^13.10.1",
"vite": "^5.2.6",
"vite": "^5.2.7",
"vite-plugin-inspect": "^0.8.3",
"vitest": "^1.4.0"
},
Expand Down
17 changes: 10 additions & 7 deletions packages/thoth/transform/template-generators.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ export function makeTargets(template) {
const { length: elLength } = boundElements;
if(isStatic) return 'null';

const values = bindings.map(({ element, type, index }) => {
const { isRoot, queryIndex } = element;
const target = isRoot ? 'r' : `${'t'}[${queryIndex}]`;
return type === BIND.CHILD ? `${target}.childNodes[${index}]` : target;
});
const values = bindings
.map(({ element, type, index }) => {
const { isRoot, queryIndex } = element;
const target = isRoot ? 'r' : `${'t'}[${queryIndex}]`;
const isComposed = type === BIND.CHILD || type === BIND.COMPONENT;
return isComposed ? `${target}.childNodes[${index}]` : target;
})
.join(',');

return elLength ? `(r,t) => [${values.join()}]` : `r => [${values.join()}]`;
return elLength ? `(r,t) => [${values}]` : `r => [${values}]`;
}

export function makeRenderer({ isEmpty, id, targetKey, tMap, bindKey, bMap, isDomFragment, html }, options) {
Expand All @@ -22,7 +25,7 @@ export function makeRenderer({ isEmpty, id, targetKey, tMap, bindKey, bMap, isDo
const target = targetKey ? `g${targetKey}` : `null`;
const bind = bindKey ? `b${bindKey}` : `null`;
let renderer = `__renderer(`;
renderer += `"${id}", /* ${JSON.stringify(tMap)} */ ${target}, /* ${JSON.stringify(bMap)} */ ${bind}, ${isDomFragment}`;
renderer += `"${id}", ${target}, ${bind}, ${isDomFragment}`;
if(content) renderer += ', `' + `${html}` + '`';
renderer += `)`;

Expand Down
40 changes: 24 additions & 16 deletions packages/thoth/transform/template-generators.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,50 @@ import { makeTargets, makeRenderer, makeBind } from './template-generators.js';
import { parse, generate as _generate } from '../compiler.js';
import { describe, test, beforeEach } from 'vitest';

function preParse(input, expect) {
function preParse(input) {
return preParseAll(input)[0];
}

function preParseAll(input) {
const ast = parse(input);
const initial = _generate(ast);
const template = initial.templates[0];
expect(template.node.type).toBe('JSXElement');
return template;
return initial.templates;
}

describe('targets generator', () => {

beforeEach(context => {
context.compile = code => {
const template = preParse(code, context.expect);
const template = preParse(code);
return makeTargets(template);
};
context.compileAll = code => {
return preParseAll(code).map(makeTargets);
};
});

test('simple', ({ compile, expect }) => {
const code = compile(`name => <p>{name}</p>`);
expect(code).toMatchInlineSnapshot(`"r => [r.childNodes[0]]"`);
test('composes', ({ compile, expect }) => {
const code = compile(`name => <p>hello {name} <Display/></p>`);
expect(code).toMatchInlineSnapshot(
`"r => [r.childNodes[1],r.childNodes[3]]"`
);
});

test('edge case', ({ expect }) => {
const input = `
test('fragment composes', ({ compile, expect }) => {
const code = compile(`name => <><p>hello</p><Display/></>`);
expect(code).toMatchInlineSnapshot(`"r => [r.childNodes[1]]"`);
});

test('edge case', ({ compileAll, expect }) => {
const code = compileAll(`
export const Loading = () => <p>loading...</p>;
export const Cat = ({ name }) => <p>{name}</p>;
export const CatList = cats => <ul>{cats.map(Cat)}</ul>;
export const CatCount = cats => <p>{cats.length} cats</p>;
export const CatName = (name) => <li>{name}</li>;
export const CatNames = cats => <ul>{cats.map(CatName)}</ul>;
`;

const ast = parse(input);
const initial = _generate(ast);
const mapped = initial.templates.map(makeTargets);
expect(mapped).toMatchInlineSnapshot(`
`);
expect(code).toMatchInlineSnapshot(`
[
"null",
"r => [r.childNodes[0]]",
Expand Down
62 changes: 52 additions & 10 deletions packages/vite-plugin/index.test.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
import { test } from 'vitest';
import plugin from './index.js';

const [jsx] = plugin();
function run(code) {
const [jsx] = plugin();
const out = jsx.transform(code, 'test.jsx');
const { bindings, node, bMap, tMap, boundElements, ...rest } = [...jsx.templates.values()][0];
const template = {
bMap: JSON.stringify(bMap),
tMap: JSON.stringify(tMap),
...rest
};
// jsx.load()

return { code: out.code, template };
}

test('basic plugin', ({ expect }) => {
const code = `<div>
const { code, template } = run`<div>
<p title="static" className={status} {...spread}>
Hello {world}
</p>
<Component prop1={prop1} {...obj} option="static">
<p>{name} slottable!</p>
</Component>
</div>`;
const out = jsx.transform(code, 'test.jsx');
expect(out.code)

expect(code)
.toMatchInlineSnapshot(`
"import { tf89f8a98, tb550bd5b } from 'virtual:azoth-templates?id=f89f8a98&id=b550bd5b';
tf89f8a98(status,spread,world,[Component, { prop1: prop1, ...obj, option: "static", }, tb550bd5b(name)]);
"
`);
const { bindings, node, bMap, tMap, boundElements, ...rest } = [...jsx.templates.values()][0];
const template = {
bMap: JSON.stringify(bMap),
tMap: JSON.stringify(tMap),
...rest
};

expect(template).toMatchInlineSnapshot(`
{
"bMap": "[0,4,1,2]",
Expand All @@ -48,4 +55,39 @@ test('basic plugin', ({ expect }) => {
"targetKey": "88185d12",
}
`);
});

test('fragment w/ component', ({ expect }) => {
const { code, template } = run`<>
<h1>Hello Sandbox</h1>
<div>
<Title />
</div>
</>`;

expect(code).toMatchInlineSnapshot(`
"import { tafdcadae } from 'virtual:azoth-templates?id=afdcadae';
tafdcadae([Title]);
"
`);

expect(template).toMatchInlineSnapshot(`
{
"bMap": "[2]",
"bindKey": "dbc1b4c9",
"html": "<h1>Hello Sandbox</h1>
<div data-bind>
<!--0-->
</div>",
"id": "afdcadae",
"imports": [],
"isDomFragment": true,
"isEmpty": false,
"isStatic": false,
"propertyNames": null,
"tMap": "[[0,1]]",
"targetKey": "6e340b9c",
}
`);
});
Loading

0 comments on commit aff268f

Please sign in to comment.