From 0c0274cef353570c57e15f0162e0b855420a41de Mon Sep 17 00:00:00 2001 From: "andrea.bergia" Date: Thu, 22 Aug 2024 14:19:41 +0200 Subject: [PATCH] Fixed a bug with interpreter peeling introduced in #1510 --- .../org/mozilla/javascript/Interpreter.java | 2 + ...reterFunctionPeelingNonRegressionTest.java | 86 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 tests/src/test/java/org/mozilla/javascript/tests/InterpreterFunctionPeelingNonRegressionTest.java diff --git a/rhino/src/main/java/org/mozilla/javascript/Interpreter.java b/rhino/src/main/java/org/mozilla/javascript/Interpreter.java index f476be5cee..aeffdf6ee0 100644 --- a/rhino/src/main/java/org/mozilla/javascript/Interpreter.java +++ b/rhino/src/main/java/org/mozilla/javascript/Interpreter.java @@ -1784,6 +1784,8 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl ArrowFunction afun = (ArrowFunction) fun; fun = afun.getTargetFunction(); funThisObj = afun.getCallThis(cx); + } else if (fun instanceof LambdaConstructor) { + break; } else if (fun instanceof LambdaFunction) { fun = ((LambdaFunction) fun).getTarget(); } else if (fun instanceof BoundFunction) { diff --git a/tests/src/test/java/org/mozilla/javascript/tests/InterpreterFunctionPeelingNonRegressionTest.java b/tests/src/test/java/org/mozilla/javascript/tests/InterpreterFunctionPeelingNonRegressionTest.java new file mode 100644 index 0000000000..3532892647 --- /dev/null +++ b/tests/src/test/java/org/mozilla/javascript/tests/InterpreterFunctionPeelingNonRegressionTest.java @@ -0,0 +1,86 @@ +package org.mozilla.javascript.tests; + +import static org.junit.Assert.assertEquals; +import static org.mozilla.javascript.LambdaConstructor.CONSTRUCTOR_FUNCTION; + +import org.junit.Test; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.LambdaConstructor; +import org.mozilla.javascript.LambdaFunction; +import org.mozilla.javascript.ScriptRuntime; +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; + +public class InterpreterFunctionPeelingNonRegressionTest { + @Test + public void testLambdaFunction() { + try (var cx = Context.enter()) { + cx.setOptimizationLevel(-1); + Scriptable scope = cx.initStandardObjects(); + + LambdaFunction makePerson = + new LambdaFunction( + scope, + "makePerson", + 1, + (cx1, scope1, thisObj, args) -> + new Person(ScriptRuntime.toString(args[0]))); + scope.put("makePerson", scope, makePerson); + + String source = + "function testLambdaFunction() {\n" + + " return makePerson('Andrea');\n" + + "}\n" + + "testLambdaFunction().name"; + Object value = cx.evaluateString(scope, source, "test", 1, null); + assertEquals("Andrea", value); + } + } + + @Test + public void testLambdaConstructor() { + try (var cx = Context.enter()) { + cx.setOptimizationLevel(-1); + Scriptable scope = cx.initStandardObjects(); + + LambdaConstructor personCtor = + new LambdaConstructor( + scope, + "Person", + 1, + CONSTRUCTOR_FUNCTION, + (cx1, scope1, args) -> new Person(ScriptRuntime.toString(args[0]))); + scope.put("Person", scope, personCtor); + + String source = + "function testLambdaConstructor() {\n" + + " return Person('Andrea');\n" + + "}\n" + + "testLambdaConstructor().name"; + Object value = cx.evaluateString(scope, source, "test", 1, null); + assertEquals("Andrea", value); + } + } + + static class Person extends ScriptableObject { + private final String name; + + public Person(String name) { + this.name = name; + } + + @Override + public String getClassName() { + return "Person"; + } + + @Override + public Object get(String name, Scriptable start) { + if (name.equals("name")) { + return this.name; + } else { + return super.get(name, start); + } + } + } +}