summaryrefslogtreecommitdiff
path: root/Libraries/LibJS
diff options
context:
space:
mode:
authorJack Karamanian <karamanian.jack@gmail.com>2020-04-01 22:28:48 -0500
committerAndreas Kling <kling@serenityos.org>2020-04-02 08:50:28 +0200
commitbb15b372283230814e82da8e398dbbf3a0572849 (patch)
tree542f34df7d48524e6d96033dfe80a04aa13f407b /Libraries/LibJS
parent8f08ec5038bbee43621af6cd9ef088448d044ee3 (diff)
downloadserenity-bb15b372283230814e82da8e398dbbf3a0572849.zip
LibJS: Evaluate CallExpression arguments before pushing a CallFrame
Diffstat (limited to 'Libraries/LibJS')
-rw-r--r--Libraries/LibJS/AST.cpp8
-rw-r--r--Libraries/LibJS/Tests/function-this-in-arguments.js17
2 files changed, 23 insertions, 2 deletions
diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp
index 23baf14d23..407ecd8caa 100644
--- a/Libraries/LibJS/AST.cpp
+++ b/Libraries/LibJS/AST.cpp
@@ -101,16 +101,20 @@ Value CallExpression::execute(Interpreter& interpreter) const
auto& function = static_cast<Function&>(callee.as_object());
- auto& call_frame = interpreter.push_call_frame();
+ Vector<Value> arguments;
+ arguments.ensure_capacity(m_arguments.size());
for (size_t i = 0; i < m_arguments.size(); ++i) {
auto value = m_arguments[i].execute(interpreter);
if (interpreter.exception())
return {};
- call_frame.arguments.append(value);
+ arguments.append(value);
if (interpreter.exception())
return {};
}
+ auto& call_frame = interpreter.push_call_frame();
+ call_frame.arguments = move(arguments);
+
Object* new_object = nullptr;
Value result;
if (is_new_expression()) {
diff --git a/Libraries/LibJS/Tests/function-this-in-arguments.js b/Libraries/LibJS/Tests/function-this-in-arguments.js
new file mode 100644
index 0000000000..23bf80937c
--- /dev/null
+++ b/Libraries/LibJS/Tests/function-this-in-arguments.js
@@ -0,0 +1,17 @@
+function assert(x) { if (!x) throw 1; }
+
+try {
+ assert(typeof this === "object");
+ assert(this === global);
+
+ function Foo() {
+ this.x = 5;
+ assert(typeof this === "object");
+ assert(this.x === 5);
+ }
+
+ new Foo();
+ console.log("PASS");
+} catch (err) {
+ console.log("FAIL: " + err);
+}