فهرست منبع

LibJS: Add private references

davidot 3 سال پیش
والد
کامیت
c7a6572789
2فایلهای تغییر یافته به همراه43 افزوده شده و 5 حذف شده
  1. 18 1
      Userland/Libraries/LibJS/Runtime/Reference.cpp
  2. 25 4
      Userland/Libraries/LibJS/Runtime/Reference.h

+ 18 - 1
Userland/Libraries/LibJS/Runtime/Reference.cpp

@@ -37,6 +37,11 @@ void Reference::put_value(GlobalObject& global_object, Value value)
             return;
         auto* base_obj = base_obj_or_error.release_value();
 
+        if (is_private_reference()) {
+            base_obj->private_set(m_private_name, value);
+            return;
+        }
+
         auto succeeded_or_error = base_obj->internal_set(m_name, value, get_this_value());
         if (succeeded_or_error.is_error())
             return;
@@ -76,6 +81,10 @@ Value Reference::get_value(GlobalObject& global_object) const
 
     if (is_property_reference()) {
         auto* base_obj = TRY_OR_DISCARD(m_base_value.to_object(global_object));
+
+        if (is_private_reference())
+            return TRY_OR_DISCARD(base_obj->private_get(m_private_name));
+
         return TRY_OR_DISCARD(base_obj->get(m_name));
     }
 
@@ -111,7 +120,7 @@ bool Reference::delete_(GlobalObject& global_object)
     // 5. If IsPropertyReference(ref) is true, then
     if (is_property_reference()) {
         // a. Assert: ! IsPrivateReference(ref) is false.
-        // FIXME: We don't have private references yet.
+        VERIFY(!is_private_reference());
 
         // b. If IsSuperReference(ref) is true, throw a ReferenceError exception.
         if (is_super_reference()) {
@@ -181,4 +190,12 @@ String Reference::to_string() const
     return builder.to_string();
 }
 
+// 6.2.4.9 MakePrivateReference ( baseValue, privateIdentifier ), https://tc39.es/ecma262/#sec-makeprivatereference
+Reference make_private_reference(VM& vm, Value base_value, FlyString const& private_identifier)
+{
+    auto* private_environment = vm.running_execution_context().private_environment;
+    VERIFY(private_environment);
+    return Reference { base_value, private_environment->resolve_private_identifier(private_identifier) };
+}
+
 }

+ 25 - 4
Userland/Libraries/LibJS/Runtime/Reference.h

@@ -15,6 +15,8 @@
 
 namespace JS {
 
+Reference make_private_reference(VM&, Value base_value, FlyString const& private_identifier);
+
 class Reference {
 public:
     enum class BaseType : u8 {
@@ -55,6 +57,16 @@ public:
     {
     }
 
+    Reference(Value base, PrivateName name)
+        : m_base_type(BaseType::Value)
+        , m_base_value(base)
+        , m_this_value(Value {})
+        , m_strict(true)
+        , m_is_private(true)
+        , m_private_name(move(name))
+    {
+    }
+
     Value base() const
     {
         VERIFY(m_base_type == BaseType::Value);
@@ -80,9 +92,7 @@ public:
             return false;
         if (m_base_type == BaseType::Environment)
             return false;
-        if (m_base_value.is_boolean() || m_base_value.is_string() || m_base_value.is_symbol() || m_base_value.is_bigint() || m_base_value.is_number() || m_base_value.is_object())
-            return true;
-        return false;
+        return true;
     }
 
     // 6.2.4.7 GetThisValue ( V ), https://tc39.es/ecma262/#sec-getthisvalue
@@ -100,6 +110,12 @@ public:
         return !m_this_value.is_empty();
     }
 
+    // 6.2.4.4 IsPrivateReference ( V ), https://tc39.es/ecma262/#sec-isprivatereference
+    bool is_private_reference() const
+    {
+        return m_is_private;
+    }
+
     // Note: Non-standard helper.
     bool is_environment_reference() const
     {
@@ -119,7 +135,7 @@ public:
 
     String to_string() const;
 
-    bool is_valid_reference() const { return m_name.is_valid(); }
+    bool is_valid_reference() const { return m_name.is_valid() || m_is_private; }
 
     Optional<EnvironmentCoordinate> environment_coordinate() const { return m_environment_coordinate; }
 
@@ -134,6 +150,11 @@ private:
     PropertyName m_name;
     Value m_this_value;
     bool m_strict { false };
+
+    bool m_is_private { false };
+    // FIXME: This can (probably) be an union with m_name.
+    PrivateName m_private_name { 0, "" };
+
     Optional<EnvironmentCoordinate> m_environment_coordinate;
 };