Forráskód Böngészése

LibJS: Add StringPrototype and make it the prototype of StringObject

This patch adds String.prototype.charAt() to demonstrate that prototype
property lookup works, and that you can call a prototype function on an
object, and it will do what you expect. :^)
Andreas Kling 5 éve
szülő
commit
2c5b9fb8f9

+ 2 - 0
Base/home/anon/js/charAt.js

@@ -0,0 +1,2 @@
+var foo = "foobar";
+print(foo.charAt(3));

+ 1 - 0
Libraries/LibJS/Makefile

@@ -13,6 +13,7 @@ OBJS = \
     PrimitiveString.o \
     ScriptFunction.o \
     StringObject.o \
+    StringPrototype.o \
     Token.o \
     Value.o
 

+ 3 - 0
Libraries/LibJS/StringObject.cpp

@@ -24,8 +24,10 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <LibJS/Heap.h>
 #include <LibJS/PrimitiveString.h>
 #include <LibJS/StringObject.h>
+#include <LibJS/StringPrototype.h>
 #include <LibJS/Value.h>
 
 namespace JS {
@@ -33,6 +35,7 @@ namespace JS {
 StringObject::StringObject(PrimitiveString* string)
     : m_string(string)
 {
+    set_prototype(heap().allocate<StringPrototype>());
     put("length", Value(static_cast<i32>(m_string->string().length())));
 }
 

+ 4 - 0
Libraries/LibJS/StringObject.h

@@ -37,8 +37,12 @@ public:
 
     virtual void visit_children(Visitor&) override;
 
+    const PrimitiveString* primitive_string() const { return m_string; }
+
 private:
     virtual const char* class_name() const override { return "StringObject"; }
+    virtual bool is_string_object() const override { return true; }
+
     PrimitiveString* m_string { nullptr };
 };
 

+ 57 - 0
Libraries/LibJS/StringPrototype.cpp

@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * 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 <AK/Function.h>
+#include <LibJS/Heap.h>
+#include <LibJS/Interpreter.h>
+#include <LibJS/PrimitiveString.h>
+#include <LibJS/StringObject.h>
+#include <LibJS/StringPrototype.h>
+#include <LibJS/Value.h>
+
+namespace JS {
+
+StringPrototype::StringPrototype()
+{
+    put_native_function("charAt", [](Interpreter& interpreter, Vector<Value> arguments) -> Value {
+        i32 index = 0;
+        if (!arguments.is_empty())
+            index = arguments[0].to_i32();
+        Value this_value = interpreter.this_value();
+        ASSERT(this_value.is_object());
+        ASSERT(this_value.as_object()->is_string_object());
+        auto underlying_string = static_cast<const StringObject*>(this_value.as_object())->primitive_string()->string();
+        if (index < 0 || index >= static_cast<i32>(underlying_string.length()))
+            return js_string(interpreter.heap(), String::empty());
+        return js_string(interpreter.heap(), underlying_string.substring(index, 1));
+    });
+}
+
+StringPrototype::~StringPrototype()
+{
+}
+
+}

+ 42 - 0
Libraries/LibJS/StringPrototype.h

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * 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/Object.h>
+
+namespace JS {
+
+class StringPrototype final : public Object {
+public:
+    StringPrototype();
+    virtual ~StringPrototype() override;
+
+private:
+    virtual const char* class_name() const override { return "StringPrototype"; }
+};
+
+}