浏览代码

LibJS: Add Number()

Linus Groh 5 年之前
父节点
当前提交
f631f6a2e6

+ 1 - 0
Libraries/LibJS/Makefile

@@ -28,6 +28,7 @@ OBJS = \
     Runtime/MathObject.o \
     Runtime/MathObject.o \
     Runtime/NativeFunction.o \
     Runtime/NativeFunction.o \
     Runtime/NativeProperty.o \
     Runtime/NativeProperty.o \
+    Runtime/NumberConstructor.o \
     Runtime/NumberObject.o \
     Runtime/NumberObject.o \
     Runtime/NumberPrototype.o \
     Runtime/NumberPrototype.o \
     Runtime/Object.o \
     Runtime/Object.o \

+ 2 - 0
Libraries/LibJS/Runtime/GlobalObject.cpp

@@ -37,6 +37,7 @@
 #include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/MathObject.h>
 #include <LibJS/Runtime/MathObject.h>
 #include <LibJS/Runtime/NativeFunction.h>
 #include <LibJS/Runtime/NativeFunction.h>
+#include <LibJS/Runtime/NumberConstructor.h>
 #include <LibJS/Runtime/ObjectConstructor.h>
 #include <LibJS/Runtime/ObjectConstructor.h>
 #include <LibJS/Runtime/Value.h>
 #include <LibJS/Runtime/Value.h>
 
 
@@ -60,6 +61,7 @@ GlobalObject::GlobalObject()
     put("Object", heap().allocate<ObjectConstructor>());
     put("Object", heap().allocate<ObjectConstructor>());
     put("Array", heap().allocate<ArrayConstructor>());
     put("Array", heap().allocate<ArrayConstructor>());
     put("Boolean", heap().allocate<BooleanConstructor>());
     put("Boolean", heap().allocate<BooleanConstructor>());
+    put("Number", heap().allocate<NumberConstructor>());
 }
 }
 
 
 GlobalObject::~GlobalObject()
 GlobalObject::~GlobalObject()

+ 61 - 0
Libraries/LibJS/Runtime/NumberConstructor.cpp

@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2020, Linus Groh <mail@linusgroh.de>
+ * 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 <LibJS/Interpreter.h>
+#include <LibJS/Runtime/Error.h>
+#include <LibJS/Runtime/NumberConstructor.h>
+#include <LibJS/Runtime/NumberObject.h>
+
+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<NumberObject>(number));
+}
+
+}

+ 46 - 0
Libraries/LibJS/Runtime/NumberConstructor.h

@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2020, Linus Groh <mail@linusgroh.de>
+ * 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 <LibJS/Runtime/NativeFunction.h>
+
+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"; }
+};
+
+}

+ 27 - 0
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);
+}