diff --git a/Libraries/LibJS/Makefile b/Libraries/LibJS/Makefile index ff059321fb2..ef9514d9b36 100644 --- a/Libraries/LibJS/Makefile +++ b/Libraries/LibJS/Makefile @@ -7,6 +7,7 @@ OBJS = \ Lexer.o \ Parser.o \ Runtime/Array.o \ + Runtime/ArrayConstructor.o \ Runtime/ArrayPrototype.o \ Runtime/Cell.o \ Runtime/ConsoleObject.o \ diff --git a/Libraries/LibJS/Runtime/ArrayConstructor.cpp b/Libraries/LibJS/Runtime/ArrayConstructor.cpp new file mode 100644 index 00000000000..6be1953fffb --- /dev/null +++ b/Libraries/LibJS/Runtime/ArrayConstructor.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020, Andreas Kling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +namespace JS { + +ArrayConstructor::ArrayConstructor() +{ + put("prototype", interpreter().array_prototype()); + put("length", Value(1)); +} + +ArrayConstructor::~ArrayConstructor() +{ +} + +Value ArrayConstructor::call(Interpreter& interpreter) +{ + if (interpreter.argument_count() == 0) + return interpreter.heap().allocate(); + + if (interpreter.argument_count() == 1) { + auto* array = interpreter.heap().allocate(); + array->elements().resize(interpreter.argument(0).to_i32()); + return array; + } + + // FIXME: Handle "new Array(element0, element1, ...)" + ASSERT_NOT_REACHED(); +} + +Value ArrayConstructor::construct(Interpreter& interpreter) +{ + return call(interpreter); +} + +} diff --git a/Libraries/LibJS/Runtime/ArrayConstructor.h b/Libraries/LibJS/Runtime/ArrayConstructor.h new file mode 100644 index 00000000000..07763cfdaf5 --- /dev/null +++ b/Libraries/LibJS/Runtime/ArrayConstructor.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020, Andreas Kling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +namespace JS { + +class ArrayConstructor final : public NativeFunction { +public: + ArrayConstructor(); + virtual ~ArrayConstructor() override; + + virtual Value call(Interpreter&) override; + virtual Value construct(Interpreter&) override; + +private: + virtual bool has_constructor() const override { return true; } + virtual const char* class_name() const override { return "ArrayConstructor"; } +}; + +} diff --git a/Libraries/LibJS/Runtime/ArrayPrototype.cpp b/Libraries/LibJS/Runtime/ArrayPrototype.cpp index e46be323cdc..23a807d0a67 100644 --- a/Libraries/LibJS/Runtime/ArrayPrototype.cpp +++ b/Libraries/LibJS/Runtime/ArrayPrototype.cpp @@ -38,6 +38,7 @@ ArrayPrototype::ArrayPrototype() put_native_function("shift", shift); put_native_function("pop", pop); put_native_function("push", push, 1); + put("length", Value(0)); } ArrayPrototype::~ArrayPrototype() diff --git a/Libraries/LibJS/Runtime/GlobalObject.cpp b/Libraries/LibJS/Runtime/GlobalObject.cpp index 881b6800ff2..770ccdb709f 100644 --- a/Libraries/LibJS/Runtime/GlobalObject.cpp +++ b/Libraries/LibJS/Runtime/GlobalObject.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,7 @@ GlobalObject::GlobalObject() put("Function", heap().allocate()); put("Math", heap().allocate()); put("Object", heap().allocate()); + put("Array", heap().allocate()); } GlobalObject::~GlobalObject() diff --git a/Libraries/LibJS/Tests/Array.js b/Libraries/LibJS/Tests/Array.js new file mode 100644 index 00000000000..87cd168e35c --- /dev/null +++ b/Libraries/LibJS/Tests/Array.js @@ -0,0 +1,16 @@ +function assert(x) { if (!x) throw 1; } + +try { + assert(Array.length === 1); + assert(Array.prototype.length === 0); + assert(typeof Array() === "object"); + assert(typeof new Array() === "object"); + + x = new Array(5); + + assert(x.length === 5); + + console.log("PASS"); +} catch (e) { + console.log("FAIL: " + e.message); +}