1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 01:58:12 +00:00

LibJS: Support spreading of strings and string objects

This commit is contained in:
Linus Groh 2020-04-27 14:01:04 +01:00 committed by Andreas Kling
parent bcd5e97286
commit 30fe1b5d58
3 changed files with 60 additions and 19 deletions

View file

@ -39,6 +39,7 @@
#include <LibJS/Runtime/PrimitiveString.h> #include <LibJS/Runtime/PrimitiveString.h>
#include <LibJS/Runtime/Reference.h> #include <LibJS/Runtime/Reference.h>
#include <LibJS/Runtime/ScriptFunction.h> #include <LibJS/Runtime/ScriptFunction.h>
#include <LibJS/Runtime/StringObject.h>
#include <LibJS/Runtime/Value.h> #include <LibJS/Runtime/Value.h>
#include <stdio.h> #include <stdio.h>
@ -1127,21 +1128,30 @@ Value ArrayExpression::execute(Interpreter& interpreter) const
return {}; return {};
if (element->is_spread_expression()) { if (element->is_spread_expression()) {
if (!value.is_array()) { // FIXME: Support arbitrary iterables
interpreter.throw_exception<TypeError>(String::format("%s is not iterable", value.to_string().characters())); if (value.is_array()) {
return {}; auto& array_to_spread = static_cast<Array&>(value.as_object());
} for (auto& it : array_to_spread.elements()) {
if (it.is_empty()) {
auto& array_to_spread = static_cast<Array&>(value.as_object()); array->elements().append(js_undefined());
for (auto& it : array_to_spread.elements()) { } else {
if (it.is_empty()) { array->elements().append(it);
array->elements().append(js_undefined()); }
} else {
array->elements().append(it);
} }
continue;
} }
if (value.is_string() || (value.is_object() && value.as_object().is_string_object())) {
continue; String string_to_spread;
if (value.is_string())
string_to_spread = value.as_string()->string();
else
string_to_spread = static_cast<StringObject*>(&value.as_object())->primitive_string()->string();
for (size_t i = 0; i < string_to_spread.length(); ++i)
array->elements().append(js_string(interpreter, string_to_spread.substring(i, 1)));
continue;
}
interpreter.throw_exception<TypeError>(String::format("%s is not iterable", value.to_string().characters()));
return {};
} }
} }
array->elements().append(value); array->elements().append(value);

View file

@ -24,17 +24,17 @@ try {
assert(testArray(arr)); assert(testArray(arr));
assertThrowsError(() => { assertThrowsError(() => {
[...1]; [...1];
}, { }, {
error: TypeError, error: TypeError,
message: "1 is not iterable", message: "1 is not iterable",
}); });
assertThrowsError(() => { assertThrowsError(() => {
[...{}]; [...{}];
}, { }, {
error: TypeError, error: TypeError,
message: "[object Object] is not iterable", message: "[object Object] is not iterable",
}); });
console.log("PASS"); console.log("PASS");

View file

@ -0,0 +1,31 @@
load("test-common.js");
function testArray(arr) {
return arr.length === 4 &&
arr[0] === "a" &&
arr[1] === "b" &&
arr[2] === "c" &&
arr[3] === "d";
}
try {
var arr;
arr = ["a", ..."bc", "d"];
assert(testArray(arr));
let s = "bc";
arr = ["a", ...s, "d"];
assert(testArray(arr));
let obj = { a: "bc" };
arr = ["a", ...obj.a, "d"];
assert(testArray(arr));
arr = [..."", ...[...new String("abc")], "d"];
assert(testArray(arr));
console.log("PASS");
} catch (e) {
console.log("FAIL: " + e);
}