]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/MapConstructor.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / MapConstructor.cpp
index 04f17d985f616a887b9c77b4df0ca86bb2cd26a1..fad52c056048e18b7eec498ff14953fd90fcfedd 100644 (file)
@@ -27,6 +27,7 @@
 #include "MapConstructor.h"
 
 #include "Error.h"
+#include "IteratorOperations.h"
 #include "JSCJSValueInlines.h"
 #include "JSCellInlines.h"
 #include "JSGlobalObject.h"
@@ -36,7 +37,7 @@
 
 namespace JSC {
 
-const ClassInfo MapConstructor::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(MapConstructor) };
+const ClassInfo MapConstructor::s_info = { "Function", &Base::s_info, 0, CREATE_METHOD_TABLE(MapConstructor) };
 
 void MapConstructor::finishCreation(VM& vm, MapPrototype* mapPrototype)
 {
@@ -45,18 +46,87 @@ void MapConstructor::finishCreation(VM& vm, MapPrototype* mapPrototype)
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum | DontDelete);
 }
 
-static EncodedJSValue JSC_HOST_CALL constructMap(ExecState* exec)
+static EncodedJSValue JSC_HOST_CALL callMap(ExecState* exec)
 {
-    // Until we have iterators we throw if we've been given
-    // any arguments that could require us to throw.
-    if (!exec->argument(0).isUndefinedOrNull())
-        return JSValue::encode(throwTypeError(exec, ASCIILiteral("Map constructor does not accept arguments")));
-    if (!exec->argument(1).isUndefined())
-        return throwVMError(exec, createRangeError(exec, WTF::ASCIILiteral("Invalid comparator function")));
+    return JSValue::encode(throwTypeError(exec, ASCIILiteral("Map cannot be called as a function")));
+}
 
+static EncodedJSValue JSC_HOST_CALL constructMap(ExecState* exec)
+{
     JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
     Structure* mapStructure = globalObject->mapStructure();
-    return JSValue::encode(JSMap::create(exec, mapStructure));
+    JSMap* map = JSMap::create(exec, mapStructure);
+    JSValue iterable = exec->argument(0);
+    if (iterable.isUndefinedOrNull())
+        return JSValue::encode(map);
+
+    JSValue adderFunction = map->JSObject::get(exec, exec->propertyNames().set);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    CallData adderFunctionCallData;
+    CallType adderFunctionCallType = getCallData(adderFunction, adderFunctionCallData);
+    if (adderFunctionCallType == CallTypeNone)
+        return JSValue::encode(throwTypeError(exec));
+
+    JSValue iteratorFunction = iterable.get(exec, exec->propertyNames().iteratorSymbol);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    CallData iteratorFunctionCallData;
+    CallType iteratorFunctionCallType = getCallData(iteratorFunction, iteratorFunctionCallData);
+    if (iteratorFunctionCallType == CallTypeNone)
+        return JSValue::encode(throwTypeError(exec));
+
+    ArgList iteratorFunctionArguments;
+    JSValue iterator = call(exec, iteratorFunction, iteratorFunctionCallType, iteratorFunctionCallData, iterable, iteratorFunctionArguments);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    if (!iterator.isObject())
+        return JSValue::encode(throwTypeError(exec));
+
+    while (true) {
+        JSValue next = iteratorStep(exec, iterator);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+
+        if (next.isFalse())
+            return JSValue::encode(map);
+
+        JSValue nextItem = iteratorValue(exec, next);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+
+        if (!nextItem.isObject()) {
+            throwTypeError(exec);
+            iteratorClose(exec, iterator);
+            return JSValue::encode(jsUndefined());
+        }
+
+        JSValue key = nextItem.get(exec, 0);
+        if (exec->hadException()) {
+            iteratorClose(exec, iterator);
+            return JSValue::encode(jsUndefined());
+        }
+
+        JSValue value = nextItem.get(exec, 1);
+        if (exec->hadException()) {
+            iteratorClose(exec, iterator);
+            return JSValue::encode(jsUndefined());
+        }
+
+        MarkedArgumentBuffer arguments;
+        arguments.append(key);
+        arguments.append(value);
+        call(exec, adderFunction, adderFunctionCallType, adderFunctionCallData, map, arguments);
+        if (exec->hadException()) {
+            iteratorClose(exec, iterator);
+            return JSValue::encode(jsUndefined());
+        }
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return JSValue::encode(map);
 }
 
 ConstructType MapConstructor::getConstructData(JSCell*, ConstructData& constructData)
@@ -67,7 +137,7 @@ ConstructType MapConstructor::getConstructData(JSCell*, ConstructData& construct
 
 CallType MapConstructor::getCallData(JSCell*, CallData& callData)
 {
-    callData.native.function = constructMap;
+    callData.native.function = callMap;
     return CallTypeHost;
 }