1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-20 17:45:07 +00:00

LibJS: Support empty values in array expression

This commit is contained in:
Linus Groh 2020-04-15 20:09:06 +01:00 committed by Andreas Kling
parent d30db07048
commit cea950fd70
4 changed files with 44 additions and 10 deletions

View file

@ -973,7 +973,12 @@ void ArrayExpression::dump(int indent) const
{ {
ASTNode::dump(indent); ASTNode::dump(indent);
for (auto& element : m_elements) { for (auto& element : m_elements) {
element.dump(indent + 1); if (element) {
element->dump(indent + 1);
} else {
print_indent(indent + 1);
printf("<empty>\n");
}
} }
} }
@ -981,9 +986,12 @@ Value ArrayExpression::execute(Interpreter& interpreter) const
{ {
auto* array = interpreter.heap().allocate<Array>(); auto* array = interpreter.heap().allocate<Array>();
for (auto& element : m_elements) { for (auto& element : m_elements) {
auto value = element.execute(interpreter); auto value = Value();
if (interpreter.exception()) if (element) {
return {}; value = element->execute(interpreter);
if (interpreter.exception())
return {};
}
array->elements().append(value); array->elements().append(value);
} }
return array; return array;

View file

@ -681,12 +681,12 @@ private:
class ArrayExpression : public Expression { class ArrayExpression : public Expression {
public: public:
ArrayExpression(NonnullRefPtrVector<Expression> elements) ArrayExpression(Vector<RefPtr<Expression>> elements)
: m_elements(move(elements)) : m_elements(move(elements))
{ {
} }
const NonnullRefPtrVector<Expression>& elements() const { return m_elements; } const Vector<RefPtr<Expression>>& elements() const { return m_elements; }
virtual Value execute(Interpreter&) const override; virtual Value execute(Interpreter&) const override;
virtual void dump(int indent) const override; virtual void dump(int indent) const override;
@ -694,7 +694,7 @@ public:
private: private:
virtual const char* class_name() const override { return "ArrayExpression"; } virtual const char* class_name() const override { return "ArrayExpression"; }
NonnullRefPtrVector<Expression> m_elements; Vector<RefPtr<Expression>> m_elements;
}; };
class MemberExpression final : public Expression { class MemberExpression final : public Expression {

View file

@ -473,9 +473,12 @@ NonnullRefPtr<ArrayExpression> Parser::parse_array_expression()
{ {
consume(TokenType::BracketOpen); consume(TokenType::BracketOpen);
NonnullRefPtrVector<Expression> elements; Vector<RefPtr<Expression>> elements;
while (match_expression()) { while (match_expression() || match(TokenType::Comma)) {
elements.append(parse_expression(0)); RefPtr<Expression> expression;
if (match_expression())
expression = parse_expression(0);
elements.append(expression);
if (!match(TokenType::Comma)) if (!match(TokenType::Comma))
break; break;
consume(TokenType::Comma); consume(TokenType::Comma);

View file

@ -17,6 +17,29 @@ try {
assert(a[3] === 7); assert(a[3] === 7);
assert(a.length === 4); assert(a.length === 4);
a = [,];
assert(a.length === 1);
assert(a.toString() === "");
assert(a[0] === undefined);
a = [,,,,];
assert(a.length === 4);
assert(a.toString() === ",,,");
assert(a[0] === undefined);
assert(a[1] === undefined);
assert(a[2] === undefined);
assert(a[3] === undefined);
a = [1,,2,,,3,];
assert(a.length === 6);
assert(a.toString() === "1,,2,,,3");
assert(a[0] === 1);
assert(a[1] === undefined);
assert(a[2] === 2);
assert(a[3] === undefined);
assert(a[4] === undefined);
assert(a[5] === 3);
console.log("PASS"); console.log("PASS");
} catch (e) { } catch (e) {
console.log("FAIL: " + e); console.log("FAIL: " + e);