Changeset 204438 in webkit


Ignore:
Timestamp:
Aug 12, 2016 7:02:04 PM (8 years ago)
Author:
rniwa@webkit.org
Message:

Add a helper class for enumerating elements in an iterable object
https://bugs.webkit.org/show_bug.cgi?id=160800

Reviewed by Benjamin Poulain.

Added iteratorForIterable which provides an abstraction for iterating over an iterable object,
and deployed it in the constructors of Set, WeakSet, Map, and WeakMap.

Also added a helper function iteratorForIterable, which retrieves the iterator out of an iterable object.

  • runtime/IteratorOperations.cpp:

(JSC::iteratorForIterable): Added.

  • runtime/IteratorOperations.h:

(JSC::forEachInIterable): Added.

  • runtime/MapConstructor.cpp:

(JSC::constructMap):

  • runtime/SetConstructor.cpp:

(JSC::constructSet):

  • runtime/WeakMapConstructor.cpp:

(JSC::constructWeakMap):

  • runtime/WeakSetConstructor.cpp:

(JSC::constructWeakSet):

Location:
trunk/Source/JavaScriptCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r204424 r204438  
     12016-08-12  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Add a helper class for enumerating elements in an iterable object
     4        https://bugs.webkit.org/show_bug.cgi?id=160800
     5
     6        Reviewed by Benjamin Poulain.
     7
     8        Added iteratorForIterable which provides an abstraction for iterating over an iterable object,
     9        and deployed it in the constructors of Set, WeakSet, Map, and WeakMap.
     10
     11        Also added a helper function iteratorForIterable, which retrieves the iterator out of an iterable object.
     12
     13        * runtime/IteratorOperations.cpp:
     14        (JSC::iteratorForIterable): Added.
     15        * runtime/IteratorOperations.h:
     16        (JSC::forEachInIterable): Added.
     17        * runtime/MapConstructor.cpp:
     18        (JSC::constructMap):
     19        * runtime/SetConstructor.cpp:
     20        (JSC::constructSet):
     21        * runtime/WeakMapConstructor.cpp:
     22        (JSC::constructWeakMap):
     23        * runtime/WeakSetConstructor.cpp:
     24        (JSC::constructWeakSet):
     25
    1262016-08-12  Joseph Pecoraro  <pecoraro@apple.com>
    227
  • trunk/Source/JavaScriptCore/runtime/IteratorOperations.cpp

    r197614 r204438  
    154154}
    155155
     156JSValue iteratorForIterable(ExecState* state, JSValue iterable)
     157{
     158    JSValue iteratorFunction = iterable.get(state, state->propertyNames().iteratorSymbol);
     159    if (state->hadException())
     160        return JSValue();
     161   
     162    CallData iteratorFunctionCallData;
     163    CallType iteratorFunctionCallType = getCallData(iteratorFunction, iteratorFunctionCallData);
     164    if (iteratorFunctionCallType == CallType::None) {
     165        throwTypeError(state);
     166        return JSValue();
     167    }
     168
     169    ArgList iteratorFunctionArguments;
     170    JSValue iterator = call(state, iteratorFunction, iteratorFunctionCallType, iteratorFunctionCallData, iterable, iteratorFunctionArguments);
     171    if (state->hadException())
     172        return JSValue();
     173
     174    if (!iterator.isObject()) {
     175        throwTypeError(state);
     176        return JSValue();
     177    }
     178
     179    return iterator;
     180}
     181
    156182} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/IteratorOperations.h

    r194838 r204438  
    4242Structure* createIteratorResultObjectStructure(VM&, JSGlobalObject&);
    4343
     44JSValue iteratorForIterable(ExecState*, JSValue iterable);
     45
     46template <typename CallBackType>
     47void forEachInIterable(ExecState* state, JSValue iterable, const CallBackType& callback)
     48{
     49    auto& vm = state->vm();
     50    JSValue iterator = iteratorForIterable(state, iterable);
     51    if (vm.exception())
     52        return;
     53    while (true) {
     54        JSValue next = iteratorStep(state, iterator);
     55        if (next.isFalse() || vm.exception())
     56            return;
     57
     58        JSValue nextValue = iteratorValue(state, next);
     59        if (vm.exception())
     60            return;
     61
     62        callback(vm, state, nextValue);
     63        if (vm.exception()) {
     64            iteratorClose(state, iterator);
     65            return;
     66        }
     67    }
     68}
     69
    4470}
    4571
  • trunk/Source/JavaScriptCore/runtime/MapConstructor.cpp

    r197614 r204438  
    7474        return JSValue::encode(throwTypeError(exec));
    7575
    76     JSValue iteratorFunction = iterable.get(exec, exec->propertyNames().iteratorSymbol);
    77     if (exec->hadException())
    78         return JSValue::encode(jsUndefined());
    79 
    80     CallData iteratorFunctionCallData;
    81     CallType iteratorFunctionCallType = getCallData(iteratorFunction, iteratorFunctionCallData);
    82     if (iteratorFunctionCallType == CallType::None)
    83         return JSValue::encode(throwTypeError(exec));
    84 
    85     ArgList iteratorFunctionArguments;
    86     JSValue iterator = call(exec, iteratorFunction, iteratorFunctionCallType, iteratorFunctionCallData, iterable, iteratorFunctionArguments);
    87     if (exec->hadException())
    88         return JSValue::encode(jsUndefined());
    89 
    90     if (!iterator.isObject())
    91         return JSValue::encode(throwTypeError(exec));
    92 
    93     while (true) {
    94         JSValue next = iteratorStep(exec, iterator);
    95         if (exec->hadException())
    96             return JSValue::encode(jsUndefined());
    97 
    98         if (next.isFalse())
    99             return JSValue::encode(map);
    100 
    101         JSValue nextItem = iteratorValue(exec, next);
    102         if (exec->hadException())
    103             return JSValue::encode(jsUndefined());
    104 
     76    forEachInIterable(exec, iterable, [&](VM& vm, ExecState* exec, JSValue nextItem) {
    10577        if (!nextItem.isObject()) {
    10678            throwTypeError(exec);
    107             iteratorClose(exec, iterator);
    108             return JSValue::encode(jsUndefined());
     79            return;
    10980        }
    11081
    11182        JSValue key = nextItem.get(exec, static_cast<unsigned>(0));
    112         if (exec->hadException()) {
    113             iteratorClose(exec, iterator);
    114             return JSValue::encode(jsUndefined());
    115         }
     83        if (vm.exception())
     84            return;
    11685
    11786        JSValue value = nextItem.get(exec, static_cast<unsigned>(1));
    118         if (exec->hadException()) {
    119             iteratorClose(exec, iterator);
    120             return JSValue::encode(jsUndefined());
    121         }
     87        if (vm.exception())
     88            return;
    12289
    12390        MarkedArgumentBuffer arguments;
     
    12592        arguments.append(value);
    12693        call(exec, adderFunction, adderFunctionCallType, adderFunctionCallData, map, arguments);
    127         if (exec->hadException()) {
    128             iteratorClose(exec, iterator);
    129             return JSValue::encode(jsUndefined());
    130         }
    131     }
    132     RELEASE_ASSERT_NOT_REACHED();
     94    });
     95
    13396    return JSValue::encode(map);
    13497}
  • trunk/Source/JavaScriptCore/runtime/SetConstructor.cpp

    r197614 r204438  
    7575        return JSValue::encode(throwTypeError(exec));
    7676
    77     JSValue iteratorFunction = iterable.get(exec, exec->propertyNames().iteratorSymbol);
    78     if (exec->hadException())
    79         return JSValue::encode(jsUndefined());
    80 
    81     CallData iteratorFunctionCallData;
    82     CallType iteratorFunctionCallType = getCallData(iteratorFunction, iteratorFunctionCallData);
    83     if (iteratorFunctionCallType == CallType::None)
    84         return JSValue::encode(throwTypeError(exec));
    85 
    86     ArgList iteratorFunctionArguments;
    87     JSValue iterator = call(exec, iteratorFunction, iteratorFunctionCallType, iteratorFunctionCallData, iterable, iteratorFunctionArguments);
    88     if (exec->hadException())
    89         return JSValue::encode(jsUndefined());
    90 
    91     if (!iterator.isObject())
    92         return JSValue::encode(throwTypeError(exec));
    93 
    94     while (true) {
    95         JSValue next = iteratorStep(exec, iterator);
    96         if (exec->hadException())
    97             return JSValue::encode(jsUndefined());
    98 
    99         if (next.isFalse())
    100             return JSValue::encode(set);
    101 
    102         JSValue nextValue = iteratorValue(exec, next);
    103         if (exec->hadException())
    104             return JSValue::encode(jsUndefined());
    105 
     77    forEachInIterable(exec, iterable, [&](VM&, ExecState* exec, JSValue nextValue) {
    10678        MarkedArgumentBuffer arguments;
    10779        arguments.append(nextValue);
    10880        call(exec, adderFunction, adderFunctionCallType, adderFunctionCallData, set, arguments);
    109         if (exec->hadException()) {
    110             iteratorClose(exec, iterator);
    111             return JSValue::encode(jsUndefined());
    112         }
    113     }
    114     RELEASE_ASSERT_NOT_REACHED();
     81    });
     82
    11583    return JSValue::encode(set);
    11684}
  • trunk/Source/JavaScriptCore/runtime/WeakMapConstructor.cpp

    r197614 r204438  
    7272        return JSValue::encode(throwTypeError(exec));
    7373
    74     JSValue iteratorFunction = iterable.get(exec, exec->propertyNames().iteratorSymbol);
    75     if (exec->hadException())
    76         return JSValue::encode(jsUndefined());
    77 
    78     CallData iteratorFunctionCallData;
    79     CallType iteratorFunctionCallType = getCallData(iteratorFunction, iteratorFunctionCallData);
    80     if (iteratorFunctionCallType == CallType::None)
    81         return JSValue::encode(throwTypeError(exec));
    82 
    83     ArgList iteratorFunctionArguments;
    84     JSValue iterator = call(exec, iteratorFunction, iteratorFunctionCallType, iteratorFunctionCallData, iterable, iteratorFunctionArguments);
    85     if (exec->hadException())
    86         return JSValue::encode(jsUndefined());
    87 
    88     if (!iterator.isObject())
    89         return JSValue::encode(throwTypeError(exec));
    90 
    91     while (true) {
    92         JSValue next = iteratorStep(exec, iterator);
    93         if (exec->hadException())
    94             return JSValue::encode(jsUndefined());
    95 
    96         if (next.isFalse())
    97             return JSValue::encode(weakMap);
    98 
    99         JSValue nextItem = iteratorValue(exec, next);
    100         if (exec->hadException())
    101             return JSValue::encode(jsUndefined());
    102 
     74    forEachInIterable(exec, iterable, [&](VM& vm, ExecState* exec, JSValue nextItem) {
    10375        if (!nextItem.isObject()) {
    10476            throwTypeError(exec);
    105             iteratorClose(exec, iterator);
    106             return JSValue::encode(jsUndefined());
     77            return;
    10778        }
    10879
    10980        JSValue key = nextItem.get(exec, static_cast<unsigned>(0));
    110         if (exec->hadException()) {
    111             iteratorClose(exec, iterator);
    112             return JSValue::encode(jsUndefined());
    113         }
     81        if (vm.exception())
     82            return;
    11483
    11584        JSValue value = nextItem.get(exec, static_cast<unsigned>(1));
    116         if (exec->hadException()) {
    117             iteratorClose(exec, iterator);
    118             return JSValue::encode(jsUndefined());
    119         }
     85        if (vm.exception())
     86            return;
    12087
    12188        MarkedArgumentBuffer arguments;
     
    12390        arguments.append(value);
    12491        call(exec, adderFunction, adderFunctionCallType, adderFunctionCallData, weakMap, arguments);
    125         if (exec->hadException()) {
    126             iteratorClose(exec, iterator);
    127             return JSValue::encode(jsUndefined());
    128         }
    129     }
    130     RELEASE_ASSERT_NOT_REACHED();
     92    });
     93
    13194    return JSValue::encode(weakMap);
    13295}
  • trunk/Source/JavaScriptCore/runtime/WeakSetConstructor.cpp

    r197614 r204438  
    7272        return JSValue::encode(throwTypeError(exec));
    7373
    74     JSValue iteratorFunction = iterable.get(exec, exec->propertyNames().iteratorSymbol);
    75     if (exec->hadException())
    76         return JSValue::encode(jsUndefined());
    77 
    78     CallData iteratorFunctionCallData;
    79     CallType iteratorFunctionCallType = getCallData(iteratorFunction, iteratorFunctionCallData);
    80     if (iteratorFunctionCallType == CallType::None)
    81         return JSValue::encode(throwTypeError(exec));
    82 
    83     ArgList iteratorFunctionArguments;
    84     JSValue iterator = call(exec, iteratorFunction, iteratorFunctionCallType, iteratorFunctionCallData, iterable, iteratorFunctionArguments);
    85     if (exec->hadException())
    86         return JSValue::encode(jsUndefined());
    87 
    88     if (!iterator.isObject())
    89         return JSValue::encode(throwTypeError(exec));
    90 
    91     while (true) {
    92         JSValue next = iteratorStep(exec, iterator);
    93         if (exec->hadException())
    94             return JSValue::encode(jsUndefined());
    95 
    96         if (next.isFalse())
    97             return JSValue::encode(weakSet);
    98 
    99         JSValue nextValue = iteratorValue(exec, next);
    100         if (exec->hadException())
    101             return JSValue::encode(jsUndefined());
    102 
     74    forEachInIterable(exec, iterable, [&](VM&, ExecState* exec, JSValue nextValue) {
    10375        MarkedArgumentBuffer arguments;
    10476        arguments.append(nextValue);
    10577        call(exec, adderFunction, adderFunctionCallType, adderFunctionCallData, weakSet, arguments);
    106         if (exec->hadException()) {
    107             iteratorClose(exec, iterator);
    108             return JSValue::encode(jsUndefined());
    109         }
    110     }
    111     RELEASE_ASSERT_NOT_REACHED();
     78    });
     79
    11280    return JSValue::encode(weakSet);
    11381}
Note: See TracChangeset for help on using the changeset viewer.