Changeset 185699 in webkit


Ignore:
Timestamp:
Jun 18, 2015 5:35:32 AM (9 years ago)
Author:
saambarati1@gmail.com
Message:

[ES6] support default values in deconstruction parameter nodes
https://bugs.webkit.org/show_bug.cgi?id=142679

Reviewed by Darin Adler.

Source/JavaScriptCore:

ES6 destructuring allows destructuring properties to assign
default values. A link to the spec:
https://people.mozilla.org/~jorendorff/es6-draft.html#sec-destructuring-binding-patterns

This patch implements default values for all places where deconstruction
is allowed besides function parameters. This is because function
parameters are parsed in a separate parser arena than the function
body itself and ExpresionNode's which are default values for
deconstruction parameters will be deallocated by the time we parse the body
of the function. I have opened a bug to address this problem:
https://bugs.webkit.org/show_bug.cgi?id=145995

  • bytecompiler/NodesCodegen.cpp:

(JSC::DeconstructionPatternNode::~DeconstructionPatternNode):
(JSC::assignDefaultValueIfUndefined):
(JSC::ArrayPatternNode::bindValue):
(JSC::ArrayPatternNode::emitDirectBinding):
(JSC::ArrayPatternNode::toString):
(JSC::ArrayPatternNode::collectBoundIdentifiers):
(JSC::ObjectPatternNode::bindValue):

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::appendArrayPatternSkipEntry):
(JSC::ASTBuilder::appendArrayPatternEntry):
(JSC::ASTBuilder::createObjectPattern):
(JSC::ASTBuilder::appendObjectPatternEntry):
(JSC::ASTBuilder::createBindingLocation):

  • parser/Nodes.h:

(JSC::ArrayPatternNode::appendIndex):
(JSC::ObjectPatternNode::appendEntry):
(JSC::ObjectPatternNode::Entry::Entry): Deleted.

  • parser/Parser.cpp:

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

  • parser/Parser.h:
  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::operatorStackPop):

LayoutTests:

  • js/destructuring-assignment-default-values-expected.txt: Added.
  • js/destructuring-assignment-default-values.html: Added.
  • js/script-tests/destructuring-assignment-default-values.js: Added.

(assert):
(test1):
(arr):
(test2):
(test3):
(test4):
(test5):
(test6):
(test7):
(test8):
(shouldThrow):

Location:
trunk
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r185697 r185699  
     12015-06-18  Saam Barati  <saambarati1@gmail.com>
     2
     3        [ES6] support default values in deconstruction parameter nodes
     4        https://bugs.webkit.org/show_bug.cgi?id=142679
     5
     6        Reviewed by Darin Adler.
     7
     8        * js/destructuring-assignment-default-values-expected.txt: Added.
     9        * js/destructuring-assignment-default-values.html: Added.
     10        * js/script-tests/destructuring-assignment-default-values.js: Added.
     11        (assert):
     12        (test1):
     13        (arr):
     14        (test2):
     15        (test3):
     16        (test4):
     17        (test5):
     18        (test6):
     19        (test7):
     20        (test8):
     21        (shouldThrow):
     22
    1232015-06-18  Youenn Fablet <youenn.fablet@crf.canon.fr> and Xabier Rodriguez Calvar  <calvaris@igalia.com>
    224
  • trunk/Source/JavaScriptCore/ChangeLog

    r185670 r185699  
     12015-06-18  Saam Barati  <saambarati1@gmail.com>
     2
     3        [ES6] support default values in deconstruction parameter nodes
     4        https://bugs.webkit.org/show_bug.cgi?id=142679
     5
     6        Reviewed by Darin Adler.
     7
     8        ES6 destructuring allows destructuring properties to assign
     9        default values. A link to the spec:
     10        https://people.mozilla.org/~jorendorff/es6-draft.html#sec-destructuring-binding-patterns
     11
     12        This patch implements default values for all places where deconstruction
     13        is allowed besides function parameters. This is because function
     14        parameters are parsed in a separate parser arena than the function
     15        body itself and ExpresionNode's which are default values for
     16        deconstruction parameters will be deallocated by the time we parse the body
     17        of the function. I have opened a bug to address this problem:
     18        https://bugs.webkit.org/show_bug.cgi?id=145995
     19
     20        * bytecompiler/NodesCodegen.cpp:
     21        (JSC::DeconstructionPatternNode::~DeconstructionPatternNode):
     22        (JSC::assignDefaultValueIfUndefined):
     23        (JSC::ArrayPatternNode::bindValue):
     24        (JSC::ArrayPatternNode::emitDirectBinding):
     25        (JSC::ArrayPatternNode::toString):
     26        (JSC::ArrayPatternNode::collectBoundIdentifiers):
     27        (JSC::ObjectPatternNode::bindValue):
     28        * parser/ASTBuilder.h:
     29        (JSC::ASTBuilder::appendArrayPatternSkipEntry):
     30        (JSC::ASTBuilder::appendArrayPatternEntry):
     31        (JSC::ASTBuilder::createObjectPattern):
     32        (JSC::ASTBuilder::appendObjectPatternEntry):
     33        (JSC::ASTBuilder::createBindingLocation):
     34        * parser/Nodes.h:
     35        (JSC::ArrayPatternNode::appendIndex):
     36        (JSC::ObjectPatternNode::appendEntry):
     37        (JSC::ObjectPatternNode::Entry::Entry): Deleted.
     38        * parser/Parser.cpp:
     39        (JSC::Parser<LexerType>::parseDeconstructionPattern):
     40        (JSC::Parser<LexerType>::parseDefaultValueForDeconstructionPattern):
     41        (JSC::Parser<LexerType>::parseConstDeclarationList):
     42        * parser/Parser.h:
     43        * parser/SyntaxChecker.h:
     44        (JSC::SyntaxChecker::operatorStackPop):
     45
    1462015-06-17  Joseph Pecoraro  <pecoraro@apple.com>
    247
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r185259 r185699  
    31203120{
    31213121}
     3122
     3123static void assignDefaultValueIfUndefined(BytecodeGenerator& generator, RegisterID* maybeUndefined, ExpressionNode* defaultValue)
     3124{
     3125    ASSERT(defaultValue);
     3126    RefPtr<Label> isNotUndefined = generator.newLabel();
     3127    generator.emitJumpIfFalse(generator.emitIsUndefined(generator.newTemporary(), maybeUndefined), isNotUndefined.get());
     3128    generator.emitNode(maybeUndefined, defaultValue);
     3129    generator.emitLabel(isNotUndefined.get());
     3130}
    31223131   
    31233132void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
     
    31253134    for (size_t i = 0; i < m_targetPatterns.size(); i++) {
    31263135        auto target = m_targetPatterns[i];
    3127         if (!target)
     3136        if (!target.pattern)
    31283137            continue;
    31293138        RefPtr<RegisterID> temp = generator.newTemporary();
    31303139        generator.emitLoad(temp.get(), jsNumber(i));
    31313140        generator.emitGetByVal(temp.get(), rhs, temp.get());
    3132         target->bindValue(generator, temp.get());
     3141        if (target.defaultValue)
     3142            assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
     3143        target.pattern->bindValue(generator, temp.get());
    31333144    }
    31343145}
     
    31533164        registers.uncheckedAppend(generator.newTemporary());
    31543165        generator.emitNode(registers.last().get(), elements[i]);
     3166        if (m_targetPatterns[i].defaultValue)
     3167            assignDefaultValueIfUndefined(generator, registers.last().get(), m_targetPatterns[i].defaultValue);
    31553168        if (resultRegister)
    31563169            generator.emitPutByIndex(resultRegister.get(), i, registers.last().get());
     
    31583171   
    31593172    for (size_t i = 0; i < m_targetPatterns.size(); i++) {
    3160         if (m_targetPatterns[i])
    3161             m_targetPatterns[i]->bindValue(generator, registers[i].get());
     3173        if (m_targetPatterns[i].pattern)
     3174            m_targetPatterns[i].pattern->bindValue(generator, registers[i].get());
    31623175    }
    31633176    if (resultRegister)
     
    31703183    builder.append('[');
    31713184    for (size_t i = 0; i < m_targetPatterns.size(); i++) {
    3172         if (!m_targetPatterns[i]) {
     3185        if (!m_targetPatterns[i].pattern) {
    31733186            builder.append(',');
    31743187            continue;
    31753188        }
    3176         m_targetPatterns[i]->toString(builder);
     3189        m_targetPatterns[i].pattern->toString(builder);
    31773190        if (i < m_targetPatterns.size() - 1)
    31783191            builder.append(',');
     
    31843197{
    31853198    for (size_t i = 0; i < m_targetPatterns.size(); i++) {
    3186         if (DeconstructionPatternNode* node = m_targetPatterns[i].get())
     3199        if (DeconstructionPatternNode* node = m_targetPatterns[i].pattern.get())
    31873200            node->collectBoundIdentifiers(identifiers);
    31883201    }
     
    32113224        RefPtr<RegisterID> temp = generator.newTemporary();
    32123225        generator.emitGetById(temp.get(), rhs, target.propertyName);
     3226        if (target.defaultValue)
     3227            assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
    32133228        target.pattern->bindValue(generator, temp.get());
    32143229    }
  • trunk/Source/JavaScriptCore/parser/ASTBuilder.h

    r184640 r185699  
    738738    void appendArrayPatternSkipEntry(ArrayPattern node, const JSTokenLocation& location)
    739739    {
    740         node->appendIndex(location, 0);
    741     }
    742 
    743     void appendArrayPatternEntry(ArrayPattern node, const JSTokenLocation& location, DeconstructionPattern pattern)
    744     {
    745         node->appendIndex(location, pattern.get());
     740        node->appendIndex(location, 0, nullptr);
     741    }
     742
     743    void appendArrayPatternEntry(ArrayPattern node, const JSTokenLocation& location, DeconstructionPattern pattern, ExpressionNode* defaultValue)
     744    {
     745        node->appendIndex(location, pattern.get(), defaultValue);
    746746    }
    747747   
     
    751751    }
    752752   
    753     void appendObjectPatternEntry(ObjectPattern node, const JSTokenLocation& location, bool wasString, const Identifier& identifier, DeconstructionPattern pattern)
    754     {
    755         node->appendEntry(location, identifier, wasString, pattern.get());
     753    void appendObjectPatternEntry(ObjectPattern node, const JSTokenLocation& location, bool wasString, const Identifier& identifier, DeconstructionPattern pattern, ExpressionNode* defaultValue)
     754    {
     755        node->appendEntry(location, identifier, wasString, pattern.get(), defaultValue);
    756756    }
    757757   
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r185346 r185699  
    17841784    public:
    17851785        static Ref<ArrayPatternNode> create();
    1786         void appendIndex(const JSTokenLocation&, DeconstructionPatternNode* node)
     1786        void appendIndex(const JSTokenLocation&, DeconstructionPatternNode* node, ExpressionNode* defaultValue)
    17871787        {
    1788             m_targetPatterns.append(node);
     1788            m_targetPatterns.append(Entry{ node, defaultValue });
    17891789        }
    17901790
    17911791    private:
     1792        struct Entry {
     1793            RefPtr<DeconstructionPatternNode> pattern;
     1794            ExpressionNode* defaultValue;
     1795        };
    17921796        ArrayPatternNode();
    17931797        virtual void collectBoundIdentifiers(Vector<Identifier>&) const override;
     
    17961800        virtual void toString(StringBuilder&) const override;
    17971801
    1798         Vector<RefPtr<DeconstructionPatternNode>> m_targetPatterns;
     1802        Vector<Entry> m_targetPatterns;
    17991803    };
    18001804   
     
    18021806    public:
    18031807        static Ref<ObjectPatternNode> create();
    1804         void appendEntry(const JSTokenLocation&, const Identifier& identifier, bool wasString, DeconstructionPatternNode* pattern)
     1808        void appendEntry(const JSTokenLocation&, const Identifier& identifier, bool wasString, DeconstructionPatternNode* pattern, ExpressionNode* defaultValue)
    18051809        {
    1806             m_targetPatterns.append(Entry(identifier, wasString, pattern));
     1810            m_targetPatterns.append(Entry{ identifier, wasString, pattern, defaultValue });
    18071811        }
    18081812       
     
    18131817        virtual void toString(StringBuilder&) const override;
    18141818        struct Entry {
    1815             Entry(const Identifier& propertyName, bool wasString, DeconstructionPatternNode* pattern)
    1816                 : propertyName(propertyName)
    1817                 , wasString(wasString)
    1818                 , pattern(pattern)
    1819             {
    1820             }
    18211819            Identifier propertyName;
    18221820            bool wasString;
    18231821            RefPtr<DeconstructionPatternNode> pattern;
     1822            ExpressionNode* defaultValue;
    18241823        };
    18251824        Vector<Entry> m_targetPatterns;
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r184926 r185699  
    614614                return 0;
    615615            failIfFalse(innerPattern, "Cannot parse this deconstruction pattern");
    616             context.appendArrayPatternEntry(arrayPattern, location, innerPattern);
     616            TreeExpression defaultValue = parseDefaultValueForDeconstructionPattern(context);
     617            failIfTrue(kind == DeconstructToParameters && defaultValue,  "Default values in destructuring parameters are currently not supported");
     618            context.appendArrayPatternEntry(arrayPattern, location, innerPattern, defaultValue);
    617619        } while (consume(COMMA));
    618620       
     
    680682                return 0;
    681683            failIfFalse(innerPattern, "Cannot parse this deconstruction pattern");
    682             context.appendObjectPatternEntry(objectPattern, location, wasString, propertyName, innerPattern);
     684            TreeExpression defaultValue = parseDefaultValueForDeconstructionPattern(context);
     685            failIfTrue(kind == DeconstructToParameters && defaultValue, "Default values in destructuring parameters are currently not supported");
     686            context.appendObjectPatternEntry(objectPattern, location, wasString, propertyName, innerPattern, defaultValue);
    683687        } while (consume(COMMA));
    684688        if (kind == DeconstructToExpressions && !match(CLOSEBRACE))
     
    703707    m_nonLHSCount = nonLHSCount;
    704708    return pattern;
     709}
     710
     711template <typename LexerType>
     712template <class TreeBuilder> TreeExpression Parser<LexerType>::parseDefaultValueForDeconstructionPattern(TreeBuilder& context)
     713{
     714    if (!match(EQUAL))
     715        return 0;
     716
     717    next(TreeBuilder::DontBuildStrings); // consume '='
     718    return parseAssignmentExpression(context);
    705719}
    706720
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r184828 r185699  
    766766    template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern parseDeconstructionPattern(TreeBuilder&, DeconstructionKind, int depth = 0);
    767767    template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern tryParseDeconstructionPatternExpression(TreeBuilder&);
     768    template <class TreeBuilder> NEVER_INLINE TreeExpression parseDefaultValueForDeconstructionPattern(TreeBuilder&);
    768769
    769770    template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, ConstructorKind, SuperBinding, int functionKeywordStart, ParserFunctionInfo<TreeBuilder>&);
  • trunk/Source/JavaScriptCore/parser/SyntaxChecker.h

    r184640 r185699  
    309309    {
    310310    }
    311     void appendArrayPatternEntry(ArrayPattern, const JSTokenLocation&, DeconstructionPattern)
     311    void appendArrayPatternEntry(ArrayPattern, const JSTokenLocation&, DeconstructionPattern, int)
    312312    {
    313313    }
     
    316316        return ObjectDeconstruction;
    317317    }
    318     void appendObjectPatternEntry(ArrayPattern, const JSTokenLocation&, bool, const Identifier&, DeconstructionPattern)
     318    void appendObjectPatternEntry(ArrayPattern, const JSTokenLocation&, bool, const Identifier&, DeconstructionPattern, int)
    319319    {
    320320    }
Note: See TracChangeset for help on using the changeset viewer.