Bug 1494930 - Part 4: Respect strictness directives. (r=arai)
authorEric Faust <efausbmo@gmail.com>
Tue, 02 Oct 2018 01:16:51 -0700
changeset 487459 8820b0b524e07926b62e72b8dc4120e46f5405a5
parent 487458 afa82a9888b4cc5316f94fc3dd93f65e87536b88
child 487460 1487cec16a9c092cf2affd5ef0ecab41c88fb02d
push id246
push userfmarier@mozilla.com
push dateSat, 13 Oct 2018 00:15:40 +0000
reviewersarai
bugs1494930
milestone64.0a1
Bug 1494930 - Part 4: Respect strictness directives. (r=arai)
js/src/frontend/BinSource-auto.cpp
js/src/frontend/BinSource.cpp
js/src/frontend/BinSource.h
js/src/frontend/BinSource.yaml
--- a/js/src/frontend/BinSource-auto.cpp
+++ b/js/src/frontend/BinSource-auto.cpp
@@ -4631,16 +4631,18 @@ BinASTParser<Tok>::parseInterfaceEagerFu
         isGenerator ? GeneratorKind::Generator
                     : GeneratorKind::NotGenerator,
         isAsync ? FunctionAsyncKind::AsyncFunction
                 : FunctionAsyncKind::SyncFunction,
         syntax,
         (syntax != FunctionSyntaxKind::Setter &&
          syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
 
+    forceStrictIfNecessary(funbox, directives);
+
     // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
     BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
     BINJS_TRY(funpc.init());
     parseContext_->functionScope().useAsVarScope(parseContext_);
     MOZ_ASSERT(parseContext_->isFunctionBox());
 
     ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
     BINJS_TRY(lexicalScope.init(parseContext_));
@@ -4710,16 +4712,18 @@ BinASTParser<Tok>::parseInterfaceEagerFu
         isGenerator ? GeneratorKind::Generator
                     : GeneratorKind::NotGenerator,
         isAsync ? FunctionAsyncKind::AsyncFunction
                 : FunctionAsyncKind::SyncFunction,
         syntax,
         (syntax != FunctionSyntaxKind::Setter &&
          syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
 
+    forceStrictIfNecessary(funbox, directives);
+
     // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
     BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
     BINJS_TRY(funpc.init());
     parseContext_->functionScope().useAsVarScope(parseContext_);
     MOZ_ASSERT(parseContext_->isFunctionBox());
 
     ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
     BINJS_TRY(lexicalScope.init(parseContext_));
@@ -4784,16 +4788,18 @@ BinASTParser<Tok>::parseInterfaceEagerGe
         isGenerator ? GeneratorKind::Generator
                     : GeneratorKind::NotGenerator,
         isAsync ? FunctionAsyncKind::AsyncFunction
                 : FunctionAsyncKind::SyncFunction,
         syntax,
         (syntax != FunctionSyntaxKind::Setter &&
          syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
 
+    forceStrictIfNecessary(funbox, directives);
+
     // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
     BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
     BINJS_TRY(funpc.init());
     parseContext_->functionScope().useAsVarScope(parseContext_);
     MOZ_ASSERT(parseContext_->isFunctionBox());
 
     ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
     BINJS_TRY(lexicalScope.init(parseContext_));
@@ -4863,16 +4869,18 @@ BinASTParser<Tok>::parseInterfaceEagerMe
         isGenerator ? GeneratorKind::Generator
                     : GeneratorKind::NotGenerator,
         isAsync ? FunctionAsyncKind::AsyncFunction
                 : FunctionAsyncKind::SyncFunction,
         syntax,
         (syntax != FunctionSyntaxKind::Setter &&
          syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
 
+    forceStrictIfNecessary(funbox, directives);
+
     // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
     BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
     BINJS_TRY(funpc.init());
     parseContext_->functionScope().useAsVarScope(parseContext_);
     MOZ_ASSERT(parseContext_->isFunctionBox());
 
     ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
     BINJS_TRY(lexicalScope.init(parseContext_));
@@ -4938,16 +4946,18 @@ BinASTParser<Tok>::parseInterfaceEagerSe
         isGenerator ? GeneratorKind::Generator
                     : GeneratorKind::NotGenerator,
         isAsync ? FunctionAsyncKind::AsyncFunction
                 : FunctionAsyncKind::SyncFunction,
         syntax,
         (syntax != FunctionSyntaxKind::Setter &&
          syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
 
+    forceStrictIfNecessary(funbox, directives);
+
     // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
     BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
     BINJS_TRY(funpc.init());
     parseContext_->functionScope().useAsVarScope(parseContext_);
     MOZ_ASSERT(parseContext_->isFunctionBox());
 
     ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
     BINJS_TRY(lexicalScope.init(parseContext_));
--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -149,16 +149,28 @@ BinASTParser<Tok>::parseAux(GlobalShared
     if (!bindings) {
         return cx_->alreadyReportedError();
     }
     globalsc->bindings = *bindings;
 
     return result; // Magic conversion to Ok.
 }
 
+template<typename Tok> void
+BinASTParser<Tok>::forceStrictIfNecessary(FunctionBox* funbox, ListNode* directives)
+{
+    JSAtom* useStrict = cx_->names().useStrict;
+
+    for (const ParseNode* directive : directives->contents()) {
+        if (directive->as<NameNode>().atom() == useStrict) {
+            funbox->strictScript = true;
+            break;
+        }
+    }
+}
 
 template<typename Tok> JS::Result<FunctionBox*>
 BinASTParser<Tok>::buildFunctionBox(GeneratorKind generatorKind,
     FunctionAsyncKind functionAsyncKind,
     FunctionSyntaxKind syntax,
     ParseNode* name)
 {
     RootedAtom atom(cx_);
--- a/js/src/frontend/BinSource.h
+++ b/js/src/frontend/BinSource.h
@@ -208,16 +208,20 @@ class BinASTParser : public BinASTParser
     // As a convenience, a helper that checks the body, parameter, and recursive binding scopes.
     MOZ_MUST_USE JS::Result<Ok> checkFunctionClosedVars();
 
     // --- Utilities.
 
     MOZ_MUST_USE JS::Result<ParseNode*> appendDirectivesToBody(ListNode* body,
         ListNode* directives);
 
+    // Optionally force a strict context without restarting the parse when we see a strict
+    // directive.
+    void forceStrictIfNecessary(FunctionBox* funbox, ListNode* directives);
+
   private: // Implement ErrorReporter
     const JS::ReadOnlyCompileOptions& options_;
 
     const JS::ReadOnlyCompileOptions& options() const override {
         return this->options_;
     }
 
   public:
--- a/js/src/frontend/BinSource.yaml
+++ b/js/src/frontend/BinSource.yaml
@@ -697,16 +697,18 @@ EagerFunctionExpression:
                     isGenerator ? GeneratorKind::Generator
                                 : GeneratorKind::NotGenerator,
                     isAsync ? FunctionAsyncKind::AsyncFunction
                             : FunctionAsyncKind::SyncFunction,
                     syntax,
                     (syntax != FunctionSyntaxKind::Setter &&
                      syntax != FunctionSyntaxKind::Getter) ? name : nullptr));
 
+                forceStrictIfNecessary(funbox, directives);
+
                 // Push a new ParseContext. It will be used to parse `scope`, the arguments, the function.
                 BinParseContext funpc(cx_, this, funbox, /* newDirectives = */ nullptr);
                 BINJS_TRY(funpc.init());
                 parseContext_->functionScope().useAsVarScope(parseContext_);
                 MOZ_ASSERT(parseContext_->isFunctionBox());
 
                 ParseContext::Scope lexicalScope(cx_, parseContext_, usedNames_);
                 BINJS_TRY(lexicalScope.init(parseContext_));