Bug 1456989 - CatchClause now contains a AssertedParameterScope;r=efaust
authorDavid Teller <dteller@mozilla.com>
Thu, 26 Apr 2018 10:11:42 +0200
changeset 472881 0483a4252c05487ee3edd871adedb7f968fbe695
parent 472880 7135781f4a792dc5f6c415c94a57e96a1288e2dd
child 472882 e6a508975adb7be53c5d3506c86c5b590a9d6c9b
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersefaust
bugs1456989
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1456989 - CatchClause now contains a AssertedParameterScope;r=efaust This follows the spec changes and the binjs-ref change at https://github.com/binast/binjs-ref/pull/113 . MozReview-Commit-ID: 3k8p3hUx7Rb
js/src/frontend/BinSource-auto.cpp
js/src/frontend/BinSource.webidl_
js/src/frontend/BinSource.yaml
js/src/frontend/BinToken.h
--- a/js/src/frontend/BinSource-auto.cpp
+++ b/js/src/frontend/BinSource-auto.cpp
@@ -3093,17 +3093,25 @@ BinASTParser<Tok>::parseInterfaceAsserte
     CheckRecursionLimit(cx_);
 
 
 #if defined(DEBUG)
     const BinField expected_fields[3] = { BinField::ParameterNames, BinField::CapturedNames, BinField::HasDirectEval };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
-    MOZ_TRY(parseAndUpdateScopeNames(parseContext_->functionScope(), DeclarationKind:: PositionalFormalParameter));
+    ParseContext::Statement* inStatement = parseContext_->innermostStatement();
+
+    // If we are in a `CatchClause`, the binding is a implicit CatchParameter
+    // and it goes into the innermost scope. Otherwise, we're in a function,
+    // so it goes in the function scope.
+    if (inStatement && inStatement->kind() == StatementKind::Catch)
+        MOZ_TRY(parseAndUpdateScopeNames(*parseContext_->innermostScope(), DeclarationKind::CatchParameter));
+    else
+        MOZ_TRY(parseAndUpdateScopeNames(parseContext_->functionScope(), DeclarationKind::PositionalFormalParameter));
     MOZ_TRY(parseAndUpdateCapturedNames(kind));
 
 
 
     BINJS_MOZ_TRY_DECL(hasDirectEval, tokenizer_->readBool());
     if (hasDirectEval) {
         parseContext_->sc()->setHasDirectEval();
         parseContext_->sc()->setBindingsAccessedDynamically();
@@ -3842,16 +3850,17 @@ BinASTParser<Tok>::parseInterfaceCallExp
     result->prepend(callee);
     result->setOp(op);
     return result;
 }
 
 
 /*
  interface CatchClause : Node {
+    AssertedParameterScope? bindingScope;
     Binding binding;
     Block body;
  }
 */
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseCatchClause()
 {
     BinKind kind;
@@ -3870,39 +3879,38 @@ BinASTParser<Tok>::parseCatchClause()
 template<typename Tok> JS::Result<ParseNode*>
 BinASTParser<Tok>::parseInterfaceCatchClause(const size_t start, const BinKind kind, const BinFields& fields)
 {
     MOZ_ASSERT(kind == BinKind::CatchClause);
     CheckRecursionLimit(cx_);
 
 
 #if defined(DEBUG)
-    const BinField expected_fields[2] = { BinField::Binding, BinField::Body };
+    const BinField expected_fields[3] = { BinField::BindingScope, BinField::Binding, BinField::Body };
     MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields));
 #endif // defined(DEBUG)
 
     ParseContext::Statement stmt(parseContext_, StatementKind::Catch);
     ParseContext::Scope currentScope(cx_, parseContext_, usedNames_);
     BINJS_TRY(currentScope.init(parseContext_));
 
 
+    MOZ_TRY(parseOptionalAssertedParameterScope());
+
+
+
+
     BINJS_MOZ_TRY_DECL(binding, parseBinding());
 
 
 
 
     BINJS_MOZ_TRY_DECL(body, parseBlock());
 
 
-    // Export implicit variables to the scope.
-    // FIXME: Handle cases other than Name.
-    MOZ_ASSERT(binding->isKind(ParseNodeKind::Name));
-    auto ptr = currentScope.lookupDeclaredNameForAdd(binding->name());
-    BINJS_TRY(currentScope.addDeclaredName(parseContext_, ptr, binding->name(), DeclarationKind::Let, start));
-
     BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, parseContext_));
     BINJS_TRY_DECL(result, factory_.newLexicalScope(*bindings, body));
     BINJS_TRY(factory_.setupCatchScope(result, binding, body));
     return result;
 }
 
 
 /*
--- a/js/src/frontend/BinSource.webidl_
+++ b/js/src/frontend/BinSource.webidl_
@@ -825,16 +825,19 @@ interface WithStatement : Node {
 
 interface Block : Node {
   attribute AssertedBlockScope? scope;
   attribute FrozenArray<Statement> statements;
 };
 
 // `Catch`
 interface CatchClause : Node {
+  // `AssertedParameterScope` is used for catch bindings so the declared names
+  // are checked using BoundNames.
+  attribute AssertedParameterScope? bindingScope;
   attribute Binding binding;
   attribute Block body;
 };
 
 // An item in a `DirectivePrologue`
 interface Directive : Node {
   attribute string rawValue;
 };
--- a/js/src/frontend/BinSource.yaml
+++ b/js/src/frontend/BinSource.yaml
@@ -229,17 +229,25 @@ AssertedBlockScope:
                     MOZ_TRY(parseAndUpdateScopeNames(*parseContext_->innermostScope(), DeclarationKind::Let));
 
 AssertedParameterScope:
     inherits: AssertedBlockScope
     fields:
         parameterNames:
             block:
                 replace: |
-                    MOZ_TRY(parseAndUpdateScopeNames(parseContext_->functionScope(), DeclarationKind:: PositionalFormalParameter));
+                    ParseContext::Statement* inStatement = parseContext_->innermostStatement();
+
+                    // If we are in a `CatchClause`, the binding is a implicit CatchParameter
+                    // and it goes into the innermost scope. Otherwise, we're in a function,
+                    // so it goes in the function scope.
+                    if (inStatement && inStatement->kind() == StatementKind::Catch)
+                        MOZ_TRY(parseAndUpdateScopeNames(*parseContext_->innermostScope(), DeclarationKind::CatchParameter));
+                    else
+                        MOZ_TRY(parseAndUpdateScopeNames(parseContext_->functionScope(), DeclarationKind::PositionalFormalParameter));
 
 AssertedVarScope:
     inherits: AssertedBlockScope
     fields:
         varDeclaredNames:
             block:
                 replace:
                     MOZ_TRY(parseAndUpdateScopeNames(parseContext_->varScope(), DeclarationKind::Var));
@@ -414,22 +422,16 @@ CallExpression:
 
 
 CatchClause:
     init: |
         ParseContext::Statement stmt(parseContext_, StatementKind::Catch);
         ParseContext::Scope currentScope(cx_, parseContext_, usedNames_);
         BINJS_TRY(currentScope.init(parseContext_));
     build: |
-        // Export implicit variables to the scope.
-        // FIXME: Handle cases other than Name.
-        MOZ_ASSERT(binding->isKind(ParseNodeKind::Name));
-        auto ptr = currentScope.lookupDeclaredNameForAdd(binding->name());
-        BINJS_TRY(currentScope.addDeclaredName(parseContext_, ptr, binding->name(), DeclarationKind::Let, start));
-
         BINJS_TRY_DECL(bindings, NewLexicalScopeData(cx_, currentScope, alloc_, parseContext_));
         BINJS_TRY_DECL(result, factory_.newLexicalScope(*bindings, body));
         BINJS_TRY(factory_.setupCatchScope(result, binding, body));
 
 CompoundAssignmentExpression:
     build: |
         ParseNodeKind pnk;
         switch (operator_){
--- a/js/src/frontend/BinToken.h
+++ b/js/src/frontend/BinToken.h
@@ -273,16 +273,17 @@ const size_t BINKIND_LIMIT = 183;
  *
  * (sorted by alphabetical order)
  */
 #define FOR_EACH_BIN_FIELD(F) \
     F(Offset, "_offset") \
     F(Alternate, "alternate") \
     F(Arguments, "arguments") \
     F(Binding, "binding") \
+    F(BindingScope, "bindingScope") \
     F(Body, "body") \
     F(BodyScope, "bodyScope") \
     F(Callee, "callee") \
     F(CapturedNames, "capturedNames") \
     F(Cases, "cases") \
     F(CatchClause, "catchClause") \
     F(Consequent, "consequent") \
     F(Declaration, "declaration") \
@@ -340,17 +341,17 @@ const size_t BINKIND_LIMIT = 183;
 
 enum class BinField {
 #define EMIT_ENUM(name, _) name,
     FOR_EACH_BIN_FIELD(EMIT_ENUM)
 #undef EMIT_ENUM
 };
 
 // The number of distinct values of BinField.
-const size_t BINFIELD_LIMIT = 63;
+const size_t BINFIELD_LIMIT = 64;
 
 
 
 #define FOR_EACH_BIN_VARIANT(F) \
     F(BinaryOperatorBitAnd, "&") \
     F(BinaryOperatorBitOr, "|") \
     F(BinaryOperatorBitXor, "^") \
     F(BinaryOperatorComma, ",") \