diff --git a/Libraries/LibJS/Makefile b/Libraries/LibJS/Makefile index 75352c97422..77057749ade 100644 --- a/Libraries/LibJS/Makefile +++ b/Libraries/LibJS/Makefile @@ -28,6 +28,7 @@ OBJS = \ Runtime/MathObject.o \ Runtime/NativeFunction.o \ Runtime/NativeProperty.o \ + Runtime/NumberConstructor.o \ Runtime/NumberObject.o \ Runtime/NumberPrototype.o \ Runtime/Object.o \ diff --git a/Libraries/LibJS/Runtime/GlobalObject.cpp b/Libraries/LibJS/Runtime/GlobalObject.cpp index 4bda346d81b..d5dc5b37f74 100644 --- a/Libraries/LibJS/Runtime/GlobalObject.cpp +++ b/Libraries/LibJS/Runtime/GlobalObject.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -60,6 +61,7 @@ GlobalObject::GlobalObject() put("Object", heap().allocate()); put("Array", heap().allocate()); put("Boolean", heap().allocate()); + put("Number", heap().allocate()); } GlobalObject::~GlobalObject() diff --git a/Libraries/LibJS/Runtime/NumberConstructor.cpp b/Libraries/LibJS/Runtime/NumberConstructor.cpp new file mode 100644 index 00000000000..924c14a0d45 --- /dev/null +++ b/Libraries/LibJS/Runtime/NumberConstructor.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020, Linus Groh + * 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 + +namespace JS { + +NumberConstructor::NumberConstructor() +{ + put("prototype", interpreter().number_prototype()); + put("length", Value(1)); +} + +NumberConstructor::~NumberConstructor() +{ +} + +Value NumberConstructor::call(Interpreter& interpreter) +{ + if (!interpreter.argument_count()) + return Value(0); + return interpreter.argument(0).to_number(); +} + +Value NumberConstructor::construct(Interpreter& interpreter) +{ + double number; + if (!interpreter.argument_count()) + number = 0; + else + number = interpreter.argument(0).to_number().as_double(); + return Value(interpreter.heap().allocate(number)); +} + +} diff --git a/Libraries/LibJS/Runtime/NumberConstructor.h b/Libraries/LibJS/Runtime/NumberConstructor.h new file mode 100644 index 00000000000..31bf3052a0b --- /dev/null +++ b/Libraries/LibJS/Runtime/NumberConstructor.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020, Linus Groh + * 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 NumberConstructor final : public NativeFunction { +public: + NumberConstructor(); + virtual ~NumberConstructor() 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 "NumberConstructor"; } +}; + +} diff --git a/Libraries/LibJS/Tests/Number.js b/Libraries/LibJS/Tests/Number.js new file mode 100644 index 00000000000..9b24b613b90 --- /dev/null +++ b/Libraries/LibJS/Tests/Number.js @@ -0,0 +1,27 @@ +try { + assert(Number.length === 1); + assert(typeof Number() === "number"); + assert(typeof new Number() === "object"); + assert(Number() === 0); + assert(new Number().valueOf() === 0); + assert(Number("42") === 42); + assert(new Number("42").valueOf() === 42); + assert(Number(null) === 0); + assert(new Number(null).valueOf() === 0); + assert(Number(true) === 1); + assert(new Number(true).valueOf() === 1); + assert(isNaN(Number(undefined))); + assert(isNaN(new Number(undefined).valueOf())); + assert(isNaN(Number({}))); + assert(isNaN(new Number({}).valueOf())); + assert(isNaN(Number({a: 1}))); + assert(isNaN(new Number({a: 1}).valueOf())); + assert(isNaN(Number([1, 2, 3]))); + assert(isNaN(new Number([1, 2, 3]).valueOf())); + assert(isNaN(Number("foo"))); + assert(isNaN(new Number("foo").valueOf())); + + console.log("PASS"); +} catch (e) { + console.log("FAIL: " + e.message); +}