Bug 1293305 - Part 1: Disable non-standard for-each on Nightly and add testing function to enable/disable it. r=evilpie
authorTooru Fujisawa <arai_a@mac.com>
Mon, 21 Nov 2016 15:03:26 +0900
changeset 323591 63ec09d6484c37e80958849ec2ebc891d375bce6
parent 323590 10daeea4d322f4d396538ebac11b4bfdd5f5a798
child 323592 c8d173e66fa2c9ddf5cec2bf20411e7e29404ce4
push id21
push usermaklebus@msu.edu
push dateThu, 01 Dec 2016 06:22:08 +0000
reviewersevilpie
bugs1293305
milestone53.0a1
Bug 1293305 - Part 1: Disable non-standard for-each on Nightly and add testing function to enable/disable it. r=evilpie
js/src/builtin/TestingFunctions.cpp
js/src/frontend/Parser.h
js/src/jsapi.cpp
js/src/jsapi.h
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -4077,16 +4077,34 @@ DisRegExp(JSContext* cx, unsigned argc, 
     if (!reobj->dumpBytecode(cx, match_only, input))
         return false;
 
     args.rval().setUndefined();
     return true;
 }
 #endif // DEBUG
 
+static bool
+EnableForEach(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    JS::ContextOptionsRef(cx).setForEachStatement(true);
+    args.rval().setUndefined();
+    return true;
+}
+
+static bool
+DisableForEach(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    JS::ContextOptionsRef(cx).setForEachStatement(false);
+    args.rval().setUndefined();
+    return true;
+}
+
 static const JSFunctionSpecWithHelp TestingFunctions[] = {
     JS_FN_HELP("gc", ::GC, 0, 0,
 "gc([obj] | 'zone' [, 'shrinking'])",
 "  Run the garbage collector. When obj is given, GC only its zone.\n"
 "  If 'zone' is given, GC any zones that were scheduled for\n"
 "  GC via schedulegc.\n"
 "  If 'shrinking' is passed as the optional second argument, perform a\n"
 "  shrinking GC rather than a normal GC."),
@@ -4607,16 +4625,24 @@ gc::ZealModeHelpText),
     JS_FN_HELP("getModuleEnvironmentNames", GetModuleEnvironmentNames, 1, 0,
 "getModuleEnvironmentNames(module)",
 "  Get the list of a module environment's bound names for a specified module.\n"),
 
     JS_FN_HELP("getModuleEnvironmentValue", GetModuleEnvironmentValue, 2, 0,
 "getModuleEnvironmentValue(module, name)",
 "  Get the value of a bound name in a module environment.\n"),
 
+    JS_FN_HELP("enableForEach", EnableForEach, 0, 0,
+"enableForEach()",
+"  Enables the deprecated, non-standard for-each.\n"),
+
+    JS_FN_HELP("disableForEach", DisableForEach, 0, 0,
+"disableForEach()",
+"  Disables the deprecated, non-standard for-each.\n"),
+
     JS_FS_HELP_END
 };
 
 static const JSFunctionSpecWithHelp FuzzingUnsafeTestingFunctions[] = {
 #ifdef DEBUG
     JS_FN_HELP("parseRegExp", ParseRegExp, 3, 0,
 "parseRegExp(pattern[, flags[, match_only])",
 "  Parses a RegExp pattern and returns a tree, potentially throwing."),
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -1316,17 +1316,17 @@ class Parser final : private JS::AutoGCR
     Node identifierReference(Handle<PropertyName*> name);
 
     bool matchLabel(YieldHandling yieldHandling, MutableHandle<PropertyName*> label);
 
     bool allowsForEachIn() {
 #if !JS_HAS_FOR_EACH_IN
         return false;
 #else
-        return versionNumber() >= JSVERSION_1_6;
+        return options().forEachStatementOption && versionNumber() >= JSVERSION_1_6;
 #endif
     }
 
     bool matchInOrOf(bool* isForInp, bool* isForOfp);
 
     bool hasUsedFunctionSpecialName(HandlePropertyName name);
     bool declareFunctionArgumentsObject();
     bool declareFunctionThis();
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3770,16 +3770,17 @@ JS::TransitiveCompileOptions::copyPODTra
     mutedErrors_ = rhs.mutedErrors_;
     version = rhs.version;
     versionSet = rhs.versionSet;
     utf8 = rhs.utf8;
     selfHostingMode = rhs.selfHostingMode;
     canLazilyParse = rhs.canLazilyParse;
     strictOption = rhs.strictOption;
     extraWarningsOption = rhs.extraWarningsOption;
+    forEachStatementOption = rhs.forEachStatementOption;
     werrorOption = rhs.werrorOption;
     asmJSOption = rhs.asmJSOption;
     throwOnAsmJSValidationFailureOption = rhs.throwOnAsmJSValidationFailureOption;
     forceAsync = rhs.forceAsync;
     installedFile = rhs.installedFile;
     sourceIsLazy = rhs.sourceIsLazy;
     introductionType = rhs.introductionType;
     introductionLineno = rhs.introductionLineno;
@@ -3891,16 +3892,17 @@ JS::OwningCompileOptions::setIntroducerF
 JS::CompileOptions::CompileOptions(JSContext* cx, JSVersion version)
     : ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx),
       introductionScriptRoot(cx)
 {
     this->version = (version != JSVERSION_UNKNOWN) ? version : cx->findVersion();
 
     strictOption = cx->options().strictMode();
     extraWarningsOption = cx->compartment()->behaviors().extraWarnings(cx);
+    forEachStatementOption = cx->options().forEachStatement();
     werrorOption = cx->options().werror();
     if (!cx->options().asmJS())
         asmJSOption = AsmJSOption::Disabled;
     else if (cx->compartment()->debuggerObservesAsmJS())
         asmJSOption = AsmJSOption::DisabledByDebugger;
     else
         asmJSOption = AsmJSOption::Enabled;
     throwOnAsmJSValidationFailureOption = cx->options().throwOnAsmJSValidationFailure();
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1090,17 +1090,22 @@ class JS_PUBLIC_API(ContextOptions) {
         throwOnAsmJSValidationFailure_(false),
         nativeRegExp_(true),
         unboxedArrays_(false),
         asyncStack_(true),
         throwOnDebuggeeWouldRun_(true),
         dumpStackOnDebuggeeWouldRun_(false),
         werror_(false),
         strictMode_(false),
-        extraWarnings_(false)
+        extraWarnings_(false),
+#ifdef NIGHTLY_BUILD
+        forEachStatement_(false)
+#else
+        forEachStatement_(true)
+#endif
     {
     }
 
     bool baseline() const { return baseline_; }
     ContextOptions& setBaseline(bool flag) {
         baseline_ = flag;
         return *this;
     }
@@ -1214,31 +1219,38 @@ class JS_PUBLIC_API(ContextOptions) {
         extraWarnings_ = flag;
         return *this;
     }
     ContextOptions& toggleExtraWarnings() {
         extraWarnings_ = !extraWarnings_;
         return *this;
     }
 
+    bool forEachStatement() const { return forEachStatement_; }
+    ContextOptions& setForEachStatement(bool flag) {
+        forEachStatement_ = flag;
+        return *this;
+    }
+
   private:
     bool baseline_ : 1;
     bool ion_ : 1;
     bool asmJS_ : 1;
     bool wasm_ : 1;
     bool wasmAlwaysBaseline_ : 1;
     bool throwOnAsmJSValidationFailure_ : 1;
     bool nativeRegExp_ : 1;
     bool unboxedArrays_ : 1;
     bool asyncStack_ : 1;
     bool throwOnDebuggeeWouldRun_ : 1;
     bool dumpStackOnDebuggeeWouldRun_ : 1;
     bool werror_ : 1;
     bool strictMode_ : 1;
     bool extraWarnings_ : 1;
+    bool forEachStatement_: 1;
 };
 
 JS_PUBLIC_API(ContextOptions&)
 ContextOptionsRef(JSContext* cx);
 
 /**
  * Initialize the runtime's self-hosted code. Embeddings should call this
  * exactly once per runtime/context, before the first JS_NewGlobalObject
@@ -3745,16 +3757,17 @@ class JS_FRIEND_API(TransitiveCompileOpt
         sourceMapURL_(nullptr),
         version(JSVERSION_UNKNOWN),
         versionSet(false),
         utf8(false),
         selfHostingMode(false),
         canLazilyParse(true),
         strictOption(false),
         extraWarningsOption(false),
+        forEachStatementOption(false),
         werrorOption(false),
         asmJSOption(AsmJSOption::Disabled),
         throwOnAsmJSValidationFailureOption(false),
         forceAsync(false),
         installedFile(false),
         sourceIsLazy(false),
         introductionType(nullptr),
         introductionLineno(0),
@@ -3780,16 +3793,17 @@ class JS_FRIEND_API(TransitiveCompileOpt
     // POD options.
     JSVersion version;
     bool versionSet;
     bool utf8;
     bool selfHostingMode;
     bool canLazilyParse;
     bool strictOption;
     bool extraWarningsOption;
+    bool forEachStatementOption;
     bool werrorOption;
     AsmJSOption asmJSOption;
     bool throwOnAsmJSValidationFailureOption;
     bool forceAsync;
     bool installedFile;  // 'true' iff pre-compiling js file in packaged app
     bool sourceIsLazy;
 
     // |introductionType| is a statically allocated C string: