···7575 }
76767777 for (const [id, func] of Object.entries(entry)) {
7878+ if (func.__moonlight === true) continue;
7879 let moduleString = Object.hasOwn(moduleCache, id)
7980 ? moduleCache[id]
8081 : func.toString().replace(/\n/g, "");
···150151 }
151152 }
152153153153- let parsed = moonlight.lunast.parseScript(id, `(${moduleString})`);
154154- if (parsed != null) {
155155- // parseScript adds an extra ; for some reason
156156- parsed = parsed.trimEnd().substring(0, parsed.lastIndexOf(";"));
157157- if (patchModule(id, "lunast", parsed)) {
158158- moduleString = parsed;
154154+ try {
155155+ let parsed = moonlight.lunast.parseScript(id, `(\n${moduleString}\n)`);
156156+ if (parsed != null) {
157157+ // parseScript adds an extra ; for some reason
158158+ parsed = parsed.trimEnd().substring(0, parsed.lastIndexOf(";"));
159159+ if (patchModule(id, "lunast", parsed)) {
160160+ moduleString = parsed;
161161+ }
159162 }
163163+ } catch (e) {
164164+ logger.error("Failed to parse script for LunAST", id, e);
160165 }
161166162167 if (moonlightNode.config.patchAll === true) {
+4
packages/lunast/TODO.md
···2233- [ ] Experiment more! We need to know what's bad with this
44- [ ] Write utility functions for imports, exports, etc.
55+ - [ ] Imports
66+ - [ ] Exports
77+ - [ ] Constant bindings for an object
58- [ ] Map Z/ZP to default
69- [x] Steal Webpack require and use it in our LunAST instance
710- [ ] Map `import` statements to LunAST
···1114- [ ] Run in parallel with service workers
1215 - This is gonna require making Webpack entrypoint async and us doing kickoff ourselves
1316- [ ] Support lazy loaded chunks
1717+ - Works right now, but will break when caching is implemented
1418- [ ] Split into a new repo on GitHub, publish to NPM maybe
1519- [ ] Implement caching based off of the client build and LunAST commit
1620 - Means you only have to have a long client start once per client build
+2-4
packages/lunast/src/index.ts
···11import { RemapField, RemapModule, RemapType } from "./types";
22import { Remapped } from "./modules";
33-import { getProcessors } from "./utils";
44-import { parse } from "meriyah";
33+import { getProcessors, parseFixed } from "./utils";
54import { Processor, ProcessorState } from "./remap";
65import { generate } from "astring";
76···5150 );
5251 if (available.length === 0) return null;
53525454- const module = parse(code);
5353+ const module = parseFixed(code);
5554 let dirty = false;
5655 const state: ProcessorState = {
5756 id,
5858- // @ts-expect-error The ESTree types are mismatched with estree-toolkit, but ESTree is a standard so this is fine
5957 ast: module,
6058 lunast: this,
6159 markDirty: () => {
+12-4
packages/lunast/src/modules/test.ts
···88 find: "marginCenterHorz:",
99 process({ ast }) {
1010 const exports = getExports(ast);
1111- // eslint-disable-next-line no-console
1212- console.log(exports);
1111+ // console.log(exports);
1312 return Object.keys(exports).length > 0;
1413 }
1514});
···3938 },
4039 "balls"
4140)`)!;
4242- for (const node of Object.values(getters)) {
4141+ for (const data of Object.values(getters)) {
4242+ if (!is.identifier(data.argument)) continue;
4343+4444+ const node = data.scope.getOwnBinding(data.argument.name);
4545+ if (!node) continue;
4646+4347 const body = node.path.get<BlockStatement>("body");
4448 body.replaceWith(replacement);
4549 }
···5660 const getters = getPropertyGetters(ast);
5761 const fields = [];
58625959- for (const [name, node] of Object.entries(getters)) {
6363+ for (const [name, data] of Object.entries(getters)) {
6464+ if (!is.identifier(data.argument)) continue;
6565+ const node = data.scope.getOwnBinding(data.argument.name);
6666+ if (!node) continue;
6767+6068 let isSupportsCopy = false;
6169 traverse(node.path.node!, {
6270 MemberExpression(path) {
+20-11
packages/lunast/src/utils.ts
···11import type { Processor } from "./remap";
22-import { traverse, is, Binding } from "estree-toolkit";
22+import { traverse, is, Scope } from "estree-toolkit";
33// FIXME something's fishy with these types
44import type {
55+ Expression,
56 ExpressionStatement,
67 ObjectExpression,
78 Program,
···8687 return ret;
8788}
88899090+export type PropertyGetter = {
9191+ argument: Expression;
9292+ scope: Scope;
9393+};
9494+9595+// TODO: util function to resolve the value of an expression
8996export function getPropertyGetters(ast: Program) {
9090- const ret: Record<string, Binding> = {};
9797+ const ret: Record<string, PropertyGetter> = {};
91989299 traverse(ast, {
93100 $: { scope: true },
94101 CallExpression(path) {
102102+ if (path.scope == null) return;
95103 if (!is.callExpression(path.node)) return;
96104 if (!is.memberExpression(path.node.callee)) return;
97105 if (!is.identifier(path.node?.callee?.property)) return;
···111119 const returnStatement = property.value.body.body.find(
112120 (node): node is ReturnStatement => is.returnStatement(node)
113121 );
114114- if (!returnStatement) continue;
115115- if (!is.identifier(returnStatement.argument)) continue;
116116-117117- const binding = path.scope?.getOwnBinding(
118118- returnStatement.argument.name
119119- );
120120- if (!binding) continue;
121121- if (!binding.path.node) continue;
122122- ret[property.key.name] = binding;
122122+ if (!returnStatement || !returnStatement.argument) continue;
123123+ ret[property.key.name] = {
124124+ argument: returnStatement.argument,
125125+ scope: path.scope
126126+ };
123127 }
124128125129 this.stop();
···127131 });
128132129133 return ret;
134134+}
135135+136136+// The ESTree types are mismatched with estree-toolkit, but ESTree is a standard so this is fine
137137+export function parseFixed(code: string): Program {
138138+ return parse(code) as any as Program;
130139}
131140132141export function magicAST(code: string) {