Title: [155008] trunk
Revision
155008
Author
[email protected]
Date
2013-09-03 16:21:10 -0700 (Tue, 03 Sep 2013)

Log Message

Support structured clone of Map and Set
https://bugs.webkit.org/show_bug.cgi?id=120654

Reviewed by Simon Fraser.

Source/_javascript_Core:

Make xcode copy the required headers, and add appropriate export attributes

* _javascript_Core.xcodeproj/project.pbxproj:
* runtime/JSMap.h:
* runtime/JSSet.h:
* runtime/MapData.h:

Source/WebCore:

Add support for cloning Map and Set.  Fairly self explanatory change.
Needed to add Forwarding headers for the JSMap, JSSet and MapData classes.

* ForwardingHeaders/runtime/JSMap.h: Added.
* ForwardingHeaders/runtime/JSSet.h: Added.
* ForwardingHeaders/runtime/MapData.h: Added.
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::isMap):
(WebCore::CloneSerializer::isSet):
(WebCore::CloneSerializer::startSet):
(WebCore::CloneSerializer::startMap):
(WebCore::CloneSerializer::serialize):
(WebCore::CloneDeserializer::consumeMapDataTerminationIfPossible):
(WebCore::CloneDeserializer::deserialize):

LayoutTests:

Tests!

* fast/dom/Window/script-tests/postmessage-clone.js:
(set new):
(set add.set add):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (155007 => 155008)


--- trunk/LayoutTests/ChangeLog	2013-09-03 23:04:12 UTC (rev 155007)
+++ trunk/LayoutTests/ChangeLog	2013-09-03 23:21:10 UTC (rev 155008)
@@ -1,3 +1,16 @@
+2013-09-03  Oliver Hunt  <[email protected]>
+
+        Support structured clone of Map and Set
+        https://bugs.webkit.org/show_bug.cgi?id=120654
+
+        Reviewed by Simon Fraser.
+
+        Tests!
+
+        * fast/dom/Window/script-tests/postmessage-clone.js:
+        (set new):
+        (set add.set add):
+
 2013-09-03  Bear Travis  <[email protected]>
 
         [CSS Shapes] Shape's content gets extra left offset when left-border is positive on the content box

Modified: trunk/LayoutTests/fast/dom/Window/script-tests/postmessage-clone.js (155007 => 155008)


--- trunk/LayoutTests/fast/dom/Window/script-tests/postmessage-clone.js	2013-09-03 23:04:12 UTC (rev 155007)
+++ trunk/LayoutTests/fast/dom/Window/script-tests/postmessage-clone.js	2013-09-03 23:21:10 UTC (rev 155008)
@@ -43,6 +43,28 @@
 tryPostMessage('window', true);
 tryPostMessage('({get a() { throw "x" }})', true);
 
+var map = new Map;
+var set = new Set;
+map.expando1 = {};
+map.expando2 = {};
+map.aSet = set;
+map.set(1, 2.5)
+map.set("entry", map.expando1);
+map.set(true, set);
+map.set(map.expando2, map);
+set.add(false)
+set.add(map)
+tryPostMessage("map", false, "evalThunk", function (v) {
+    newMap = v
+    doPassFail(newMap.get("entry") === newMap.expando1, "String keyed entry was cloned correctly");
+    doPassFail(newMap.get(newMap.expando2) === newMap, "Object key entry was cloned correctly");
+    shouldBe("newMap.get(true)", "newMap.aSet")
+    shouldBe("newMap.aSet.has(newMap)", "true")
+    newMap.forEach(function (value, key) { 
+        console.innerHTML += "LOG: " + value + " => " + key + "<br>"
+    })
+})
+
 if (window.eventSender) {
     var fileInput = document.getElementById("fileInput");
     var fileRect = fileInput.getClientRects()[0];

Modified: trunk/LayoutTests/fast/dom/Window/window-postmessage-clone-expected.txt (155007 => 155008)


--- trunk/LayoutTests/fast/dom/Window/window-postmessage-clone-expected.txt	2013-09-03 23:04:12 UTC (rev 155007)
+++ trunk/LayoutTests/fast/dom/Window/window-postmessage-clone-expected.txt	2013-09-03 23:21:10 UTC (rev 155008)
@@ -37,6 +37,14 @@
 PASS: eventData is === to eventData[0]
 PASS: eventData.graph1 is === to eventData.graph2
 PASS: eventData[0] is === to eventData[1]
+PASS: String keyed entry was cloned correctly
+PASS: Object key entry was cloned correctly
+PASS: newMap.get(true) is [object Set] of type object
+PASS: newMap.aSet.has(newMap) is true of type boolean
+LOG: 2.5 => 1
+LOG: [object Object] => entry
+LOG: [object Set] => true
+LOG: [object Map] => [object Object]
 PASS: eventData is [object ImageData] of type object
 PASS: eventData is [object Uint8ClampedArray] of type object
 PASS: eventData is [object ImageData] of type object

Modified: trunk/Source/_javascript_Core/ChangeLog (155007 => 155008)


--- trunk/Source/_javascript_Core/ChangeLog	2013-09-03 23:04:12 UTC (rev 155007)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-09-03 23:21:10 UTC (rev 155008)
@@ -1,3 +1,17 @@
+2013-09-03  Oliver Hunt  <[email protected]>
+
+        Support structured clone of Map and Set
+        https://bugs.webkit.org/show_bug.cgi?id=120654
+
+        Reviewed by Simon Fraser.
+
+        Make xcode copy the required headers, and add appropriate export attributes
+
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * runtime/JSMap.h:
+        * runtime/JSSet.h:
+        * runtime/MapData.h:
+
 2013-09-02  Ryosuke Niwa  <[email protected]>
 
         Support the "json" responseType and JSON response entity in XHR

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (155007 => 155008)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2013-09-03 23:04:12 UTC (rev 155007)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2013-09-03 23:21:10 UTC (rev 155008)
@@ -815,7 +815,7 @@
 		A700873D17CBE8D300C3E643 /* MapPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A700873B17CBE8D300C3E643 /* MapPrototype.cpp */; };
 		A700873E17CBE8D300C3E643 /* MapPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = A700873C17CBE8D300C3E643 /* MapPrototype.h */; };
 		A700874117CBE8EB00C3E643 /* JSMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A700873F17CBE8EB00C3E643 /* JSMap.cpp */; };
-		A700874217CBE8EB00C3E643 /* JSMap.h in Headers */ = {isa = PBXBuildFile; fileRef = A700874017CBE8EB00C3E643 /* JSMap.h */; };
+		A700874217CBE8EB00C3E643 /* JSMap.h in Headers */ = {isa = PBXBuildFile; fileRef = A700874017CBE8EB00C3E643 /* JSMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A70447EA17A0BD4600F5898E /* OperandsInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = A70447E917A0BD4600F5898E /* OperandsInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A70447ED17A0BD7000F5898E /* DumpContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A70447EB17A0BD7000F5898E /* DumpContext.cpp */; };
 		A70447EE17A0BD7000F5898E /* DumpContext.h in Headers */ = {isa = PBXBuildFile; fileRef = A70447EC17A0BD7000F5898E /* DumpContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -838,7 +838,7 @@
 		A7280A2811557E3000D56957 /* JSObjectRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A729009B17976C6000317298 /* MacroAssemblerARMv7.cpp */; };
 		A7299D9D17D12837005F5FF9 /* JSSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7299D9B17D12837005F5FF9 /* JSSet.cpp */; };
-		A7299D9E17D12837005F5FF9 /* JSSet.h in Headers */ = {isa = PBXBuildFile; fileRef = A7299D9C17D12837005F5FF9 /* JSSet.h */; };
+		A7299D9E17D12837005F5FF9 /* JSSet.h in Headers */ = {isa = PBXBuildFile; fileRef = A7299D9C17D12837005F5FF9 /* JSSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A7299DA117D12848005F5FF9 /* SetPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7299D9F17D12848005F5FF9 /* SetPrototype.cpp */; };
 		A7299DA217D12848005F5FF9 /* SetPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = A7299DA017D12848005F5FF9 /* SetPrototype.h */; };
 		A7299DA517D12858005F5FF9 /* SetConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7299DA317D12858005F5FF9 /* SetConstructor.cpp */; };
@@ -882,7 +882,7 @@
 		A784A26111D16622005776AC /* ASTBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7EE7411B98B8D0065A14F /* ASTBuilder.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A784A26411D16622005776AC /* SyntaxChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7EE7711B98B8D0065A14F /* SyntaxChecker.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A78507D617CBC6FD0011F6E7 /* MapData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A78507D417CBC6FD0011F6E7 /* MapData.cpp */; };
-		A78507D717CBC6FD0011F6E7 /* MapData.h in Headers */ = {isa = PBXBuildFile; fileRef = A78507D517CBC6FD0011F6E7 /* MapData.h */; };
+		A78507D717CBC6FD0011F6E7 /* MapData.h in Headers */ = {isa = PBXBuildFile; fileRef = A78507D517CBC6FD0011F6E7 /* MapData.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A78853F917972629001440E4 /* IntendedStructureChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A78853F717972629001440E4 /* IntendedStructureChain.cpp */; };
 		A78853FA17972629001440E4 /* IntendedStructureChain.h in Headers */ = {isa = PBXBuildFile; fileRef = A78853F817972629001440E4 /* IntendedStructureChain.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A78A9774179738B8009DF744 /* DFGFailedFinalizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A78A976C179738B8009DF744 /* DFGFailedFinalizer.cpp */; };

Modified: trunk/Source/_javascript_Core/runtime/JSMap.h (155007 => 155008)


--- trunk/Source/_javascript_Core/runtime/JSMap.h	2013-09-03 23:04:12 UTC (rev 155007)
+++ trunk/Source/_javascript_Core/runtime/JSMap.h	2013-09-03 23:21:10 UTC (rev 155008)
@@ -36,7 +36,7 @@
 public:
     typedef JSNonFinalObject Base;
 
-    DECLARE_INFO;
+    DECLARE_EXPORT_INFO;
 
     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     {
@@ -66,7 +66,7 @@
     {
     }
 
-    void finishCreation(VM&, JSGlobalObject*);
+    JS_EXPORT_PRIVATE void finishCreation(VM&, JSGlobalObject*);
 
     static void visitChildren(JSCell*, SlotVisitor&);
 

Modified: trunk/Source/_javascript_Core/runtime/JSSet.h (155007 => 155008)


--- trunk/Source/_javascript_Core/runtime/JSSet.h	2013-09-03 23:04:12 UTC (rev 155007)
+++ trunk/Source/_javascript_Core/runtime/JSSet.h	2013-09-03 23:21:10 UTC (rev 155008)
@@ -36,7 +36,7 @@
 public:
     typedef JSNonFinalObject Base;
 
-    DECLARE_INFO;
+    DECLARE_EXPORT_INFO;
 
     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     {
@@ -66,7 +66,7 @@
     {
     }
 
-    void finishCreation(VM&, JSGlobalObject*);
+    JS_EXPORT_PRIVATE void finishCreation(VM&, JSGlobalObject*);
     
     static void visitChildren(JSCell*, SlotVisitor&);
     

Modified: trunk/Source/_javascript_Core/runtime/MapData.h (155007 => 155008)


--- trunk/Source/_javascript_Core/runtime/MapData.h	2013-09-03 23:04:12 UTC (rev 155007)
+++ trunk/Source/_javascript_Core/runtime/MapData.h	2013-09-03 23:21:10 UTC (rev 155008)
@@ -80,7 +80,7 @@
         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
     }
 
-    void set(CallFrame*, KeyType, JSValue);
+    JS_EXPORT_PRIVATE void set(CallFrame*, KeyType, JSValue);
     JSValue get(CallFrame*, KeyType);
     bool remove(CallFrame*, KeyType);
     bool contains(CallFrame*, KeyType);

Modified: trunk/Source/WebCore/ChangeLog (155007 => 155008)


--- trunk/Source/WebCore/ChangeLog	2013-09-03 23:04:12 UTC (rev 155007)
+++ trunk/Source/WebCore/ChangeLog	2013-09-03 23:21:10 UTC (rev 155008)
@@ -1,3 +1,25 @@
+2013-09-03  Oliver Hunt  <[email protected]>
+
+        Support structured clone of Map and Set
+        https://bugs.webkit.org/show_bug.cgi?id=120654
+
+        Reviewed by Simon Fraser.
+
+        Add support for cloning Map and Set.  Fairly self explanatory change.
+        Needed to add Forwarding headers for the JSMap, JSSet and MapData classes.
+
+        * ForwardingHeaders/runtime/JSMap.h: Added.
+        * ForwardingHeaders/runtime/JSSet.h: Added.
+        * ForwardingHeaders/runtime/MapData.h: Added.
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::CloneSerializer::isMap):
+        (WebCore::CloneSerializer::isSet):
+        (WebCore::CloneSerializer::startSet):
+        (WebCore::CloneSerializer::startMap):
+        (WebCore::CloneSerializer::serialize):
+        (WebCore::CloneDeserializer::consumeMapDataTerminationIfPossible):
+        (WebCore::CloneDeserializer::deserialize):
+
 2013-09-03  Bear Travis  <[email protected]>
 
         [CSS Shapes] Shape's content gets extra left offset when left-border is positive on the content box

Added: trunk/Source/WebCore/ForwardingHeaders/runtime/JSMap.h (0 => 155008)


--- trunk/Source/WebCore/ForwardingHeaders/runtime/JSMap.h	                        (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/runtime/JSMap.h	2013-09-03 23:21:10 UTC (rev 155008)
@@ -0,0 +1,4 @@
+#ifndef WebCore_FWD_JSMap_h
+#define WebCore_FWD_JSMap_h
+#include <_javascript_Core/JSMap.h>
+#endif

Added: trunk/Source/WebCore/ForwardingHeaders/runtime/JSSet.h (0 => 155008)


--- trunk/Source/WebCore/ForwardingHeaders/runtime/JSSet.h	                        (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/runtime/JSSet.h	2013-09-03 23:21:10 UTC (rev 155008)
@@ -0,0 +1,4 @@
+#ifndef WebCore_FWD_JSSet_h
+#define WebCore_FWD_JSSet_h
+#include <_javascript_Core/JSSet.h>
+#endif

Added: trunk/Source/WebCore/ForwardingHeaders/runtime/MapData.h (0 => 155008)


--- trunk/Source/WebCore/ForwardingHeaders/runtime/MapData.h	                        (rev 0)
+++ trunk/Source/WebCore/ForwardingHeaders/runtime/MapData.h	2013-09-03 23:21:10 UTC (rev 155008)
@@ -0,0 +1,4 @@
+#ifndef WebCore_FWD_MapData_h
+#define WebCore_FWD_MapData_h
+#include <_javascript_Core/MapData.h>
+#endif

Modified: trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp (155007 => 155008)


--- trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp	2013-09-03 23:04:12 UTC (rev 155007)
+++ trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp	2013-09-03 23:21:10 UTC (rev 155008)
@@ -54,7 +54,10 @@
 #include <runtime/JSArrayBuffer.h>
 #include <runtime/JSArrayBufferView.h>
 #include <runtime/JSDataView.h>
+#include <runtime/JSMap.h>
+#include <runtime/JSSet.h>
 #include <runtime/JSTypedArrays.h>
+#include <runtime/MapData.h>
 #include <runtime/ObjectConstructor.h>
 #include <runtime/Operations.h>
 #include <runtime/PropertyNameArray.h>
@@ -79,7 +82,8 @@
 static const unsigned maximumFilterRecursion = 40000;
 
 enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember,
-    ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember };
+    ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember,
+    MapDataStartVisitEntry, MapDataEndVisitKey, MapDataEndVisitValue };
 
 // These can't be reordered, and any new types must be added to the end of the list
 enum SerializationTag {
@@ -111,6 +115,9 @@
     StringObjectTag = 26,
     EmptyStringObjectTag = 27,
     NumberObjectTag = 28,
+    SetObjectTag = 29,
+    MapObjectTag = 30,
+    NonMapPropertiesTag = 31,
     ErrorTag = 255
 };
 
@@ -158,8 +165,9 @@
  * Version 3. added the FalseObjectTag, TrueObjectTag, NumberObjectTag, StringObjectTag
  * and EmptyStringObjectTag for serialization of Boolean, Number and String objects.
  * Version 4. added support for serializing non-index properties of arrays.
+ * Version 5. added support for Map and Set types.
  */
-static const unsigned CurrentVersion = 4;
+static const unsigned CurrentVersion = 5;
 static const unsigned TerminatorTag = 0xFFFFFFFF;
 static const unsigned StringPoolTag = 0xFFFFFFFE;
 static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
@@ -173,7 +181,7 @@
  * in the constant pool.
  *
  * SerializedValue :- <CurrentVersion:uint32_t> Value
- * Value :- Array | Object | Terminal
+ * Value :- Array | Object | Map | Set | Terminal
  *
  * Array :-
  *     ArrayTag <length:uint32_t>(<index:uint32_t><value:Value>)* TerminatorTag
@@ -181,6 +189,12 @@
  * Object :-
  *     ObjectTag (<name:StringData><value:Value>)* TerminatorTag
  *
+ * Map :- MapObjectTag MapData
+ *
+ * Set :- SetObjectTag MapData
+ *
+ * MapData :- (<key:Value><value:Value>) NonMapPropertiesTag (<name:StringData><value:Value>)* TerminatorTag
+ *
  * Terminal :-
  *      UndefinedTag
  *    | NullTag
@@ -399,6 +413,21 @@
         return isJSArray(object) || object->inherits(JSArray::info());
     }
 
+    bool isMap(JSValue value)
+    {
+        if (!value.isObject())
+            return false;
+        JSObject* object = asObject(value);
+        return object->inherits(JSMap::info());
+    }
+    bool isSet(JSValue value)
+    {
+        if (!value.isObject())
+            return false;
+        JSObject* object = asObject(value);
+        return object->inherits(JSSet::info());
+    }
+
     bool checkForDuplicate(JSObject* object)
     {
         // Record object for graph reconstruction
@@ -448,6 +477,24 @@
         return true;
     }
 
+    bool startSet(JSSet* set)
+    {
+        if (!startObjectInternal(set))
+            return false;
+
+        write(SetObjectTag);
+        return true;
+    }
+
+    bool startMap(JSMap* map)
+    {
+        if (!startObjectInternal(map))
+            return false;
+
+        write(MapObjectTag);
+        return true;
+    }
+
     void endObject()
     {
         write(TerminatorTag);
@@ -821,6 +868,8 @@
     Vector<uint32_t, 16> lengthStack;
     Vector<PropertyNameArray, 16> propertyStack;
     Vector<JSObject*, 32> inputObjectStack;
+    Vector<MapData*, 4> mapDataStack;
+    Vector<MapData::const_iterator, 4> iteratorStack;
     Vector<WalkerState, 16> stateStack;
     WalkerState state = StateUnknown;
     JSValue inValue = in;
@@ -945,6 +994,63 @@
                 indexStack.last()++;
                 goto objectStartVisitMember;
             }
+            mapStartState: {
+                ASSERT(inValue.isObject());
+                if (inputObjectStack.size() > maximumFilterRecursion)
+                    return StackOverflowError;
+                JSMap* inMap = jsCast<JSMap*>(inValue);
+                if (!startMap(inMap))
+                    break;
+                MapData* mapData = inMap->mapData();
+                m_gcBuffer.append(mapData);
+                mapDataStack.append(mapData);
+                iteratorStack.append(mapData->begin());
+                inputObjectStack.append(inMap);
+                goto mapDataStartVisitEntry;
+            }
+            setStartState: {
+                ASSERT(inValue.isObject());
+                if (inputObjectStack.size() > maximumFilterRecursion)
+                    return StackOverflowError;
+                JSSet* inSet = jsCast<JSSet*>(inValue);
+                if (!startSet(inSet))
+                    break;
+                MapData* mapData = inSet->mapData();
+                m_gcBuffer.append(mapData);
+                mapDataStack.append(mapData);
+                iteratorStack.append(mapData->begin());
+                inputObjectStack.append(inSet);
+                goto mapDataStartVisitEntry;
+            }
+            mapDataStartVisitEntry:
+            case MapDataStartVisitEntry: {
+                MapData::const_iterator& ptr = iteratorStack.last();
+                MapData* mapData = mapDataStack.last();
+                if (ptr == mapData->end()) {
+                    iteratorStack.removeLast();
+                    mapDataStack.removeLast();
+                    JSObject* object = inputObjectStack.last();
+                    ASSERT(jsDynamicCast<JSSet*>(object) || jsDynamicCast<JSMap*>(object));
+                    propertyStack.append(PropertyNameArray(m_exec));
+                    object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), ExcludeDontEnumProperties);
+                    write(NonMapPropertiesTag);
+                    indexStack.append(0);
+                    goto objectStartVisitMember;
+                }
+                inValue = ptr.key();
+                stateStack.append(MapDataEndVisitKey);
+                goto stateUnknown;
+            }
+            case MapDataEndVisitKey: {
+                inValue = iteratorStack.last().value();
+                stateStack.append(MapDataEndVisitValue);
+                goto stateUnknown;
+            }
+            case MapDataEndVisitValue: {
+                ++iteratorStack.last();
+                goto mapDataStartVisitEntry;
+            }
+
             stateUnknown:
             case StateUnknown: {
                 SerializationReturnCode terminalCode = SuccessfullyCompleted;
@@ -956,6 +1062,10 @@
 
                 if (isArray(inValue))
                     goto arrayStartState;
+                if (isMap(inValue))
+                    goto mapStartState;
+                if (isSet(inValue))
+                    goto setStartState;
                 goto objectStartState;
             }
         }
@@ -1557,6 +1667,14 @@
         }
     }
 
+    bool consumeMapDataTerminationIfPossible()
+    {
+        if (readTag() == NonMapPropertiesTag)
+            return true;
+        m_ptr--;
+        return false;
+    }
+
     JSGlobalObject* m_globalObject;
     bool m_isDOMGlobalObject;
     const uint8_t* m_ptr;
@@ -1573,6 +1691,8 @@
     Vector<uint32_t, 16> indexStack;
     Vector<Identifier, 16> propertyNameStack;
     Vector<JSObject*, 32> outputObjectStack;
+    Vector<JSValue, 4> keyStack;
+    Vector<MapData*, 4> mapDataStack;
     Vector<WalkerState, 16> stateStack;
     WalkerState state = StateUnknown;
     JSValue outValue;
@@ -1659,6 +1779,47 @@
             propertyNameStack.removeLast();
             goto objectStartVisitMember;
         }
+        mapObjectStartState: {
+            if (outputObjectStack.size() > maximumFilterRecursion)
+                return make_pair(JSValue(), StackOverflowError);
+            JSMap* map = JSMap::create(m_exec->vm(), m_globalObject->mapStructure());
+            m_gcBuffer.append(map);
+            outputObjectStack.append(map);
+            MapData* mapData = map->mapData();
+            mapDataStack.append(mapData);
+            goto mapDataStartVisitEntry;
+        }
+        setObjectStartState: {
+            if (outputObjectStack.size() > maximumFilterRecursion)
+                return make_pair(JSValue(), StackOverflowError);
+            JSSet* set = JSSet::create(m_exec->vm(), m_globalObject->setStructure());
+            m_gcBuffer.append(set);
+            outputObjectStack.append(set);
+            MapData* mapData = set->mapData();
+            mapDataStack.append(mapData);
+            goto mapDataStartVisitEntry;
+        }
+        mapDataStartVisitEntry:
+        case MapDataStartVisitEntry: {
+            if (consumeMapDataTerminationIfPossible()) {
+                mapDataStack.removeLast();
+                goto objectStartVisitMember;
+            }
+            stateStack.append(MapDataEndVisitKey);
+            goto stateUnknown;
+        }
+
+        case MapDataEndVisitKey: {
+            keyStack.append(outValue);
+            stateStack.append(MapDataEndVisitValue);
+            goto stateUnknown;
+        }
+
+        case MapDataEndVisitValue: {
+            mapDataStack.last()->set(m_exec, keyStack.last(), outValue);
+            keyStack.removeLast();
+            goto mapDataStartVisitEntry;
+        }
         stateUnknown:
         case StateUnknown:
             if (JSValue terminal = readTerminal()) {
@@ -1670,6 +1831,10 @@
                 goto arrayStartState;
             if (tag == ObjectTag)
                 goto objectStartState;
+            if (tag == MapObjectTag)
+                goto mapObjectStartState;
+            if (tag == SetObjectTag)
+                goto setObjectStartState;
             goto error;
         }
         if (stateStack.isEmpty())
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to