diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 8b713fe036..55db8784d8 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -559,15 +559,12 @@ Reference Identifier::to_reference(Interpreter& interpreter) const Reference MemberExpression::to_reference(Interpreter& interpreter) const { auto object_value = m_object->execute(interpreter); - if (object_value.is_empty()) - return {}; - auto* object = object_value.to_object(interpreter); - if (!object) + if (interpreter.exception()) return {}; auto property_name = computed_property_name(interpreter); if (!property_name.is_valid()) return {}; - return { object, property_name }; + return { object_value, property_name }; } Value UnaryExpression::execute(Interpreter& interpreter) const diff --git a/Libraries/LibJS/Runtime/Reference.cpp b/Libraries/LibJS/Runtime/Reference.cpp index aa2d1ac96d..1e8bbe878f 100644 --- a/Libraries/LibJS/Runtime/Reference.cpp +++ b/Libraries/LibJS/Runtime/Reference.cpp @@ -50,6 +50,11 @@ void Reference::put(Interpreter& interpreter, Value value) return; } + if (!base().is_object() && interpreter.in_strict_mode()) { + interpreter.throw_exception(String::format("Can't assign property %s to primitive value", m_name.to_string().characters())); + return; + } + auto* object = base().to_object(interpreter); if (!object) return; diff --git a/Libraries/LibJS/Tests/strict-mode-errors.js b/Libraries/LibJS/Tests/strict-mode-errors.js new file mode 100644 index 0000000000..7695957f0d --- /dev/null +++ b/Libraries/LibJS/Tests/strict-mode-errors.js @@ -0,0 +1,18 @@ +"use strict"; + +load("test-common.js") + +try { + [true, false, "foo", 123].forEach(primitive => { + assertThrowsError(() => { + primitive.foo = "bar"; + }, { + error: TypeError, + message: "Can't assign property foo to primitive value" + }); + }); + + console.log("PASS"); +} catch (e) { + console.log("FAIL: " + e); +}