summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2021-06-12 05:37:09 +0300
committerLinus Groh <mail@linusgroh.de>2021-06-12 10:44:28 +0100
commit77c2db41835294d60d01396865f0c9c81e7378c3 (patch)
treedd095964c7b992bf7bbc91cf56e58b0eb55725da /Userland/Libraries
parent39554f3787eae7e52094cab16a966e62f00dea22 (diff)
downloadserenity-77c2db41835294d60d01396865f0c9c81e7378c3.zip
LibJS: Add all of the WeakMap.prototype methods (delete, get, has, set)
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakMapPrototype.cpp58
-rw-r--r--Userland/Libraries/LibJS/Runtime/WeakMapPrototype.h5
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.js34
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.delete.js13
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.get.js12
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.has.js16
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.set.js30
-rw-r--r--Userland/Libraries/LibTest/JavaScriptTestRunner.h1
8 files changed, 169 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.cpp b/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.cpp
index 892b1c14b6..6b63c47115 100644
--- a/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.cpp
+++ b/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.cpp
@@ -18,6 +18,12 @@ void WeakMapPrototype::initialize(GlobalObject& global_object)
{
auto& vm = this->vm();
Object::initialize(global_object);
+ u8 attr = Attribute::Writable | Attribute::Configurable;
+
+ define_native_function(vm.names.delete_, delete_, 1, attr);
+ define_native_function(vm.names.get, get, 1, attr);
+ define_native_function(vm.names.has, has, 1, attr);
+ define_native_function(vm.names.set, set, 2, attr);
define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), vm.names.WeakMap), Attribute::Configurable);
}
@@ -38,4 +44,56 @@ WeakMap* WeakMapPrototype::typed_this(VM& vm, GlobalObject& global_object)
return static_cast<WeakMap*>(this_object);
}
+JS_DEFINE_NATIVE_FUNCTION(WeakMapPrototype::delete_)
+{
+ auto* weak_map = typed_this(vm, global_object);
+ if (!weak_map)
+ return {};
+ auto value = vm.argument(0);
+ if (!value.is_object())
+ return Value(false);
+ return Value(weak_map->values().remove(&value.as_object()));
+}
+
+JS_DEFINE_NATIVE_FUNCTION(WeakMapPrototype::get)
+{
+ auto* weak_map = typed_this(vm, global_object);
+ if (!weak_map)
+ return {};
+ auto value = vm.argument(0);
+ if (!value.is_object())
+ return js_undefined();
+ auto& values = weak_map->values();
+ auto result = values.find(&value.as_object());
+ if (result == values.end())
+ return js_undefined();
+ return result->value;
+}
+
+JS_DEFINE_NATIVE_FUNCTION(WeakMapPrototype::has)
+{
+ auto* weak_map = typed_this(vm, global_object);
+ if (!weak_map)
+ return {};
+ auto value = vm.argument(0);
+ if (!value.is_object())
+ return Value(false);
+ auto& values = weak_map->values();
+ return Value(values.find(&value.as_object()) != values.end());
+}
+
+JS_DEFINE_NATIVE_FUNCTION(WeakMapPrototype::set)
+{
+ auto* weak_map = typed_this(vm, global_object);
+ if (!weak_map)
+ return {};
+ auto value = vm.argument(0);
+ if (!value.is_object()) {
+ vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, value.to_string_without_side_effects());
+ return {};
+ }
+ weak_map->values().set(&value.as_object(), vm.argument(1));
+ return weak_map;
+}
+
}
diff --git a/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.h b/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.h
index 267ddeb689..f662f62eb2 100644
--- a/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.h
+++ b/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.h
@@ -20,6 +20,11 @@ public:
private:
static WeakMap* typed_this(VM&, GlobalObject&);
+
+ JS_DECLARE_NATIVE_FUNCTION(delete_);
+ JS_DECLARE_NATIVE_FUNCTION(get);
+ JS_DECLARE_NATIVE_FUNCTION(has);
+ JS_DECLARE_NATIVE_FUNCTION(set);
};
}
diff --git a/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.js b/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.js
new file mode 100644
index 0000000000..9dcbe59fb9
--- /dev/null
+++ b/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.js
@@ -0,0 +1,34 @@
+test("constructor properties", () => {
+ expect(WeakMap).toHaveLength(0);
+ expect(WeakMap.name).toBe("WeakMap");
+});
+
+describe("errors", () => {
+ test("invalid array iterators", () => {
+ [-100, Infinity, NaN, {}, 152n].forEach(value => {
+ expect(() => {
+ new WeakMap(value);
+ }).toThrowWithMessage(TypeError, "is not iterable");
+ });
+ });
+ test("called without new", () => {
+ expect(() => {
+ WeakMap();
+ }).toThrowWithMessage(TypeError, "WeakMap constructor must be called with 'new'");
+ });
+});
+
+describe("normal behavior", () => {
+ test("typeof", () => {
+ expect(typeof new WeakMap()).toBe("object");
+ });
+
+ test("constructor with single array of entries argument", () => {
+ var a = new WeakMap([
+ [{ a: 1 }, 1],
+ [{ a: 2 }, 2],
+ [{ a: 3 }, 3],
+ ]);
+ expect(a instanceof WeakMap).toBeTrue();
+ });
+});
diff --git a/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.delete.js b/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.delete.js
new file mode 100644
index 0000000000..dd12bd8b1a
--- /dev/null
+++ b/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.delete.js
@@ -0,0 +1,13 @@
+test("basic functionality", () => {
+ expect(WeakMap.prototype.delete).toHaveLength(1);
+
+ var original = [
+ [{ a: 1 }, 1],
+ [{ a: 2 }, 2],
+ [{ a: 3 }, 3],
+ ];
+ const weakMap = new WeakMap(original);
+ expect(weakMap.delete(original[0][0])).toBeTrue();
+ expect(weakMap.delete(original[0][0])).toBeFalse();
+ expect(weakMap.delete(null)).toBeFalse();
+});
diff --git a/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.get.js b/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.get.js
new file mode 100644
index 0000000000..09cd06c970
--- /dev/null
+++ b/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.get.js
@@ -0,0 +1,12 @@
+test("basic functionality", () => {
+ expect(WeakMap.prototype.get).toHaveLength(1);
+
+ var original = [
+ [{ a: 1 }, 1],
+ [{ a: 2 }, 2],
+ [{ a: 3 }, 3],
+ ];
+ const weakMap = new WeakMap(original);
+ expect(weakMap.get(original[0][0])).toBe(original[0][1]);
+ expect(weakMap.get(null)).toBe(undefined);
+});
diff --git a/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.has.js b/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.has.js
new file mode 100644
index 0000000000..b0d67baa54
--- /dev/null
+++ b/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.has.js
@@ -0,0 +1,16 @@
+test("length is 1", () => {
+ expect(WeakMap.prototype.has).toHaveLength(1);
+});
+
+test("basic functionality", () => {
+ var original = [
+ [{ a: 1 }, 1],
+ [{ a: 2 }, 2],
+ [{ a: 3 }, 3],
+ ];
+ var weakMap = new WeakMap(original);
+
+ expect(new WeakMap().has()).toBeFalse();
+ expect(weakMap.has(original[0][0])).toBeTrue();
+ expect(weakMap.has({ a: 1 })).toBeFalse();
+});
diff --git a/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.set.js b/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.set.js
new file mode 100644
index 0000000000..f7e422da8e
--- /dev/null
+++ b/Userland/Libraries/LibJS/Tests/builtins/WeakMap/WeakMap.prototype.set.js
@@ -0,0 +1,30 @@
+test("basic functionality", () => {
+ expect(WeakMap.prototype.set).toHaveLength(2);
+
+ const weakMap = new WeakMap([
+ [{ a: 1 }, 1],
+ [{ a: 2 }, 2],
+ [{ a: 3 }, 3],
+ ]);
+ expect(weakMap.set({ a: 4 }, 4)).toBe(weakMap);
+ expect(weakMap.set({ a: 1 }, 2)).toBe(weakMap);
+});
+
+test("invalid values", () => {
+ const weakMap = new WeakMap();
+ [-100, Infinity, NaN, "hello", 152n].forEach(value => {
+ expect(() => {
+ weakMap.set(value, value);
+ }).toThrowWithMessage(TypeError, "is not an object");
+ });
+});
+
+test("automatic removal of garbage-collected values", () => {
+ const weakMap = new WeakMap();
+ {
+ expect(weakMap.set({ a: 1 }, 1)).toBe(weakMap);
+ expect(getWeakMapSize(weakMap)).toBe(1);
+ }
+ gc();
+ expect(getWeakMapSize(weakMap)).toBe(0);
+});
diff --git a/Userland/Libraries/LibTest/JavaScriptTestRunner.h b/Userland/Libraries/LibTest/JavaScriptTestRunner.h
index 57ce930e3b..a810cee517 100644
--- a/Userland/Libraries/LibTest/JavaScriptTestRunner.h
+++ b/Userland/Libraries/LibTest/JavaScriptTestRunner.h
@@ -27,6 +27,7 @@
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/JSONObject.h>
#include <LibJS/Runtime/TypedArray.h>
+#include <LibJS/Runtime/WeakMap.h>
#include <LibJS/Runtime/WeakSet.h>
#include <LibTest/Results.h>
#include <fcntl.h>