Changeset 181077 in webkit


Ignore:
Timestamp:
Mar 5, 2015 6:57:17 AM (9 years ago)
Author:
Yusuke Suzuki
Message:

Upgrade ES6 Iterator interfaces
https://bugs.webkit.org/show_bug.cgi?id=141351

Reviewed by Filip Pizlo.

This patch upgrades the exising ES6 iterator to align the latest spec.
In the latest spec,

  1. Iterator.next returns object that implements IteratorResult interface { value: value, done, boolean }.
  2. Iterator.return is introduced. When the iteration is terminated by the abrupt completion,

it is called to close iterator state.

  1. Iterator.next of Array is moved from an iterator object to %ArrayIteratorPrototype%.

To upgrade it, we changes the bytecode that represents for-of loops.
And to embody the efficient iteration with an iterator object,
we implemented %ArrayIteratorPrototype%.next in JavaScript and
it is located in builtins/ArrayIterator.prototype.js.
Implementing it in JavaScript encourages inlining and
utilizes escape analysis for an iterator result object in DFG JIT.
And we dropped the intrinsic version of %ArrayIteratorPrototype%.next.

And we introduced IteratorOperations that is defined in the spec.
It aligns the iteration in the runtime to the latest spec.
Currently, Promise.all and Promise.race uses an iterable object.
However, Promise.all and Promise.race implementation is also based on the old spec.
Subsequent patches will upgrade it.

  • CMakeLists.txt:
  • DerivedSources.make:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • builtins/ArrayIterator.prototype.js: Copied from Source/JavaScriptCore/runtime/ArrayIteratorPrototype.h.

(next):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitReturn):
(JSC::BytecodeGenerator::emitThrowTypeError):
(JSC::BytecodeGenerator::emitEnumeration):
(JSC::BytecodeGenerator::emitIsObject):
(JSC::BytecodeGenerator::emitIsUndefined):

  • bytecompiler/BytecodeGenerator.h:
  • jit/ThunkGenerators.cpp:

(JSC::arrayIteratorNextThunkGenerator): Deleted.
(JSC::arrayIteratorNextKeyThunkGenerator): Deleted.
(JSC::arrayIteratorNextValueThunkGenerator): Deleted.

  • jit/ThunkGenerators.h:
  • runtime/ArgumentsIteratorPrototype.cpp:

(JSC::ArgumentsIteratorPrototype::finishCreation):
(JSC::argumentsIteratorPrototypeFuncNext):

  • runtime/ArrayIteratorPrototype.cpp:

(JSC::ArrayIteratorPrototype::finishCreation):
(JSC::ArrayIteratorPrototype::getOwnPropertySlot):
(JSC::arrayIteratorProtoFuncIterator):
(JSC::arrayIteratorPrototypeIterate): Deleted.

  • runtime/ArrayIteratorPrototype.h:
  • runtime/CommonIdentifiers.h:
  • runtime/Intrinsic.h:
  • runtime/IteratorOperations.cpp: Added.

(JSC::iteratorNext):
(JSC::iteratorValue):
(JSC::iteratorComplete):
(JSC::iteratorStep):
(JSC::iteratorClose):
(JSC::createIterResultObject):

  • runtime/IteratorOperations.h: Copied from Source/JavaScriptCore/runtime/ArrayIteratorPrototype.cpp.
  • runtime/JSArrayIterator.cpp:

(JSC::JSArrayIterator::finishCreation):
(JSC::JSArrayIterator::visitChildren): Deleted.
(JSC::createIteratorResult): Deleted.
(JSC::arrayIteratorNext): Deleted.
(JSC::arrayIteratorNextKey): Deleted.
(JSC::arrayIteratorNextValue): Deleted.
(JSC::arrayIteratorNextGeneric): Deleted.

  • runtime/JSArrayIterator.h:

(JSC::JSArrayIterator::JSArrayIterator):
(JSC::JSArrayIterator::iterationKind): Deleted.
(JSC::JSArrayIterator::iteratedObject): Deleted.
(JSC::JSArrayIterator::nextIndex): Deleted.
(JSC::JSArrayIterator::setNextIndex): Deleted.
(JSC::JSArrayIterator::finish): Deleted.
(JSC::JSArrayIterator::offsetOfIterationKind): Deleted.
(JSC::JSArrayIterator::offsetOfIteratedObject): Deleted.
(JSC::JSArrayIterator::offsetOfNextIndex): Deleted.

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):

  • runtime/JSPromiseConstructor.cpp:

(JSC::performPromiseRaceLoop):
(JSC::JSPromiseConstructorFuncRace):
(JSC::performPromiseAll):
(JSC::JSPromiseConstructorFuncAll):

  • runtime/MapIteratorPrototype.cpp:

(JSC::MapIteratorPrototype::finishCreation):
(JSC::MapIteratorPrototypeFuncNext):

  • runtime/SetIteratorPrototype.cpp:

(JSC::SetIteratorPrototype::finishCreation):
(JSC::SetIteratorPrototypeFuncNext):

  • runtime/VM.cpp:

(JSC::thunkGeneratorForIntrinsic):

  • tests/stress/array-iterators-next-with-call.js: Added.

(increment):
(for):

  • tests/stress/array-iterators-next.js: Added.

Revive the older Array iterator tests that manually call 'next' method.

  • tests/stress/custom-iterators.js: Added.

(iter.next):
(iter.Symbol.iterator):
(iter.return):
(iter.get next):
(iter.get return):
(iteratorInterfaceErrorTest.iter.next):
(iteratorInterfaceErrorTest.iter.Symbol.iterator):
(iteratorInterfaceErrorTest.iter.return):
(iteratorInterfaceErrorTest):
(iteratorInterfaceErrorTestReturn.iter.next):
(iteratorInterfaceErrorTestReturn.iter.Symbol.iterator):
(iteratorInterfaceErrorTestReturn.iter.return):
(iteratorInterfaceErrorTestReturn):
(iteratorInterfaceBreakTestReturn.iter.next):
(iteratorInterfaceBreakTestReturn.iter.Symbol.iterator):
(iteratorInterfaceBreakTestReturn.iter.return):
(iteratorInterfaceBreakTestReturn):

This tests the behavior of custom iterators.
'next' and 'return' of iterator work with for-of.

  • tests/stress/iterators-shape.js: Added.

(iteratorShape):
(sameNextMethods):
(set var):

This tests the shape of iterators; iterators of Array have 'next' method in %ArrayIteratorPrototype%.

  • tests/stress/map-iterators-next.js: Added.

(set var):
(.get if):
(otherKey):

  • tests/stress/set-iterators-next.js: Added.

(otherKey):

Location:
trunk/Source/JavaScriptCore
Files:
7 added
22 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r180691 r181077  
    439439    runtime/ErrorPrototype.cpp
    440440    runtime/ExceptionFuzz.cpp
    441     runtime/ExceptionHelpers.cpp 
     441    runtime/ExceptionHelpers.cpp
    442442    runtime/Executable.cpp
    443443    runtime/FunctionConstructor.cpp
     
    451451    runtime/IntendedStructureChain.cpp
    452452    runtime/InternalFunction.cpp
     453    runtime/IteratorOperations.cpp
    453454    runtime/JSAPIValueWrapper.cpp
    454455    runtime/JSLexicalEnvironment.cpp
     
    580581set(JavaScriptCore_LUT_FILES
    581582    runtime/ArrayConstructor.cpp
     583    runtime/ArrayIteratorPrototype.cpp
    582584    runtime/ArrayPrototype.cpp
    583585    runtime/BooleanPrototype.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r181064 r181077  
     12015-03-05  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        Upgrade ES6 Iterator interfaces
     4        https://bugs.webkit.org/show_bug.cgi?id=141351
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This patch upgrades the exising ES6 iterator to align the latest spec.
     9        In the latest spec,
     10        1. `Iterator.next` returns object that implements IteratorResult interface { value: value, done, boolean }.
     11        2. `Iterator.return` is introduced. When the iteration is terminated by the abrupt completion,
     12        it is called to close iterator state.
     13        3. Iterator.next of Array is moved from an iterator object to `%ArrayIteratorPrototype%`.
     14
     15        To upgrade it, we changes the bytecode that represents for-of loops.
     16        And to embody the efficient iteration with an iterator object,
     17        we implemented %ArrayIteratorPrototype%.next in JavaScript and
     18        it is located in builtins/ArrayIterator.prototype.js.
     19        Implementing it in JavaScript encourages inlining and
     20        utilizes escape analysis for an iterator result object in DFG JIT.
     21        And we dropped the intrinsic version of %ArrayIteratorPrototype%.next.
     22
     23        And we introduced IteratorOperations that is defined in the spec.
     24        It aligns the iteration in the runtime to the latest spec.
     25        Currently, Promise.all and Promise.race uses an iterable object.
     26        However, Promise.all and Promise.race implementation is also based on the old spec.
     27        Subsequent patches will upgrade it.
     28
     29        * CMakeLists.txt:
     30        * DerivedSources.make:
     31        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     32        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
     33        * JavaScriptCore.xcodeproj/project.pbxproj:
     34        * builtins/ArrayIterator.prototype.js: Copied from Source/JavaScriptCore/runtime/ArrayIteratorPrototype.h.
     35        (next):
     36        * bytecompiler/BytecodeGenerator.cpp:
     37        (JSC::BytecodeGenerator::emitReturn):
     38        (JSC::BytecodeGenerator::emitThrowTypeError):
     39        (JSC::BytecodeGenerator::emitEnumeration):
     40        (JSC::BytecodeGenerator::emitIsObject):
     41        (JSC::BytecodeGenerator::emitIsUndefined):
     42        * bytecompiler/BytecodeGenerator.h:
     43        * jit/ThunkGenerators.cpp:
     44        (JSC::arrayIteratorNextThunkGenerator): Deleted.
     45        (JSC::arrayIteratorNextKeyThunkGenerator): Deleted.
     46        (JSC::arrayIteratorNextValueThunkGenerator): Deleted.
     47        * jit/ThunkGenerators.h:
     48        * runtime/ArgumentsIteratorPrototype.cpp:
     49        (JSC::ArgumentsIteratorPrototype::finishCreation):
     50        (JSC::argumentsIteratorPrototypeFuncNext):
     51        * runtime/ArrayIteratorPrototype.cpp:
     52        (JSC::ArrayIteratorPrototype::finishCreation):
     53        (JSC::ArrayIteratorPrototype::getOwnPropertySlot):
     54        (JSC::arrayIteratorProtoFuncIterator):
     55        (JSC::arrayIteratorPrototypeIterate): Deleted.
     56        * runtime/ArrayIteratorPrototype.h:
     57        * runtime/CommonIdentifiers.h:
     58        * runtime/Intrinsic.h:
     59        * runtime/IteratorOperations.cpp: Added.
     60        (JSC::iteratorNext):
     61        (JSC::iteratorValue):
     62        (JSC::iteratorComplete):
     63        (JSC::iteratorStep):
     64        (JSC::iteratorClose):
     65        (JSC::createIterResultObject):
     66        * runtime/IteratorOperations.h: Copied from Source/JavaScriptCore/runtime/ArrayIteratorPrototype.cpp.
     67        * runtime/JSArrayIterator.cpp:
     68        (JSC::JSArrayIterator::finishCreation):
     69        (JSC::JSArrayIterator::visitChildren): Deleted.
     70        (JSC::createIteratorResult): Deleted.
     71        (JSC::arrayIteratorNext): Deleted.
     72        (JSC::arrayIteratorNextKey): Deleted.
     73        (JSC::arrayIteratorNextValue): Deleted.
     74        (JSC::arrayIteratorNextGeneric): Deleted.
     75        * runtime/JSArrayIterator.h:
     76        (JSC::JSArrayIterator::JSArrayIterator):
     77        (JSC::JSArrayIterator::iterationKind): Deleted.
     78        (JSC::JSArrayIterator::iteratedObject): Deleted.
     79        (JSC::JSArrayIterator::nextIndex): Deleted.
     80        (JSC::JSArrayIterator::setNextIndex): Deleted.
     81        (JSC::JSArrayIterator::finish): Deleted.
     82        (JSC::JSArrayIterator::offsetOfIterationKind): Deleted.
     83        (JSC::JSArrayIterator::offsetOfIteratedObject): Deleted.
     84        (JSC::JSArrayIterator::offsetOfNextIndex): Deleted.
     85        * runtime/JSGlobalObject.cpp:
     86        (JSC::JSGlobalObject::init):
     87        * runtime/JSPromiseConstructor.cpp:
     88        (JSC::performPromiseRaceLoop):
     89        (JSC::JSPromiseConstructorFuncRace):
     90        (JSC::performPromiseAll):
     91        (JSC::JSPromiseConstructorFuncAll):
     92        * runtime/MapIteratorPrototype.cpp:
     93        (JSC::MapIteratorPrototype::finishCreation):
     94        (JSC::MapIteratorPrototypeFuncNext):
     95        * runtime/SetIteratorPrototype.cpp:
     96        (JSC::SetIteratorPrototype::finishCreation):
     97        (JSC::SetIteratorPrototypeFuncNext):
     98        * runtime/VM.cpp:
     99        (JSC::thunkGeneratorForIntrinsic):
     100        * tests/stress/array-iterators-next-with-call.js: Added.
     101        (increment):
     102        (for):
     103        * tests/stress/array-iterators-next.js: Added.
     104
     105        Revive the older Array iterator tests that manually call 'next' method.
     106
     107        * tests/stress/custom-iterators.js: Added.
     108        (iter.next):
     109        (iter.Symbol.iterator):
     110        (iter.return):
     111        (iter.get next):
     112        (iter.get return):
     113        (iteratorInterfaceErrorTest.iter.next):
     114        (iteratorInterfaceErrorTest.iter.Symbol.iterator):
     115        (iteratorInterfaceErrorTest.iter.return):
     116        (iteratorInterfaceErrorTest):
     117        (iteratorInterfaceErrorTestReturn.iter.next):
     118        (iteratorInterfaceErrorTestReturn.iter.Symbol.iterator):
     119        (iteratorInterfaceErrorTestReturn.iter.return):
     120        (iteratorInterfaceErrorTestReturn):
     121        (iteratorInterfaceBreakTestReturn.iter.next):
     122        (iteratorInterfaceBreakTestReturn.iter.Symbol.iterator):
     123        (iteratorInterfaceBreakTestReturn.iter.return):
     124        (iteratorInterfaceBreakTestReturn):
     125
     126        This tests the behavior of custom iterators.
     127        'next' and 'return' of iterator work with for-of.
     128
     129        * tests/stress/iterators-shape.js: Added.
     130        (iteratorShape):
     131        (sameNextMethods):
     132        (set var):
     133
     134        This tests the shape of iterators; iterators of Array have 'next' method in %ArrayIteratorPrototype%.
     135
     136        * tests/stress/map-iterators-next.js: Added.
     137        (set var):
     138        (.get if):
     139        (otherKey):
     140        * tests/stress/set-iterators-next.js: Added.
     141        (otherKey):
     142
    11432015-03-04  Yusuke Suzuki  <utatane.tea@gmail.com>
    2144
  • trunk/Source/JavaScriptCore/DerivedSources.make

    r179429 r181077  
    3737all : \
    3838    ArrayConstructor.lut.h \
     39    ArrayIteratorPrototype.lut.h \
    3940    ArrayPrototype.lut.h \
    4041    BooleanPrototype.lut.h \
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r180691 r181077  
    719719    <ClCompile Include="..\runtime\IntendedStructureChain.cpp" />
    720720    <ClCompile Include="..\runtime\InternalFunction.cpp" />
     721    <ClCompile Include="..\runtime\IteratorOperations.cpp" />
    721722    <ClCompile Include="..\runtime\JSAPIValueWrapper.cpp" />
    722723    <ClCompile Include="..\runtime\JSLexicalEnvironment.cpp" />
     
    855856  <ItemGroup>
    856857    <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\ArrayConstructor.lut.h" />
     858    <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\ArrayIteratorPrototype.lut.h" />
    857859    <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\ArrayPrototype.lut.h" />
    858860    <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\BooleanPrototype.lut.h" />
     
    14931495    <ClInclude Include="..\runtime\InternalFunction.h" />
    14941496    <ClInclude Include="..\runtime\Intrinsic.h" />
     1497    <ClInclude Include="..\runtime\IteratorOperations.h" />
    14951498    <ClInclude Include="..\runtime\JSAPIValueWrapper.h" />
    14961499    <ClInclude Include="..\runtime\JSLexicalEnvironment.h" />
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters

    r180570 r181077  
    631631      <Filter>runtime</Filter>
    632632    </ClCompile>
     633    <ClCompile Include="..\runtime\IteratorOperations.cpp">
     634      <Filter>runtime</Filter>
     635    </ClCompile>
    633636    <ClCompile Include="..\runtime\JSLexicalEnvironment.cpp">
    634637      <Filter>runtime</Filter>
     
    26622665      <Filter>runtime</Filter>
    26632666    </ClInclude>
     2667    <ClInclude Include="..\runtime\IteratorOperations.h">
     2668      <Filter>runtime</Filter>
     2669    </ClInclude>
    26642670    <ClInclude Include="..\runtime\JSLexicalEnvironment.h">
    26652671      <Filter>runtime</Filter>
     
    30633069    </ClInclude>
    30643070    <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\StringConstructor.lut.h">
     3071      <Filter>Derived Sources</Filter>
     3072    </ClInclude>
     3073    <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\ArrayIteratorPrototype.lut.h">
    30653074      <Filter>Derived Sources</Filter>
    30663075    </ClInclude>
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r181010 r181077  
    945945                65FB5117184EEE7000C12B70 /* ProtoCallFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65FB5116184EE9BC00C12B70 /* ProtoCallFrame.cpp */; };
    946946                6AD2CB4D19B9140100065719 /* DebuggerEvalEnabler.h in Headers */ = {isa = PBXBuildFile; fileRef = 6AD2CB4C19B9140100065719 /* DebuggerEvalEnabler.h */; settings = {ATTRIBUTES = (Private, ); }; };
     947                70113D4B1A8DB093003848C4 /* IteratorOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70113D491A8DB093003848C4 /* IteratorOperations.cpp */; };
     948                70113D4C1A8DB093003848C4 /* IteratorOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = 70113D4A1A8DB093003848C4 /* IteratorOperations.h */; settings = {ATTRIBUTES = (Private, ); }; };
    947949                705B41AB1A6E501E00716757 /* Symbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 705B41A31A6E501E00716757 /* Symbol.cpp */; };
    948950                705B41AC1A6E501E00716757 /* Symbol.h in Headers */ = {isa = PBXBuildFile; fileRef = 705B41A41A6E501E00716757 /* Symbol.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    26272629                65FB5116184EE9BC00C12B70 /* ProtoCallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProtoCallFrame.cpp; sourceTree = "<group>"; };
    26282630                6AD2CB4C19B9140100065719 /* DebuggerEvalEnabler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerEvalEnabler.h; sourceTree = "<group>"; };
     2631                70113D491A8DB093003848C4 /* IteratorOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IteratorOperations.cpp; sourceTree = "<group>"; };
     2632                70113D4A1A8DB093003848C4 /* IteratorOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IteratorOperations.h; sourceTree = "<group>"; };
    26292633                704FD35305697E6D003DBED9 /* BooleanObject.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = BooleanObject.h; sourceTree = "<group>"; tabWidth = 8; };
    26302634                705B41A31A6E501E00716757 /* Symbol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Symbol.cpp; sourceTree = "<group>"; };
     
    43394343                                BC11667A0E199C05008066DD /* InternalFunction.h */,
    43404344                                86BF642A148DB2B5004DE36A /* Intrinsic.h */,
     4345                                70113D491A8DB093003848C4 /* IteratorOperations.cpp */,
     4346                                70113D4A1A8DB093003848C4 /* IteratorOperations.h */,
    43414347                                A76140CB182982CB00750624 /* JSArgumentsIterator.cpp */,
    43424348                                A76140CC182982CB00750624 /* JSArgumentsIterator.h */,
     
    58885894                                1429D77C0ED20D7300B89619 /* Interpreter.h in Headers */,
    58895895                                860BD801148EA6F200112B2F /* Intrinsic.h in Headers */,
     5896                                70113D4C1A8DB093003848C4 /* IteratorOperations.h in Headers */,
    58905897                                BC18C4130E16F5CD00B34460 /* JavaScript.h in Headers */,
    58915898                                0F2B9CF519D0BAC100B1D1B5 /* FTLExitPropertyValue.h in Headers */,
     
    70947101                                147F39CF107EC37600427A48 /* InternalFunction.cpp in Sources */,
    70957102                                1429D7D40ED2128200B89619 /* Interpreter.cpp in Sources */,
     7103                                70113D4B1A8DB093003848C4 /* IteratorOperations.cpp in Sources */,
    70967104                                A503FA19188E0FB000110F14 /* JavaScriptCallFrame.cpp in Sources */,
    70977105                                1429D92F0ED22D7000B89619 /* JIT.cpp in Sources */,
  • trunk/Source/JavaScriptCore/builtins/ArrayIterator.prototype.js

    r181075 r181077  
    11/*
    2  * Copyright (C) 2013 Apple, Inc. All rights reserved.
     2 * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2121 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    2222 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
     23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2424 */
    2525
    26 #ifndef ArrayIteratorPrototype_h
    27 #define ArrayIteratorPrototype_h
     26function next() {
     27    "use strict";
    2828
    29 #include "JSObject.h"
     29    if (this == null)
     30        throw new @TypeError("%ArrayIteratorPrototype%.next requires that |this| not be null or undefined");
    3031
    31 namespace JSC {
     32    var itemKind = this.@arrayIterationKind;
     33    if (itemKind === undefined)
     34        throw new @TypeError("%ArrayIteratorPrototype%.next requires that |this| be Array Iterator Instance");
    3235
    33 class ArrayIteratorPrototype : public JSNonFinalObject {
    34 public:
    35     typedef JSNonFinalObject Base;
     36    var done = true;
     37    var value = undefined;
    3638
    37     static ArrayIteratorPrototype* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
    38     {
    39         ArrayIteratorPrototype* prototype = new (NotNull, allocateCell<ArrayIteratorPrototype>(vm.heap)) ArrayIteratorPrototype(vm, structure);
    40         prototype->finishCreation(vm, globalObject);
    41         return prototype;
     39    var array = this.@iteratedObject;
     40    if (array !== undefined) {
     41        var index = this.@arrayIteratorNextIndex;
     42        var length = array.length >>> 0;
     43        if (index >= length) {
     44            this.@iteratedObject = undefined;
     45        } else {
     46            this.@arrayIteratorNextIndex = index + 1;
     47            done = false;
     48            if (itemKind === @arrayIterationKindKey) {
     49                value = index;
     50            } else if (itemKind === @arrayIterationKindValue) {
     51                value = array[index];
     52            } else {
     53                value = [ index, array[index] ];
     54            }
     55        }
    4256    }
    4357
    44     DECLARE_INFO;
    45 
    46     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
    47     {
    48         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
    49     }
    50 
    51 private:
    52     ArrayIteratorPrototype(VM& vm, Structure* structure)
    53         : Base(vm, structure)
    54     {
    55     }
    56     void finishCreation(VM&, JSGlobalObject*);
    57 };
    58 
     58    return {
     59        done: done,
     60        value: value
     61    };
    5962}
    60 
    61 #endif // !defined(ArrayIteratorPrototype_h)
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r180875 r181077  
    19061906    if (isConstructor() && src->index() != m_thisRegister.index()) {
    19071907        RefPtr<Label> isObjectLabel = newLabel();
    1908         RefPtr<RegisterID> isObjectRegister = newTemporary();
    1909 
    1910         emitOpcode(op_is_object);
    1911         instructions().append(isObjectRegister->index());
    1912         instructions().append(src->index());
    1913 
    1914         size_t begin = instructions().size();
    1915         emitOpcode(op_jtrue);
    1916         instructions().append(isObjectRegister->index());
    1917         instructions().append(isObjectLabel->bind(begin, instructions().size()));
     1908
     1909        emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectLabel.get());
    19181910
    19191911        emitUnaryNoDstOp(op_ret, &m_thisRegister);
     
    23532345}
    23542346
     2347void BytecodeGenerator::emitThrowTypeError(const String& message)
     2348{
     2349    emitOpcode(op_throw_static_error);
     2350    instructions().append(addConstantValue(addStringConstant(Identifier(m_vm, message)))->index());
     2351    instructions().append(false);
     2352}
     2353
    23552354void BytecodeGenerator::emitPushFunctionNameScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes)
    23562355{
     
    25522551    RefPtr<RegisterID> iterator = emitGetById(newTemporary(), subject.get(), propertyNames().iteratorPrivateName);
    25532552    {
    2554         CallArguments args(*this, 0);
     2553        CallArguments args(*this, nullptr);
    25552554        emitMove(args.thisRegister(), subject.get());
    25562555        emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, node->divot(), node->divotStart(), node->divotEnd());
    25572556    }
    2558     RefPtr<RegisterID> iteratorNext = emitGetById(newTemporary(), iterator.get(), propertyNames().iteratorNextPrivateName);
    25592557    RefPtr<RegisterID> value = newTemporary();
    25602558    emitLoad(value.get(), jsUndefined());
     
    25632561   
    25642562    RefPtr<Label> loopStart = newLabel();
     2563    RefPtr<Label> iteratorDone = newLabel();
    25652564    emitLabel(loopStart.get());
    25662565    emitLoopHint();
     2566
     2567    RefPtr<Label> tryStartLabel = newLabel();
     2568    emitLabel(tryStartLabel.get());
     2569    TryData* tryData = pushTry(tryStartLabel.get());
    25672570    callBack(*this, value.get());
     2571    RefPtr<Label> catchHere = emitLabel(newLabel().get());
     2572
    25682573    emitLabel(scope->continueTarget());
    2569     CallArguments nextArguments(*this, 0, 1);
    2570     emitMove(nextArguments.thisRegister(), iterator.get());
    2571     emitMove(nextArguments.argumentRegister(0), value.get());
    2572     emitCall(value.get(), iteratorNext.get(), NoExpectedFunction, nextArguments, node->divot(), node->divotStart(), node->divotEnd());
    2573     RefPtr<RegisterID> result = newTemporary();
    2574     emitJumpIfFalse(emitEqualityOp(op_stricteq, result.get(), value.get(), emitLoad(0, JSValue(vm()->iterationTerminator.get()))), loopStart.get());
     2574    {
     2575        RefPtr<RegisterID> next = emitGetById(newTemporary(), iterator.get(), propertyNames().next);
     2576        CallArguments nextArguments(*this, nullptr);
     2577        emitMove(nextArguments.thisRegister(), iterator.get());
     2578        emitCall(value.get(), next.get(), NoExpectedFunction, nextArguments, node->divot(), node->divotStart(), node->divotEnd());
     2579    }
     2580    {
     2581        RefPtr<Label> typeIsObject = newLabel();
     2582        emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), typeIsObject.get());
     2583        emitThrowTypeError(ASCIILiteral("Iterator result interface is not an object."));
     2584        emitLabel(typeIsObject.get());
     2585    }
     2586    emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), iteratorDone.get());
     2587    emitGetById(value.get(), value.get(), propertyNames().value);
     2588    emitJump(loopStart.get());
     2589
     2590    // IteratorClose sequence for throw-ed control flow.
     2591    {
     2592        RefPtr<RegisterID> exceptionRegister = popTryAndEmitCatch(tryData, newTemporary(), catchHere.get());
     2593        RefPtr<Label> rethrow = newLabel();
     2594
     2595        RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword);
     2596        emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), rethrow.get());
     2597
     2598        RefPtr<Label> returnCallTryStart = newLabel();
     2599        emitLabel(returnCallTryStart.get());
     2600        TryData* returnCallTryData = pushTry(returnCallTryStart.get());
     2601
     2602        CallArguments returnArguments(*this, nullptr);
     2603        emitMove(returnArguments.thisRegister(), iterator.get());
     2604        emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd());
     2605
     2606        RefPtr<Label> returnCallCatchHere = emitLabel(newLabel().get());
     2607        emitJump(rethrow.get());
     2608
     2609        popTryAndEmitCatch(returnCallTryData, newTemporary(), returnCallCatchHere.get());
     2610        emitLabel(rethrow.get());
     2611        emitThrow(exceptionRegister.get());
     2612    }
     2613
     2614    // IteratorClose sequence for break-ed control flow.
    25752615    emitLabel(scope->breakTarget());
     2616    {
     2617        RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword);
     2618        emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), iteratorDone.get());
     2619
     2620        CallArguments returnArguments(*this, nullptr);
     2621        emitMove(returnArguments.thisRegister(), iterator.get());
     2622        emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd());
     2623        emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), iteratorDone.get());
     2624        emitThrowTypeError(ASCIILiteral("Iterator result interface is not an object."));
     2625    }
     2626
     2627    emitLabel(iteratorDone.get());
    25762628}
    25772629
     
    26472699    instructions().append(dst->index());
    26482700    instructions().append(index->index());
     2701    return dst;
     2702}
     2703
     2704
     2705RegisterID* BytecodeGenerator::emitIsObject(RegisterID* dst, RegisterID* src)
     2706{
     2707    emitOpcode(op_is_object);
     2708    instructions().append(dst->index());
     2709    instructions().append(src->index());
     2710    return dst;
     2711}
     2712
     2713RegisterID* BytecodeGenerator::emitIsUndefined(RegisterID* dst, RegisterID* src)
     2714{
     2715    emitOpcode(op_is_undefined);
     2716    instructions().append(dst->index());
     2717    instructions().append(src->index());
    26492718    return dst;
    26502719}
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r180875 r181077  
    530530        RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index);
    531531
     532        RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
     533        RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
     534
    532535        void emitReadOnlyExceptionIfNeeded();
    533536
     
    544547
    545548        void emitThrowReferenceError(const String& message);
     549        void emitThrowTypeError(const String& message);
    546550
    547551        void emitPushFunctionNameScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes);
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp

    r179478 r181077  
    10451045}
    10461046
    1047 static MacroAssemblerCodeRef arrayIteratorNextThunkGenerator(VM* vm, ArrayIterationKind kind)
    1048 {
    1049     typedef SpecializedThunkJIT::TrustedImm32 TrustedImm32;
    1050     typedef SpecializedThunkJIT::TrustedImmPtr TrustedImmPtr;
    1051     typedef SpecializedThunkJIT::Address Address;
    1052     typedef SpecializedThunkJIT::BaseIndex BaseIndex;
    1053     typedef SpecializedThunkJIT::Jump Jump;
    1054    
    1055     SpecializedThunkJIT jit(vm);
    1056     // Make sure we're being called on an array iterator, and load m_iteratedObject, and m_nextIndex into regT0 and regT1 respectively
    1057     jit.loadArgumentWithSpecificClass(JSArrayIterator::info(), SpecializedThunkJIT::ThisArgument, SpecializedThunkJIT::regT4, SpecializedThunkJIT::regT1);
    1058 
    1059     // Early exit if we don't have a thunk for this form of iteration
    1060     jit.appendFailure(jit.branch32(SpecializedThunkJIT::AboveOrEqual, Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfIterationKind()), TrustedImm32(ArrayIterateKeyValue)));
    1061    
    1062     jit.loadPtr(Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfIteratedObject()), SpecializedThunkJIT::regT0);
    1063    
    1064     jit.load32(Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex()), SpecializedThunkJIT::regT1);
    1065    
    1066     // Pull out the butterfly from iteratedObject
    1067     jit.load8(Address(SpecializedThunkJIT::regT0, JSCell::indexingTypeOffset()), SpecializedThunkJIT::regT3);
    1068     jit.loadPtr(Address(SpecializedThunkJIT::regT0, JSObject::butterflyOffset()), SpecializedThunkJIT::regT2);
    1069     Jump nullButterfly = jit.branchTestPtr(SpecializedThunkJIT::Zero, SpecializedThunkJIT::regT2);
    1070    
    1071     Jump notDone = jit.branch32(SpecializedThunkJIT::Below, SpecializedThunkJIT::regT1, Address(SpecializedThunkJIT::regT2, Butterfly::offsetOfPublicLength()));
    1072 
    1073     nullButterfly.link(&jit);
    1074 
    1075     // Return the termination signal to indicate that we've finished
    1076     jit.move(TrustedImmPtr(vm->iterationTerminator.get()), SpecializedThunkJIT::regT0);
    1077     jit.returnJSCell(SpecializedThunkJIT::regT0);
    1078    
    1079     notDone.link(&jit);
    1080    
    1081     if (kind == ArrayIterateKey) {
    1082         jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex()));
    1083         jit.returnInt32(SpecializedThunkJIT::regT1);
    1084         return jit.finalize(vm->jitStubs->ctiNativeTailCall(vm), "array-iterator-next-key");
    1085        
    1086     }
    1087     ASSERT(kind == ArrayIterateValue);
    1088    
    1089     // Okay, now we're returning a value so make sure we're inside the vector size
    1090     jit.appendFailure(jit.branch32(SpecializedThunkJIT::AboveOrEqual, SpecializedThunkJIT::regT1, Address(SpecializedThunkJIT::regT2, Butterfly::offsetOfVectorLength())));
    1091    
    1092     // So now we perform inline loads for int32, value/undecided, and double storage
    1093     Jump undecidedStorage = jit.branch32(SpecializedThunkJIT::Equal, SpecializedThunkJIT::regT3, TrustedImm32(ArrayWithUndecided));
    1094     Jump notContiguousStorage = jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(ArrayWithContiguous));
    1095    
    1096     undecidedStorage.link(&jit);
    1097    
    1098     jit.loadPtr(Address(SpecializedThunkJIT::regT0, JSObject::butterflyOffset()), SpecializedThunkJIT::regT2);
    1099    
    1100 #if USE(JSVALUE64)
    1101     jit.load64(BaseIndex(SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT1, SpecializedThunkJIT::TimesEight), SpecializedThunkJIT::regT0);
    1102     Jump notHole = jit.branchTest64(SpecializedThunkJIT::NonZero, SpecializedThunkJIT::regT0);
    1103     jit.move(JSInterfaceJIT::TrustedImm64(ValueUndefined), JSInterfaceJIT::regT0);
    1104     notHole.link(&jit);
    1105     jit.addPtr(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex()));
    1106     jit.returnJSValue(SpecializedThunkJIT::regT0);
    1107 #else
    1108     jit.load32(BaseIndex(SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT1, SpecializedThunkJIT::TimesEight, JSValue::offsetOfTag()), SpecializedThunkJIT::regT3);
    1109     Jump notHole = jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(JSValue::EmptyValueTag));
    1110     jit.move(JSInterfaceJIT::TrustedImm32(JSValue::UndefinedTag), JSInterfaceJIT::regT1);
    1111     jit.move(JSInterfaceJIT::TrustedImm32(0), JSInterfaceJIT::regT0);
    1112     jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex()));
    1113     jit.returnJSValue(SpecializedThunkJIT::regT0, JSInterfaceJIT::regT1);
    1114     notHole.link(&jit);
    1115     jit.load32(BaseIndex(SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT1, SpecializedThunkJIT::TimesEight, JSValue::offsetOfPayload()), SpecializedThunkJIT::regT0);
    1116     jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex()));
    1117     jit.move(SpecializedThunkJIT::regT3, SpecializedThunkJIT::regT1);
    1118     jit.returnJSValue(SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1);
    1119 #endif
    1120     notContiguousStorage.link(&jit);
    1121    
    1122     Jump notInt32Storage = jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(ArrayWithInt32));
    1123     jit.loadPtr(Address(SpecializedThunkJIT::regT0, JSObject::butterflyOffset()), SpecializedThunkJIT::regT2);
    1124     jit.load32(BaseIndex(SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT1, SpecializedThunkJIT::TimesEight, JSValue::offsetOfPayload()), SpecializedThunkJIT::regT0);
    1125     jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex()));
    1126     jit.returnInt32(SpecializedThunkJIT::regT0);
    1127     notInt32Storage.link(&jit);
    1128    
    1129     jit.appendFailure(jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(ArrayWithDouble)));
    1130     jit.loadPtr(Address(SpecializedThunkJIT::regT0, JSObject::butterflyOffset()), SpecializedThunkJIT::regT2);
    1131     jit.loadDouble(BaseIndex(SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT1, SpecializedThunkJIT::TimesEight), SpecializedThunkJIT::fpRegT0);
    1132     jit.add32(TrustedImm32(1), Address(SpecializedThunkJIT::regT4, JSArrayIterator::offsetOfNextIndex()));
    1133     jit.returnDouble(SpecializedThunkJIT::fpRegT0);
    1134    
    1135     return jit.finalize(vm->jitStubs->ctiNativeTailCall(vm), "array-iterator-next-value");
    1136 }
    1137 
    1138 MacroAssemblerCodeRef arrayIteratorNextKeyThunkGenerator(VM* vm)
    1139 {
    1140     return arrayIteratorNextThunkGenerator(vm, ArrayIterateKey);
    1141 }
    1142 
    1143 MacroAssemblerCodeRef arrayIteratorNextValueThunkGenerator(VM* vm)
    1144 {
    1145     return arrayIteratorNextThunkGenerator(vm, ArrayIterateValue);
    1146 }
    1147    
    11481047}
    11491048
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.h

    r179478 r181077  
    131131MacroAssemblerCodeRef powThunkGenerator(VM*);
    132132MacroAssemblerCodeRef imulThunkGenerator(VM*);
    133 MacroAssemblerCodeRef arrayIteratorNextKeyThunkGenerator(VM*);
    134 MacroAssemblerCodeRef arrayIteratorNextValueThunkGenerator(VM*);
    135133
    136134}
  • trunk/Source/JavaScriptCore/runtime/ArgumentsIteratorPrototype.cpp

    r171824 r181077  
    2727#include "ArgumentsIteratorPrototype.h"
    2828
     29#include "IteratorOperations.h"
    2930#include "JSArgumentsIterator.h"
    3031#include "JSCInlines.h"
     
    4445
    4546    JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorPrivateName, argumentsIteratorPrototypeFuncIterator, DontEnum, 0);
    46     JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorNextPrivateName, argumentsIteratorPrototypeFuncNext, DontEnum, 0);
     47    JSC_NATIVE_FUNCTION(vm.propertyNames->next, argumentsIteratorPrototypeFuncNext, DontEnum, 0);
    4748}
    4849
     
    5657    JSValue result;
    5758    if (jsCast<JSArgumentsIterator*>(callFrame->thisValue())->next(callFrame, result))
    58         return JSValue::encode(result);
    59     return JSValue::encode(callFrame->vm().iterationTerminator.get());
     59        return JSValue::encode(createIterResultObject(callFrame, result, false));
     60    return JSValue::encode(createIterResultObject(callFrame, jsUndefined(), true));
    6061}
    6162
  • trunk/Source/JavaScriptCore/runtime/ArrayIteratorPrototype.cpp

    r171824 r181077  
    2121 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    2222 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
     23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2424 */
    2525
     
    2727#include "ArrayIteratorPrototype.h"
    2828
     29namespace JSC {
     30
     31static EncodedJSValue JSC_HOST_CALL arrayIteratorProtoFuncIterator(ExecState*);
     32
     33}
     34
     35#include "ArrayIteratorPrototype.lut.h"
     36
     37#include "IteratorOperations.h"
    2938#include "JSArrayIterator.h"
     39#include "JSCInlines.h"
    3040#include "JSCJSValueInlines.h"
    3141#include "JSCellInlines.h"
     
    3646namespace JSC {
    3747
    38 const ClassInfo ArrayIteratorPrototype::s_info = { "Array Iterator", &Base::s_info, 0, CREATE_METHOD_TABLE(ArrayIteratorPrototype) };
    3948
    40 static EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeIterate(ExecState*);
     49const ClassInfo ArrayIteratorPrototype::s_info = { "Array Iterator", &Base::s_info, &arrayIteratorPrototypeTable, CREATE_METHOD_TABLE(ArrayIteratorPrototype) };
     50
     51/* Source for ArrayIteratorPrototype.lut.h
     52@begin arrayIteratorPrototypeTable
     53  next      arrayIteratorProtoFuncNext  DontEnum|Function 0
     54@end
     55*/
    4156
    4257void ArrayIteratorPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     
    4560    ASSERT(inherits(info()));
    4661    vm.prototypeMap.addPrototype(this);
    47 
    48     JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorPrivateName, arrayIteratorPrototypeIterate, DontEnum, 0);
     62    JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorPrivateName, arrayIteratorProtoFuncIterator, DontEnum, 0);
    4963}
    5064
    51 EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeIterate(CallFrame* callFrame)
     65bool ArrayIteratorPrototype::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
    5266{
    53     return JSValue::encode(callFrame->thisValue());
     67    return getStaticFunctionSlot<Base>(exec, arrayIteratorPrototypeTable, jsCast<ArrayIteratorPrototype*>(object), propertyName, slot);
    5468}
    5569
     70// ------------------------------ Array Functions ----------------------------
     71
     72EncodedJSValue JSC_HOST_CALL arrayIteratorProtoFuncIterator(ExecState* exec)
     73{
     74    return JSValue::encode(exec->thisValue());
    5675}
     76
     77} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/ArrayIteratorPrototype.h

    r156791 r181077  
    4949    }
    5050
     51protected:
     52    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | Base::StructureFlags;
     53
    5154private:
    5255    ArrayIteratorPrototype(VM& vm, Structure* structure)
     
    5457    {
    5558    }
     59
    5660    void finishCreation(VM&, JSGlobalObject*);
     61    static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
    5762};
    5863
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r180370 r181077  
    236236#define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
    237237    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_WELL_KNOWN_SYMBOL(macro) \
    238     macro(iteratorNext) \
     238    macro(iteratedObject) \
     239    macro(arrayIteratorNextIndex) \
     240    macro(arrayIterationKind) \
     241    macro(arrayIterationKindKey) \
     242    macro(arrayIterationKindValue) \
     243    macro(arrayIterationKindKeyValue) \
    239244    macro(resolve) \
    240245    macro(reject) \
  • trunk/Source/JavaScriptCore/runtime/Intrinsic.h

    r171096 r181077  
    5353    IMulIntrinsic,
    5454    FRoundIntrinsic,
    55     ArrayIteratorNextValueIntrinsic,
    56     ArrayIteratorNextKeyIntrinsic,
    57     ArrayIteratorNextGenericIntrinsic,
    58    
     55
    5956    // Debugging intrinsics. These are meant to be used as testing hacks within
    6057    // jsc.cpp and should never be exposed to users.
  • trunk/Source/JavaScriptCore/runtime/IteratorOperations.h

    r181075 r181077  
    11/*
    2  * Copyright (C) 2013 Apple, Inc. All rights reserved.
     2 * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2121 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    2222 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
     23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2424 */
    2525
    26 #include "config.h"
    27 #include "ArrayIteratorPrototype.h"
     26#ifndef IteratorOperations_h
     27#define IteratorOperations_h
    2828
    29 #include "JSArrayIterator.h"
    30 #include "JSCJSValueInlines.h"
    31 #include "JSCellInlines.h"
    32 #include "JSGlobalObject.h"
    33 #include "ObjectConstructor.h"
    34 #include "StructureInlines.h"
     29#include "JSCJSValue.h"
     30#include "JSObject.h"
    3531
    3632namespace JSC {
    3733
    38 const ClassInfo ArrayIteratorPrototype::s_info = { "Array Iterator", &Base::s_info, 0, CREATE_METHOD_TABLE(ArrayIteratorPrototype) };
     34JSValue iteratorNext(ExecState*, JSValue iterator, JSValue);
     35JSValue iteratorNext(ExecState*, JSValue iterator);
     36JSValue iteratorValue(ExecState*, JSValue iterResult);
     37bool iteratorComplete(ExecState*, JSValue iterResult);
     38JSValue iteratorStep(ExecState*, JSValue iterator);
     39void iteratorClose(ExecState*, JSValue iterator);
     40JSObject* createIterResultObject(ExecState*, JSValue, bool done);
    3941
    40 static EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeIterate(ExecState*);
    41 
    42 void ArrayIteratorPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
    43 {
    44     Base::finishCreation(vm);
    45     ASSERT(inherits(info()));
    46     vm.prototypeMap.addPrototype(this);
    47 
    48     JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorPrivateName, arrayIteratorPrototypeIterate, DontEnum, 0);
    4942}
    5043
    51 EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeIterate(CallFrame* callFrame)
    52 {
    53     return JSValue::encode(callFrame->thisValue());
    54 }
    55 
    56 }
     44#endif // !defined(IteratorOperations_h)
  • trunk/Source/JavaScriptCore/runtime/JSArrayIterator.cpp

    r173410 r181077  
    3636const ClassInfo JSArrayIterator::s_info = { "ArrayIterator", &Base::s_info, 0, CREATE_METHOD_TABLE(JSArrayIterator) };
    3737
    38 static EncodedJSValue JSC_HOST_CALL arrayIteratorNextKey(ExecState*);
    39 static EncodedJSValue JSC_HOST_CALL arrayIteratorNextValue(ExecState*);
    40 static EncodedJSValue JSC_HOST_CALL arrayIteratorNextGeneric(ExecState*);
    41 
    42 void JSArrayIterator::finishCreation(VM& vm, JSGlobalObject* globalObject, ArrayIterationKind kind, JSObject* iteratedObject)
     38void JSArrayIterator::finishCreation(VM& vm, JSGlobalObject*, ArrayIterationKind kind, JSObject* iteratedObject)
    4339{
    4440    Base::finishCreation(vm);
    4541    ASSERT(inherits(info()));
    46     m_iterationKind = kind;
    47     m_iteratedObject.set(vm, this, iteratedObject);
    48     switch (kind) {
    49     case ArrayIterateKey:
    50         JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorNextKey, DontEnum, 0, ArrayIteratorNextKeyIntrinsic);
    51         break;
    52     case ArrayIterateValue:
    53         JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorNextValue, DontEnum, 0, ArrayIteratorNextValueIntrinsic);
    54         break;
    55     default:
    56         JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorNextGeneric, DontEnum, 0, ArrayIteratorNextGenericIntrinsic);
    57         break;
    58     }
    5942
    60 }
    61    
    62    
    63 void JSArrayIterator::visitChildren(JSCell* cell, SlotVisitor& visitor)
    64 {
    65     JSArrayIterator* thisObject = jsCast<JSArrayIterator*>(cell);
    66     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    67     Base::visitChildren(thisObject, visitor);
    68     visitor.append(&thisObject->m_iteratedObject);
    69 }
    70 
    71 static EncodedJSValue createIteratorResult(CallFrame* callFrame, ArrayIterationKind kind, size_t index, JSValue result, bool done)
    72 {
    73     if (done)
    74         return JSValue::encode(callFrame->vm().iterationTerminator.get());
    75    
    76     switch (kind & ~ArrayIterateSparseTag) {
    77     case ArrayIterateKey:
    78         return JSValue::encode(jsNumber(index));
    79        
    80     case ArrayIterateValue:
    81         return JSValue::encode(result);
    82        
    83     case ArrayIterateKeyValue: {
    84         MarkedArgumentBuffer args;
    85         args.append(jsNumber(index));
    86         args.append(result);
    87         JSGlobalObject* globalObject = callFrame->callee()->globalObject();
    88         return JSValue::encode(constructArray(callFrame, 0, globalObject, args));
    89        
    90     }
    91     default:
    92         RELEASE_ASSERT_NOT_REACHED();
    93     }
    94     return JSValue::encode(JSValue());
    95 }
    96 
    97 static inline EncodedJSValue JSC_HOST_CALL arrayIteratorNext(CallFrame* callFrame)
    98 {
    99     JSArrayIterator* iterator = jsDynamicCast<JSArrayIterator*>(callFrame->thisValue());
    100     if (!iterator) {
    101         ASSERT_NOT_REACHED();
    102         return JSValue::encode(throwTypeError(callFrame, ASCIILiteral("Cannot call ArrayIterator.next() on a non-ArrayIterator object")));
    103     }
    104     JSObject* iteratedObject = iterator->iteratedObject();
    105     size_t index = iterator->nextIndex();
    106     ArrayIterationKind kind = iterator->iterationKind();
    107     JSValue jsLength = JSValue(iteratedObject).get(callFrame, callFrame->propertyNames().length);
    108     if (callFrame->hadException())
    109         return JSValue::encode(jsNull());
    110    
    111     size_t length = jsLength.toUInt32(callFrame);
    112     if (callFrame->hadException())
    113         return JSValue::encode(jsNull());
    114    
    115     if (index >= length) {
    116         iterator->finish();
    117         return createIteratorResult(callFrame, kind, index, jsUndefined(), true);
    118     }
    119     if (JSValue result = iteratedObject->tryGetIndexQuickly(index)) {
    120         iterator->setNextIndex(index + 1);
    121         return createIteratorResult(callFrame, kind, index, result, false);
    122     }
    123    
    124     JSValue result = jsUndefined();
    125     PropertySlot slot(iteratedObject);
    126     if (kind > ArrayIterateSparseTag) {
    127         // We assume that the indexed property will be an own property so cache the getOwnProperty
    128         // method locally
    129         auto getOwnPropertySlotByIndex = iteratedObject->methodTable()->getOwnPropertySlotByIndex;
    130         while (index < length) {
    131             if (getOwnPropertySlotByIndex(iteratedObject, callFrame, index, slot)) {
    132                 result = slot.getValue(callFrame, index);
    133                 break;
    134             }
    135             if (iteratedObject->getPropertySlot(callFrame, index, slot)) {
    136                 result = slot.getValue(callFrame, index);
    137                 break;
    138             }
    139             index++;
    140         }
    141     } else if (iteratedObject->getPropertySlot(callFrame, index, slot))
    142         result = slot.getValue(callFrame, index);
    143    
    144     if (index == length)
    145         iterator->finish();
    146     else
    147         iterator->setNextIndex(index + 1);
    148     return createIteratorResult(callFrame, kind, index, jsUndefined(), index == length);
    149 }
    150    
    151 EncodedJSValue JSC_HOST_CALL arrayIteratorNextKey(CallFrame* callFrame)
    152 {
    153     return arrayIteratorNext(callFrame);
    154 }
    155    
    156 EncodedJSValue JSC_HOST_CALL arrayIteratorNextValue(CallFrame* callFrame)
    157 {
    158     return arrayIteratorNext(callFrame);
    159 }
    160    
    161 EncodedJSValue JSC_HOST_CALL arrayIteratorNextGeneric(CallFrame* callFrame)
    162 {
    163     return arrayIteratorNext(callFrame);
     43    putDirect(vm, vm.propertyNames->iteratedObjectPrivateName, iteratedObject);
     44    putDirect(vm, vm.propertyNames->arrayIteratorNextIndexPrivateName, jsNumber(0));
     45    putDirect(vm, vm.propertyNames->arrayIterationKindPrivateName, jsNumber(kind));
    16446}
    16547
  • trunk/Source/JavaScriptCore/runtime/JSArrayIterator.h

    r171939 r181077  
    3434    ArrayIterateKey,
    3535    ArrayIterateValue,
    36     ArrayIterateKeyValue,
    37     ArrayIterateSparseTag = 4,
    38     ArrayIterateSparseKey,
    39     ArrayIterateSparseValue,
    40     ArrayIterateSparseKeyValue
     36    ArrayIterateKeyValue
    4137};
    4238
     
    6056    }
    6157
    62     ArrayIterationKind iterationKind() const { return m_iterationKind; }
    63     JSObject* iteratedObject() const { return m_iteratedObject.get(); }
    64     size_t nextIndex() const { return m_nextIndex; }
    65     void setNextIndex(size_t nextIndex) { m_nextIndex = nextIndex; }
    66     void finish() { m_nextIndex = std::numeric_limits<uint32_t>::max(); }
    67    
    6858    using JSNonFinalObject::arrayStorageOrNull;
    69     static ptrdiff_t offsetOfIterationKind() { return OBJECT_OFFSETOF(JSArrayIterator, m_iterationKind); }
    70     static ptrdiff_t offsetOfIteratedObject() { return OBJECT_OFFSETOF(JSArrayIterator, m_iteratedObject); }
    71     static ptrdiff_t offsetOfNextIndex() { return OBJECT_OFFSETOF(JSArrayIterator, m_nextIndex); }
    72 
    7359private:
    7460    JSArrayIterator(VM& vm, Structure* structure)
    7561        : Base(vm, structure)
    76         , m_nextIndex(0)
    7762    {
    7863    }
    7964
    8065    void finishCreation(VM&, JSGlobalObject*, ArrayIterationKind, JSObject* iteratedObject);
    81     static void visitChildren(JSCell*, SlotVisitor&);
    82    
    83     ArrayIterationKind m_iterationKind;
    84     WriteBarrier<JSObject> m_iteratedObject;
    85     uint32_t m_nextIndex;
    8666};
    8767
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r181064 r181077  
    430430        GlobalPropertyInfo(vm.propertyNames->floorPrivateName, privateFuncFloor, DontEnum | DontDelete | ReadOnly),
    431431        GlobalPropertyInfo(vm.propertyNames->isFinitePrivateName, privateFuncIsFinite, DontEnum | DontDelete | ReadOnly),
     432        GlobalPropertyInfo(vm.propertyNames->arrayIterationKindKeyPrivateName, jsNumber(ArrayIterateKey), DontEnum | DontDelete | ReadOnly),
     433        GlobalPropertyInfo(vm.propertyNames->arrayIterationKindValuePrivateName, jsNumber(ArrayIterateValue), DontEnum | DontDelete | ReadOnly),
     434        GlobalPropertyInfo(vm.propertyNames->arrayIterationKindKeyValuePrivateName, jsNumber(ArrayIterateKeyValue), DontEnum | DontDelete | ReadOnly),
    432435    };
    433436    addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
  • trunk/Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp

    r173681 r181077  
    3030
    3131#include "Error.h"
     32#include "IteratorOperations.h"
    3233#include "JSCJSValueInlines.h"
    3334#include "JSCellInlines.h"
     
    233234}
    234235
     236static void performPromiseRaceLoop(ExecState* exec, JSValue iterator, JSPromiseDeferred* deferred, JSValue C)
     237{
     238    // 6. Repeat
     239    do {
     240        // i. Let 'next' be the result of calling IteratorStep(iterator).
     241        JSValue next = iteratorStep(exec, iterator);
     242
     243        // ii. RejectIfAbrupt(next, deferred).
     244        if (exec->hadException())
     245            return;
     246
     247        // iii. If 'next' is false, return deferred.[[Promise]].
     248        if (next.isFalse())
     249            return;
     250
     251        // iv. Let 'nextValue' be the result of calling IteratorValue(next).
     252        // v. RejectIfAbrupt(nextValue, deferred).
     253        JSValue nextValue = iteratorValue(exec, next);
     254        if (exec->hadException())
     255            return;
     256
     257        // vi. Let 'nextPromise' be the result of calling Invoke(C, "resolve", (nextValue)).
     258        JSValue resolveFunction = C.get(exec, exec->vm().propertyNames->resolve);
     259        if (exec->hadException())
     260            return;
     261
     262        CallData resolveFunctionCallData;
     263        CallType resolveFunctionCallType = getCallData(resolveFunction, resolveFunctionCallData);
     264        if (resolveFunctionCallType == CallTypeNone) {
     265            throwTypeError(exec);
     266            return;
     267        }
     268
     269        MarkedArgumentBuffer resolveFunctionArguments;
     270        resolveFunctionArguments.append(nextValue);
     271        JSValue nextPromise = call(exec, resolveFunction, resolveFunctionCallType, resolveFunctionCallData, C, resolveFunctionArguments);
     272
     273        // vii. RejectIfAbrupt(nextPromise, deferred).
     274        if (exec->hadException())
     275            return;
     276
     277        // viii. Let 'result' be the result of calling Invoke(nextPromise, "then", (deferred.[[Resolve]], deferred.[[Reject]])).
     278        JSValue thenFunction = nextPromise.get(exec, exec->vm().propertyNames->then);
     279        if (exec->hadException())
     280            return;
     281
     282        CallData thenFunctionCallData;
     283        CallType thenFunctionCallType = getCallData(thenFunction, thenFunctionCallData);
     284        if (thenFunctionCallType == CallTypeNone) {
     285            throwTypeError(exec);
     286            return;
     287        }
     288
     289        MarkedArgumentBuffer thenFunctionArguments;
     290        thenFunctionArguments.append(deferred->resolve());
     291        thenFunctionArguments.append(deferred->reject());
     292
     293        call(exec, thenFunction, thenFunctionCallType, thenFunctionCallData, nextPromise, thenFunctionArguments);
     294
     295        // ix. RejectIfAbrupt(result, deferred).
     296        if (exec->hadException())
     297            return;
     298    } while (true);
     299}
     300
    235301EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncRace(ExecState* exec)
    236302{
     
    270336        return JSValue::encode(abruptRejection(exec, deferred));
    271337
    272     // 6. Repeat
    273     do {
    274         // i. Let 'next' be the result of calling IteratorStep(iterator).
    275         JSValue nextFunction = iterator.get(exec, exec->vm().propertyNames->iteratorNextPrivateName);
    276         if (exec->hadException())
    277             return JSValue::encode(abruptRejection(exec, deferred));
    278 
    279         CallData nextFunctionCallData;
    280         CallType nextFunctionCallType = getCallData(nextFunction, nextFunctionCallData);
    281         if (nextFunctionCallType == CallTypeNone) {
    282             throwTypeError(exec);
    283             return JSValue::encode(abruptRejection(exec, deferred));
    284         }
    285 
    286         MarkedArgumentBuffer nextFunctionArguments;
    287         nextFunctionArguments.append(jsUndefined());
    288         JSValue next = call(exec, nextFunction, nextFunctionCallType, nextFunctionCallData, iterator, nextFunctionArguments);
    289        
    290         // ii. RejectIfAbrupt(next, deferred).
    291         if (exec->hadException())
    292             return JSValue::encode(abruptRejection(exec, deferred));
    293    
    294         // iii. If 'next' is false, return deferred.[[Promise]].
    295         // Note: We implement this as an iterationTerminator
    296         if (next == vm.iterationTerminator.get())
    297             return JSValue::encode(deferred->promise());
    298        
    299         // iv. Let 'nextValue' be the result of calling IteratorValue(next).
    300         // v. RejectIfAbrupt(nextValue, deferred).
    301         // Note: 'next' is already the value, so there is nothing to do here.
    302 
    303         // vi. Let 'nextPromise' be the result of calling Invoke(C, "resolve", (nextValue)).
    304         JSValue resolveFunction = C.get(exec, vm.propertyNames->resolve);
    305         if (exec->hadException())
    306             return JSValue::encode(abruptRejection(exec, deferred));
    307 
    308         CallData resolveFunctionCallData;
    309         CallType resolveFunctionCallType = getCallData(resolveFunction, resolveFunctionCallData);
    310         if (resolveFunctionCallType == CallTypeNone) {
    311             throwTypeError(exec);
    312             return JSValue::encode(abruptRejection(exec, deferred));
    313         }
    314 
    315         MarkedArgumentBuffer resolveFunctionArguments;
    316         resolveFunctionArguments.append(next);
    317         JSValue nextPromise = call(exec, resolveFunction, resolveFunctionCallType, resolveFunctionCallData, C, resolveFunctionArguments);
    318 
    319         // vii. RejectIfAbrupt(nextPromise, deferred).
    320         if (exec->hadException())
    321             return JSValue::encode(abruptRejection(exec, deferred));
    322 
    323         // viii. Let 'result' be the result of calling Invoke(nextPromise, "then", (deferred.[[Resolve]], deferred.[[Reject]])).
    324         JSValue thenFunction = nextPromise.get(exec, vm.propertyNames->then);
    325         if (exec->hadException())
    326             return JSValue::encode(abruptRejection(exec, deferred));
    327 
    328         CallData thenFunctionCallData;
    329         CallType thenFunctionCallType = getCallData(thenFunction, thenFunctionCallData);
    330         if (thenFunctionCallType == CallTypeNone) {
    331             throwTypeError(exec);
    332             return JSValue::encode(abruptRejection(exec, deferred));
    333         }
    334 
    335         MarkedArgumentBuffer thenFunctionArguments;
    336         thenFunctionArguments.append(deferred->resolve());
    337         thenFunctionArguments.append(deferred->reject());
    338 
    339         call(exec, thenFunction, thenFunctionCallType, thenFunctionCallData, nextPromise, thenFunctionArguments);
    340 
    341         // ix. RejectIfAbrupt(result, deferred).
    342         if (exec->hadException())
    343             return JSValue::encode(abruptRejection(exec, deferred));
    344     } while (true);
    345 }
    346 
    347 EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncAll(ExecState* exec)
    348 {
    349     // -- Promise.all(iterable) --
    350 
    351     JSValue iterable = exec->argument(0);
     338    performPromiseRaceLoop(exec, iterator, deferred, C);
     339    if (exec->hadException())
     340        iteratorClose(exec, iterator);
     341    if (exec->hadException())
     342        return JSValue::encode(abruptRejection(exec, deferred));
     343    return JSValue::encode(deferred->promise());
     344}
     345
     346static JSValue performPromiseAll(ExecState* exec, JSValue iterator, JSValue C, JSPromiseDeferred* deferred)
     347{
     348    JSObject* thisObject = asObject(C);
    352349    VM& vm = exec->vm();
    353 
    354     // 1. Let 'C' be the this value.
    355     JSValue C = exec->thisValue();
    356 
    357     // 2. Let 'deferred' be the result of calling GetDeferred(C).
    358     JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C);
    359 
    360     // 3. ReturnIfAbrupt(deferred).
    361     if (exec->hadException())
    362         return JSValue::encode(jsUndefined());
    363 
    364     // NOTE: A non-abrupt completion of createJSPromiseDeferredFromConstructor implies that
    365     // C and deferredValue are objects.
    366     JSObject* thisObject = asObject(C);
    367     JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue);
    368 
    369     // 4. Let 'iterator' be the result of calling GetIterator(iterable).
    370     JSValue iteratorFunction = iterable.get(exec, vm.propertyNames->iteratorPrivateName);
    371     if (exec->hadException())
    372         return JSValue::encode(abruptRejection(exec, deferred));
    373 
    374     CallData iteratorFunctionCallData;
    375     CallType iteratorFunctionCallType = getCallData(iteratorFunction, iteratorFunctionCallData);
    376     if (iteratorFunctionCallType == CallTypeNone) {
    377         throwTypeError(exec);
    378         return JSValue::encode(abruptRejection(exec, deferred));
    379     }
    380 
    381     ArgList iteratorFunctionArguments;
    382     JSValue iterator = call(exec, iteratorFunction, iteratorFunctionCallType, iteratorFunctionCallData, iterable, iteratorFunctionArguments);
    383 
    384     // 5. RejectIfAbrupt(iterator, deferred).
    385     if (exec->hadException())
    386         return JSValue::encode(abruptRejection(exec, deferred));
    387350
    388351    // 6. Let 'values' be the result of calling ArrayCreate(0).
    389352    JSArray* values = constructEmptyArray(exec, nullptr, thisObject->globalObject());
    390    
     353
    391354    // 7. Let 'countdownHolder' be Record { [[Countdown]]: 0 }.
    392355    NumberObject* countdownHolder = constructNumber(exec, thisObject->globalObject(), JSValue(0));
    393    
     356
    394357    // 8. Let 'index' be 0.
    395358    unsigned index = 0;
    396    
     359
    397360    // 9. Repeat.
    398361    do {
    399362        // i. Let 'next' be the result of calling IteratorStep(iterator).
    400         JSValue nextFunction = iterator.get(exec, exec->vm().propertyNames->iteratorNextPrivateName);
    401         if (exec->hadException())
    402             return JSValue::encode(abruptRejection(exec, deferred));
    403 
    404         CallData nextFunctionCallData;
    405         CallType nextFunctionCallType = getCallData(nextFunction, nextFunctionCallData);
    406         if (nextFunctionCallType == CallTypeNone) {
    407             throwTypeError(exec);
    408             return JSValue::encode(abruptRejection(exec, deferred));
    409         }
    410 
    411         MarkedArgumentBuffer nextFunctionArguments;
    412         nextFunctionArguments.append(jsUndefined());
    413         JSValue next = call(exec, nextFunction, nextFunctionCallType, nextFunctionCallData, iterator, nextFunctionArguments);
    414        
    415         // ii. RejectIfAbrupt(next, deferred).
    416         if (exec->hadException())
    417             return JSValue::encode(abruptRejection(exec, deferred));
     363        JSValue next = iteratorStep(exec, iterator);
     364        if (exec->hadException())
     365            return jsUndefined();
    418366
    419367        // iii. If 'next' is false,
    420         // Note: We implement this as an iterationTerminator
    421         if (next == vm.iterationTerminator.get()) {
     368        if (next.isFalse()) {
    422369            // a. If 'index' is 0,
    423370            if (!index) {
     
    429376                // b. ReturnIfAbrupt(resolveResult).
    430377                if (exec->hadException())
    431                     return JSValue::encode(jsUndefined());
     378                    return jsUndefined();
    432379            }
    433            
     380
    434381            // b. Return deferred.[[Promise]].
    435             return JSValue::encode(deferred->promise());
     382            return deferred->promise();
    436383        }
    437        
     384
    438385        // iv. Let 'nextValue' be the result of calling IteratorValue(next).
    439386        // v. RejectIfAbrupt(nextValue, deferred).
    440         // Note: 'next' is already the value, so there is nothing to do here.
     387        JSValue nextValue = iteratorValue(exec, next);
     388        if (exec->hadException())
     389            return jsUndefined();
     390
     391        values->push(exec, jsUndefined());
    441392
    442393        // vi. Let 'nextPromise' be the result of calling Invoke(C, "resolve", (nextValue)).
    443394        JSValue resolveFunction = C.get(exec, vm.propertyNames->resolve);
    444395        if (exec->hadException())
    445             return JSValue::encode(abruptRejection(exec, deferred));
     396            return jsUndefined();
    446397
    447398        CallData resolveFunctionCallData;
     
    449400        if (resolveFunctionCallType == CallTypeNone) {
    450401            throwTypeError(exec);
    451             return JSValue::encode(abruptRejection(exec, deferred));
     402            return jsUndefined();
    452403        }
    453404
    454405        MarkedArgumentBuffer resolveFunctionArguments;
    455         resolveFunctionArguments.append(next);
     406        resolveFunctionArguments.append(nextValue);
    456407        JSValue nextPromise = call(exec, resolveFunction, resolveFunctionCallType, resolveFunctionCallData, C, resolveFunctionArguments);
    457408
    458409        // vii. RejectIfAbrupt(nextPromise, deferred).
    459410        if (exec->hadException())
    460             return JSValue::encode(abruptRejection(exec, deferred));
     411            return jsUndefined();
    461412
    462413        // viii. Let 'countdownFunction' be a new built-in function object as defined in Promise.all Countdown Functions.
    463414        JSFunction* countdownFunction = createPromiseAllCountdownFunction(vm, thisObject->globalObject());
    464        
     415
    465416        // ix. Set the [[Index]] internal slot of 'countdownFunction' to 'index'.
    466417        countdownFunction->putDirect(vm, vm.propertyNames->indexPrivateName, JSValue(index));
     
    478429        JSValue thenFunction = nextPromise.get(exec, vm.propertyNames->then);
    479430        if (exec->hadException())
    480             return JSValue::encode(abruptRejection(exec, deferred));
     431            return jsUndefined();
    481432
    482433        CallData thenFunctionCallData;
     
    484435        if (thenFunctionCallType == CallTypeNone) {
    485436            throwTypeError(exec);
    486             return JSValue::encode(abruptRejection(exec, deferred));
     437            return jsUndefined();
    487438        }
    488439
     
    495446        // xiv. RejectIfAbrupt(result, deferred).
    496447        if (exec->hadException())
    497             return JSValue::encode(abruptRejection(exec, deferred));
     448            return jsUndefined();
    498449
    499450        // xv. Set index to index + 1.
     
    504455        countdownHolder->setInternalValue(vm, JSValue(newCountdownValue));
    505456    } while (true);
     457    ASSERT_NOT_REACHED();
     458    return jsUndefined();
     459}
     460
     461EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncAll(ExecState* exec)
     462{
     463    // -- Promise.all(iterable) --
     464
     465    JSValue iterable = exec->argument(0);
     466    VM& vm = exec->vm();
     467
     468    // 1. Let 'C' be the this value.
     469    JSValue C = exec->thisValue();
     470
     471    // 2. Let 'deferred' be the result of calling GetDeferred(C).
     472    JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C);
     473
     474    // 3. ReturnIfAbrupt(deferred).
     475    if (exec->hadException())
     476        return JSValue::encode(jsUndefined());
     477
     478    // NOTE: A non-abrupt completion of createJSPromiseDeferredFromConstructor implies that
     479    // C and deferredValue are objects.
     480    JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue);
     481
     482    // 4. Let 'iterator' be the result of calling GetIterator(iterable).
     483    JSValue iteratorFunction = iterable.get(exec, vm.propertyNames->iteratorPrivateName);
     484    if (exec->hadException())
     485        return JSValue::encode(abruptRejection(exec, deferred));
     486
     487    CallData iteratorFunctionCallData;
     488    CallType iteratorFunctionCallType = getCallData(iteratorFunction, iteratorFunctionCallData);
     489    if (iteratorFunctionCallType == CallTypeNone) {
     490        throwTypeError(exec);
     491        return JSValue::encode(abruptRejection(exec, deferred));
     492    }
     493
     494    ArgList iteratorFunctionArguments;
     495    JSValue iterator = call(exec, iteratorFunction, iteratorFunctionCallType, iteratorFunctionCallData, iterable, iteratorFunctionArguments);
     496
     497    // 5. RejectIfAbrupt(iterator, deferred).
     498    if (exec->hadException())
     499        return JSValue::encode(abruptRejection(exec, deferred));
     500
     501    JSValue result = performPromiseAll(exec, iterator, C, deferred);
     502    if (exec->hadException()) {
     503        iteratorClose(exec, iterator);
     504        if (exec->hadException())
     505            return JSValue::encode(abruptRejection(exec, deferred));
     506    }
     507    return JSValue::encode(result);
    506508}
    507509
  • trunk/Source/JavaScriptCore/runtime/MapIteratorPrototype.cpp

    r173410 r181077  
    2727#include "MapIteratorPrototype.h"
    2828
     29#include "IteratorOperations.h"
    2930#include "JSCJSValueInlines.h"
    3031#include "JSCellInlines.h"
     
    4748
    4849    JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorPrivateName, MapIteratorPrototypeFuncIterator, DontEnum, 0);
    49     JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorNextPrivateName, MapIteratorPrototypeFuncNext, DontEnum, 0);
     50    JSC_NATIVE_FUNCTION(vm.propertyNames->next, MapIteratorPrototypeFuncNext, DontEnum, 0);
    5051}
    5152
     
    6061    if (!iterator)
    6162        return JSValue::encode(throwTypeError(callFrame, ASCIILiteral("Cannot call MapIterator.next() on a non-MapIterator object")));
    62    
     63
    6364    JSValue result;
    6465    if (iterator->next(callFrame, result))
    65         return JSValue::encode(result);
     66        return JSValue::encode(createIterResultObject(callFrame, result, false));
    6667    iterator->finish();
    67     return JSValue::encode(callFrame->vm().iterationTerminator.get());
     68    return JSValue::encode(createIterResultObject(callFrame, jsUndefined(), true));
    6869}
    6970
  • trunk/Source/JavaScriptCore/runtime/SetIteratorPrototype.cpp

    r173410 r181077  
    2727#include "SetIteratorPrototype.h"
    2828
     29#include "IteratorOperations.h"
    2930#include "JSCJSValueInlines.h"
    3031#include "JSCellInlines.h"
     
    4748
    4849    JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorPrivateName, SetIteratorPrototypeFuncIterator, DontEnum, 0);
    49     JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorNextPrivateName, SetIteratorPrototypeFuncNext, DontEnum, 0);
     50    JSC_NATIVE_FUNCTION(vm.propertyNames->next, SetIteratorPrototypeFuncNext, DontEnum, 0);
    5051}
    5152
     
    6364
    6465    if (iterator->next(callFrame, result))
    65         return JSValue::encode(result);
     66        return JSValue::encode(createIterResultObject(callFrame, result, false));
    6667    iterator->finish();
    67     return JSValue::encode(callFrame->vm().iterationTerminator.get());
     68    return JSValue::encode(createIterResultObject(callFrame, jsUndefined(), true));
    6869}
    6970
    70 
    7171}
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r181010 r181077  
    400400    case IMulIntrinsic:
    401401        return imulThunkGenerator;
    402     case ArrayIteratorNextKeyIntrinsic:
    403         return arrayIteratorNextKeyThunkGenerator;
    404     case ArrayIteratorNextValueIntrinsic:
    405         return arrayIteratorNextValueThunkGenerator;
    406402    default:
    407403        return 0;
Note: See TracChangeset for help on using the changeset viewer.