Skip to content

Commit

Permalink
fix: parameter variable infinite recursion error (#5500)
Browse files Browse the repository at this point in the history
* fix: parameter variable infinite recursion error

Ensure before hasEffects of function body (triggered by function call), the arguments are first provided

* update test
  • Loading branch information
liuly0322 committed Apr 29, 2024
1 parent 9135249 commit 571929f
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 23 deletions.
23 changes: 10 additions & 13 deletions src/ast/nodes/NewExpression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,17 @@ export default class NewExpression extends NodeBase {
declare annotationPure?: boolean;

hasEffects(context: HasEffectsContext): boolean {
try {
for (const argument of this.arguments) {
if (argument.hasEffects(context)) return true;
}
if (this.annotationPure) {
return false;
}
return (
this.callee.hasEffects(context) ||
this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context)
);
} finally {
if (!this.deoptimized) this.applyDeoptimizations();
if (!this.deoptimized) this.applyDeoptimizations();
for (const argument of this.arguments) {
if (argument.hasEffects(context)) return true;
}
if (this.annotationPure) {
return false;
}
return (
this.callee.hasEffects(context) ||
this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context)
);
}

hasEffectsOnInteractionAtPath(path: ObjectPath, { type }: NodeInteraction): boolean {
Expand Down
17 changes: 7 additions & 10 deletions src/ast/nodes/TaggedTemplateExpression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,14 @@ export default class TaggedTemplateExpression extends CallExpressionBase {
}

hasEffects(context: HasEffectsContext): boolean {
try {
for (const argument of this.quasi.expressions) {
if (argument.hasEffects(context)) return true;
}
return (
this.tag.hasEffects(context) ||
this.tag.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context)
);
} finally {
if (!this.deoptimized) this.applyDeoptimizations();
if (!this.deoptimized) this.applyDeoptimizations();
for (const argument of this.quasi.expressions) {
if (argument.hasEffects(context)) return true;
}
return (
this.tag.hasEffects(context) ||
this.tag.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context)
);
}

include(context: InclusionContext, includeChildrenRecursively: IncludeChildren): void {
Expand Down
5 changes: 5 additions & 0 deletions test/function/samples/recursive-parameter-assignments/main.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
let created = false;

class Test {
constructor ( name, opts ) {
opts = opts || {};
Expand All @@ -10,7 +12,10 @@ class Test {

this.name = name;
this.opts = opts;
// to make the function call not pure
created = true;
}
}

new Test( 'a', {} );
assert.equal( created, true );
4 changes: 4 additions & 0 deletions test/function/samples/recursive-parameter-binding/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = defineTest({
description:
'Avoid maximum call stack error, make sure parameter value is optimized before hasEffects (#5499).'
});
26 changes: 26 additions & 0 deletions test/function/samples/recursive-parameter-binding/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
let created = 0;

function Test(options) {
if (!this) {
return new Test(options);
}
if (options.x) {
return 0;
}
created++;
}

function Test2(options) {
if (!this) {
return new Test2(options);
}
if (options.x) {
return 0;
}
created++;
}

new Test({});
Test2`{}`;

assert.equal(created, 2);

0 comments on commit 571929f

Please sign in to comment.