Changeset 185791 in webkit


Ignore:
Timestamp:
Jun 20, 2015 4:04:27 AM (9 years ago)
Author:
Yusuke Suzuki
Message:

[ES6] Destructuring assignment need to accept iterables
https://bugs.webkit.org/show_bug.cgi?id=144111

Reviewed by Darin Adler.

Source/JavaScriptCore:

This patch makes that destructuring assignments to array binding patterns accept iterables.
Previously, it just access the indexed properties.
After this patch, it iterates the given value by using ES6 iterator protocol.

The iteration becomes different from the for-of case.

  1. Since there's no break/continue case, finally scope is not necessary.
  2. When the error is raised, the close status of the iterator becomes true. So IteratorClose is not called for that.
  3. Since the array binding patterns requires a limited count of iterations (if there is no rest(...rest) case), IteratorClose is called when the iteration does not consume the all values of the iterator.
  4. Since the array binding patterns requires a specified count of iterations, iterator's next call is skipped when iterator becomes closed.
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitIteratorClose):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::ArrayPatternNode::bindValue):

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::finishArrayPattern):

  • parser/Nodes.h:
  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseDeconstructionPattern):

  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::operatorStackPop):

  • tests/stress/destructuring-assignment-accepts-iterables.js: Added.

(shouldBe):
(shouldThrow):
(.set shouldThrow):

LayoutTests:

From this patch, we use iterators for destructuring assignments to array binding patterns.
So test results become different.

  • js/destructuring-assignment-expected.txt:
  • js/parser-syntax-check-expected.txt:
  • js/script-tests/destructuring-assignment.js:
Location:
trunk
Files:
1 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r185787 r185791  
     12015-06-20  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [ES6] Destructuring assignment need to accept iterables
     4        https://bugs.webkit.org/show_bug.cgi?id=144111
     5
     6        Reviewed by Darin Adler.
     7
     8        From this patch, we use iterators for destructuring assignments to array binding patterns.
     9        So test results become different.
     10
     11        * js/destructuring-assignment-expected.txt:
     12        * js/parser-syntax-check-expected.txt:
     13        * js/script-tests/destructuring-assignment.js:
     14
    1152015-06-19  Dean Jackson  <dino@apple.com>
    216
  • trunk/LayoutTests/js/destructuring-assignment-expected.txt

    r181901 r185791  
    8181PASS testDeconstructArgs('1', '2') is '12'
    8282PASS testDeconstructArgLength('1', '2') is 2
    83 PASS testDeconstructArgs('2') is '23'
     83PASS testDeconstructArgs('2') is '2undefined'
    8484PASS a is 1
    8585PASS b is 2
  • trunk/LayoutTests/js/parser-syntax-check-expected.txt

    r181929 r185791  
    776776PASS Valid:   "var {x, y}=1"
    777777PASS Valid:   "function f() { var {x, y}=1 }"
    778 PASS Valid:   "var [x]=1"
     778PASS Valid:   "var [x]=1" with TypeError
    779779PASS Valid:   "function f() { var [x]=1 }"
    780 PASS Valid:   "var [x, y]=1"
     780PASS Valid:   "var [x, y]=1" with TypeError
    781781PASS Valid:   "function f() { var [x, y]=1 }"
    782 PASS Valid:   "[x]=1"
     782PASS Valid:   "[x]=1" with TypeError
    783783PASS Valid:   "function f() { [x]=1 }"
    784 PASS Valid:   "var [x]=1"
     784PASS Valid:   "var [x]=1" with TypeError
    785785PASS Valid:   "function f() { var [x]=1 }"
    786786PASS Valid:   "({[x]: 1})"
  • trunk/LayoutTests/js/script-tests/destructuring-assignment.js

    r172381 r185791  
    4949var text = '3';
    5050Object.prototype.__defineGetter__(1, function(){ var r = text; text = "fail"; return r; })
    51 shouldBe("testDeconstructArgs('2')", "'23'");
     51shouldBe("testDeconstructArgs('2')", "'2undefined'");
    5252
    5353var [a,b] = [1,2], [c,d] = [3,4]
  • trunk/Source/JavaScriptCore/ChangeLog

    r185784 r185791  
     12015-06-20  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [ES6] Destructuring assignment need to accept iterables
     4        https://bugs.webkit.org/show_bug.cgi?id=144111
     5
     6        Reviewed by Darin Adler.
     7
     8        This patch makes that destructuring assignments to array binding patterns accept iterables.
     9        Previously, it just access the indexed properties.
     10        After this patch, it iterates the given value by using ES6 iterator protocol.
     11
     12        The iteration becomes different from the for-of case.
     13        1. Since there's no break/continue case, finally scope is not necessary.
     14        2. When the error is raised, the close status of the iterator becomes true. So IteratorClose is not called for that.
     15        3. Since the array binding patterns requires a limited count of iterations (if there is no rest(...rest) case), IteratorClose is called when the iteration does not consume the all values of the iterator.
     16        4. Since the array binding patterns requires a specified count of iterations, iterator's next call is skipped when iterator becomes closed.
     17
     18        * bytecompiler/BytecodeGenerator.cpp:
     19        (JSC::BytecodeGenerator::emitIteratorClose):
     20        * bytecompiler/BytecodeGenerator.h:
     21        * bytecompiler/NodesCodegen.cpp:
     22        (JSC::ArrayPatternNode::bindValue):
     23        * parser/ASTBuilder.h:
     24        (JSC::ASTBuilder::finishArrayPattern):
     25        * parser/Nodes.h:
     26        * parser/Parser.cpp:
     27        (JSC::Parser<LexerType>::parseDeconstructionPattern):
     28        * parser/SyntaxChecker.h:
     29        (JSC::SyntaxChecker::operatorStackPop):
     30        * tests/stress/destructuring-assignment-accepts-iterables.js: Added.
     31        (shouldBe):
     32        (shouldThrow):
     33        (.set shouldThrow):
     34
    1352015-06-19  Devin Rousso  <drousso@apple.com>
    236
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r185259 r185791  
    29342934}
    29352935
    2936 void BytecodeGenerator::emitIteratorClose(RegisterID* iterator, ThrowableExpressionData* node)
     2936void BytecodeGenerator::emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node)
    29372937{
    29382938    RefPtr<Label> done = newLabel();
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r185259 r185791  
    547547        RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
    548548
    549         void emitIteratorClose(RegisterID* iterator, ThrowableExpressionData* node);
     549        void emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node);
    550550
    551551        void emitReadOnlyExceptionIfNeeded();
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r185699 r185791  
    31293129    generator.emitLabel(isNotUndefined.get());
    31303130}
    3131    
     3131
    31323132void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
    31333133{
    3134     for (size_t i = 0; i < m_targetPatterns.size(); i++) {
    3135         auto target = m_targetPatterns[i];
     3134    RefPtr<RegisterID> iterator = generator.newTemporary();
     3135    {
     3136        generator.emitGetById(iterator.get(), rhs, generator.propertyNames().iteratorSymbol);
     3137        CallArguments args(generator, nullptr);
     3138        generator.emitMove(args.thisRegister(), rhs);
     3139        generator.emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd());
     3140    }
     3141
     3142    RefPtr<RegisterID> done;
     3143    ASSERT(!m_targetPatterns.isEmpty());
     3144    for (auto& target : m_targetPatterns) {
     3145        RefPtr<RegisterID> value = generator.newTemporary();
     3146
     3147        RefPtr<Label> iterationSkipped = generator.newLabel();
     3148        if (!done)
     3149            done = generator.newTemporary();
     3150        else
     3151            generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
     3152
     3153        {
     3154            RefPtr<RegisterID> next = generator.emitGetById(generator.newTemporary(), iterator.get(), generator.propertyNames().next);
     3155            CallArguments nextArguments(generator, nullptr);
     3156            generator.emitMove(nextArguments.thisRegister(), iterator.get());
     3157            generator.emitCall(value.get(), next.get(), NoExpectedFunction, nextArguments, divot(), divotStart(), divotEnd());
     3158        }
     3159        {
     3160            RefPtr<Label> typeIsObject = generator.newLabel();
     3161            generator.emitJumpIfTrue(generator.emitIsObject(generator.newTemporary(), value.get()), typeIsObject.get());
     3162            generator.emitThrowTypeError(ASCIILiteral("Iterator result interface is not an object."));
     3163            generator.emitLabel(typeIsObject.get());
     3164        }
     3165
     3166        {
     3167            generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
     3168            RefPtr<Label> valueIsSet = generator.newLabel();
     3169            generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
     3170            generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
     3171            generator.emitJump(valueIsSet.get());
     3172            generator.emitLabel(iterationSkipped.get());
     3173            generator.emitLoad(value.get(), jsUndefined());
     3174            generator.emitLabel(valueIsSet.get());
     3175        }
     3176
    31363177        if (!target.pattern)
    31373178            continue;
    3138         RefPtr<RegisterID> temp = generator.newTemporary();
    3139         generator.emitLoad(temp.get(), jsNumber(i));
    3140         generator.emitGetByVal(temp.get(), rhs, temp.get());
    31413179        if (target.defaultValue)
    3142             assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
    3143         target.pattern->bindValue(generator, temp.get());
    3144     }
     3180            assignDefaultValueIfUndefined(generator, value.get(), target.defaultValue);
     3181        target.pattern->bindValue(generator, value.get());
     3182    }
     3183
     3184    RefPtr<Label> iteratorClosed = generator.newLabel();
     3185    generator.emitJumpIfTrue(done.get(), iteratorClosed.get());
     3186    generator.emitIteratorClose(iterator.get(), this);
     3187    generator.emitLabel(iteratorClosed.get());
    31453188}
    31463189
  • trunk/Source/JavaScriptCore/parser/ASTBuilder.h

    r185699 r185791  
    745745        node->appendIndex(location, pattern.get(), defaultValue);
    746746    }
     747
     748    void finishArrayPattern(ArrayPattern node, const JSTextPosition& divotStart, const JSTextPosition& divot, const JSTextPosition& divotEnd)
     749    {
     750        setExceptionLocation(node.get(), divotStart, divot, divotEnd);
     751    }
    747752   
    748753    ObjectPattern createObjectPattern(const JSTokenLocation&)
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r185699 r185791  
    17811781    };
    17821782
    1783     class ArrayPatternNode : public DeconstructionPatternNode {
     1783    class ArrayPatternNode : public DeconstructionPatternNode, public ThrowableExpressionData {
    17841784    public:
    17851785        static Ref<ArrayPatternNode> create();
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r185699 r185791  
    598598    switch (m_token.m_type) {
    599599    case OPENBRACKET: {
     600        JSTextPosition divotStart = tokenStartPosition();
    600601        auto arrayPattern = context.createArrayPattern(m_token.m_location);
    601602        next();
     
    623624
    624625        consumeOrFail(CLOSEBRACKET, "Expected either a closing ']' or a ',' following an element deconstruction pattern");
     626        context.finishArrayPattern(arrayPattern, divotStart, divotStart, lastTokenEndPosition());
    625627        pattern = arrayPattern;
    626628        break;
  • trunk/Source/JavaScriptCore/parser/SyntaxChecker.h

    r185699 r185791  
    312312    {
    313313    }
     314    void finishArrayPattern(ArrayPattern, const JSTextPosition&, const JSTextPosition&, const JSTextPosition&)
     315    {
     316    }
    314317    ObjectPattern createObjectPattern(const JSTokenLocation&)
    315318    {
Note: See TracChangeset for help on using the changeset viewer.