Ignore:
Timestamp:
Jul 25, 2019, 12:50:46 AM (6 years ago)
Author:
Ross Kirsling
Message:

[ESNext] Implement nullish coalescing
https://bugs.webkit.org/show_bug.cgi?id=200072

Reviewed by Darin Adler.

JSTests:

  • stress/nullish-coalescing.js: Added.

Source/JavaScriptCore:

Implement the nullish coalescing proposal, which has now reached Stage 3 at TC39.

This introduces a ?? operator which:

acts like
but checks for nullishness instead of truthiness
has a precedence lower than
(or any other binary operator)
must be disambiguated with parentheses when combined with
or &&
  • bytecompiler/NodesCodegen.cpp:

(JSC::CoalesceNode::emitBytecode): Added.
Bytecode must use OpIsUndefinedOrNull and not OpNeqNull because of document.all.

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::makeBinaryNode):

  • parser/Lexer.cpp:

(JSC::Lexer<T>::lexWithoutClearingLineTerminator):

  • parser/NodeConstructors.h:

(JSC::CoalesceNode::CoalesceNode): Added.

  • parser/Nodes.h:

Introduce new token and AST node.

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseBinaryExpression):
Implement early error.

  • parser/ParserTokens.h:

Since this patch needs to shift the value of every binary operator token anyway,
let's only bother to increment their LSBs when we actually have a precedence conflict.

  • parser/ResultType.h:

(JSC::ResultType::definitelyIsNull const): Added.
(JSC::ResultType::mightBeUndefinedOrNull const): Added.
(JSC::ResultType::forCoalesce): Added.
We can do better than forLogicalOp here; let's be as accurate as possible.

  • runtime/Options.h:

Add runtime feature flag.

Tools:

  • Scripts/run-jsc-stress-tests:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/parser/ParserTokens.h

    r241201 r247819  
    149149    VOIDTOKEN = 7 | UnaryOpTokenFlag | KeywordTokenFlag,
    150150    DELETETOKEN = 8 | UnaryOpTokenFlag | KeywordTokenFlag,
    151     OR = 0 | BINARY_OP_PRECEDENCE(1),
    152     AND = 1 | BINARY_OP_PRECEDENCE(2),
    153     BITOR = 2 | BINARY_OP_PRECEDENCE(3),
    154     BITXOR = 3 | BINARY_OP_PRECEDENCE(4),
    155     BITAND = 4 | BINARY_OP_PRECEDENCE(5),
    156     EQEQ = 5 | BINARY_OP_PRECEDENCE(6),
    157     NE = 6 | BINARY_OP_PRECEDENCE(6),
    158     STREQ = 7 | BINARY_OP_PRECEDENCE(6),
    159     STRNEQ = 8 | BINARY_OP_PRECEDENCE(6),
    160     LT = 9 | BINARY_OP_PRECEDENCE(7),
    161     GT = 10 | BINARY_OP_PRECEDENCE(7),
    162     LE = 11 | BINARY_OP_PRECEDENCE(7),
    163     GE = 12 | BINARY_OP_PRECEDENCE(7),
    164     INSTANCEOF = 13 | BINARY_OP_PRECEDENCE(7) | KeywordTokenFlag,
    165     INTOKEN = 14 | IN_OP_PRECEDENCE(7) | KeywordTokenFlag,
    166     LSHIFT = 15 | BINARY_OP_PRECEDENCE(8),
    167     RSHIFT = 16 | BINARY_OP_PRECEDENCE(8),
    168     URSHIFT = 17 | BINARY_OP_PRECEDENCE(8),
    169     PLUS = 18 | BINARY_OP_PRECEDENCE(9) | UnaryOpTokenFlag,
    170     MINUS = 19 | BINARY_OP_PRECEDENCE(9) | UnaryOpTokenFlag,
    171     TIMES = 20 | BINARY_OP_PRECEDENCE(10),
    172     DIVIDE = 21 | BINARY_OP_PRECEDENCE(10),
    173     MOD = 22 | BINARY_OP_PRECEDENCE(10),
    174     POW = 23 | BINARY_OP_PRECEDENCE(11) | RightAssociativeBinaryOpTokenFlag, // Make sure that POW has the highest operator precedence.
     151    COALESCE = 0 | BINARY_OP_PRECEDENCE(1),
     152    OR = 0 | BINARY_OP_PRECEDENCE(2),
     153    AND = 0 | BINARY_OP_PRECEDENCE(3),
     154    BITOR = 0 | BINARY_OP_PRECEDENCE(4),
     155    BITXOR = 0 | BINARY_OP_PRECEDENCE(5),
     156    BITAND = 0 | BINARY_OP_PRECEDENCE(6),
     157    EQEQ = 0 | BINARY_OP_PRECEDENCE(7),
     158    NE = 1 | BINARY_OP_PRECEDENCE(7),
     159    STREQ = 2 | BINARY_OP_PRECEDENCE(7),
     160    STRNEQ = 3 | BINARY_OP_PRECEDENCE(7),
     161    LT = 0 | BINARY_OP_PRECEDENCE(8),
     162    GT = 1 | BINARY_OP_PRECEDENCE(8),
     163    LE = 2 | BINARY_OP_PRECEDENCE(8),
     164    GE = 3 | BINARY_OP_PRECEDENCE(8),
     165    INSTANCEOF = 4 | BINARY_OP_PRECEDENCE(8) | KeywordTokenFlag,
     166    INTOKEN = 5 | IN_OP_PRECEDENCE(8) | KeywordTokenFlag,
     167    LSHIFT = 0 | BINARY_OP_PRECEDENCE(9),
     168    RSHIFT = 1 | BINARY_OP_PRECEDENCE(9),
     169    URSHIFT = 2 | BINARY_OP_PRECEDENCE(9),
     170    PLUS = 0 | BINARY_OP_PRECEDENCE(10) | UnaryOpTokenFlag,
     171    MINUS = 1 | BINARY_OP_PRECEDENCE(10) | UnaryOpTokenFlag,
     172    TIMES = 0 | BINARY_OP_PRECEDENCE(11),
     173    DIVIDE = 1 | BINARY_OP_PRECEDENCE(11),
     174    MOD = 2 | BINARY_OP_PRECEDENCE(11),
     175    POW = 0 | BINARY_OP_PRECEDENCE(12) | RightAssociativeBinaryOpTokenFlag, // Make sure that POW has the highest operator precedence.
    175176    ERRORTOK = 0 | ErrorTokenFlag,
    176177    UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK = 0 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
Note: See TracChangeset for help on using the changeset viewer.