Skip __awaiter this captures
This commit is contained in:
parent
443e1b9053
commit
cf7ba79f81
|
@ -191,13 +191,22 @@ function serializeCapturedObjectAsync(obj: any, resolve: (v: AsyncEnvironmentEnt
|
||||||
// expected to be the usual V8-serialized function expression text.
|
// expected to be the usual V8-serialized function expression text.
|
||||||
function computeFreeVariables(funcstr: string): string[] {
|
function computeFreeVariables(funcstr: string): string[] {
|
||||||
Log.debug(`Computing free variables for function: ${funcstr}`);
|
Log.debug(`Computing free variables for function: ${funcstr}`);
|
||||||
|
if (funcstr.indexOf("[native code]") !== -1) {
|
||||||
|
throw new Error(`Cannot serialize native code function: "${funcstr}"`);
|
||||||
|
}
|
||||||
|
|
||||||
let opts: acorn.Options = {
|
let opts: acorn.Options = {
|
||||||
ecmaVersion: 8,
|
ecmaVersion: 8,
|
||||||
sourceType: "script",
|
sourceType: "script",
|
||||||
};
|
};
|
||||||
let parser = new acorn.Parser(opts, funcstr);
|
let parser = new acorn.Parser(opts, funcstr);
|
||||||
let program: estree.Program = parser.parse();
|
let program: estree.Program;
|
||||||
|
try {
|
||||||
|
program = parser.parse();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
throw new Error(`Could not parse function: ${err}\n${funcstr}`);
|
||||||
|
}
|
||||||
|
|
||||||
// Now that we've parsed the program, compute the free variables, and return them.
|
// Now that we've parsed the program, compute the free variables, and return them.
|
||||||
return new FreeVariableComputer().compute(program);
|
return new FreeVariableComputer().compute(program);
|
||||||
|
@ -237,6 +246,7 @@ class FreeVariableComputer {
|
||||||
ThisExpression: this.visitThisExpression.bind(this),
|
ThisExpression: this.visitThisExpression.bind(this),
|
||||||
BlockStatement: this.visitBlockStatement.bind(this),
|
BlockStatement: this.visitBlockStatement.bind(this),
|
||||||
CatchClause: this.visitCatchClause.bind(this),
|
CatchClause: this.visitCatchClause.bind(this),
|
||||||
|
CallExpression: this.visitCallExpression.bind(this),
|
||||||
FunctionDeclaration: this.visitFunctionDeclaration.bind(this),
|
FunctionDeclaration: this.visitFunctionDeclaration.bind(this),
|
||||||
FunctionExpression: this.visitBaseFunction.bind(this),
|
FunctionExpression: this.visitBaseFunction.bind(this),
|
||||||
ArrowFunctionExpression: this.visitBaseFunction.bind(this),
|
ArrowFunctionExpression: this.visitBaseFunction.bind(this),
|
||||||
|
@ -348,6 +358,22 @@ class FreeVariableComputer {
|
||||||
this.scope.pop();
|
this.scope.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private visitCallExpression(node: estree.SimpleCallExpression, state: any, cb: walkCallback): void {
|
||||||
|
// Most call expressions are normal. But we must special case one kind of function:
|
||||||
|
// TypeScript's __awaiter functions. They are of the form `__awaiter(this, void 0, void 0, function* (){})`,
|
||||||
|
// which will cause us to attempt to capture and serialize the entire surrounding function in
|
||||||
|
// which any lambda is created (thanks to `this`). That spirals into craziness, and bottoms out on native
|
||||||
|
// functions which we cannot serialize. We only want to capture `this` if the user code mentioned it.
|
||||||
|
cb(node.callee, state);
|
||||||
|
let isAwaiterCall: boolean =
|
||||||
|
(node.callee.type === "Identifier" && (node.callee as estree.Identifier).name === "__awaiter");
|
||||||
|
for (let i = 0; i < node.arguments.length; i++) {
|
||||||
|
if (i > 0 || !isAwaiterCall) {
|
||||||
|
cb(node.arguments[i], state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private visitVariableDeclaration(node: estree.VariableDeclaration, state: any, cb: walkCallback): void {
|
private visitVariableDeclaration(node: estree.VariableDeclaration, state: any, cb: walkCallback): void {
|
||||||
for (let decl of node.declarations) {
|
for (let decl of node.declarations) {
|
||||||
// If the declaration is an identifier, it isn't a free variable, for whatever scope it
|
// If the declaration is an identifier, it isn't a free variable, for whatever scope it
|
||||||
|
|
Loading…
Reference in a new issue