Changeset 156910 in webkit


Ignore:
Timestamp:
Oct 4, 2013 1:35:24 PM (10 years ago)
Author:
oliver@apple.com
Message:

Support for-of syntax
https://bugs.webkit.org/show_bug.cgi?id=122339

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Add support for for-of syntax to JSC. As part of doing this I had to make
us support unique empty strings as identifiers. In a follow on patch i'm
going to remove the distinction entirely as it's purely a complicating
separation.

Otherwise the logic here is fairly self-explanatory.

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::addConstant):
(JSC::BytecodeGenerator::emitCall):

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

(JSC::CallArguments::CallArguments):
(JSC::ForOfNode::emitBytecode):

  • jit/JITOperations.cpp:
  • parser/ASTBuilder.h:

(JSC::ASTBuilder::createForOfLoop):

  • parser/NodeConstructors.h:

(JSC::EnumerationNode::EnumerationNode):
(JSC::ForInNode::ForInNode):
(JSC::ForOfNode::ForOfNode):

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

(JSC::::parseVarDeclarationList):
(JSC::::parseForStatement):

  • parser/Parser.h:

(JSC::Parser::isofToken):

  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::createForOfLoop):

  • runtime/ArrayIteratorPrototype.cpp:

(JSC::ArrayIteratorPrototype::finishCreation):
(JSC::arrayIteratorPrototypeIterate):

  • runtime/ArrayPrototype.cpp:

(JSC::ArrayPrototype::create):
(JSC::ArrayPrototype::finishCreation):

  • runtime/ArrayPrototype.h:
  • runtime/CommonIdentifiers.cpp:

(JSC::CommonIdentifiers::CommonIdentifiers):

  • runtime/CommonIdentifiers.h:
  • runtime/Identifier.h:

(JSC::Identifier::from):

  • runtime/JSCJSValue.cpp:

(JSC::JSValue::dumpInContext):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::reset):

  • runtime/JSObject.cpp:

(JSC::JSObject::putDirectNativeFunction):

  • runtime/PrivateName.h:

(JSC::PrivateName::PrivateName):

  • runtime/PropertyName.h:

(JSC::PropertyName::PropertyName):

Source/WTF:

Update assertions and add a helper function to StringImpl
to save repeated unique or identifier calls.

  • wtf/text/StringImpl.h:

(WTF::StringImpl::isIdentifierOrUnique):
(WTF::StringImpl::setIsIdentifier):
(WTF::StringImpl::setIsAtomic):

LayoutTests:

Add test cases for the one type that supports for-of so far

  • js/basic-for-of-expected.txt: Added.
  • js/basic-for-of.html: Added.
  • js/regress/for-of-iterate-array-entries.html: Added.
  • js/regress/for-of-iterate-array-keys.html: Added.
  • js/regress/for-of-iterate-array-values.html: Added.
  • js/regress/script-tests/for-of-iterate-array-entries.js: Added.

(foo):

  • js/regress/script-tests/for-of-iterate-array-keys.js: Added.

(foo):

  • js/regress/script-tests/for-of-iterate-array-values.js: Added.

(foo):

Location:
trunk
Files:
11 added
29 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r156905 r156910  
     12013-10-04  Oliver Hunt  <oliver@apple.com>
     2
     3        Support for-of syntax
     4        https://bugs.webkit.org/show_bug.cgi?id=122339
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Add test cases for the one type that supports for-of so far
     9
     10        * js/basic-for-of-expected.txt: Added.
     11        * js/basic-for-of.html: Added.
     12        * js/regress/for-of-iterate-array-entries.html: Added.
     13        * js/regress/for-of-iterate-array-keys.html: Added.
     14        * js/regress/for-of-iterate-array-values.html: Added.
     15        * js/regress/script-tests/for-of-iterate-array-entries.js: Added.
     16        (foo):
     17        * js/regress/script-tests/for-of-iterate-array-keys.js: Added.
     18        (foo):
     19        * js/regress/script-tests/for-of-iterate-array-values.js: Added.
     20        (foo):
     21
    1222013-10-04  Bear Travis  <betravis@adobe.com>
    223
  • trunk/LayoutTests/js/parser-syntax-check-expected.txt

    r155724 r156910  
    580580PASS Invalid: "var a.b;"
    581581PASS Invalid: "function f() { var a.b; }"
     582PASS Valid:   "for (of of of){}"
     583PASS Valid:   "function f() { for (of of of){} }"
     584PASS Valid:   "for (of; of; of){}"
     585PASS Valid:   "function f() { for (of; of; of){} }"
     586PASS Valid:   "for (var of of of){}"
     587PASS Valid:   "function f() { for (var of of of){} }"
     588PASS Valid:   "for (var of; of; of){}"
     589PASS Valid:   "function f() { for (var of; of; of){} }"
     590PASS Invalid: "for (var of.of of of){}"
     591PASS Invalid: "function f() { for (var of.of of of){} }"
     592PASS Invalid: "for (var of[of] of of){}"
     593PASS Invalid: "function f() { for (var of[of] of of){} }"
     594PASS Valid:   "for (of.of of of){}"
     595PASS Valid:   "function f() { for (of.of of of){} }"
     596PASS Valid:   "for (of[of] of of){}"
     597PASS Valid:   "function f() { for (of[of] of of){} }"
     598PASS Valid:   "for (var [of] of of){}"
     599PASS Valid:   "function f() { for (var [of] of of){} }"
     600PASS Valid:   "for (var {of} of of){}"
     601PASS Valid:   "function f() { for (var {of} of of){} }"
     602PASS Valid:   "for (of in of){}"
     603PASS Valid:   "function f() { for (of in of){} }"
     604PASS Valid:   "for (var of in of){}"
     605PASS Valid:   "function f() { for (var of in of){} }"
     606PASS Invalid: "for (var of.of in of){}"
     607PASS Invalid: "function f() { for (var of.of in of){} }"
     608PASS Valid:   "for (of.of in of){}"
     609PASS Valid:   "function f() { for (of.of in of){} }"
     610PASS Valid:   "for (of[of] in of){}"
     611PASS Valid:   "function f() { for (of[of] in of){} }"
     612PASS Invalid: "for (var of[of] in of){}"
     613PASS Invalid: "function f() { for (var of[of] in of){} }"
     614PASS Valid:   "for (var [of] in of){}"
     615PASS Valid:   "function f() { for (var [of] in of){} }"
     616PASS Valid:   "for (var {of} in of){}"
     617PASS Valid:   "function f() { for (var {of} in of){} }"
     618PASS Invalid: "for (of of of of){}"
     619PASS Invalid: "function f() { for (of of of of){} }"
     620PASS Invalid: "for (of of; of; of){}"
     621PASS Invalid: "function f() { for (of of; of; of){} }"
     622PASS Invalid: "for (of of []; of; of){}"
     623PASS Invalid: "function f() { for (of of []; of; of){} }"
     624PASS Invalid: "for (of of){}"
     625PASS Invalid: "function f() { for (of of){} }"
     626PASS Invalid: "for (var of of){}"
     627PASS Invalid: "function f() { for (var of of){} }"
     628PASS Invalid: "for (of of in of){}"
     629PASS Invalid: "function f() { for (of of in of){} }"
     630PASS Invalid: "for (of in){}"
     631PASS Invalid: "function f() { for (of in){} }"
     632PASS Invalid: "for (var of in){}"
     633PASS Invalid: "function f() { for (var of in){} }"
    582634PASS e.line is 1
    583635PASS foo is 'PASS'
  • trunk/LayoutTests/js/script-tests/parser-syntax-check.js

    r155724 r156910  
    370370invalid("var a.b;");
    371371
     372valid("for (of of of){}")
     373valid("for (of; of; of){}")
     374valid("for (var of of of){}")
     375valid("for (var of; of; of){}")
     376invalid("for (var of.of of of){}")
     377invalid("for (var of[of] of of){}")
     378valid("for (of.of of of){}")
     379valid("for (of[of] of of){}")
     380valid("for (var [of] of of){}")
     381valid("for (var {of} of of){}")
     382valid("for (of in of){}")
     383valid("for (var of in of){}")
     384invalid("for (var of.of in of){}")
     385valid("for (of.of in of){}")
     386valid("for (of[of] in of){}")
     387invalid("for (var of[of] in of){}")
     388valid("for (var [of] in of){}")
     389valid("for (var {of} in of){}")
     390
     391
     392invalid("for (of of of of){}")
     393invalid("for (of of; of; of){}")
     394invalid("for (of of []; of; of){}")
     395invalid("for (of of){}")
     396invalid("for (var of of){}")
     397invalid("for (of of in of){}")
     398invalid("for (of in){}")
     399invalid("for (var of in){}")
     400
     401
     402
    372403try { eval("a.b.c = {};"); } catch(e1) { e=e1; shouldBe("e.line", "1") }
    373404foo = 'FAIL';
  • trunk/Source/JavaScriptCore/ChangeLog

    r156906 r156910  
     12013-10-04  Oliver Hunt  <oliver@apple.com>
     2
     3        Support for-of syntax
     4        https://bugs.webkit.org/show_bug.cgi?id=122339
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Add support for for-of syntax to JSC.  As part of doing this I had to make
     9        us support unique empty strings as identifiers.  In a follow on patch i'm
     10        going to remove the distinction entirely as it's purely a complicating
     11        separation.
     12
     13        Otherwise the logic here is fairly self-explanatory.
     14
     15        * bytecompiler/BytecodeGenerator.cpp:
     16        (JSC::BytecodeGenerator::addConstant):
     17        (JSC::BytecodeGenerator::emitCall):
     18        * bytecompiler/BytecodeGenerator.h:
     19        * bytecompiler/NodesCodegen.cpp:
     20        (JSC::CallArguments::CallArguments):
     21        (JSC::ForOfNode::emitBytecode):
     22        * jit/JITOperations.cpp:
     23        * parser/ASTBuilder.h:
     24        (JSC::ASTBuilder::createForOfLoop):
     25        * parser/NodeConstructors.h:
     26        (JSC::EnumerationNode::EnumerationNode):
     27        (JSC::ForInNode::ForInNode):
     28        (JSC::ForOfNode::ForOfNode):
     29        * parser/Nodes.h:
     30        * parser/Parser.cpp:
     31        (JSC::::parseVarDeclarationList):
     32        (JSC::::parseForStatement):
     33        * parser/Parser.h:
     34        (JSC::Parser::isofToken):
     35        * parser/SyntaxChecker.h:
     36        (JSC::SyntaxChecker::createForOfLoop):
     37        * runtime/ArrayIteratorPrototype.cpp:
     38        (JSC::ArrayIteratorPrototype::finishCreation):
     39        (JSC::arrayIteratorPrototypeIterate):
     40        * runtime/ArrayPrototype.cpp:
     41        (JSC::ArrayPrototype::create):
     42        (JSC::ArrayPrototype::finishCreation):
     43        * runtime/ArrayPrototype.h:
     44        * runtime/CommonIdentifiers.cpp:
     45        (JSC::CommonIdentifiers::CommonIdentifiers):
     46        * runtime/CommonIdentifiers.h:
     47        * runtime/Identifier.h:
     48        (JSC::Identifier::from):
     49        * runtime/JSCJSValue.cpp:
     50        (JSC::JSValue::dumpInContext):
     51        * runtime/JSGlobalObject.cpp:
     52        (JSC::JSGlobalObject::reset):
     53        * runtime/JSObject.cpp:
     54        (JSC::JSObject::putDirectNativeFunction):
     55        * runtime/PrivateName.h:
     56        (JSC::PrivateName::PrivateName):
     57        * runtime/PropertyName.h:
     58        (JSC::PropertyName::PropertyName):
     59
    1602013-10-04  Michael Saboff  <msaboff@apple.com>
    261
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r156787 r156910  
    958958    IdentifierMap::AddResult result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers());
    959959    if (result.isNewEntry)
    960         m_codeBlock->addIdentifier(Identifier(m_vm, rep));
     960        m_codeBlock->addIdentifier(ident);
    961961
    962962    return result.iterator->value;
     
    16941694    // Generate code for arguments.
    16951695    unsigned argument = 0;
    1696     for (ArgumentListNode* n = callArguments.argumentsNode()->m_listNode; n; n = n->m_next)
    1697         emitNode(callArguments.argumentRegister(argument++), n);
    1698 
     1696    if (callArguments.argumentsNode()) {
     1697        for (ArgumentListNode* n = callArguments.argumentsNode()->m_listNode; n; n = n->m_next)
     1698            emitNode(callArguments.argumentRegister(argument++), n);
     1699    }
     1700   
    16991701    // Reserve space for call frame.
    17001702    Vector<RefPtr<RegisterID>, JSStack::CallFrameHeaderSize, UnsafeVectorOverflow> callFrame;
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r156785 r156910  
    6363    class CallArguments {
    6464    public:
    65         CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode);
     65        CallArguments(BytecodeGenerator&, ArgumentsNode*, unsigned additionalArguments = 0);
    6666
    6767        RegisterID* thisRegister() { return m_argv[0].get(); }
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r156785 r156910  
    380380}
    381381
    382 inline CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode)
     382inline CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
    383383    : m_argumentsNode(argumentsNode)
    384384{
     
    386386        m_profileHookRegister = generator.newTemporary();
    387387
    388     size_t argumentCountIncludingThis = 1; // 'this' register.
     388    size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
    389389    if (argumentsNode) {
    390390        for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
     
    17601760}
    17611761
     1762// ------------------------------ ForOfNode ------------------------------------
     1763
     1764void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
     1765{
     1766    LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
     1767   
     1768    if (!m_lexpr->isLocation()) {
     1769        emitThrowReferenceError(generator, "Left side of for-of statement is not a reference.");
     1770        return;
     1771    }
     1772   
     1773    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
     1774    RefPtr<RegisterID> subject = generator.emitNode(m_expr);
     1775    RefPtr<RegisterID> iterator = generator.emitGetById(generator.newTemporary(), subject.get(), generator.propertyNames().iteratorPrivateName);
     1776    {
     1777        CallArguments args(generator, 0);
     1778        generator.emitMove(args.thisRegister(), subject.get());
     1779        generator.emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd());
     1780    }
     1781    RefPtr<RegisterID> iteratorNext = generator.emitGetById(generator.newTemporary(), iterator.get(), generator.propertyNames().next);
     1782    RefPtr<RegisterID> value = generator.newTemporary();
     1783    generator.emitLoad(value.get(), jsUndefined());
     1784   
     1785    generator.emitJump(scope->continueTarget());
     1786   
     1787    RefPtr<Label> loopStart = generator.newLabel();
     1788    generator.emitLabel(loopStart.get());
     1789    generator.emitLoopHint();
     1790   
     1791    if (m_lexpr->isResolveNode()) {
     1792        const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
     1793        if (Local local = generator.local(ident))
     1794            generator.emitMove(local.get(), value.get());
     1795        else {
     1796            if (generator.isStrictMode())
     1797                generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     1798            RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident);
     1799            generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     1800            generator.emitPutToScope(scope, ident, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
     1801        }
     1802    } else if (m_lexpr->isDotAccessorNode()) {
     1803        DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
     1804        const Identifier& ident = assignNode->identifier();
     1805        RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
     1806       
     1807        generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
     1808        generator.emitPutById(base.get(), ident, value.get());
     1809    } else if (m_lexpr->isBracketAccessorNode()) {
     1810        BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
     1811        RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
     1812        RegisterID* subscript = generator.emitNode(assignNode->subscript());
     1813       
     1814        generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
     1815        generator.emitPutByVal(base.get(), subscript, value.get());
     1816    } else {
     1817        ASSERT(m_lexpr->isDeconstructionNode());
     1818        DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
     1819        assignNode->bindings()->emitBytecode(generator, value.get());
     1820    }
     1821   
     1822    generator.emitNode(dst, m_statement);
     1823   
     1824    generator.emitLabel(scope->continueTarget());
     1825    RefPtr<RegisterID> result = generator.newTemporary();
     1826    CallArguments nextArguments(generator, 0, 1);
     1827    generator.emitMove(nextArguments.thisRegister(), iterator.get());
     1828    generator.emitMove(nextArguments.argumentRegister(0), value.get());
     1829    generator.emitCall(result.get(), iteratorNext.get(), NoExpectedFunction, nextArguments, divot(), divotStart(), divotEnd());
     1830    generator.emitGetById(value.get(), result.get(), generator.propertyNames().value);
     1831    RefPtr<RegisterID> done = generator.emitGetById(generator.newTemporary(), result.get(), generator.propertyNames().done);
     1832    generator.emitJumpIfFalse(done.get(), loopStart.get());
     1833    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
     1834    generator.emitLabel(scope->breakTarget());
     1835}
     1836
    17621837// ------------------------------ ContinueNode ---------------------------------
    17631838
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r156896 r156910  
    7575    VM* vm = &exec->vm();
    7676    NativeCallFrameTracer tracer(vm, exec);
    77 
    78     Identifier ident(vm, uid);
     77    Identifier ident = uid->isEmptyUnique() ? Identifier::from(PrivateName(uid)) : Identifier(vm, uid);
    7978    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
    8079    AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
  • trunk/Source/JavaScriptCore/parser/ASTBuilder.h

    r156785 r156910  
    381381        return result;
    382382    }
     383   
     384    StatementNode* createForOfLoop(const JSTokenLocation& location, ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end)
     385    {
     386        ForOfNode* result = new (m_vm) ForOfNode(location, lhs, iter, statements);
     387        result->setLoc(start, end, location.startOffset, location.lineStartOffset);
     388        setExceptionLocation(result, eStart, eDivot, eEnd);
     389        return result;
     390    }
     391   
     392    StatementNode* createForOfLoop(const JSTokenLocation& location, PassRefPtr<DeconstructionPatternNode> pattern, ExpressionNode* iter, StatementNode* statements, const JSTextPosition& eStart, const JSTextPosition& eDivot, const JSTextPosition& eEnd, int start, int end)
     393    {
     394        ForOfNode* result = new (m_vm) ForOfNode(m_vm, location, pattern.get(), iter, statements);
     395        result->setLoc(start, end, location.startOffset, location.lineStartOffset);
     396        setExceptionLocation(result, eStart, eDivot, eEnd);
     397        return result;
     398    }
    383399
    384400    StatementNode* createEmptyStatement(const JSTokenLocation& location) { return new (m_vm) EmptyStatementNode(location); }
  • trunk/Source/JavaScriptCore/parser/NodeConstructors.h

    r156785 r156910  
    812812    }
    813813
     814    inline EnumerationNode::EnumerationNode(const JSTokenLocation& location, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
     815        : StatementNode(location)
     816        , m_lexpr(l)
     817        , m_expr(expr)
     818        , m_statement(statement)
     819    {
     820        ASSERT(l);
     821    }
     822   
     823    inline EnumerationNode::EnumerationNode(VM* vm, const JSTokenLocation& location, DeconstructionPatternNode* pattern, ExpressionNode* expr, StatementNode* statement)
     824        : StatementNode(location)
     825        , m_lexpr(new (vm) DeconstructingAssignmentNode(location, pattern, 0))
     826        , m_expr(expr)
     827        , m_statement(statement)
     828    {
     829        ASSERT(pattern);
     830    }
     831   
    814832    inline ForInNode::ForInNode(const JSTokenLocation& location, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
    815         : StatementNode(location)
    816         , m_lexpr(l)
    817         , m_expr(expr)
    818         , m_statement(statement)
    819     {
    820         ASSERT(l);
     833        : EnumerationNode(location, l, expr, statement)
     834    {
    821835    }
    822836   
    823837    inline ForInNode::ForInNode(VM* vm, const JSTokenLocation& location, DeconstructionPatternNode* pattern, ExpressionNode* expr, StatementNode* statement)
    824         : StatementNode(location)
    825         , m_lexpr(new (vm) DeconstructingAssignmentNode(location, pattern, 0))
    826         , m_expr(expr)
    827         , m_statement(statement)
    828     {
    829         ASSERT(pattern);
     838        : EnumerationNode(vm, location, pattern, expr, statement)
     839    {
     840    }
     841   
     842    inline ForOfNode::ForOfNode(const JSTokenLocation& location, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
     843        : EnumerationNode(location, l, expr, statement)
     844    {
     845    }
     846   
     847    inline ForOfNode::ForOfNode(VM* vm, const JSTokenLocation& location, DeconstructionPatternNode* pattern, ExpressionNode* expr, StatementNode* statement)
     848        : EnumerationNode(vm, location, pattern, expr, statement)
     849    {
    830850    }
    831851   
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r156785 r156910  
    12431243   
    12441244    class DeconstructionPatternNode;
    1245 
    1246     class ForInNode : public StatementNode, public ThrowableExpressionData {
    1247     public:
    1248         ForInNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*);
    1249         ForInNode(VM*, const JSTokenLocation&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*);
    1250 
    1251     private:
    1252         virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    1253 
     1245   
     1246    class EnumerationNode : public StatementNode, public ThrowableExpressionData {
     1247    public:
     1248        EnumerationNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*);
     1249        EnumerationNode(VM*, const JSTokenLocation&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*);
     1250       
     1251    protected:
    12541252        ExpressionNode* m_lexpr;
    12551253        ExpressionNode* m_expr;
    12561254        StatementNode* m_statement;
     1255    };
     1256   
     1257    class ForInNode : public EnumerationNode {
     1258    public:
     1259        ForInNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*);
     1260        ForInNode(VM*, const JSTokenLocation&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*);
     1261
     1262    private:
     1263        virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0);
     1264    };
     1265   
     1266    class ForOfNode : public EnumerationNode {
     1267    public:
     1268        ForOfNode(const JSTokenLocation&, ExpressionNode*, ExpressionNode*, StatementNode*);
     1269        ForOfNode(VM*, const JSTokenLocation&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*);
     1270       
     1271    private:
     1272        virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    12571273    };
    12581274
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r156785 r156910  
    295295            hasInitializer = match(EQUAL);
    296296            failIfFalseIfStrictWithNameAndMessage(declareVariable(name), "Cannot declare a variable named", name->impl(), "in strict mode.");
    297             context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0);
     297            context.addVar(name, (hasInitializer || (!m_allowsIn && (match(INTOKEN) || isofToken()))) ? DeclarationStacks::HasInitializer : 0);
    298298            if (hasInitializer) {
    299299                JSTextPosition varDivot = tokenStartPosition() + 1;
     
    318318                node = context.createDeconstructingAssignment(location, pattern, rhs);
    319319            }
    320             ASSERT(node);
    321320        }
    322321       
     
    502501        // Handle for-in with var declaration
    503502        JSTextPosition inLocation = tokenStartPosition();
    504         consumeOrFail(INTOKEN);
     503        bool isOfEnumeration = false;
     504        if (!consume(INTOKEN)) {
     505            failIfFalseWithMessage(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
     506            isOfEnumeration = true;
     507            next();
     508        }
    505509       
    506510        TreeExpression expr = parseExpression(context);
     
    516520        endLoop();
    517521        failIfFalse(statement);
     522        if (isOfEnumeration)
     523            return context.createForOfLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine);
    518524        return context.createForInLoop(location, forInTarget, expr, statement, declsStart, inLocation, exprEnd, startLine, endLine);
    519525    }
     
    557563    // For-in loop
    558564    failIfFalse(nonLHSCount == m_nonLHSCount);
    559     consumeOrFail(INTOKEN);
     565    bool isOfEnumeration = false;
     566    if (!consume(INTOKEN)) {
     567        failIfFalseWithMessage(match(IDENT) && *m_token.m_data.ident == m_vm->propertyNames->of, "Expected either 'in' or 'of' in enumeration syntax");
     568        isOfEnumeration = true;
     569        next();
     570    }
    560571    TreeExpression expr = parseExpression(context);
    561572    failIfFalse(expr);
     
    568579    endLoop();
    569580    failIfFalse(statement);
    570    
     581    if (isOfEnumeration)
     582        return context.createForOfLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
    571583    return context.createForInLoop(location, decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
    572584}
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r156785 r156910  
    554554    {
    555555        return m_token.m_type == expected;
     556    }
     557   
     558    ALWAYS_INLINE bool isofToken()
     559    {
     560        return m_token.m_type == IDENT && *m_token.m_data.ident == m_vm->propertyNames->of;
    556561    }
    557562   
  • trunk/Source/JavaScriptCore/parser/SyntaxChecker.h

    r156785 r156910  
    190190    int createForLoop(const JSTokenLocation&, int, int, int, int, int, int) { return 1; }
    191191    int createForInLoop(const JSTokenLocation&, int, int, int, int, int, int, int, int) { return 1; }
     192    int createForOfLoop(const JSTokenLocation&, int, int, int, int, int, int, int, int) { return 1; }
    192193    int createEmptyStatement(const JSTokenLocation&) { return 1; }
    193194    int createVarStatement(const JSTokenLocation&, int, int, int) { return 1; }
  • trunk/Source/JavaScriptCore/runtime/ArrayIteratorPrototype.cpp

    r156791 r156910  
    3838
    3939static EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeNext(ExecState*);
     40static EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeIterate(ExecState*);
    4041
    4142void ArrayIteratorPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     
    4647
    4748    JSC_NATIVE_FUNCTION(vm.propertyNames->next, arrayIteratorPrototypeNext, DontEnum, 0);
     49    JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorPrivateName, arrayIteratorPrototypeIterate, DontEnum, 0);
    4850}
    4951
     
    7779    return JSValue::encode(resultObject);
    7880}
    79    
     81
    8082EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeNext(CallFrame* callFrame)
    8183{
     
    130132}
    131133
     134EncodedJSValue JSC_HOST_CALL arrayIteratorPrototypeIterate(CallFrame* callFrame)
     135{
     136    return JSValue::encode(callFrame->thisValue());
    132137}
     138
     139}
  • trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp

    r156791 r156910  
    123123*/
    124124
    125 ArrayPrototype* ArrayPrototype::create(VM& vm, Structure* structure)
     125ArrayPrototype* ArrayPrototype::create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
    126126{
    127127    ArrayPrototype* prototype = new (NotNull, allocateCell<ArrayPrototype>(vm.heap)) ArrayPrototype(vm, structure);
    128     prototype->finishCreation(vm);
     128    prototype->finishCreation(vm, globalObject);
    129129    return prototype;
    130130}
     
    136136}
    137137
    138 void ArrayPrototype::finishCreation(VM& vm)
     138void ArrayPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
    139139{
    140140    Base::finishCreation(vm);
    141141    ASSERT(inherits(info()));
    142142    vm.prototypeMap.addPrototype(this);
     143    JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorPrivateName, arrayProtoFuncValues, DontEnum, 0);
    143144}
    144145
  • trunk/Source/JavaScriptCore/runtime/ArrayPrototype.h

    r156621 r156910  
    3434    typedef JSArray Base;
    3535
    36     static ArrayPrototype* create(VM&, Structure*);
     36    static ArrayPrototype* create(VM&, JSGlobalObject*, Structure*);
    3737       
    3838    static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
     
    4646
    4747protected:
    48     void finishCreation(VM&);
     48    void finishCreation(VM&, JSGlobalObject*);
    4949};
    5050
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.cpp

    r148696 r156910  
    2222#include "CommonIdentifiers.h"
    2323
     24#include "PrivateName.h"
     25
    2426namespace JSC {
    2527
     
    3335    , thisIdentifier(vm, "this")
    3436    , useStrictIdentifier(vm, "use strict")
     37    , iteratorPrivateName(Identifier::from(PrivateName()))
     38    , hasNextIdentifier(vm, "hasNext")
    3539    JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(INITIALIZE_KEYWORD)
    3640    JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME)
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r156791 r156910  
    114114    macro(numInlinedGetByIds) \
    115115    macro(numInlinedPutByIds) \
     116    macro(of) \
    116117    macro(opcode) \
    117118    macro(origin) \
     
    212213        const Identifier thisIdentifier;
    213214        const Identifier useStrictIdentifier;
    214         const PrivateName iteratorPrivateName;
     215        const Identifier iteratorPrivateName;
     216        const Identifier hasNextIdentifier;
    215217
    216218       
  • trunk/Source/JavaScriptCore/runtime/Identifier.h

    r156791 r156910  
    6262        CString utf8() const { return m_string.utf8(); }
    6363       
    64         static Identifier createEmptyUnique(VM* vm)
    65         {
    66             return Identifier(vm, String(StringImpl::createEmptyUnique()));
     64        static Identifier from(const PrivateName& name)
     65        {
     66            Identifier result;
     67            result.m_string = name.uid();
     68            return result;
    6769        }
    6870
  • trunk/Source/JavaScriptCore/runtime/JSArrayIterator.cpp

    r156791 r156910  
    4040    m_iteratedObject.set(vm, this, iteratedObject);
    4141}
     42   
     43   
     44void JSArrayIterator::visitChildren(JSCell* cell, SlotVisitor& visitor)
     45{
     46    JSArrayIterator* thisObject = jsCast<JSArrayIterator*>(cell);
     47    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     48    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     49    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
     50       
     51    Base::visitChildren(thisObject, visitor);
     52    visitor.append(&thisObject->m_iteratedObject);
    4253
    4354}
     55
     56}
  • trunk/Source/JavaScriptCore/runtime/JSArrayIterator.h

    r156791 r156910  
    7070private:
    7171
    72     static const unsigned StructureFlags = Base::StructureFlags;
     72    static const unsigned StructureFlags = Base::StructureFlags | OverridesVisitChildren;
    7373
    7474    JSArrayIterator(VM& vm, Structure* structure)
     
    7979
    8080    void finishCreation(VM&, JSGlobalObject*, ArrayIterationKind, JSObject* iteratedObject);
     81    static void visitChildren(JSCell*, SlotVisitor&);
    8182   
    8283    ArrayIterationKind m_iterationKind;
  • trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp

    r156597 r156910  
    217217                if (impl->isIdentifier())
    218218                    out.print(" (identifier)");
     219                if (impl->isEmptyUnique())
     220                    out.print(" (unique)");
    219221            } else
    220222                out.print(" (unresolved)");
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r156791 r156910  
    287287#endif
    288288
    289     m_arrayPrototype.set(vm, this, ArrayPrototype::create(vm, ArrayPrototype::createStructure(vm, this, m_objectPrototype.get())));
     289    m_arrayPrototype.set(vm, this, ArrayPrototype::create(vm, this, ArrayPrototype::createStructure(vm, this, m_objectPrototype.get())));
    290290   
    291291    m_originalArrayStructureForIndexingShape[UndecidedShape >> IndexingShapeShift].set(vm, this, JSArray::createStructure(vm, this, m_arrayPrototype.get(), ArrayWithUndecided));
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r156679 r156910  
    22052205{
    22062206    StringImpl* name = propertyName.publicName();
     2207    if (!name)
     2208        name = vm.propertyNames->anonymous.impl();
    22072209    ASSERT(name);
    22082210
  • trunk/Source/JavaScriptCore/runtime/PrivateName.h

    r117859 r156910  
    3737    {
    3838    }
     39    explicit PrivateName(StringImpl* uid)
     40        : m_impl(uid)
     41    {
     42        ASSERT(m_impl->isEmptyUnique());
     43    }
    3944
    4045    StringImpl* uid() const { return m_impl.get(); }
  • trunk/Source/JavaScriptCore/runtime/PropertyName.h

    r117859 r156910  
    8282        : m_impl(propertyName.impl())
    8383    {
    84         ASSERT(!m_impl || m_impl->isIdentifier());
     84        ASSERT(!m_impl || m_impl->isIdentifier() || m_impl->isEmptyUnique());
    8585    }
    8686
  • trunk/Source/WTF/ChangeLog

    r156862 r156910  
     12013-10-04  Oliver Hunt  <oliver@apple.com>
     2
     3        Support for-of syntax
     4        https://bugs.webkit.org/show_bug.cgi?id=122339
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Update assertions and add a helper function to StringImpl
     9        to save repeated unique or identifier calls.
     10
     11        * wtf/text/StringImpl.h:
     12        (WTF::StringImpl::isIdentifierOrUnique):
     13        (WTF::StringImpl::setIsIdentifier):
     14        (WTF::StringImpl::setIsAtomic):
     15
    1162013-10-02  Brent Fulgham  <bfulgham@apple.com>
    217
  • trunk/Source/WTF/wtf/text/StringImpl.h

    r156775 r156910  
    502502    WTF_EXPORT_STRING_API void upconvertCharacters(unsigned, unsigned) const;
    503503    bool isIdentifier() const { return m_hashAndFlags & s_hashFlagIsIdentifier; }
     504    bool isIdentifierOrUnique() const { return isIdentifier() || isEmptyUnique(); }
    504505    void setIsIdentifier(bool isIdentifier)
    505506    {
    506507        ASSERT(!isStatic());
     508        ASSERT(!isEmptyUnique());
    507509        if (isIdentifier)
    508510            m_hashAndFlags |= s_hashFlagIsIdentifier;
     
    520522    {
    521523        ASSERT(!isStatic());
     524        ASSERT(!isEmptyUnique());
    522525        if (isAtomic)
    523526            m_hashAndFlags |= s_hashFlagIsAtomic;
Note: See TracChangeset for help on using the changeset viewer.