@reckona/mreact-compiler 0.0.153 → 0.0.154
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/emit-server.d.ts.map +1 -1
- package/dist/emit-server.js +81 -8
- package/dist/emit-server.js.map +1 -1
- package/dist/ir.d.ts +2 -1
- package/dist/ir.d.ts.map +1 -1
- package/dist/ir.js.map +1 -1
- package/dist/oxc-compat-create-element.d.ts +11 -0
- package/dist/oxc-compat-create-element.d.ts.map +1 -0
- package/dist/oxc-compat-create-element.js +489 -0
- package/dist/oxc-compat-create-element.js.map +1 -0
- package/dist/oxc.d.ts.map +1 -1
- package/dist/oxc.js +79 -11
- package/dist/oxc.js.map +1 -1
- package/package.json +2 -2
- package/src/emit-server.ts +103 -4
- package/src/ir.ts +4 -1
- package/src/oxc-compat-create-element.ts +705 -0
- package/src/oxc.ts +130 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit-server.d.ts","sourceRoot":"","sources":["../src/emit-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwD,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9F,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAqBrE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpC,MAAM,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACzC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"emit-server.d.ts","sourceRoot":"","sources":["../src/emit-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwD,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9F,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAqBrE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACpC,MAAM,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACzC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAUD,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,GAAE,iBAAsB,GAAG,UAAU,CAoHpF"}
|
package/dist/emit-server.js
CHANGED
|
@@ -8,6 +8,7 @@ import { emitOxcCompatObjectChildren, oxcServerStringReactNodeRenderHelperPlaceh
|
|
|
8
8
|
// name through every signature. Reset at the top of `emitServer`.
|
|
9
9
|
let currentUrlSafeHelperName = "_urlAttrSafe";
|
|
10
10
|
let currentClientBoundaryHelperName;
|
|
11
|
+
let currentCompatChildHelperName;
|
|
11
12
|
let currentSpreadAttributesHelperName = "_renderSpreadAttributes";
|
|
12
13
|
export function emitServer(ir, options = {}) {
|
|
13
14
|
const escapeHelperName = allocateEscapeHelperName(ir);
|
|
@@ -24,12 +25,16 @@ export function emitServer(ir, options = {}) {
|
|
|
24
25
|
const clientBoundaryHelperName = usesClientBoundary(ir)
|
|
25
26
|
? allocateHelperName(ir, "_renderClientBoundary")
|
|
26
27
|
: undefined;
|
|
28
|
+
const compatChildHelperName = usesCompatChildRender(ir)
|
|
29
|
+
? allocateHelperName(ir, "_renderCompatChild")
|
|
30
|
+
: undefined;
|
|
27
31
|
const spreadAttributesHelperName = allocateHelperName(ir, "_renderSpreadAttributes");
|
|
28
32
|
const outAccumulatorName = allocateHelperName(ir, "_out");
|
|
29
33
|
const urlSafeHelperName = allocateHelperName(ir, "_urlAttrSafe");
|
|
30
34
|
currentUrlSafeHelperName = urlSafeHelperName;
|
|
31
35
|
setOxcServerStringUrlSafeHelperName(urlSafeHelperName);
|
|
32
36
|
currentClientBoundaryHelperName = clientBoundaryHelperName;
|
|
37
|
+
currentCompatChildHelperName = compatChildHelperName;
|
|
33
38
|
currentSpreadAttributesHelperName = spreadAttributesHelperName;
|
|
34
39
|
const helper = emitEscapeHtmlHelper(escapeHelperName);
|
|
35
40
|
// Inline URL-scheme guard mirroring packages/server/src/url-safety.ts.
|
|
@@ -77,7 +82,7 @@ export function emitServer(ir, options = {}) {
|
|
|
77
82
|
? ""
|
|
78
83
|
: `import { ${options.escape.batchImportName} as ${escapeBatchHelperName} } from ${stringLiteral(options.escape.batchImportSource)};`;
|
|
79
84
|
const userImports = emitUserImports(ir);
|
|
80
|
-
const contextImport = emitContextImport(contextProviderHelperName, contextConsumerHelperName, reactNodeRenderHelperName);
|
|
85
|
+
const contextImport = emitContextImport(contextProviderHelperName, contextConsumerHelperName, reactNodeRenderHelperName, compatChildHelperName);
|
|
81
86
|
const moduleStatements = emitModuleStatements(ir);
|
|
82
87
|
const code = createCodeBuilder();
|
|
83
88
|
code.section(userImports);
|
|
@@ -91,14 +96,17 @@ export function emitServer(ir, options = {}) {
|
|
|
91
96
|
code.section(components);
|
|
92
97
|
return {
|
|
93
98
|
code: code.toString(),
|
|
94
|
-
imports: collectContextImports(contextProviderHelperName, contextConsumerHelperName, reactNodeRenderHelperName),
|
|
99
|
+
imports: collectContextImports(contextProviderHelperName, contextConsumerHelperName, reactNodeRenderHelperName, compatChildHelperName),
|
|
95
100
|
};
|
|
96
101
|
}
|
|
97
|
-
function emitContextImport(contextProviderHelperName, contextConsumerHelperName, reactNodeRenderHelperName) {
|
|
102
|
+
function emitContextImport(contextProviderHelperName, contextConsumerHelperName, reactNodeRenderHelperName, compatChildHelperName) {
|
|
98
103
|
const specifiers = [
|
|
99
104
|
reactNodeRenderHelperName === undefined
|
|
100
105
|
? undefined
|
|
101
106
|
: `renderToString as ${reactNodeRenderHelperName}`,
|
|
107
|
+
compatChildHelperName === undefined
|
|
108
|
+
? undefined
|
|
109
|
+
: `renderChildToString as ${compatChildHelperName}`,
|
|
102
110
|
contextProviderHelperName === undefined
|
|
103
111
|
? undefined
|
|
104
112
|
: `renderContextProviderToString as ${contextProviderHelperName}`,
|
|
@@ -110,11 +118,12 @@ function emitContextImport(contextProviderHelperName, contextConsumerHelperName,
|
|
|
110
118
|
? ""
|
|
111
119
|
: `import { ${specifiers.join(", ")} } from "@reckona/mreact-compat";`;
|
|
112
120
|
}
|
|
113
|
-
function collectContextImports(contextProviderHelperName, contextConsumerHelperName, reactNodeRenderHelperName) {
|
|
121
|
+
function collectContextImports(contextProviderHelperName, contextConsumerHelperName, reactNodeRenderHelperName, compatChildHelperName) {
|
|
114
122
|
const specifiers = [
|
|
115
123
|
reactNodeRenderHelperName === undefined ? undefined : "renderToString",
|
|
116
124
|
contextProviderHelperName === undefined ? undefined : "renderContextProviderToString",
|
|
117
125
|
contextConsumerHelperName === undefined ? undefined : "renderContextConsumerToString",
|
|
126
|
+
compatChildHelperName === undefined ? undefined : "renderChildToString",
|
|
118
127
|
].filter((specifier) => specifier !== undefined);
|
|
119
128
|
return specifiers.length === 0 ? [] : [{ source: "@reckona/mreact-compat", specifiers }];
|
|
120
129
|
}
|
|
@@ -179,6 +188,9 @@ function collectHtmlStatements(node, outVar, escapeHelperName, escapeBatchHelper
|
|
|
179
188
|
if (node.renderMode === "react-node" && reactNodeRenderHelperName !== undefined) {
|
|
180
189
|
return [`${outVar} += ${reactNodeRenderHelperName}(() => (${node.code}));`];
|
|
181
190
|
}
|
|
191
|
+
if (node.renderMode === "compat-child" && currentCompatChildHelperName !== undefined) {
|
|
192
|
+
return [`${outVar} += ${currentCompatChildHelperName}(${node.code});`];
|
|
193
|
+
}
|
|
182
194
|
return [`${outVar} += ${escapeHelperName}(${node.code});`];
|
|
183
195
|
}
|
|
184
196
|
if (node.kind === "conditional") {
|
|
@@ -364,6 +376,9 @@ function collectHtmlParts(node, escapeHelperName, escapeBatchHelperName, asyncCo
|
|
|
364
376
|
if (node.renderMode === "react-node" && reactNodeRenderHelperName !== undefined) {
|
|
365
377
|
return [`${reactNodeRenderHelperName}(() => (${node.code}))`];
|
|
366
378
|
}
|
|
379
|
+
if (node.renderMode === "compat-child" && currentCompatChildHelperName !== undefined) {
|
|
380
|
+
return [`${currentCompatChildHelperName}(${node.code})`];
|
|
381
|
+
}
|
|
367
382
|
return [`${escapeHelperName}(${node.code})`];
|
|
368
383
|
}
|
|
369
384
|
if (node.kind === "conditional") {
|
|
@@ -514,7 +529,9 @@ function collectHtmlAttributeParts(tagName, attr, escapeHelperName, escapeBatchH
|
|
|
514
529
|
}
|
|
515
530
|
if (attr.name === "style") {
|
|
516
531
|
return [
|
|
517
|
-
|
|
532
|
+
attr.serialization === "compat"
|
|
533
|
+
? emitCompatDynamicStyleAttributeExpression(attr.code, escapeHelperName)
|
|
534
|
+
: emitDynamicStyleAttributeExpression(attr.code, escapeHelperName, escapeBatchHelperName),
|
|
518
535
|
];
|
|
519
536
|
}
|
|
520
537
|
if (isDangerousHtmlAttribute(htmlName)) {
|
|
@@ -525,7 +542,11 @@ function collectHtmlAttributeParts(tagName, attr, escapeHelperName, escapeBatchH
|
|
|
525
542
|
`(() => { const _value = (${attr.code}); if (_value == null || _value === false) return ""; if (typeof _value === "object" && _value !== null && typeof _value.__html === "string") return ${stringLiteral(` ${htmlName}="`)} + ${escapeHelperName}(_value.__html) + ${stringLiteral('"')}; return ""; })()`,
|
|
526
543
|
];
|
|
527
544
|
}
|
|
528
|
-
return [
|
|
545
|
+
return [
|
|
546
|
+
attr.serialization === "compat" && !isUrlAttribute(htmlName)
|
|
547
|
+
? emitCompatDynamicAttributeExpression(htmlName, attr.code, escapeHelperName)
|
|
548
|
+
: emitDynamicAttributeExpression(htmlName, attr.code, escapeHelperName),
|
|
549
|
+
];
|
|
529
550
|
}
|
|
530
551
|
function collectElementAttributeParts(tagName, attrs, escapeHelperName, escapeBatchHelperName, dynamicAttributes, attributeScan = scanElementAttributes(tagName, attrs)) {
|
|
531
552
|
if (dynamicAttributes === "emit" && attrs.some((attr) => attr.kind === "spread-attr")) {
|
|
@@ -620,6 +641,29 @@ function emitDynamicAttributeExpression(name, code, escapeHelperName) {
|
|
|
620
641
|
? `(() => { const _value = (${code}); return _value == null ? "" : ${stringLiteral(` ${name}="`)} + ${escapeHelperName}(_value) + ${stringLiteral('"')}; })()`
|
|
621
642
|
: `(() => { const _value = (${code}); return _value == null || _value === false ? "" : ${stringLiteral(` ${name}="`)} + ${escapeHelperName}(_value === true ? "" : _value) + ${stringLiteral('"')}; })()`;
|
|
622
643
|
}
|
|
644
|
+
// Mirrors packages/react-compat/src/server-render.ts renderHtmlAttribute for
|
|
645
|
+
// dynamic values: functions and objects drop, booleans serialize as
|
|
646
|
+
// "true"/"false" for booleanish-string and data attributes, and false drops
|
|
647
|
+
// elsewhere. Byte parity with the interpreter is pinned by tests.
|
|
648
|
+
function emitCompatDynamicAttributeExpression(name, code, escapeHelperName) {
|
|
649
|
+
const lowerCased = name.toLowerCase();
|
|
650
|
+
const booleanishOrData = lowerCased.startsWith("aria-") ||
|
|
651
|
+
lowerCased.startsWith("data-") ||
|
|
652
|
+
lowerCased === "contenteditable" ||
|
|
653
|
+
lowerCased === "draggable" ||
|
|
654
|
+
lowerCased === "spellcheck";
|
|
655
|
+
const booleanBranch = booleanishOrData
|
|
656
|
+
? `return ${stringLiteral(` ${name}="`)} + (_value ? "true" : "false") + ${stringLiteral('"')};`
|
|
657
|
+
: `return _value ? ${stringLiteral(` ${name}=""`)} : "";`;
|
|
658
|
+
return `(() => { const _value = (${code}); if (_value == null || typeof _value === "function") return ""; if (typeof _value === "boolean") { ${booleanBranch} } if (typeof _value === "object") return ""; return ${stringLiteral(` ${name}="`)} + ${escapeHelperName}(_value) + ${stringLiteral('"')}; })()`;
|
|
659
|
+
}
|
|
660
|
+
// Mirrors packages/react-compat/src/server-render.ts renderStyleAttribute and
|
|
661
|
+
// renderCssValue: skips null/boolean/empty entries and appends px to nonzero
|
|
662
|
+
// numeric values outside the react unitless list.
|
|
663
|
+
function emitCompatDynamicStyleAttributeExpression(code, escapeHelperName) {
|
|
664
|
+
const unitlessCheck = '_styleName === "flex" || _styleName === "fontWeight" || _styleName === "lineHeight" || _styleName === "opacity" || _styleName === "order" || _styleName === "zIndex" || _styleName === "zoom"';
|
|
665
|
+
return `(() => { const _value = (${code}); if (_value == null || typeof _value !== "object") return ""; let _style = ""; for (const _styleName in _value) { const _styleValue = _value[_styleName]; if (_styleValue == null || typeof _styleValue === "boolean" || _styleValue === "") continue; const _cssName = _styleName.startsWith("--") ? _styleName : _styleName.replace(/[A-Z]/g, (_char) => "-" + _char.toLowerCase()); const _css = typeof _styleValue !== "number" || _styleValue === 0 || (${unitlessCheck}) ? String(_styleValue) : _styleValue + "px"; _style += (_style === "" ? "" : ";") + ${escapeHelperName}(_cssName) + ":" + ${escapeHelperName}(_css); } return _style === "" ? "" : ${stringLiteral(' style="')} + _style + ${stringLiteral('"')}; })()`;
|
|
666
|
+
}
|
|
623
667
|
function emitDynamicStyleAttributeExpression(code, escapeHelperName, escapeBatchHelperName) {
|
|
624
668
|
const staticStyleExpression = emitStaticStyleObjectAttributeExpression(code, escapeHelperName);
|
|
625
669
|
if (staticStyleExpression !== undefined) {
|
|
@@ -704,14 +748,18 @@ function emitBatchedSimpleChildrenExpression(children, escapeBatchHelperName) {
|
|
|
704
748
|
if (escapeBatchHelperName === undefined) {
|
|
705
749
|
return undefined;
|
|
706
750
|
}
|
|
707
|
-
const dynamicChildren = children.filter((child) => child.kind === "expr" &&
|
|
751
|
+
const dynamicChildren = children.filter((child) => child.kind === "expr" &&
|
|
752
|
+
child.renderMode !== "html" &&
|
|
753
|
+
child.renderMode !== "react-node" &&
|
|
754
|
+
child.renderMode !== "compat-child");
|
|
708
755
|
if (dynamicChildren.length < 2) {
|
|
709
756
|
return undefined;
|
|
710
757
|
}
|
|
711
758
|
if (children.some((child) => child.kind !== "text" &&
|
|
712
759
|
!(child.kind === "expr" &&
|
|
713
760
|
child.renderMode !== "html" &&
|
|
714
|
-
child.renderMode !== "react-node"
|
|
761
|
+
child.renderMode !== "react-node" &&
|
|
762
|
+
child.renderMode !== "compat-child"))) {
|
|
715
763
|
return undefined;
|
|
716
764
|
}
|
|
717
765
|
const values = dynamicChildren.map((child) => child.code);
|
|
@@ -885,6 +933,31 @@ function replaceOxcServerStringReactNodeRenderHelper(code, helperName) {
|
|
|
885
933
|
function usesClientBoundary(ir) {
|
|
886
934
|
return ir.components.some((component) => containsClientBoundary(component.root));
|
|
887
935
|
}
|
|
936
|
+
function usesCompatChildRender(ir) {
|
|
937
|
+
return ir.components.some((component) => containsCompatChildRender(component.root));
|
|
938
|
+
}
|
|
939
|
+
function containsCompatChildRender(node) {
|
|
940
|
+
if (node.kind === "expr") {
|
|
941
|
+
return node.renderMode === "compat-child";
|
|
942
|
+
}
|
|
943
|
+
if (node.kind === "conditional") {
|
|
944
|
+
return [...node.whenTrue, ...node.whenFalse].some(containsCompatChildRender);
|
|
945
|
+
}
|
|
946
|
+
if (node.kind === "list" || node.kind === "element" || node.kind === "fragment") {
|
|
947
|
+
return node.children.some(containsCompatChildRender);
|
|
948
|
+
}
|
|
949
|
+
if (node.kind === "async-boundary") {
|
|
950
|
+
return [
|
|
951
|
+
...node.children,
|
|
952
|
+
...(node.placeholderChildren ?? []),
|
|
953
|
+
...(node.catchChildren ?? []),
|
|
954
|
+
].some(containsCompatChildRender);
|
|
955
|
+
}
|
|
956
|
+
if (node.kind === "component") {
|
|
957
|
+
return node.children.some(containsCompatChildRender);
|
|
958
|
+
}
|
|
959
|
+
return false;
|
|
960
|
+
}
|
|
888
961
|
function emitClientBoundaryHelper(name) {
|
|
889
962
|
const propsHelperName = `${name}$hasNonSerializableProps`;
|
|
890
963
|
return [
|