Changeset 220068 in webkit

Timestamp:
Jul 31, 2017, 9:15:32 AM (7 years ago)
Author:
Yusuke Suzuki
Message:

[JSC] Support optional catch binding
https://bugs.webkit.org/show_bug.cgi?id=174981

Reviewed by Saam Barati.

JSTests:

  • stress/optional-catch-binding-syntax.js: Added.

(testSyntax):
(testSyntaxError):
(catch.catch):

  • stress/optional-catch-binding.js: Added.

(shouldBe):
(throwException):

Source/JavaScriptCore:

This patch implements optional catch binding proposal[1], which is now stage 3.
This proposal adds a new catch brace with no error value binding.

`

try {

...

} catch {

...

}

`

Sometimes we do not need to get error value actually. For example, the function returns
boolean which means whether the function succeeds.

`
function parse(result) -> bool
{

try {

parseInner(result);

} catch {

return false;

}
return true;

}
`

In the above case, we are not interested in the actual error value. Without this syntax,
we always need to introduce a binding for an error value that is just ignored.

[1]: https://michaelficarra.github.io/optional-catch-binding-proposal/

  • bytecompiler/NodesCodegen.cpp:

(JSC::TryNode::emitBytecode):

  • parser/Parser.cpp:

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

LayoutTests:

Rebaseline existing tests.

  • js/parser-syntax-check-expected.txt:
  • js/script-tests/parser-syntax-check.js:
  • sputnik/Conformance/12_Statement/12.14_The_try_Statement/S12.14_A16_T4-expected.txt:
  • sputnik/Conformance/12_Statement/12.14_The_try_Statement/S12.14_A16_T4.html:
Location:
trunk
Files:
2 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r220012 r220068  
     1
     2
     3
     4
     5
     6
     7
     8
     9
     10
     11
     12
     13
     14
     15
    1162017-07-28  Mark Lam  <mark.lam@apple.com>
    217
  • trunk/LayoutTests/ChangeLog

    r220067 r220068  
     1
     2
     3
     4
     5
     6
     7
     8
     9
     10
     11
     12
     13
     14
    1152017-07-31  Per Arne Vollan  <pvollan@apple.com>
    216
  • trunk/LayoutTests/js/parser-syntax-check-expected.txt

    r219443 r220068  
    632632PASS Invalid: "try {} catch (...) {}". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a parameter pattern or a ')' in parameter list."
    633633PASS Invalid: "function f() { try {} catch (...) {} }". Produced the following syntax error: "SyntaxError: Unexpected token '...'. Expected a parameter pattern or a ')' in parameter list."
    634 PASS Invalid: "try {} catch {}". Produced the following syntax error: "SyntaxError: Unexpected token '{'. Expected '(' to start a 'catch' target."
    635 PASS Invalid: "function f() { try {} catch {} }". Produced the following syntax error: "SyntaxError: Unexpected token '{'. Expected '(' to start a 'catch' target."
     634PASS "
     635PASS "
    636636PASS Valid:   "if (a) try {} finally {} else b;"
    637637PASS Valid:   "function f() { if (a) try {} finally {} else b; }"
  • trunk/LayoutTests/js/script-tests/parser-syntax-check.js

    r219443 r220068  
    412412invalid("try {} finally {} catch(e) {}");
    413413invalid("try {} catch (...) {}");
    414 invalid("try {} catch {}");
     414("try {} catch {}");
    415415valid  ("if (a) try {} finally {} else b;");
    416416valid  ("if (--a()) do with(1) try {} catch(ke) { f() ; g() } while (a in b) else {}");
  • trunk/LayoutTests/sputnik/Conformance/12_Statement/12.14_The_try_Statement/S12.14_A16_T4-expected.txt

    r158014 r220068  
    1 CONSOLE MESSAGE: line 78: SyntaxError: Unexpected token '{'. Expected '(' to start a 'catch' target.
    21S12.14_A16_T4
    32
    4 PASS Expected parsing failure
     3PASS
    54
    65TEST COMPLETE
  • trunk/LayoutTests/sputnik/Conformance/12_Statement/12.14_The_try_Statement/S12.14_A16_T4.html

    r120489 r220068  
    8787<script>
    8888if (!successfullyParsed)
    89     printTestPassed('Expected parsing failure');
     89    printTested('Expected parsing failure');
    9090else if (sputnikException)
    91     printTestPassed(sputnikException);
     91    printTested(sputnikException);
    9292else
    93     printTestFailed("No error detected");
     93    printTested("No error detected");
    9494testPrint('<br /><span class="pass">TEST COMPLETE</span>');
    9595</script>
  • trunk/Source/JavaScriptCore/ChangeLog

    r220060 r220068  
     1
     2
     3
     4
     5
     6
     7
     8
     9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
    1442017-07-31  Yusuke Suzuki  <utatane.tea@gmail.com>
    245
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r219443 r220068  
    34143414        }
    34153415
    3416         generator.emitPushCatchScope(m_lexicalVariables);
    3417         m_catchPattern->bindValue(generator, thrownValueRegister.get());
     3416        if (m_catchPattern) {
     3417            generator.emitPushCatchScope(m_lexicalVariables);
     3418            m_catchPattern->bindValue(generator, thrownValueRegister.get());
     3419        }
     3420
    34183421        generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
    34193422        if (m_finallyBlock)
     
    34223425            generator.emitNodeInTailPosition(dst, m_catchBlock);
    34233426        generator.emitLoad(thrownValueRegister.get(), jsUndefined());
    3424         generator.emitPopCatchScope(m_lexicalVariables);
     3427
     3428        if (m_catchPattern)
     3429            generator.emitPopCatchScope(m_lexicalVariables);
    34253430
    34263431        if (m_finallyBlock) {
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r219443 r220068  
    16341634        next();
    16351635       
    1636         handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
    1637         AutoPopScopeRef catchScope(this, pushScope());
    1638         catchScope->setIsLexicalScope();
    1639         catchScope->preventVarDeclarations();
    1640         const Identifier* ident = nullptr;
    1641         if (matchSpecIdentifier()) {
    1642             ident = m_token.m_data.ident;
    1643             catchPattern = context.createBindingLocation(m_token.m_location, *ident, m_token.m_startPosition, m_token.m_endPosition, AssignmentContext::DeclarationStatement);
    1644             next();
    1645             failIfTrueIfStrict(catchScope->declareLexicalVariable(ident, false) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
     1636        if (match(OPENBRACE)) {
     1637            catchBlock = parseBlockStatement(context);
     1638            failIfFalse(catchBlock, "Unable to parse 'catch' block");
    16461639        } else {
    1647             catchPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToCatchParameters, ExportType::NotExported);
    1648             failIfFalse(catchPattern, "Cannot parse this destructuring pattern");
    1649         }
    1650         handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
    1651         matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
    1652         catchBlock = parseBlockStatement(context);
    1653         failIfFalse(catchBlock, "Unable to parse 'catch' block");
    1654         catchEnvironment = catchScope->finalizeLexicalEnvironment();
    1655         RELEASE_ASSERT(!ident || (catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl())));
    1656         popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
     1640            handleProductionOrFail(OPENPAREN, "(", "start", "'catch' target");
     1641            AutoPopScopeRef catchScope(this, pushScope());
     1642            catchScope->setIsLexicalScope();
     1643            catchScope->preventVarDeclarations();
     1644            const Identifier* ident = nullptr;
     1645            if (matchSpecIdentifier()) {
     1646                ident = m_token.m_data.ident;
     1647                catchPattern = context.createBindingLocation(m_token.m_location, *ident, m_token.m_startPosition, m_token.m_endPosition, AssignmentContext::DeclarationStatement);
     1648                next();
     1649                failIfTrueIfStrict(catchScope->declareLexicalVariable(ident, false) & DeclarationResult::InvalidStrictMode, "Cannot declare a catch variable named '", ident->impl(), "' in strict mode");
     1650            } else {
     1651                catchPattern = parseDestructuringPattern(context, DestructuringKind::DestructureToCatchParameters, ExportType::NotExported);
     1652                failIfFalse(catchPattern, "Cannot parse this destructuring pattern");
     1653            }
     1654            handleProductionOrFail(CLOSEPAREN, ")", "end", "'catch' target");
     1655            matchOrFail(OPENBRACE, "Expected exception handler to be a block statement");
     1656            catchBlock = parseBlockStatement(context);
     1657            failIfFalse(catchBlock, "Unable to parse 'catch' block");
     1658            catchEnvironment = catchScope->finalizeLexicalEnvironment();
     1659            RELEASE_ASSERT(!ident || (catchEnvironment.size() == 1 && catchEnvironment.contains(ident->impl())));
     1660            popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo);
     1661        }
    16571662    }
    16581663   
Note: See TracChangeset for help on using the changeset viewer.