@backtickjs/compiler 0.0.0-stage → 0.1.1

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.
Files changed (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +25 -2
  3. package/dist/CodeInformation.d.ts +8 -0
  4. package/dist/CodeInformation.js +2 -0
  5. package/dist/CodeInformation.js.map +1 -0
  6. package/dist/SourceRange.d.ts +4 -0
  7. package/dist/SourceRange.js +2 -0
  8. package/dist/SourceRange.js.map +1 -0
  9. package/dist/buildMappings.d.ts +10 -0
  10. package/dist/buildMappings.js +21 -0
  11. package/dist/buildMappings.js.map +1 -0
  12. package/dist/compileModule.d.ts +25 -0
  13. package/dist/compileModule.js +78 -0
  14. package/dist/compileModule.js.map +1 -0
  15. package/dist/compileScript.d.ts +24 -0
  16. package/dist/compileScript.js +66 -0
  17. package/dist/compileScript.js.map +1 -0
  18. package/dist/diagnostics.d.ts +8 -0
  19. package/dist/diagnostics.js +2 -0
  20. package/dist/diagnostics.js.map +1 -0
  21. package/dist/emitScript.d.ts +52 -0
  22. package/dist/emitScript.js +201 -0
  23. package/dist/emitScript.js.map +1 -0
  24. package/dist/emitScripts.d.ts +10 -0
  25. package/dist/emitScripts.js +23 -0
  26. package/dist/emitScripts.js.map +1 -0
  27. package/dist/flattenScripts.d.ts +2 -0
  28. package/dist/flattenScripts.js +10 -0
  29. package/dist/flattenScripts.js.map +1 -0
  30. package/dist/hashText.d.ts +1 -0
  31. package/dist/hashText.js +18 -0
  32. package/dist/hashText.js.map +1 -0
  33. package/dist/hostElements.d.ts +3 -0
  34. package/dist/hostElements.js +28 -0
  35. package/dist/hostElements.js.map +1 -0
  36. package/dist/index.d.ts +16 -0
  37. package/dist/index.js +10 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/isComponentTag.d.ts +1 -0
  40. package/dist/isComponentTag.js +15 -0
  41. package/dist/isComponentTag.js.map +1 -0
  42. package/dist/nodeFactory.d.ts +3 -0
  43. package/dist/nodeFactory.js +5 -0
  44. package/dist/nodeFactory.js.map +1 -0
  45. package/dist/parseFile.d.ts +34 -0
  46. package/dist/parseFile.js +200 -0
  47. package/dist/parseFile.js.map +1 -0
  48. package/dist/printVirtualCode.d.ts +9 -0
  49. package/dist/printVirtualCode.js +52 -0
  50. package/dist/printVirtualCode.js.map +1 -0
  51. package/dist/resolveBindings.d.ts +76 -0
  52. package/dist/resolveBindings.js +240 -0
  53. package/dist/resolveBindings.js.map +1 -0
  54. package/dist/rewriteFile.d.ts +12 -0
  55. package/dist/rewriteFile.js +22 -0
  56. package/dist/rewriteFile.js.map +1 -0
  57. package/dist/rewriteScript.d.ts +27 -0
  58. package/dist/rewriteScript.js +268 -0
  59. package/dist/rewriteScript.js.map +1 -0
  60. package/dist/segmentsToString.d.ts +9 -0
  61. package/dist/segmentsToString.js +4 -0
  62. package/dist/segmentsToString.js.map +1 -0
  63. package/dist/tagRoot.d.ts +2 -0
  64. package/dist/tagRoot.js +10 -0
  65. package/dist/tagRoot.js.map +1 -0
  66. package/dist/transform.d.ts +17 -0
  67. package/dist/transform.js +61 -0
  68. package/dist/transform.js.map +1 -0
  69. package/dist/transpile.d.ts +27 -0
  70. package/dist/transpile.js +41 -0
  71. package/dist/transpile.js.map +1 -0
  72. package/dist/unmangle.d.ts +2 -0
  73. package/dist/unmangle.js +9 -0
  74. package/dist/unmangle.js.map +1 -0
  75. package/dist/virtualScript.d.ts +22 -0
  76. package/dist/virtualScript.js +305 -0
  77. package/dist/virtualScript.js.map +1 -0
  78. package/dist/virtualize.d.ts +8 -0
  79. package/dist/virtualize.js +10 -0
  80. package/dist/virtualize.js.map +1 -0
  81. package/package.json +58 -3
  82. package/src/CodeInformation.ts +14 -0
  83. package/src/SourceRange.ts +4 -0
  84. package/src/buildMappings.ts +31 -0
  85. package/src/compileModule.ts +132 -0
  86. package/src/compileScript.ts +97 -0
  87. package/src/diagnostics.ts +9 -0
  88. package/src/emitScript.ts +297 -0
  89. package/src/emitScripts.ts +39 -0
  90. package/src/flattenScripts.ts +13 -0
  91. package/src/hashText.ts +17 -0
  92. package/src/hostElements.ts +34 -0
  93. package/src/index.ts +20 -0
  94. package/src/isComponentTag.ts +15 -0
  95. package/src/nodeFactory.ts +18 -0
  96. package/src/parseFile.ts +331 -0
  97. package/src/printVirtualCode.ts +93 -0
  98. package/src/resolveBindings.ts +417 -0
  99. package/src/rewriteFile.ts +52 -0
  100. package/src/rewriteScript.ts +413 -0
  101. package/src/segmentsToString.ts +16 -0
  102. package/src/tagRoot.ts +14 -0
  103. package/src/transform.ts +96 -0
  104. package/src/transpile.ts +49 -0
  105. package/src/unmangle.ts +10 -0
  106. package/src/virtualScript.ts +355 -0
  107. package/src/virtualize.ts +29 -0
@@ -0,0 +1,23 @@
1
+ import { compileScript, } from "./compileScript.js";
2
+ import { parseSourceText } from "./parseFile.js";
3
+ import { rewriteFile } from "./rewriteFile.js";
4
+ /**
5
+ * What each of a file's scripts compiles to for the client, in source order:
6
+ * nested scripts too, each as its own entry.
7
+ */
8
+ export function emitScripts(ts, fileName, sourceText,
9
+ // Its framework's compile steps (see `TransformOptions.plugins`).
10
+ plugins = []) {
11
+ const file = rewriteFile(ts, parseSourceText(ts, fileName, sourceText));
12
+ return Array.from(file.scripts)
13
+ .flatMap(([template, { runtime }]) => runtime === null
14
+ ? []
15
+ : [
16
+ {
17
+ start: template.getStart(file.sourceFile),
18
+ ...compileScript(ts, runtime.emitted, fileName, plugins),
19
+ },
20
+ ])
21
+ .sort((a, b) => a.start - b.start);
22
+ }
23
+ //# sourceMappingURL=emitScripts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitScripts.js","sourceRoot":"","sources":["../src/emitScripts.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,aAAa,GAEd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAQ/C;;;GAGG;AACH,MAAM,UAAU,WAAW,CACzB,EAA+B,EAC/B,QAAgB,EAChB,UAAkB;AAClB,kEAAkE;AAClE,UAA6B,EAAE;IAE/B,MAAM,IAAI,GAAG,WAAW,CAAC,EAAE,EAAE,eAAe,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;IACxE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;SAC5B,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,CACnC,OAAO,KAAK,IAAI;QACd,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC;YACE;gBACE,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC;gBACzC,GAAG,aAAa,CAAC,EAAE,EAAE,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC;aACzD;SACF,CACN;SACA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { ClientScript } from "./parseFile.js";
2
+ export declare function flattenScripts(scripts: ClientScript[]): Generator<ClientScript>;
@@ -0,0 +1,10 @@
1
+ // Yields every client script in the file, descending through splices
2
+ export function* flattenScripts(scripts) {
3
+ for (const script of scripts) {
4
+ yield script;
5
+ for (const splice of Object.values(script.splices)) {
6
+ yield* flattenScripts(splice.scripts);
7
+ }
8
+ }
9
+ }
10
+ //# sourceMappingURL=flattenScripts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flattenScripts.js","sourceRoot":"","sources":["../src/flattenScripts.ts"],"names":[],"mappings":"AAEA,qEAAqE;AACrE,MAAM,SAAS,CAAC,CAAC,cAAc,CAC7B,OAAuB;IAEvB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,MAAM,CAAC;QACb,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,KAAK,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function hashText(input: string): string;
@@ -0,0 +1,18 @@
1
+ // 64-bit FNV-1a over the file's text: the per-file content hash that makes
2
+ // compiler output globally distinguishable. The compiler runs one file at a
3
+ // time and cannot hand out coordinated identifiers, and a file's path alone
4
+ // can recur across codebases (two packages each compiled against their own
5
+ // root), so both binding keys and script locations carry this hash. At 64
6
+ // bits an accidental collision between different files is out of reach
7
+ // (the birthday bound sits around four billion files), so a collision
8
+ // implies identical file content, where sharing is correct rather than a
9
+ // mixup.
10
+ export function hashText(input) {
11
+ let hash = 0xcbf29ce484222325n;
12
+ for (let i = 0; i < input.length; i++) {
13
+ hash ^= BigInt(input.charCodeAt(i));
14
+ hash = (hash * 0x100000001b3n) & 0xffffffffffffffffn;
15
+ }
16
+ return hash.toString(36);
17
+ }
18
+ //# sourceMappingURL=hashText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hashText.js","sourceRoot":"","sources":["../src/hashText.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,4EAA4E;AAC5E,4EAA4E;AAC5E,2EAA2E;AAC3E,0EAA0E;AAC1E,uEAAuE;AACvE,sEAAsE;AACtE,yEAAyE;AACzE,SAAS;AACT,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,IAAI,IAAI,GAAG,mBAAmB,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC,GAAG,mBAAmB,CAAC;IACvD,CAAC;IACD,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type ts from "typescript";
2
+ import type { Diagnostic } from "./diagnostics.js";
3
+ export declare function hostElementDiagnostics(ts: typeof import("typescript"), sourceFile: ts.SourceFile): Diagnostic[];
@@ -0,0 +1,28 @@
1
+ import { isComponentTag } from "./isComponentTag.js";
2
+ // Each element written in host code: an intrinsic element is drawn by the
3
+ // client, so it belongs in a script. Every JSX node TypeScript parsed is the
4
+ // host's, a splice's included, as a script's JSX is text in its template.
5
+ export function hostElementDiagnostics(ts, sourceFile) {
6
+ const diagnostics = [];
7
+ const visit = (node) => {
8
+ if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
9
+ const { tagName } = node;
10
+ const name = tagName.getText(sourceFile);
11
+ // A member read (`ui.button`) is a value, whatever its case.
12
+ const named = ts.isIdentifier(tagName) || ts.isJsxNamespacedName(tagName);
13
+ if (named && !isComponentTag(name)) {
14
+ diagnostics.push({
15
+ range: { start: tagName.getStart(sourceFile), end: tagName.getEnd() },
16
+ message: `\`<${name}>\` is drawn by the client, so it belongs in a ` +
17
+ `script: cs\`<${name}>…</${name}>\`.`,
18
+ category: ts.DiagnosticCategory.Error,
19
+ code: 0,
20
+ });
21
+ }
22
+ }
23
+ ts.forEachChild(node, visit);
24
+ };
25
+ visit(sourceFile);
26
+ return diagnostics;
27
+ }
28
+ //# sourceMappingURL=hostElements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostElements.js","sourceRoot":"","sources":["../src/hostElements.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,0EAA0E;AAC1E,6EAA6E;AAC7E,0EAA0E;AAC1E,MAAM,UAAU,sBAAsB,CACpC,EAA+B,EAC/B,UAAyB;IAEzB,MAAM,WAAW,GAAiB,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,CAAC,IAAa,EAAQ,EAAE;QACpC,IAAI,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,uBAAuB,CAAC,IAAI,CAAC,EAAE,CAAC;YACrE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;YACzB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACzC,6DAA6D;YAC7D,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;YAC1E,IAAI,KAAK,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnC,WAAW,CAAC,IAAI,CAAC;oBACf,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE;oBACrE,OAAO,EACL,MAAM,IAAI,iDAAiD;wBAC3D,gBAAgB,IAAI,OAAO,IAAI,MAAM;oBACvC,QAAQ,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK;oBACrC,IAAI,EAAE,CAAC;iBACR,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC,CAAC;IACF,KAAK,CAAC,UAAU,CAAC,CAAC;IAClB,OAAO,WAAW,CAAC;AACrB,CAAC"}
@@ -0,0 +1,16 @@
1
+ export type { SourceMapping } from "./buildMappings.js";
2
+ export type { CodeInformation } from "./CodeInformation.js";
3
+ export type { Diagnostic } from "./diagnostics.js";
4
+ export type { EmittedScript } from "./emitScript.js";
5
+ export { emitScripts, type EmittedScriptAt } from "./emitScripts.js";
6
+ export { flattenScripts } from "./flattenScripts.js";
7
+ export type { ClientScript, ParsedFile, Splice } from "./parseFile.js";
8
+ export { parseSourceFile, parseSourceText } from "./parseFile.js";
9
+ export { type ResolvedParam, resolveBindings } from "./resolveBindings.js";
10
+ export type { Plugin } from "./compileScript.js";
11
+ export { type CompileModuleOptions, compileModule, pluginsFrom, } from "./compileModule.js";
12
+ export { type TransformOptions, transform } from "./transform.js";
13
+ export { transpile } from "./transpile.js";
14
+ export { mangle, unmangle } from "./unmangle.js";
15
+ export type { Virtualized } from "./virtualize.js";
16
+ export { virtualize } from "./virtualize.js";
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export { emitScripts } from "./emitScripts.js";
2
+ export { flattenScripts } from "./flattenScripts.js";
3
+ export { parseSourceFile, parseSourceText } from "./parseFile.js";
4
+ export { resolveBindings } from "./resolveBindings.js";
5
+ export { compileModule, pluginsFrom, } from "./compileModule.js";
6
+ export { transform } from "./transform.js";
7
+ export { transpile } from "./transpile.js";
8
+ export { mangle, unmangle } from "./unmangle.js";
9
+ export { virtualize } from "./virtualize.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAwB,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAsB,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAEL,aAAa,EACb,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAyB,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function isComponentTag(tagName: string): boolean;
@@ -0,0 +1,15 @@
1
+ // Whether a tag names a component rather than one of the target's elements.
2
+ //
3
+ // TypeScript's own rule, spelled out because it does not publish it (`ts`'s
4
+ // `isIntrinsicJsxName` is internal): a name starting lowercase, or holding a
5
+ // `-` or a `:`, is the target's, and anything else is a value in scope. Written
6
+ // here so a tag reads the same to the compiler as it does to the checker, which
7
+ // applies this rule to the virtual code.
8
+ export function isComponentTag(tagName) {
9
+ const first = tagName.charCodeAt(0);
10
+ const intrinsic = (first >= 0x61 /* a */ && first <= 0x7a) /* z */ ||
11
+ tagName.includes("-") ||
12
+ tagName.includes(":");
13
+ return !intrinsic;
14
+ }
15
+ //# sourceMappingURL=isComponentTag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isComponentTag.js","sourceRoot":"","sources":["../src/isComponentTag.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,EAAE;AACF,4EAA4E;AAC5E,6EAA6E;AAC7E,gFAAgF;AAChF,gFAAgF;AAChF,yCAAyC;AACzC,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,SAAS,GACb,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO;QAChD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QACrB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACxB,OAAO,CAAC,SAAS,CAAC;AACpB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type ts from "typescript";
2
+ /** <receiver>.<method>(...args) */
3
+ export declare function call(ts: typeof import("typescript"), receiver: string, method: string, args: ts.Expression[]): ts.CallExpression;
@@ -0,0 +1,5 @@
1
+ /** <receiver>.<method>(...args) */
2
+ export function call(ts, receiver, method, args) {
3
+ return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(receiver), method), undefined, args);
4
+ }
5
+ //# sourceMappingURL=nodeFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeFactory.js","sourceRoot":"","sources":["../src/nodeFactory.ts"],"names":[],"mappings":"AAEA,mCAAmC;AACnC,MAAM,UAAU,IAAI,CAClB,EAA+B,EAC/B,QAAgB,EAChB,MAAc,EACd,IAAqB;IAErB,OAAO,EAAE,CAAC,OAAO,CAAC,oBAAoB,CACpC,EAAE,CAAC,OAAO,CAAC,8BAA8B,CACvC,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EACrC,MAAM,CACP,EACD,SAAS,EACT,IAAI,CACL,CAAC;AACJ,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type ts from "typescript";
2
+ import type { SourceRange } from "./SourceRange.js";
3
+ export interface ParsedFile {
4
+ sourceFile: ts.SourceFile;
5
+ scripts: ClientScript[];
6
+ }
7
+ export interface ClientScript {
8
+ sourceFile: ts.SourceFile;
9
+ sourceNode: ts.TaggedTemplateExpression;
10
+ textWithPlaceholders: string;
11
+ fileWithPlaceholders: ts.SourceFile;
12
+ splices: {
13
+ [placeholder: string]: Splice;
14
+ };
15
+ toSourceRange: (node: ts.Node) => SourceRange;
16
+ toSourceOffset: (offset: number) => number;
17
+ }
18
+ export type Splice = BracedSplice | UnbracedSplice;
19
+ export interface BracedSplice {
20
+ kind: "braced";
21
+ expression: ts.Expression;
22
+ key: string;
23
+ scripts: ClientScript[];
24
+ refs: ts.Identifier[];
25
+ }
26
+ export interface UnbracedSplice {
27
+ kind: "unbraced";
28
+ expression: ts.Identifier;
29
+ key: string;
30
+ scripts: [];
31
+ refs: ts.Identifier[];
32
+ }
33
+ export declare function parseSourceText(ts: typeof import("typescript"), filePath: string, sourceText: string): ParsedFile;
34
+ export declare function parseSourceFile(ts: typeof import("typescript"), sourceFile: ts.SourceFile): ParsedFile;
@@ -0,0 +1,200 @@
1
+ export function parseSourceText(ts, filePath, sourceText) {
2
+ const sourceFile = ts.createSourceFile(filePath, sourceText, ts.ScriptTarget.Latest, true);
3
+ return parseSourceFile(ts, sourceFile);
4
+ }
5
+ export function parseSourceFile(ts, sourceFile) {
6
+ const scripts = getDirectScripts(ts, null, sourceFile);
7
+ return { sourceFile, scripts };
8
+ }
9
+ function getDirectScripts(ts, parent, sourceFile) {
10
+ const node = parent ? parent.expression : sourceFile;
11
+ const taggedTemplates = [];
12
+ const visit = (current) => {
13
+ if (ts.isTaggedTemplateExpression(current) &&
14
+ ts.isIdentifier(current.tag) &&
15
+ current.tag.text === "cs") {
16
+ taggedTemplates.push(current);
17
+ }
18
+ else {
19
+ current.forEachChild(visit);
20
+ }
21
+ };
22
+ visit(node);
23
+ const scripts = [];
24
+ taggedTemplates.forEach((taggedTemplate) => {
25
+ const { textWithPlaceholders, mappings } = toTextWithPlaceholders(ts, taggedTemplate, sourceFile);
26
+ const fileWithPlaceholders = ts.createSourceFile(sourceFile.fileName, textWithPlaceholders, ts.ScriptTarget.Latest, true);
27
+ // The dictionary's insertion order is evaluation order: emitted as the
28
+ // script's `params` array literal, the splices' host expressions run
29
+ // first to last when the `cs` expression itself evaluates — left to
30
+ // right in source order, like a real template literal's spans.
31
+ const splices = getDirectSplices(ts, taggedTemplate, sourceFile, fileWithPlaceholders);
32
+ const toSourceRange = (node) => ({
33
+ start: toSourceOffset(mappings, node.getStart(fileWithPlaceholders)),
34
+ end: toSourceOffset(mappings, node.getEnd()),
35
+ });
36
+ scripts.push({
37
+ sourceFile,
38
+ sourceNode: taggedTemplate,
39
+ textWithPlaceholders,
40
+ fileWithPlaceholders,
41
+ toSourceRange,
42
+ toSourceOffset: (offset) => toSourceOffset(mappings, offset),
43
+ splices,
44
+ });
45
+ });
46
+ return scripts;
47
+ }
48
+ // A splice per first reference in the placeholder text, in source order, and
49
+ // every reference to it: a `$0splice<n>` placeholder resolves to its template
50
+ // span's braced splice, and any other `$x` identifier mints an unbraced
51
+ // splice, deduplicated by spelling. Property, attribute and declaration names
52
+ // are not references (a `$`-prefixed declaration is rejected at rewrite time),
53
+ // and nested scripts are already placeholders in this text, so the walk scans
54
+ // only the script's own body.
55
+ function getDirectSplices(ts, taggedTemplate, sourceFile, fileWithPlaceholders) {
56
+ // No prototype: a script's `valueOf` or `constructor` is no splice.
57
+ const splices = Object.create(null);
58
+ const template = taggedTemplate.template;
59
+ const spans = ts.isTemplateExpression(template) ? template.templateSpans : [];
60
+ const visit = (node) => {
61
+ if (ts.isPropertyAccessExpression(node)) {
62
+ visit(node.expression); // the name is not a reference
63
+ return;
64
+ }
65
+ if (ts.isPropertyAssignment(node)) {
66
+ if (ts.isComputedPropertyName(node.name)) {
67
+ visit(node.name);
68
+ }
69
+ visit(node.initializer);
70
+ return;
71
+ }
72
+ if (ts.isVariableDeclaration(node) ||
73
+ ts.isParameter(node) ||
74
+ ts.isBindingElement(node)) {
75
+ if (node.initializer) {
76
+ visit(node.initializer);
77
+ }
78
+ return;
79
+ }
80
+ if (ts.isJsxAttribute(node)) {
81
+ if (node.initializer) {
82
+ visit(node.initializer); // the name is not a reference
83
+ }
84
+ return;
85
+ }
86
+ if (ts.isCatchClause(node)) {
87
+ visit(node.block); // the catch binding is not a reference
88
+ return;
89
+ }
90
+ if (ts.isIdentifier(node) && splices[node.text] != null) {
91
+ splices[node.text].refs.push(node);
92
+ return;
93
+ }
94
+ if (ts.isIdentifier(node) &&
95
+ node.text.startsWith("$") &&
96
+ node.text.length > 1) {
97
+ const key = node.text;
98
+ if (key.startsWith("$0splice")) {
99
+ // The numeric suffix indexes the template's spans. A `$0splice`
100
+ // spelling that resolves to no span (`$0spliceFoo`, an out-of-range
101
+ // index) is no splice at all — and no host binding either, since a
102
+ // name can't start with `$0`.
103
+ const index = Number(key.slice("$0splice".length));
104
+ const span = spans[index];
105
+ if (span != null) {
106
+ const splice = {
107
+ kind: "braced",
108
+ expression: span.expression,
109
+ key,
110
+ scripts: [],
111
+ refs: [node],
112
+ };
113
+ splices[key] = splice;
114
+ splice.scripts = getDirectScripts(ts, splice, sourceFile);
115
+ }
116
+ }
117
+ else {
118
+ splices[key] = {
119
+ kind: "unbraced",
120
+ expression: ts.factory.createIdentifier(key.slice(1)),
121
+ key,
122
+ scripts: [],
123
+ refs: [node],
124
+ };
125
+ }
126
+ return;
127
+ }
128
+ node.forEachChild(visit);
129
+ };
130
+ visit(fileWithPlaceholders);
131
+ return splices;
132
+ }
133
+ function toTextWithPlaceholders(ts, taggedTemplate, sourceFile) {
134
+ const sourceText = sourceFile.text;
135
+ const template = taggedTemplate.template;
136
+ const start = template.getStart(sourceFile) + 1; // past `
137
+ const end = template.getEnd() - 1; // before `
138
+ let textWithPlaceholders = "";
139
+ const mappings = [];
140
+ if (ts.isNoSubstitutionTemplateLiteral(template)) {
141
+ textWithPlaceholders = sourceText.slice(start, end);
142
+ mappings.push({
143
+ placeholderStart: 0,
144
+ length: textWithPlaceholders.length,
145
+ sourceStart: start,
146
+ verbatim: true,
147
+ });
148
+ }
149
+ else {
150
+ let chunkStart = start;
151
+ template.templateSpans.forEach((span, index) => {
152
+ const placeholder = `$0splice${index}`;
153
+ const dollarBrace = span.expression.getFullStart() - 2; // before ${
154
+ const chunk = sourceText.slice(chunkStart, dollarBrace);
155
+ mappings.push({
156
+ placeholderStart: textWithPlaceholders.length,
157
+ length: chunk.length,
158
+ sourceStart: chunkStart,
159
+ verbatim: true,
160
+ });
161
+ textWithPlaceholders += chunk;
162
+ mappings.push({
163
+ placeholderStart: textWithPlaceholders.length,
164
+ length: placeholder.length,
165
+ sourceStart: dollarBrace,
166
+ verbatim: false,
167
+ });
168
+ textWithPlaceholders += placeholder;
169
+ chunkStart = span.literal.getStart(sourceFile) + 1; // past }
170
+ });
171
+ const tail = sourceText.slice(chunkStart, end);
172
+ mappings.push({
173
+ placeholderStart: textWithPlaceholders.length,
174
+ length: tail.length,
175
+ sourceStart: chunkStart,
176
+ verbatim: true,
177
+ });
178
+ textWithPlaceholders += tail;
179
+ }
180
+ return { textWithPlaceholders, mappings };
181
+ }
182
+ function toSourceOffset(mappings, pos) {
183
+ for (const mapping of mappings) {
184
+ if (mapping.verbatim &&
185
+ pos >= mapping.placeholderStart &&
186
+ pos <= mapping.placeholderStart + mapping.length) {
187
+ return mapping.sourceStart + (pos - mapping.placeholderStart);
188
+ }
189
+ }
190
+ for (const mapping of mappings) {
191
+ if (!mapping.verbatim &&
192
+ pos >= mapping.placeholderStart &&
193
+ pos <= mapping.placeholderStart + mapping.length) {
194
+ return mapping.sourceStart;
195
+ }
196
+ }
197
+ const last = mappings[mappings.length - 1];
198
+ return last.sourceStart + last.length;
199
+ }
200
+ //# sourceMappingURL=parseFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseFile.js","sourceRoot":"","sources":["../src/parseFile.ts"],"names":[],"mappings":"AA0DA,MAAM,UAAU,eAAe,CAC7B,EAA+B,EAC/B,QAAgB,EAChB,UAAkB;IAElB,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,CACpC,QAAQ,EACR,UAAU,EACV,EAAE,CAAC,YAAY,CAAC,MAAM,EACtB,IAAI,CACL,CAAC;IACF,OAAO,eAAe,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,EAA+B,EAC/B,UAAyB;IAEzB,MAAM,OAAO,GAAG,gBAAgB,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IACvD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,gBAAgB,CACvB,EAA+B,EAC/B,MAAqB,EACrB,UAAyB;IAEzB,MAAM,IAAI,GAAY,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;IAC9D,MAAM,eAAe,GAAkC,EAAE,CAAC;IAE1D,MAAM,KAAK,GAAG,CAAC,OAAgB,EAAQ,EAAE;QACvC,IACE,EAAE,CAAC,0BAA0B,CAAC,OAAO,CAAC;YACtC,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,IAAI,KAAK,IAAI,EACzB,CAAC;YACD,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,CAAC;IAEZ,MAAM,OAAO,GAAmB,EAAE,CAAC;IAEnC,eAAe,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE,EAAE;QACzC,MAAM,EAAE,oBAAoB,EAAE,QAAQ,EAAE,GAAG,sBAAsB,CAC/D,EAAE,EACF,cAAc,EACd,UAAU,CACX,CAAC;QACF,MAAM,oBAAoB,GAAG,EAAE,CAAC,gBAAgB,CAC9C,UAAU,CAAC,QAAQ,EACnB,oBAAoB,EACpB,EAAE,CAAC,YAAY,CAAC,MAAM,EACtB,IAAI,CACL,CAAC;QACF,uEAAuE;QACvE,qEAAqE;QACrE,oEAAoE;QACpE,+DAA+D;QAC/D,MAAM,OAAO,GAAG,gBAAgB,CAC9B,EAAE,EACF,cAAc,EACd,UAAU,EACV,oBAAoB,CACrB,CAAC;QACF,MAAM,aAAa,GAAG,CAAC,IAAa,EAAe,EAAE,CAAC,CAAC;YACrD,KAAK,EAAE,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;YACpE,GAAG,EAAE,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;SAC7C,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC;YACX,UAAU;YACV,UAAU,EAAE,cAAc;YAC1B,oBAAoB;YACpB,oBAAoB;YACpB,aAAa;YACb,cAAc,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC;YAC5D,OAAO;SACR,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,6EAA6E;AAC7E,8EAA8E;AAC9E,wEAAwE;AACxE,8EAA8E;AAC9E,+EAA+E;AAC/E,8EAA8E;AAC9E,8BAA8B;AAC9B,SAAS,gBAAgB,CACvB,EAA+B,EAC/B,cAA2C,EAC3C,UAAyB,EACzB,oBAAmC;IAEnC,oEAAoE;IACpE,MAAM,OAAO,GAAsC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAEvE,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC;IACzC,MAAM,KAAK,GAAG,EAAE,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;IAE9E,MAAM,KAAK,GAAG,CAAC,IAAa,EAAQ,EAAE;QACpC,IAAI,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,8BAA8B;YACtD,OAAO;QACT,CAAC;QACD,IAAI,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,IAAI,EAAE,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACxB,OAAO;QACT,CAAC;QACD,IACE,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC;YAC9B,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC;YACpB,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EACzB,CAAC;YACD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC1B,CAAC;YACD,OAAO;QACT,CAAC;QACD,IAAI,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,8BAA8B;YACzD,CAAC;YACD,OAAO;QACT,CAAC;QACD,IAAI,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,uCAAuC;YAC1D,OAAO;QACT,CAAC;QACD,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpC,OAAO;QACT,CAAC;QACD,IACE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EACpB,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC;YACtB,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/B,gEAAgE;gBAChE,oEAAoE;gBACpE,mEAAmE;gBACnE,8BAA8B;gBAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;gBACnD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC1B,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;oBACjB,MAAM,MAAM,GAAiB;wBAC3B,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE,IAAI,CAAC,UAAU;wBAC3B,GAAG;wBACH,OAAO,EAAE,EAAE;wBACX,IAAI,EAAE,CAAC,IAAI,CAAC;qBACb,CAAC;oBACF,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;oBACtB,MAAM,CAAC,OAAO,GAAG,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;gBAC5D,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,GAAG;oBACb,IAAI,EAAE,UAAU;oBAChB,UAAU,EAAE,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBACrD,GAAG;oBACH,OAAO,EAAE,EAAE;oBACX,IAAI,EAAE,CAAC,IAAI,CAAC;iBACb,CAAC;YACJ,CAAC;YACD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC,CAAC;IACF,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAE5B,OAAO,OAAO,CAAC;AACjB,CAAC;AASD,SAAS,sBAAsB,CAC7B,EAA+B,EAC/B,cAA2C,EAC3C,UAAyB;IAKzB,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC;IACnC,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC;IAEzC,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;IAC1D,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,WAAW;IAE9C,IAAI,oBAAoB,GAAG,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAoB,EAAE,CAAC;IAErC,IAAI,EAAE,CAAC,+BAA+B,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjD,oBAAoB,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACpD,QAAQ,CAAC,IAAI,CAAC;YACZ,gBAAgB,EAAE,CAAC;YACnB,MAAM,EAAE,oBAAoB,CAAC,MAAM;YACnC,WAAW,EAAE,KAAK;YAClB,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,IAAI,UAAU,GAAG,KAAK,CAAC;QAEvB,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YAC7C,MAAM,WAAW,GAAG,WAAW,KAAK,EAAE,CAAC;YACvC,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,YAAY;YACpE,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;YACxD,QAAQ,CAAC,IAAI,CAAC;gBACZ,gBAAgB,EAAE,oBAAoB,CAAC,MAAM;gBAC7C,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,WAAW,EAAE,UAAU;gBACvB,QAAQ,EAAE,IAAI;aACf,CAAC,CAAC;YACH,oBAAoB,IAAI,KAAK,CAAC;YAC9B,QAAQ,CAAC,IAAI,CAAC;gBACZ,gBAAgB,EAAE,oBAAoB,CAAC,MAAM;gBAC7C,MAAM,EAAE,WAAW,CAAC,MAAM;gBAC1B,WAAW,EAAE,WAAW;gBACxB,QAAQ,EAAE,KAAK;aAChB,CAAC,CAAC;YACH,oBAAoB,IAAI,WAAW,CAAC;YACpC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;QAC/D,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QAC/C,QAAQ,CAAC,IAAI,CAAC;YACZ,gBAAgB,EAAE,oBAAoB,CAAC,MAAM;YAC7C,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,WAAW,EAAE,UAAU;YACvB,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QACH,oBAAoB,IAAI,IAAI,CAAC;IAC/B,CAAC;IAED,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,CAAC;AAC5C,CAAC;AAED,SAAS,cAAc,CAAC,QAAyB,EAAE,GAAW;IAC5D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IACE,OAAO,CAAC,QAAQ;YAChB,GAAG,IAAI,OAAO,CAAC,gBAAgB;YAC/B,GAAG,IAAI,OAAO,CAAC,gBAAgB,GAAG,OAAO,CAAC,MAAM,EAChD,CAAC;YACD,OAAO,OAAO,CAAC,WAAW,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IACE,CAAC,OAAO,CAAC,QAAQ;YACjB,GAAG,IAAI,OAAO,CAAC,gBAAgB;YAC/B,GAAG,IAAI,OAAO,CAAC,gBAAgB,GAAG,OAAO,CAAC,MAAM,EAChD,CAAC;YACD,OAAO,OAAO,CAAC,WAAW,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3C,OAAO,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;AACxC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type SourceMapping } from "./buildMappings.js";
2
+ import type { ParsedFile } from "./parseFile.js";
3
+ import type { RewrittenFile } from "./rewriteFile.js";
4
+ interface VirtualizedFile {
5
+ virtualCode: string;
6
+ mappings: SourceMapping[];
7
+ }
8
+ export declare function printVirtualCode(ts: typeof import("typescript"), parsedFile: ParsedFile, rewrittenFile: RewrittenFile): VirtualizedFile;
9
+ export {};
@@ -0,0 +1,52 @@
1
+ import { buildMappings } from "./buildMappings.js";
2
+ import { segmentsToString } from "./segmentsToString.js";
3
+ import { virtualScript } from "./virtualScript.js";
4
+ export function printVirtualCode(ts, parsedFile, rewrittenFile) {
5
+ const { sourceFile } = parsedFile;
6
+ const segments = [];
7
+ let cursor = 0;
8
+ for (const script of parsedFile.scripts) {
9
+ const start = script.sourceNode.getStart(sourceFile);
10
+ segments.push(...renderVerbatim(sourceFile.text, cursor, start - cursor));
11
+ segments.push(...renderScript(ts, sourceFile, rewrittenFile, script));
12
+ cursor = script.sourceNode.getEnd();
13
+ }
14
+ segments.push(...renderVerbatim(sourceFile.text, cursor, sourceFile.text.length - cursor));
15
+ return {
16
+ virtualCode: segmentsToString(segments),
17
+ mappings: buildMappings(segments),
18
+ };
19
+ }
20
+ function renderScript(ts, sourceFile, rewrittenFile, script) {
21
+ const rewritten = rewrittenFile.scripts.get(script.sourceNode);
22
+ if (rewritten === undefined) {
23
+ return [];
24
+ }
25
+ // Left as written, its errors already said: `never` fits wherever it
26
+ // stands, so nothing else is reported for it.
27
+ if (rewritten.leftAsWritten) {
28
+ return ["cs.lift(undefined as never)"];
29
+ }
30
+ return virtualScript(ts, script, rewrittenFile.bindings, rewritten.awaits, (splice) => renderSplice(ts, sourceFile, rewrittenFile, splice));
31
+ }
32
+ function renderSplice(ts, sourceFile, rewrittenFile, splice) {
33
+ const segments = [];
34
+ const expression = splice.expression;
35
+ const end = expression.getEnd();
36
+ let cursor = expression.getStart(sourceFile);
37
+ for (const nested of splice.scripts) {
38
+ const start = nested.sourceNode.getStart(sourceFile);
39
+ segments.push(...renderVerbatim(sourceFile.text, cursor, start - cursor));
40
+ segments.push(...renderScript(ts, sourceFile, rewrittenFile, nested));
41
+ cursor = nested.sourceNode.getEnd();
42
+ }
43
+ segments.push(...renderVerbatim(sourceFile.text, cursor, end - cursor));
44
+ return segments;
45
+ }
46
+ function renderVerbatim(sourceText, start, length) {
47
+ if (length <= 0) {
48
+ return [];
49
+ }
50
+ return [[sourceText.slice(start, start + length), undefined, start, length]];
51
+ }
52
+ //# sourceMappingURL=printVirtualCode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"printVirtualCode.js","sourceRoot":"","sources":["../src/printVirtualCode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import type ts from "typescript";
2
+ import type { ClientScript } from "./parseFile.js";
3
+ /**
4
+ * Every client script in a file, its scopes resolved by TypeScript's checker,
5
+ * so any syntax TypeScript reads is resolved as the language does. It produces
6
+ * two things:
7
+ *
8
+ * - `bindings`: every *bound* variable identifier — a declaration, an arrow
9
+ * parameter, or a reference that resolves to one of those — mapped to a
10
+ * stable, globally unique binding key: what a capture is threaded by, and
11
+ * what the virtual code renames a script's own bindings from.
12
+ *
13
+ * - `params`: for each script, its parameters in order (see `ResolvedParam`):
14
+ *
15
+ * - each splice it reads, a tag's (`<$Card>`) among them, with where it
16
+ * reads it and `bindings`: the script's own bindings a fragment landing
17
+ * at that hole can reach, what the hole must hand whatever arrives.
18
+ * Unlike counting what actually reached a hole in one bundle, it is a
19
+ * fact about the script alone.
20
+ * - each capture: a free variable it references but does not itself
21
+ * declare, which it must capture from the enclosing scope, as a binding
22
+ * key. Captures are ordered by first use, which falls out of the
23
+ * source-order walk. A name bound by no script at all is not a capture:
24
+ * the rewrite reads it as a global or reports it as unresolvable.
25
+ *
26
+ * Two filters, and both matter. Declared *above* the hole, not merely in
27
+ * scope: a hoisted declaration is in scope before the source reaches it,
28
+ * and handing it over would name a binding inside its own initializer. And
29
+ * captured by something, somewhere: a binding no fragment ever wants is
30
+ * dead weight in every thunk written for that hole.
31
+ *
32
+ * Scripts are checked as one text: each written `(() => …)`, a nested script
33
+ * where its placeholder stands, as it lands at runtime. A reference is free
34
+ * for the script it appears in exactly when the binding it resolves to was
35
+ * declared in an *enclosing* script (or in none at all).
36
+ *
37
+ * Uniqueness of keys has two axes. A per-file counter distinguishes bindings
38
+ * *within* a file; a hash of the file's text (see `hashText`) distinguishes
39
+ * bindings *across* files — necessary because the compiler runs one file at a
40
+ * time and so cannot hand out globally coordinated numbers. Together
41
+ * `<name>$<fileHash>$<n>` is
42
+ * unique across the whole program, so fragments composed from different scripts
43
+ * (even different files) never collide, and the serializer never has to rename a
44
+ * capture to dodge a same-named binding it threads through.
45
+ *
46
+ * Resolution spans scripts: a reference in a nested script
47
+ * (`cs`{ const x = 0; return ${cs`x`}; }``) resolves to the enclosing binding
48
+ * and so shares its key, keeping independently rewritten scripts consistent. A
49
+ * splice placeholder is not a variable — it evaluates host code in the enclosing
50
+ * scope — so it is never captured, though the pass descends into any scripts
51
+ * nested inside it so their references resolve against this scope chain.
52
+ */
53
+ export type BindingResolution = Map<ts.Identifier, string>;
54
+ export interface ResolvedScopes {
55
+ bindings: BindingResolution;
56
+ params: Map<ClientScript, ResolvedParam[]>;
57
+ }
58
+ /**
59
+ * One of a script's parameters as the compiler knows it: `ClientScript`'s `Param`,
60
+ * with the splice's key and where it is read in place of its host value.
61
+ * `refs` are a hole's placeholder, or an unbraced `$name`, a tag's name among
62
+ * them.
63
+ */
64
+ export type ResolvedParam = ResolvedSplice | ResolvedCapture;
65
+ interface ResolvedSplice {
66
+ kind: "splice";
67
+ key: string;
68
+ bindings: string[];
69
+ refs: ts.Identifier[];
70
+ }
71
+ interface ResolvedCapture {
72
+ kind: "capture";
73
+ key: string;
74
+ }
75
+ export declare function resolveBindings(ts: typeof import("typescript"), scripts: ClientScript[], fileHash: string): ResolvedScopes;
76
+ export {};