@yuebai008/cli
Version:
Command line interface for rapid qg-minigame development
1 lines • 1.45 kB
JavaScript
import*as Acorn from"../../third_party/acorn/acorn.js";import{ECMA_VERSION}from"./AcornTokenizer.js";import{ScopeVariableAnalysis}from"./ScopeParser.js";export function substituteExpression(o,t){return applySubstitution(o,computeSubstitution(o,t))}function computeSubstitution(o,t){const s=Acorn.parse(o,{ecmaVersion:ECMA_VERSION,allowAwaitOutsideFunction:!0,ranges:!1,checkPrivateFields:!1}),n=new ScopeVariableAnalysis(s);n.run();const r=n.getFreeVariables(),e=[],i=n.getAllNames();for(const o of t.values())o&&i.add(o);function f(o){let t=1;for(;i.has(`${o}_${t}`);)t++;const s=`${o}_${t}`;return i.add(s),s}for(const[o,s]of t.entries()){const t=r.get(o);if(!t)continue;if(null===s)throw new Error(`Cannot substitute '${o}' as the underlying variable '${s}' is unavailable`);const n=[];for(const r of t)e.push({from:o,to:s,offset:r.offset,isShorthandAssignmentProperty:r.isShorthandAssignmentProperty}),n.push(...r.scope.findBinders(s));for(const o of n){if(3===o.definitionKind)throw new Error(`Cannot avoid capture of '${s}'`);const t=f(s);for(const n of o.uses)e.push({from:s,to:t,offset:n.offset,isShorthandAssignmentProperty:n.isShorthandAssignmentProperty})}}return e.sort(((o,t)=>o.offset-t.offset)),e}function applySubstitution(o,t){const s=[];let n=0;for(const r of t){s.push(o.slice(n,r.offset));let t=r.to;r.isShorthandAssignmentProperty&&(t=`${r.from}: ${r.to}`),s.push(t),n=r.offset+r.from.length}return s.push(o.slice(n)),s.join("")}