Changeset 155008 in webkit


Ignore:
Timestamp:
Sep 3, 2013 4:21:10 PM (11 years ago)
Author:
oliver@apple.com
Message:

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

Reviewed by Simon Fraser.

Source/JavaScriptCore:

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

  • JavaScriptCore.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):

Location:
trunk
Files:
3 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r155002 r155008  
     12013-09-03  Oliver Hunt  <oliver@apple.com>
     2
     3        Support structured clone of Map and Set
     4        https://bugs.webkit.org/show_bug.cgi?id=120654
     5
     6        Reviewed by Simon Fraser.
     7
     8        Tests!
     9
     10        * fast/dom/Window/script-tests/postmessage-clone.js:
     11        (set new):
     12        (set add.set add):
     13
    1142013-09-03  Bear Travis  <betravis@adobe.com>
    215
  • trunk/LayoutTests/fast/dom/Window/script-tests/postmessage-clone.js

    r114992 r155008  
    4444tryPostMessage('({get a() { throw "x" }})', true);
    4545
     46var map = new Map;
     47var set = new Set;
     48map.expando1 = {};
     49map.expando2 = {};
     50map.aSet = set;
     51map.set(1, 2.5)
     52map.set("entry", map.expando1);
     53map.set(true, set);
     54map.set(map.expando2, map);
     55set.add(false)
     56set.add(map)
     57tryPostMessage("map", false, "evalThunk", function (v) {
     58    newMap = v
     59    doPassFail(newMap.get("entry") === newMap.expando1, "String keyed entry was cloned correctly");
     60    doPassFail(newMap.get(newMap.expando2) === newMap, "Object key entry was cloned correctly");
     61    shouldBe("newMap.get(true)", "newMap.aSet")
     62    shouldBe("newMap.aSet.has(newMap)", "true")
     63    newMap.forEach(function (value, key) {
     64        console.innerHTML += "LOG: " + value + " => " + key + "<br>"
     65    })
     66})
     67
    4668if (window.eventSender) {
    4769    var fileInput = document.getElementById("fileInput");
  • trunk/LayoutTests/fast/dom/Window/window-postmessage-clone-expected.txt

    r135168 r155008  
    3838PASS: eventData.graph1 is === to eventData.graph2
    3939PASS: eventData[0] is === to eventData[1]
     40PASS: String keyed entry was cloned correctly
     41PASS: Object key entry was cloned correctly
     42PASS: newMap.get(true) is [object Set] of type object
     43PASS: newMap.aSet.has(newMap) is true of type boolean
     44LOG: 2.5 => 1
     45LOG: [object Object] => entry
     46LOG: [object Set] => true
     47LOG: [object Map] => [object Object]
    4048PASS: eventData is [object ImageData] of type object
    4149PASS: eventData is [object Uint8ClampedArray] of type object
  • trunk/Source/JavaScriptCore/ChangeLog

    r154992 r155008  
     12013-09-03  Oliver Hunt  <oliver@apple.com>
     2
     3        Support structured clone of Map and Set
     4        https://bugs.webkit.org/show_bug.cgi?id=120654
     5
     6        Reviewed by Simon Fraser.
     7
     8        Make xcode copy the required headers, and add appropriate export attributes
     9
     10        * JavaScriptCore.xcodeproj/project.pbxproj:
     11        * runtime/JSMap.h:
     12        * runtime/JSSet.h:
     13        * runtime/MapData.h:
     14
    1152013-09-02  Ryosuke Niwa  <rniwa@webkit.org>
    216
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r154992 r155008  
    816816                A700873E17CBE8D300C3E643 /* MapPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = A700873C17CBE8D300C3E643 /* MapPrototype.h */; };
    817817                A700874117CBE8EB00C3E643 /* JSMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A700873F17CBE8EB00C3E643 /* JSMap.cpp */; };
    818                 A700874217CBE8EB00C3E643 /* JSMap.h in Headers */ = {isa = PBXBuildFile; fileRef = A700874017CBE8EB00C3E643 /* JSMap.h */; };
     818                A700874217CBE8EB00C3E643 /* JSMap.h in Headers */ = {isa = PBXBuildFile; fileRef = A700874017CBE8EB00C3E643 /* JSMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
    819819                A70447EA17A0BD4600F5898E /* OperandsInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = A70447E917A0BD4600F5898E /* OperandsInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
    820820                A70447ED17A0BD7000F5898E /* DumpContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A70447EB17A0BD7000F5898E /* DumpContext.cpp */; };
     
    839839                A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A729009B17976C6000317298 /* MacroAssemblerARMv7.cpp */; };
    840840                A7299D9D17D12837005F5FF9 /* JSSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7299D9B17D12837005F5FF9 /* JSSet.cpp */; };
    841                 A7299D9E17D12837005F5FF9 /* JSSet.h in Headers */ = {isa = PBXBuildFile; fileRef = A7299D9C17D12837005F5FF9 /* JSSet.h */; };
     841                A7299D9E17D12837005F5FF9 /* JSSet.h in Headers */ = {isa = PBXBuildFile; fileRef = A7299D9C17D12837005F5FF9 /* JSSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
    842842                A7299DA117D12848005F5FF9 /* SetPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7299D9F17D12848005F5FF9 /* SetPrototype.cpp */; };
    843843                A7299DA217D12848005F5FF9 /* SetPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = A7299DA017D12848005F5FF9 /* SetPrototype.h */; };
     
    883883                A784A26411D16622005776AC /* SyntaxChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7EE7711B98B8D0065A14F /* SyntaxChecker.h */; settings = {ATTRIBUTES = (Private, ); }; };
    884884                A78507D617CBC6FD0011F6E7 /* MapData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A78507D417CBC6FD0011F6E7 /* MapData.cpp */; };
    885                 A78507D717CBC6FD0011F6E7 /* MapData.h in Headers */ = {isa = PBXBuildFile; fileRef = A78507D517CBC6FD0011F6E7 /* MapData.h */; };
     885                A78507D717CBC6FD0011F6E7 /* MapData.h in Headers */ = {isa = PBXBuildFile; fileRef = A78507D517CBC6FD0011F6E7 /* MapData.h */; settings = {ATTRIBUTES = (Private, ); }; };
    886886                A78853F917972629001440E4 /* IntendedStructureChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A78853F717972629001440E4 /* IntendedStructureChain.cpp */; };
    887887                A78853FA17972629001440E4 /* IntendedStructureChain.h in Headers */ = {isa = PBXBuildFile; fileRef = A78853F817972629001440E4 /* IntendedStructureChain.h */; settings = {ATTRIBUTES = (Private, ); }; };
  • trunk/Source/JavaScriptCore/runtime/JSMap.h

    r154861 r155008  
    3737    typedef JSNonFinalObject Base;
    3838
    39     DECLARE_INFO;
     39    DECLARE_EXPORT_INFO;
    4040
    4141    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     
    6767    }
    6868
    69     void finishCreation(VM&, JSGlobalObject*);
     69    JS_EXPORT_PRIVATE void finishCreation(VM&, JSGlobalObject*);
    7070
    7171    static void visitChildren(JSCell*, SlotVisitor&);
  • trunk/Source/JavaScriptCore/runtime/JSSet.h

    r154916 r155008  
    3737    typedef JSNonFinalObject Base;
    3838
    39     DECLARE_INFO;
     39    DECLARE_EXPORT_INFO;
    4040
    4141    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
     
    6767    }
    6868
    69     void finishCreation(VM&, JSGlobalObject*);
     69    JS_EXPORT_PRIVATE void finishCreation(VM&, JSGlobalObject*);
    7070   
    7171    static void visitChildren(JSCell*, SlotVisitor&);
  • trunk/Source/JavaScriptCore/runtime/MapData.h

    r154864 r155008  
    8181    }
    8282
    83     void set(CallFrame*, KeyType, JSValue);
     83    JS_EXPORT_PRIVATE void set(CallFrame*, KeyType, JSValue);
    8484    JSValue get(CallFrame*, KeyType);
    8585    bool remove(CallFrame*, KeyType);
  • trunk/Source/WebCore/ChangeLog

    r155002 r155008  
     12013-09-03  Oliver Hunt  <oliver@apple.com>
     2
     3        Support structured clone of Map and Set
     4        https://bugs.webkit.org/show_bug.cgi?id=120654
     5
     6        Reviewed by Simon Fraser.
     7
     8        Add support for cloning Map and Set.  Fairly self explanatory change.
     9        Needed to add Forwarding headers for the JSMap, JSSet and MapData classes.
     10
     11        * ForwardingHeaders/runtime/JSMap.h: Added.
     12        * ForwardingHeaders/runtime/JSSet.h: Added.
     13        * ForwardingHeaders/runtime/MapData.h: Added.
     14        * bindings/js/SerializedScriptValue.cpp:
     15        (WebCore::CloneSerializer::isMap):
     16        (WebCore::CloneSerializer::isSet):
     17        (WebCore::CloneSerializer::startSet):
     18        (WebCore::CloneSerializer::startMap):
     19        (WebCore::CloneSerializer::serialize):
     20        (WebCore::CloneDeserializer::consumeMapDataTerminationIfPossible):
     21        (WebCore::CloneDeserializer::deserialize):
     22
    1232013-09-03  Bear Travis  <betravis@adobe.com>
    224
  • trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp

    r154797 r155008  
    5555#include <runtime/JSArrayBufferView.h>
    5656#include <runtime/JSDataView.h>
     57#include <runtime/JSMap.h>
     58#include <runtime/JSSet.h>
    5759#include <runtime/JSTypedArrays.h>
     60#include <runtime/MapData.h>
    5861#include <runtime/ObjectConstructor.h>
    5962#include <runtime/Operations.h>
     
    8083
    8184enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember,
    82     ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember };
     85    ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember,
     86    MapDataStartVisitEntry, MapDataEndVisitKey, MapDataEndVisitValue };
    8387
    8488// These can't be reordered, and any new types must be added to the end of the list
     
    112116    EmptyStringObjectTag = 27,
    113117    NumberObjectTag = 28,
     118    SetObjectTag = 29,
     119    MapObjectTag = 30,
     120    NonMapPropertiesTag = 31,
    114121    ErrorTag = 255
    115122};
     
    159166 * and EmptyStringObjectTag for serialization of Boolean, Number and String objects.
    160167 * Version 4. added support for serializing non-index properties of arrays.
     168 * Version 5. added support for Map and Set types.
    161169 */
    162 static const unsigned CurrentVersion = 4;
     170static const unsigned CurrentVersion = 5;
    163171static const unsigned TerminatorTag = 0xFFFFFFFF;
    164172static const unsigned StringPoolTag = 0xFFFFFFFE;
     
    174182 *
    175183 * SerializedValue :- <CurrentVersion:uint32_t> Value
    176  * Value :- Array | Object | Terminal
     184 * Value :- Array | Object | Map | Set | Terminal
    177185 *
    178186 * Array :-
     
    181189 * Object :-
    182190 *     ObjectTag (<name:StringData><value:Value>)* TerminatorTag
     191 *
     192 * Map :- MapObjectTag MapData
     193 *
     194 * Set :- SetObjectTag MapData
     195 *
     196 * MapData :- (<key:Value><value:Value>) NonMapPropertiesTag (<name:StringData><value:Value>)* TerminatorTag
    183197 *
    184198 * Terminal :-
     
    400414    }
    401415
     416    bool isMap(JSValue value)
     417    {
     418        if (!value.isObject())
     419            return false;
     420        JSObject* object = asObject(value);
     421        return object->inherits(JSMap::info());
     422    }
     423    bool isSet(JSValue value)
     424    {
     425        if (!value.isObject())
     426            return false;
     427        JSObject* object = asObject(value);
     428        return object->inherits(JSSet::info());
     429    }
     430
    402431    bool checkForDuplicate(JSObject* object)
    403432    {
     
    446475        write(ArrayTag);
    447476        write(length);
     477        return true;
     478    }
     479
     480    bool startSet(JSSet* set)
     481    {
     482        if (!startObjectInternal(set))
     483            return false;
     484
     485        write(SetObjectTag);
     486        return true;
     487    }
     488
     489    bool startMap(JSMap* map)
     490    {
     491        if (!startObjectInternal(map))
     492            return false;
     493
     494        write(MapObjectTag);
    448495        return true;
    449496    }
     
    822869    Vector<PropertyNameArray, 16> propertyStack;
    823870    Vector<JSObject*, 32> inputObjectStack;
     871    Vector<MapData*, 4> mapDataStack;
     872    Vector<MapData::const_iterator, 4> iteratorStack;
    824873    Vector<WalkerState, 16> stateStack;
    825874    WalkerState state = StateUnknown;
     
    946995                goto objectStartVisitMember;
    947996            }
     997            mapStartState: {
     998                ASSERT(inValue.isObject());
     999                if (inputObjectStack.size() > maximumFilterRecursion)
     1000                    return StackOverflowError;
     1001                JSMap* inMap = jsCast<JSMap*>(inValue);
     1002                if (!startMap(inMap))
     1003                    break;
     1004                MapData* mapData = inMap->mapData();
     1005                m_gcBuffer.append(mapData);
     1006                mapDataStack.append(mapData);
     1007                iteratorStack.append(mapData->begin());
     1008                inputObjectStack.append(inMap);
     1009                goto mapDataStartVisitEntry;
     1010            }
     1011            setStartState: {
     1012                ASSERT(inValue.isObject());
     1013                if (inputObjectStack.size() > maximumFilterRecursion)
     1014                    return StackOverflowError;
     1015                JSSet* inSet = jsCast<JSSet*>(inValue);
     1016                if (!startSet(inSet))
     1017                    break;
     1018                MapData* mapData = inSet->mapData();
     1019                m_gcBuffer.append(mapData);
     1020                mapDataStack.append(mapData);
     1021                iteratorStack.append(mapData->begin());
     1022                inputObjectStack.append(inSet);
     1023                goto mapDataStartVisitEntry;
     1024            }
     1025            mapDataStartVisitEntry:
     1026            case MapDataStartVisitEntry: {
     1027                MapData::const_iterator& ptr = iteratorStack.last();
     1028                MapData* mapData = mapDataStack.last();
     1029                if (ptr == mapData->end()) {
     1030                    iteratorStack.removeLast();
     1031                    mapDataStack.removeLast();
     1032                    JSObject* object = inputObjectStack.last();
     1033                    ASSERT(jsDynamicCast<JSSet*>(object) || jsDynamicCast<JSMap*>(object));
     1034                    propertyStack.append(PropertyNameArray(m_exec));
     1035                    object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), ExcludeDontEnumProperties);
     1036                    write(NonMapPropertiesTag);
     1037                    indexStack.append(0);
     1038                    goto objectStartVisitMember;
     1039                }
     1040                inValue = ptr.key();
     1041                stateStack.append(MapDataEndVisitKey);
     1042                goto stateUnknown;
     1043            }
     1044            case MapDataEndVisitKey: {
     1045                inValue = iteratorStack.last().value();
     1046                stateStack.append(MapDataEndVisitValue);
     1047                goto stateUnknown;
     1048            }
     1049            case MapDataEndVisitValue: {
     1050                ++iteratorStack.last();
     1051                goto mapDataStartVisitEntry;
     1052            }
     1053
    9481054            stateUnknown:
    9491055            case StateUnknown: {
     
    9571063                if (isArray(inValue))
    9581064                    goto arrayStartState;
     1065                if (isMap(inValue))
     1066                    goto mapStartState;
     1067                if (isSet(inValue))
     1068                    goto setStartState;
    9591069                goto objectStartState;
    9601070            }
     
    15581668    }
    15591669
     1670    bool consumeMapDataTerminationIfPossible()
     1671    {
     1672        if (readTag() == NonMapPropertiesTag)
     1673            return true;
     1674        m_ptr--;
     1675        return false;
     1676    }
     1677
    15601678    JSGlobalObject* m_globalObject;
    15611679    bool m_isDOMGlobalObject;
     
    15741692    Vector<Identifier, 16> propertyNameStack;
    15751693    Vector<JSObject*, 32> outputObjectStack;
     1694    Vector<JSValue, 4> keyStack;
     1695    Vector<MapData*, 4> mapDataStack;
    15761696    Vector<WalkerState, 16> stateStack;
    15771697    WalkerState state = StateUnknown;
     
    16601780            goto objectStartVisitMember;
    16611781        }
     1782        mapObjectStartState: {
     1783            if (outputObjectStack.size() > maximumFilterRecursion)
     1784                return make_pair(JSValue(), StackOverflowError);
     1785            JSMap* map = JSMap::create(m_exec->vm(), m_globalObject->mapStructure());
     1786            m_gcBuffer.append(map);
     1787            outputObjectStack.append(map);
     1788            MapData* mapData = map->mapData();
     1789            mapDataStack.append(mapData);
     1790            goto mapDataStartVisitEntry;
     1791        }
     1792        setObjectStartState: {
     1793            if (outputObjectStack.size() > maximumFilterRecursion)
     1794                return make_pair(JSValue(), StackOverflowError);
     1795            JSSet* set = JSSet::create(m_exec->vm(), m_globalObject->setStructure());
     1796            m_gcBuffer.append(set);
     1797            outputObjectStack.append(set);
     1798            MapData* mapData = set->mapData();
     1799            mapDataStack.append(mapData);
     1800            goto mapDataStartVisitEntry;
     1801        }
     1802        mapDataStartVisitEntry:
     1803        case MapDataStartVisitEntry: {
     1804            if (consumeMapDataTerminationIfPossible()) {
     1805                mapDataStack.removeLast();
     1806                goto objectStartVisitMember;
     1807            }
     1808            stateStack.append(MapDataEndVisitKey);
     1809            goto stateUnknown;
     1810        }
     1811
     1812        case MapDataEndVisitKey: {
     1813            keyStack.append(outValue);
     1814            stateStack.append(MapDataEndVisitValue);
     1815            goto stateUnknown;
     1816        }
     1817
     1818        case MapDataEndVisitValue: {
     1819            mapDataStack.last()->set(m_exec, keyStack.last(), outValue);
     1820            keyStack.removeLast();
     1821            goto mapDataStartVisitEntry;
     1822        }
    16621823        stateUnknown:
    16631824        case StateUnknown:
     
    16711832            if (tag == ObjectTag)
    16721833                goto objectStartState;
     1834            if (tag == MapObjectTag)
     1835                goto mapObjectStartState;
     1836            if (tag == SetObjectTag)
     1837                goto setObjectStartState;
    16731838            goto error;
    16741839        }
Note: See TracChangeset for help on using the changeset viewer.