Bug 1108382 - Remove non-standard flag argument from String.prototype.{search,match,replace}. r=till
authorTooru Fujisawa <arai_a@mac.com>
Mon, 09 May 2016 20:48:26 +0900
changeset 296652 d1b90728ce14ed9988383975b3a0399dc8ef81f1
parent 296651 b6c20b0bbaabfcab1d21367a3c34fb3bb25696d3
child 296653 c57fdf4b8e07f197d7355ffd005cfefb75715700
push id30245
push usercbook@mozilla.com
push dateTue, 10 May 2016 10:06:29 +0000
treeherdermozilla-central@1579b9e2e50f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill
bugs1108382
milestone49.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 1108382 - Remove non-standard flag argument from String.prototype.{search,match,replace}. r=till
js/src/builtin/String.js
js/src/builtin/TestingFunctions.cpp
js/src/jit-test/tests/basic/bug593663-regexp.js
js/src/jit-test/tests/ion/bug977966.js
js/src/js.msg
js/src/jsapi.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/tests/ecma_6/extensions/String-match-flags.js
js/src/tests/js1_5/Regress/regress-179524.js
js/src/tests/js1_5/String/replace-flags.js
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpObject.h
js/src/vm/SelfHosting.cpp
toolkit/components/telemetry/Histograms.json
--- a/js/src/builtin/String.js
+++ b/js/src/builtin/String.js
@@ -35,35 +35,27 @@ function String_match(regexp) {
         // Step 2.b.
         if (matcher !== undefined)
             return callContentFunction(matcher, regexp, this);
     }
 
     // Step 3.
     var S = ToString(this);
 
-    // FIXME: Non-standard flags argument (bug 1108382).
-    var flags = undefined;
-    if (arguments.length > 1) {
-        if (IsMatchFlagsArgumentEnabled())
-            flags = ToString(arguments[1]);
-        WarnOnceAboutFlagsArgument();
-    } else {
-        if (isPatternString && IsStringMatchOptimizable()) {
-            var flatResult = FlatStringMatch(S, regexp);
-            if (flatResult !== undefined)
-                return flatResult;
-        }
+    if (isPatternString && IsStringMatchOptimizable()) {
+        var flatResult = FlatStringMatch(S, regexp);
+        if (flatResult !== undefined)
+            return flatResult;
     }
 
     // Step 4.
-    var rx = RegExpCreate(regexp, flags);
+    var rx = RegExpCreate(regexp, undefined);
 
     // Step 5 (optimized case).
-    if (IsStringMatchOptimizable() && !flags)
+    if (IsStringMatchOptimizable())
         return RegExpMatcher(rx, S, 0);
 
     // Step 5.
     return callContentFunction(GetMethod(rx, std_match), rx, S);
 }
 
 function String_generic_match(thisValue, regexp) {
     if (thisValue === undefined)
@@ -156,28 +148,16 @@ function String_replace(searchValue, rep
     }
 
     // Step 3.
     var string = ToString(this);
 
     // Step 4.
     var searchString = ToString(searchValue);
 
-    // FIXME: Non-standard flags argument (bug 1108382).
-    var flags = undefined;
-    if (arguments.length > 2) {
-        WarnOnceAboutFlagsArgument();
-        if (IsMatchFlagsArgumentEnabled()) {
-            flags = ToString(arguments[2]);
-            var rx = RegExpCreate(RegExpEscapeMetaChars(searchString), flags);
-
-            return callContentFunction(GetMethod(rx, std_replace), rx, string, replaceValue);
-        }
-    }
-
     if (typeof replaceValue === "string") {
         // Steps 6-12: Optimized for string case.
         return StringReplaceString(string, searchString, replaceValue);
     }
 
     // Step 5.
     if (!IsCallable(replaceValue)) {
         // Steps 6-12.
@@ -248,32 +228,24 @@ function String_search(regexp) {
         // Step 2.b.
         if (searcher !== undefined)
             return callContentFunction(searcher, regexp, this);
     }
 
     // Step 3.
     var string = ToString(this);
 
-    // FIXME: Non-standard flags argument (bug 1108382).
-    var flags = undefined;
-    if (arguments.length > 1) {
-        if (IsMatchFlagsArgumentEnabled())
-            flags = ToString(arguments[1]);
-        WarnOnceAboutFlagsArgument();
-    } else {
-        if (isPatternString && IsStringSearchOptimizable()) {
-            var flatResult = FlatStringSearch(string, regexp);
-            if (flatResult !== -2)
-                return flatResult;
-        }
+    if (isPatternString && IsStringSearchOptimizable()) {
+        var flatResult = FlatStringSearch(string, regexp);
+        if (flatResult !== -2)
+            return flatResult;
     }
 
     // Step 4.
-    var rx = RegExpCreate(regexp, flags);
+    var rx = RegExpCreate(regexp, undefined);
 
     // Step 5.
     return callContentFunction(GetMethod(rx, std_search), rx, string);
 }
 
 function String_generic_search(thisValue, regexp) {
     if (thisValue === undefined)
         ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.search');
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -3492,25 +3492,16 @@ GetModuleEnvironmentValue(JSContext* cx,
     RootedString name(cx, args[1].toString());
     RootedId id(cx);
     if (!JS_StringToId(cx, name, &id))
         return false;
 
     return GetProperty(cx, env, env, id, args.rval());
 }
 
-static bool
-EnableMatchFlagArgument(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    cx->runtime()->options().setMatchFlagArgument(true);
-    args.rval().setUndefined();
-    return true;
-}
-
 static const JSFunctionSpecWithHelp TestingFunctions[] = {
     JS_FN_HELP("gc", ::GC, 0, 0,
 "gc([obj] | 'compartment' [, 'shrinking'])",
 "  Run the garbage collector. When obj is given, GC only its compartment.\n"
 "  If 'compartment' is given, GC any compartments 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."),
@@ -4018,21 +4009,16 @@ 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("enableMatchFlagArgument", EnableMatchFlagArgument, 0, 0,
-"enableMatchFlagArgument()",
-"  Enables the deprecated, non-standard flag argument of\n"
-"  String.prototype.{match,search,replace}.\n"),
-
     JS_FS_HELP_END
 };
 
 static const JSPropertySpec TestingProperties[] = {
     JS_PSG("timesAccessed", TimesAccessed, 0),
     JS_PS_END
 };
 
--- a/js/src/jit-test/tests/basic/bug593663-regexp.js
+++ b/js/src/jit-test/tests/basic/bug593663-regexp.js
@@ -7,105 +7,103 @@ function isPatternSyntaxError(pattern) {
     try {
         new RegExp(pattern);
         return false;
     } catch (e if e instanceof SyntaxError) {
         return true;
     }
 }
 
-enableMatchFlagArgument();
-
 // Bug example.
-assertEq("1+2".replace("1+2", "$&+3", "g"), "1+2+3");
-assertEq("1112".replace("1+2", "", "g"), "1112");
+assertEq("1+2".replace("1+2", "$&+3"), "1+2+3");
+assertEq("1112".replace("1+2", ""), "1112");
 
 // ^
-assertEq("leading text^my hat".replace("^my hat", "", "g"), "leading text");
-assertEq("my hat".replace("^my hat", "", "g"), "my hat");
+assertEq("leading text^my hat".replace("^my hat", ""), "leading text");
+assertEq("my hat".replace("^my hat", ""), "my hat");
 
 // $
-assertEq("leading text$my money".replace("leading text$", "", "g"), "my money");
-assertEq("leading text".replace("leading text$", "", "g"), "leading text");
+assertEq("leading text$my money".replace("leading text$", ""), "my money");
+assertEq("leading text".replace("leading text$", ""), "leading text");
 
 // \
 var BSL = '\\';
-assertEq(("dir C:" + BSL + "Windoze").replace("C:" + BSL, "", "g"),
+assertEq(("dir C:" + BSL + "Windoze").replace("C:" + BSL, ""),
          "dir Windoze");
 assertEq(isPatternSyntaxError("C:" + BSL), true);
 
 // .
-assertEq("This is a sentence. It has words.".replace(".", "!", "g"),
-         "This is a sentence! It has words!");
-assertEq("This is an unterminated sentence".replace(".", "", "g"),
+assertEq("This is a sentence. It has words.".replace(".", "!"),
+         "This is a sentence! It has words.");
+assertEq("This is an unterminated sentence".replace(".", ""),
          "This is an unterminated sentence");
 
 // *
-assertEq("Video killed the radio *".replace(" *", "", "g"), "Video killed the radio");
-assertEq("aaa".replace("a*", "", "g"), "aaa");
+assertEq("Video killed the radio *".replace(" *", ""), "Video killed the radio");
+assertEq("aaa".replace("a*", ""), "aaa");
 
 // +
-assertEq("On the + side".replace(" +", "", "g"), "On the side");
-assertEq("1111111111111".replace("1+", "", "g"), "1111111111111");
+assertEq("On the + side".replace(" +", ""), "On the side");
+assertEq("1111111111111".replace("1+", ""), "1111111111111");
 
 // \+
-assertEq(("Inverse cone head: " + BSL + "++/").replace(BSL + "+", "", "g"),
+assertEq(("Inverse cone head: " + BSL + "++/").replace(BSL + "+", ""),
          "Inverse cone head: +/");
-assertEq((BSL + BSL + BSL).replace(BSL + "+", "", "g"),
+assertEq((BSL + BSL + BSL).replace(BSL + "+", ""),
          BSL + BSL + BSL);
 
 // \\+
-assertEq((BSL + BSL + "+").replace(BSL + BSL + "+", "", "g"), "");
-assertEq((BSL + BSL + BSL).replace(BSL + BSL + "+", "", "g"), (BSL + BSL + BSL));
+assertEq((BSL + BSL + "+").replace(BSL + BSL + "+", ""), "");
+assertEq((BSL + BSL + BSL).replace(BSL + BSL + "+", ""), (BSL + BSL + BSL));
 
 // \\\
-assertEq((BSL + BSL + BSL + BSL).replace(BSL + BSL + BSL, "", "g"), BSL);
+assertEq((BSL + BSL + BSL + BSL).replace(BSL + BSL + BSL, ""), BSL);
 assertEq(isPatternSyntaxError(BSL + BSL + BSL), true);
 
 // \\\\
 assertEq((BSL + BSL + BSL + BSL).replace(BSL + BSL + BSL + BSL, "", "i"), "");
-assertEq((BSL + BSL).replace(BSL + BSL + BSL + BSL, "", "g"), BSL + BSL);
+assertEq((BSL + BSL).replace(BSL + BSL + BSL + BSL, ""), BSL + BSL);
 
 
 // ?
-assertEq("Pressing question?".replace("?", ".", "g"), "Pressing question.");
-assertEq("a".replace("a?", "", "g"), "a");
+assertEq("Pressing question?".replace("?", "."), "Pressing question.");
+assertEq("a".replace("a?", ""), "a");
 
 // (
-assertEq("(a".replace("(", "", "g"), "a");
+assertEq("(a".replace("(", ""), "a");
 
 // )
-assertEq("a)".replace(")", "", "g"), "a");
+assertEq("a)".replace(")", ""), "a");
 
 // ( and )
-assertEq("(foo)".replace("(foo)", "", "g"), "");
-assertEq("a".replace("(a)", "", "g"), "a");
+assertEq("(foo)".replace("(foo)", ""), "");
+assertEq("a".replace("(a)", ""), "a");
 
 // [
-assertEq("[a".replace("[", "", "g"), "a");
+assertEq("[a".replace("[", ""), "a");
 
 // ]
-assertEq("a]".replace("]", "", "g"), "a");
+assertEq("a]".replace("]", ""), "a");
 
 // [ and ]
-assertEq("a".replace("[a-z]", "", "g"), "a");
-assertEq("You would write your regexp as [a-z]".replace("[a-z]", "", "g"),
+assertEq("a".replace("[a-z]", ""), "a");
+assertEq("You would write your regexp as [a-z]".replace("[a-z]", ""),
          "You would write your regexp as ");
 
 // {
-assertEq("Numbers may be specified in the interval {1,100}".replace("{1,", "", "g"),
+assertEq("Numbers may be specified in the interval {1,100}".replace("{1,", ""),
          "Numbers may be specified in the interval 100}");
 
 // }
-assertEq("Numbers may be specified in the interval {1,100}".replace(",100}", "", "g"),
+assertEq("Numbers may be specified in the interval {1,100}".replace(",100}", ""),
          "Numbers may be specified in the interval {1");
 
 // { and }
-assertEq("Numbers may be specified in the interval {1,100}".replace(" {1,100}", "", "g"),
+assertEq("Numbers may be specified in the interval {1,100}".replace(" {1,100}", ""),
          "Numbers may be specified in the interval");
-assertEq("aaa".replace("a{1,10}", "", "g"), "aaa");
+assertEq("aaa".replace("a{1,10}", ""), "aaa");
 
 // |
-assertEq("Mr. Gorbachev|Tear down this wall!".replace("|Tear down this wall!", "", "g"),
+assertEq("Mr. Gorbachev|Tear down this wall!".replace("|Tear down this wall!", ""),
          "Mr. Gorbachev");
-assertEq("foobar".replace("foo|bar", "", "g"), "foobar");
+assertEq("foobar".replace("foo|bar", ""), "foobar");
 
 print("PASS");
--- a/js/src/jit-test/tests/ion/bug977966.js
+++ b/js/src/jit-test/tests/ion/bug977966.js
@@ -95,29 +95,23 @@ function split_join_pattern(i) {
     var s = i + "-" + i;
     assertEq(s.split("-").join("$`$&$'"), i + "$`$&$'" + i);
     assertEq(s.replace("-", "$`$&$'"), "" + i + i + "-" + i + i);
 }
 
 // Check that, as opposed to String.replace, we are doing a global replacement
 // as String.split does.
 function split_join_multiple(i) {
-    enableMatchFlagArgument();
-
     var s1 = i + "-\n-" + i + "-\n-" + i;
     assertEq(s1.split("-\n-").join("-")  , i + "-" + i + "-" + i);
     assertEq(s1.replace("-\n-", "-")     , i + "-" + i + "-\n-" + i);
-    // SpiderMonkey extension
-    assertEq(s1.replace("-\n-", "-", "g"), i + "-" + i + "-" + i);
 
     var s2 = "abc";
     assertEq(s2.split("").join("" + i)   , "a" + i + "b" + i + "c");
     assertEq(s2.replace("", "" + i)      , i + "abc");
-    // SpiderMonkey extension
-    assertEq(s2.replace("", "" + i, "g") , i + "a" + i + "b" + i + "c" + i);
 }
 
 for (var i = 0; i < 1000; ++i) {
     join_check(i);
     split(i);
     join(i);
     split_join(i);
     split_join_2(i);
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -231,17 +231,16 @@ MSG_DEF(JSMSG_CURLY_BEFORE_CLASS,      0
 MSG_DEF(JSMSG_CURLY_BEFORE_FINALLY,    0, JSEXN_SYNTAXERR, "missing { before finally block")
 MSG_DEF(JSMSG_CURLY_BEFORE_SWITCH,     0, JSEXN_SYNTAXERR, "missing { before switch body")
 MSG_DEF(JSMSG_CURLY_BEFORE_TRY,        0, JSEXN_SYNTAXERR, "missing { before try block")
 MSG_DEF(JSMSG_CURLY_IN_COMPOUND,       0, JSEXN_SYNTAXERR, "missing } in compound statement")
 MSG_DEF(JSMSG_DECLARATION_AFTER_EXPORT,0, JSEXN_SYNTAXERR, "missing declaration after 'export' keyword")
 MSG_DEF(JSMSG_DECLARATION_AFTER_IMPORT,0, JSEXN_SYNTAXERR, "missing declaration after 'import' keyword")
 MSG_DEF(JSMSG_DEPRECATED_DELETE_OPERAND, 0, JSEXN_SYNTAXERR, "applying the 'delete' operator to an unqualified name is deprecated")
 MSG_DEF(JSMSG_DEPRECATED_EXPR_CLOSURE, 0, JSEXN_NONE, "expression closures are deprecated")
-MSG_DEF(JSMSG_DEPRECATED_FLAGS_ARG,    0, JSEXN_NONE, "flags argument of String.prototype.{search,match,replace} is deprecated")
 MSG_DEF(JSMSG_DEPRECATED_FOR_EACH,     0, JSEXN_NONE, "JavaScript 1.6's for-each-in loops are deprecated; consider using ES6 for-of instead")
 MSG_DEF(JSMSG_DEPRECATED_OCTAL,        0, JSEXN_SYNTAXERR, "\"0\"-prefixed octal literals and octal escape sequences are deprecated; for octal literals use the \"0o\" prefix instead")
 MSG_DEF(JSMSG_DEPRECATED_PRAGMA,       1, JSEXN_NONE, "Using //@ to indicate {0} pragmas is deprecated. Use //# instead")
 MSG_DEF(JSMSG_DEPRECATED_BLOCK_SCOPE_FUN_REDECL, 1, JSEXN_NONE, "redeclaration of block-scoped function `{0}' is deprecated")
 MSG_DEF(JSMSG_DUPLICATE_EXPORT_NAME,   1, JSEXN_SYNTAXERR, "duplicate export name '{0}'")
 MSG_DEF(JSMSG_DUPLICATE_FORMAL,        1, JSEXN_SYNTAXERR, "duplicate formal argument {0}")
 MSG_DEF(JSMSG_DUPLICATE_LABEL,         0, JSEXN_SYNTAXERR, "duplicate label")
 MSG_DEF(JSMSG_DUPLICATE_PROPERTY,      1, JSEXN_SYNTAXERR, "property name {0} appears more than once in object literal")
@@ -273,17 +272,16 @@ MSG_DEF(JSMSG_MISSING_HEXDIGITS,       0
 MSG_DEF(JSMSG_MISSING_OCTAL_DIGITS,    0, JSEXN_SYNTAXERR, "missing octal digits after '0o'")
 MSG_DEF(JSMSG_MODULE_SPEC_AFTER_FROM,  0, JSEXN_SYNTAXERR, "missing module specifier after 'from' keyword")
 MSG_DEF(JSMSG_NAME_AFTER_DOT,          0, JSEXN_SYNTAXERR, "missing name after . operator")
 MSG_DEF(JSMSG_NAMED_IMPORTS_OR_NAMESPACE_IMPORT, 0, JSEXN_SYNTAXERR, "expected named imports or namespace import after comma")
 MSG_DEF(JSMSG_NO_BINDING_NAME,        0, JSEXN_SYNTAXERR, "missing binding name")
 MSG_DEF(JSMSG_NO_EXPORT_NAME,          0, JSEXN_SYNTAXERR, "missing export name")
 MSG_DEF(JSMSG_NO_IMPORT_NAME,          0, JSEXN_SYNTAXERR, "missing import name")
 MSG_DEF(JSMSG_NO_VARIABLE_NAME,        0, JSEXN_SYNTAXERR, "missing variable name")
-MSG_DEF(JSMSG_OBSOLETE_FLAGS_ARG,      0, JSEXN_NONE, "flags argument of String.prototype.{search,match,replace} is no longer supported")
 MSG_DEF(JSMSG_OF_AFTER_FOR_NAME,       0, JSEXN_SYNTAXERR, "missing 'of' after for")
 MSG_DEF(JSMSG_PAREN_AFTER_ARGS,        0, JSEXN_SYNTAXERR, "missing ) after argument list")
 MSG_DEF(JSMSG_PAREN_AFTER_CATCH,       0, JSEXN_SYNTAXERR, "missing ) after catch")
 MSG_DEF(JSMSG_PAREN_AFTER_COND,        0, JSEXN_SYNTAXERR, "missing ) after condition")
 MSG_DEF(JSMSG_PAREN_AFTER_FOR,         0, JSEXN_SYNTAXERR, "missing ( after for")
 MSG_DEF(JSMSG_PAREN_AFTER_FORMAL,      0, JSEXN_SYNTAXERR, "missing ) after formal parameters")
 MSG_DEF(JSMSG_PAREN_AFTER_FOR_CTRL,    0, JSEXN_SYNTAXERR, "missing ) after for-loop control")
 MSG_DEF(JSMSG_PAREN_AFTER_FOR_OF_ITERABLE, 0, JSEXN_SYNTAXERR, "missing ) after for-of iterable")
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1109,22 +1109,17 @@ class JS_PUBLIC_API(RuntimeOptions) {
         throwOnAsmJSValidationFailure_(false),
         nativeRegExp_(true),
         unboxedArrays_(false),
         asyncStack_(true),
         throwOnDebuggeeWouldRun_(true),
         dumpStackOnDebuggeeWouldRun_(false),
         werror_(false),
         strictMode_(false),
-        extraWarnings_(false),
-#ifdef RELEASE_BUILD
-        matchFlagArgument_(true)
-#else
-        matchFlagArgument_(false)
-#endif
+        extraWarnings_(false)
     {
     }
 
     bool baseline() const { return baseline_; }
     RuntimeOptions& setBaseline(bool flag) {
         baseline_ = flag;
         return *this;
     }
@@ -1228,37 +1223,30 @@ class JS_PUBLIC_API(RuntimeOptions) {
         extraWarnings_ = flag;
         return *this;
     }
     RuntimeOptions& toggleExtraWarnings() {
         extraWarnings_ = !extraWarnings_;
         return *this;
     }
 
-    bool matchFlagArgument() const { return matchFlagArgument_; }
-    RuntimeOptions& setMatchFlagArgument(bool flag) {
-        matchFlagArgument_ = flag;
-        return *this;
-    }
-
   private:
     bool baseline_ : 1;
     bool ion_ : 1;
     bool asmJS_ : 1;
     bool wasm_ : 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 matchFlagArgument_ : 1;
 };
 
 JS_PUBLIC_API(RuntimeOptions&)
 RuntimeOptionsRef(JSRuntime* rt);
 
 JS_PUBLIC_API(RuntimeOptions&)
 RuntimeOptionsRef(JSContext* cx);
 
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -45,17 +45,16 @@ JSCompartment::JSCompartment(Zone* zone,
   : creationOptions_(options.creationOptions()),
     behaviors_(options.behaviors()),
     zone_(zone),
     runtime_(zone->runtimeFromMainThread()),
     principals_(nullptr),
     isSystem_(false),
     isSelfHosting(false),
     marked(true),
-    warnedAboutFlagsArgument(false),
     warnedAboutExprClosure(false),
 #ifdef DEBUG
     firedOnNewGlobalObject(false),
 #endif
     global_(nullptr),
     enterCompartmentDepth(0),
     performanceMonitoring(runtime_),
     data(nullptr),
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -293,17 +293,16 @@ struct JSCompartment
         return isSystem_;
     }
   private:
     JSPrincipals*                principals_;
     bool                         isSystem_;
   public:
     bool                         isSelfHosting;
     bool                         marked;
-    bool                         warnedAboutFlagsArgument;
     bool                         warnedAboutExprClosure;
 
 #ifdef DEBUG
     bool                         firedOnNewGlobalObject;
 #endif
 
     void mark() { marked = true; }
 
@@ -791,17 +790,17 @@ struct JSCompartment
     enum DeprecatedLanguageExtension {
         DeprecatedForEach = 0,              // JS 1.6+
         // NO LONGER USING 1
         DeprecatedLegacyGenerator = 2,      // JS 1.7+
         DeprecatedExpressionClosure = 3,    // Added in JS 1.8
         // NO LONGER USING 4
         // NO LONGER USING 5
         // NO LONGER USING 6
-        DeprecatedFlagsArgument = 7,        // JS 1.3 or older
+        // NO LONGER USING 7
         // NO LONGER USING 8
         // NO LONGER USING 9
         DeprecatedBlockScopeFunRedecl = 10,
         DeprecatedLanguageExtensionCount
     };
 
     js::ArgumentsObject* getOrCreateArgumentsTemplateObject(JSContext* cx, bool mapped);
 
--- a/js/src/tests/ecma_6/extensions/String-match-flags.js
+++ b/js/src/tests/ecma_6/extensions/String-match-flags.js
@@ -1,31 +1,27 @@
-// |reftest| skip-if(!xulRuntime.shell) -- needs enableMatchFlagArgument()
-
 var BUGNUMBER = 1263139;
 var summary = "String.prototype.match with non-string non-standard flags argument.";
 
 print(BUGNUMBER + ": " + summary);
 
-enableMatchFlagArgument();
-
 var called;
 var flags = {
   toString() {
     called = true;
     return "";
   }
 };
 
 called = false;
 "a".match("a", flags);
-assertEq(called, true);
+assertEq(called, false);
 
 called = false;
 "a".search("a", flags);
-assertEq(called, true);
+assertEq(called, false);
 
 called = false;
 "a".replace("a", "b", flags);
-assertEq(called, true);
+assertEq(called, false);
 
 if (typeof reportCompare === "function")
     reportCompare(true, true);
--- a/js/src/tests/js1_5/Regress/regress-179524.js
+++ b/js/src/tests/js1_5/Regress/regress-179524.js
@@ -24,18 +24,16 @@ var BUGNUMBER = 179524;
 var summary = "Don't crash on extraneous arguments to str.match(), etc.";
 var status = '';
 var statusitems = [];
 var actual = '';
 var actualvalues = [];
 var expect= '';
 var expectedvalues = [];
 
-enableMatchFlagArgument();
-
 str = 'ABC abc';
 var re = /z/ig;
 
 status = inSection(1);
 actual = str.match(re);
 expect = null;
 addThis();
 
@@ -114,130 +112,104 @@ addThis();
  */
 status = inSection(13);
 actual = str.match('a').toString();
 expect = str.match(/a/).toString();
 addThis();
 
 status = inSection(14);
 actual = str.match('a', 'i').toString();
-expect = str.match(/a/i).toString();
+expect = str.match(/a/).toString();
 addThis();
 
 status = inSection(15);
 actual = str.match('a', 'ig').toString();
-expect = str.match(/a/ig).toString();
+expect = str.match(/a/).toString();
 addThis();
 
 status = inSection(16);
 actual = str.match('\\s', 'm').toString();
-expect = str.match(/\s/m).toString();
+expect = str.match(/\s/).toString();
 addThis();
 
 
 /*
  * Now try the previous three cases with extraneous parameters
  */
 status = inSection(17);
 actual = str.match('a', 'i', 'g').toString();
-expect = str.match(/a/i).toString();
+expect = str.match(/a/).toString();
 addThis();
 
 status = inSection(18);
 actual = str.match('a', 'ig', new Object()).toString();
-expect = str.match(/a/ig).toString();
+expect = str.match(/a/).toString();
 addThis();
 
 status = inSection(19);
 actual = str.match('\\s', 'm', 999).toString();
-expect = str.match(/\s/m).toString();
+expect = str.match(/\s/).toString();
 addThis();
 
-
-/*
- * Try an invalid second parameter (i.e. an invalid regexp flag)
- */
 status = inSection(20);
-try
-{
-  actual = str.match('a', 'z').toString();
-  expect = 'SHOULD HAVE FALLEN INTO CATCH-BLOCK!';
-  addThis();
-}
-catch (e)
-{
-  actual = e instanceof SyntaxError;
-  expect = true;
-  addThis();
-}
+actual = str.match('a', 'z').toString();
+expect = str.match(/a/).toString();
+addThis();
 
 
 
 /*
  * Now test str.search() where the first argument is not a regexp object.
  * The same considerations as above apply -
  *
  * Reference: http://bugzilla.mozilla.org/show_bug.cgi?id=179524#c16
  */
 status = inSection(21);
 actual = str.search('a');
 expect = str.search(/a/);
 addThis();
 
 status = inSection(22);
 actual = str.search('a', 'i');
-expect = str.search(/a/i);
+expect = str.search(/a/);
 addThis();
 
 status = inSection(23);
 actual = str.search('a', 'ig');
-expect = str.search(/a/ig);
+expect = str.search(/a/);
 addThis();
 
 status = inSection(24);
 actual = str.search('\\s', 'm');
-expect = str.search(/\s/m);
+expect = str.search(/\s/);
 addThis();
 
 
 /*
  * Now try the previous three cases with extraneous parameters
  */
 status = inSection(25);
 actual = str.search('a', 'i', 'g');
-expect = str.search(/a/i);
+expect = str.search(/a/);
 addThis();
 
 status = inSection(26);
 actual = str.search('a', 'ig', new Object());
-expect = str.search(/a/ig);
+expect = str.search(/a/);
 addThis();
 
 status = inSection(27);
 actual = str.search('\\s', 'm', 999);
-expect = str.search(/\s/m);
+expect = str.search(/\s/);
 addThis();
 
-
-/*
- * Try an invalid second parameter (i.e. an invalid regexp flag)
- */
 status = inSection(28);
-try
-{
-  actual = str.search('a', 'z');
-  expect = 'SHOULD HAVE FALLEN INTO CATCH-BLOCK!';
-  addThis();
-}
-catch (e)
-{
-  actual = e instanceof SyntaxError;
-  expect = true;
-  addThis();
-}
+actual = str.search('a', 'z');
+expect = str.search(/a/);
+addThis();
 
 
 
 /*
  * Now test str.replace() where the first argument is not a regexp object.
  * The same considerations as above apply, EXCEPT for meta-characters.
  * See introduction to testcase above. References:
  *
@@ -246,67 +218,54 @@ catch (e)
  */
 status = inSection(29);
 actual = str.replace('a', 'Z');
 expect = str.replace(/a/, 'Z');
 addThis();
 
 status = inSection(30);
 actual = str.replace('a', 'Z', 'i');
-expect = str.replace(/a/i, 'Z');
+expect = str.replace(/a/, 'Z');
 addThis();
 
 status = inSection(31);
 actual = str.replace('a', 'Z', 'ig');
-expect = str.replace(/a/ig, 'Z');
+expect = str.replace(/a/, 'Z');
 addThis();
 
 status = inSection(32);
 actual = str.replace('\\s', 'Z', 'm'); //<--- NO!!! No meta-characters 1st arg!
 actual = str.replace(' ', 'Z', 'm');   //<--- Have to do this instead
-expect = str.replace(/\s/m, 'Z');
+expect = str.replace(/\s/, 'Z');
 addThis();
 
 
 /*
  * Now try the previous three cases with extraneous parameters
  */
 status = inSection(33);
 actual = str.replace('a', 'Z', 'i', 'g');
-expect = str.replace(/a/i, 'Z');
+expect = str.replace(/a/, 'Z');
 addThis();
 
 status = inSection(34);
 actual = str.replace('a', 'Z', 'ig', new Object());
-expect = str.replace(/a/ig, 'Z');
+expect = str.replace(/a/, 'Z');
 addThis();
 
 status = inSection(35);
 actual = str.replace('\\s', 'Z', 'm', 999); //<--- NO meta-characters 1st arg!
 actual = str.replace(' ', 'Z', 'm', 999);   //<--- Have to do this instead
-expect = str.replace(/\s/m, 'Z');
+expect = str.replace(/\s/, 'Z');
 addThis();
 
-
-/*
- * Try an invalid third parameter (i.e. an invalid regexp flag)
- */
 status = inSection(36);
-try
-{
-  actual = str.replace('a', 'Z', 'z');
-  expect = 'SHOULD HAVE FALLEN INTO CATCH-BLOCK!';
-  addThis();
-}
-catch (e)
-{
-  actual = e instanceof SyntaxError;
-  expect = true;
-  addThis();
-}
+actual = str.replace('a', 'Z', 'z');
+expect = str.replace(/a/, 'Z');
+addThis();
 
 
 
 
 //-----------------------------------------------------------------------------
 test();
 //-----------------------------------------------------------------------------
 
--- a/js/src/tests/js1_5/String/replace-flags.js
+++ b/js/src/tests/js1_5/String/replace-flags.js
@@ -1,24 +1,25 @@
-// |reftest| skip-if(!xulRuntime.shell)
-
-var BUGNUMBER = 1142351;
-var summary = 'Add console warnings for non-standard flag argument of String.prototype.{search,match,replace}.';
+var BUGNUMBER = 1108382;
+var summary = 'Remove non-standard flag argument from String.prototype.{search,match,replace}.';
 
 printBugNumber(BUGNUMBER);
 printStatus (summary);
 
-function assertWarningForComponent(code, name) {
-  enableLastWarning();
-  var g = newGlobal();
-  g.eval(code);
-  var warning = getLastWarning();
-  assertEq(warning !== null, true);
-  assertEq(warning.name, name);
-  disableLastWarning();
-}
+var result = "bbbAa".match("a", "i");
+assertEq(result.index, 4);
+assertEq(result.length, 1);
+assertEq(result[0], "a");
+
+result = "bbbA".match("a", "i");
+assertEq(result, null);
 
-assertWarningForComponent(`'aaaA'.match('a', 'i');`, "None");
-assertWarningForComponent(`'aaaA'.search('a', 'i');`, "None");
-assertWarningForComponent(`'aaaA'.replace('a', 'b', 'g');`, "None");
+result = "bbbAa".search("a", "i");
+assertEq(result, 4);
+
+result = "bbbA".search("a", "i");
+assertEq(result, -1);
+
+result = "bbbAaa".replace("a", "b", "g");
+assertEq(result, "bbbAba");
 
 if (typeof reportCompare === "function")
   reportCompare(true, true);
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -521,70 +521,16 @@ js::StringHasRegExpMetaChars(JSLinearStr
 {
     AutoCheckCannotGC nogc;
     if (str->hasLatin1Chars())
         return HasRegExpMetaChars(str->latin1Chars(nogc), str->length());
 
     return HasRegExpMetaChars(str->twoByteChars(nogc), str->length());
 }
 
-// Note: leaves the string buffer empty if no escaping need be performed.
-template <typename CharT>
-static bool
-RegExpEscapeMetaChars(StringBuffer& sb, const CharT* oldChars, size_t oldLen)
-{
-    for (const CharT* it = oldChars; it < oldChars + oldLen; ++it) {
-        CharT ch = *it;
-        if (IsRegExpMetaChar(ch)) {
-            if (sb.empty()) {
-                // This is the first char we've seen that needs escaping,
-                // copy everything up to this point.
-                if (!SetupBuffer(sb, oldChars, oldLen, it))
-                    return false;
-            }
-            if (!sb.append('\\'))
-                return false;
-        }
-
-        if (!sb.empty()) {
-            if (!sb.append(ch))
-                return false;
-        }
-    }
-
-    return true;
-}
-
-JSString*
-js::RegExpEscapeMetaChars(JSContext* cx, HandleString src)
-{
-    if (src->length() == 0)
-        return src;
-
-    RootedLinearString linear(cx, src->ensureLinear(cx));
-
-    // We may never need to use |sb|. Start using it lazily.
-    StringBuffer sb(cx);
-
-    if (linear->hasLatin1Chars()) {
-        JS::AutoCheckCannotGC nogc;
-        if (!::RegExpEscapeMetaChars(sb, linear->latin1Chars(nogc), linear->length()))
-            return nullptr;
-    } else {
-        JS::AutoCheckCannotGC nogc;
-        if (!::RegExpEscapeMetaChars(sb, linear->twoByteChars(nogc), linear->length()))
-            return nullptr;
-    }
-
-    if (sb.empty())
-        return src;
-
-    return sb.finishString();
-}
-
 /* RegExpShared */
 
 RegExpShared::RegExpShared(JSAtom* source, RegExpFlag flags)
   : source(source), flags(flags), parenCount(0), canStringMatch(false), marked_(false)
 {}
 
 RegExpShared::~RegExpShared()
 {
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -532,15 +532,11 @@ EscapeRegExpPattern(JSContext* cx, Handl
 
 template <typename CharT>
 extern bool
 HasRegExpMetaChars(const CharT* chars, size_t length);
 
 extern bool
 StringHasRegExpMetaChars(JSLinearString* str);
 
-/* Escape all meta chars in given string. */
-extern JSString*
-RegExpEscapeMetaChars(JSContext* cx, HandleString src);
-
 } /* namespace js */
 
 #endif /* vm_RegExpObject_h */
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -1623,31 +1623,16 @@ intrinsic_StringReplaceString(JSContext*
     JSString* result = str_replace_string_raw(cx, string, pattern, replacement);
     if (!result)
         return false;
 
     args.rval().setString(result);
     return true;
 }
 
-static bool
-intrinsic_RegExpEscapeMetaChars(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    MOZ_ASSERT(args.length() == 1);
-
-    RootedString string(cx, args[0].toString());
-    JSString* result = RegExpEscapeMetaChars(cx, string);
-    if (!result)
-        return false;
-
-    args.rval().setString(result);
-    return true;
-}
-
 bool
 js::intrinsic_StringSplitString(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 2);
 
     RootedString string(cx, args[0].toString());
     RootedString sep(cx, args[1].toString());
@@ -2197,42 +2182,16 @@ intrinsic_captureCurrentStack(JSContext*
     RootedObject stack(cx);
     if (!JS::CaptureCurrentStack(cx, &stack, maxFrameCount))
         return false;
 
     args.rval().setObject(*stack);
     return true;
 }
 
-static bool
-IsMatchFlagsArgumentEnabled(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    MOZ_ASSERT(args.length() == 0);
-
-    args.rval().setBoolean(cx->runtime()->options().matchFlagArgument());
-    return true;
-}
-
-static bool
-WarnOnceAboutFlagsArgument(JSContext* cx, unsigned argc, Value* vp)
-{
-    if (!cx->compartment()->warnedAboutFlagsArgument) {
-        if (!JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING, GetErrorMessage, nullptr,
-                                          cx->runtime()->options().matchFlagArgument()
-                                          ? JSMSG_DEPRECATED_FLAGS_ARG
-                                          : JSMSG_OBSOLETE_FLAGS_ARG))
-        {
-            return false;
-        }
-        cx->compartment()->warnedAboutFlagsArgument = true;
-    }
-    return true;
-}
-
 // The self-hosting global isn't initialized with the normal set of builtins.
 // Instead, individual C++-implemented functions that're required by
 // self-hosted code are defined as global functions. Accessing these
 // functions via a content compartment's builtins would be unsafe, because
 // content script might have changed the builtins' prototypes' members.
 // Installing the whole set of builtins in the self-hosting compartment, OTOH,
 // would be wasteful: it increases memory usage and initialization time for
 // self-hosting compartment.
@@ -2560,17 +2519,16 @@ static const JSFunctionSpec intrinsic_fu
     JS_INLINABLE_FN("RegExpTester", RegExpTester, 4,0,
                     RegExpTester),
     JS_FN("RegExpCreate", intrinsic_RegExpCreate, 2,0),
     JS_INLINABLE_FN("RegExpPrototypeOptimizable", RegExpPrototypeOptimizable, 1,0,
                     RegExpPrototypeOptimizable),
     JS_INLINABLE_FN("RegExpInstanceOptimizable", RegExpInstanceOptimizable, 1,0,
                     RegExpInstanceOptimizable),
     JS_FN("RegExpGetSubstitution", intrinsic_RegExpGetSubstitution, 6,0),
-    JS_FN("RegExpEscapeMetaChars", intrinsic_RegExpEscapeMetaChars, 1,0),
     JS_FN("GetElemBaseForLambda", intrinsic_GetElemBaseForLambda, 1,0),
     JS_FN("GetStringDataProperty", intrinsic_GetStringDataProperty, 2,0),
     JS_INLINABLE_FN("GetFirstDollarIndex", GetFirstDollarIndex, 1,0,
                     GetFirstDollarIndex),
 
     JS_FN("FlatStringMatch", FlatStringMatch, 2,0),
     JS_FN("FlatStringSearch", FlatStringSearch, 2,0),
     JS_INLINABLE_FN("StringReplaceString", intrinsic_StringReplaceString, 3, 0,
@@ -2580,19 +2538,16 @@ static const JSFunctionSpec intrinsic_fu
     JS_FN("StringSplitStringLimit", intrinsic_StringSplitStringLimit, 3, 0),
 
     // See builtin/RegExp.h for descriptions of the regexp_* functions.
     JS_FN("regexp_exec_no_statics", regexp_exec_no_statics, 2,0),
     JS_FN("regexp_test_no_statics", regexp_test_no_statics, 2,0),
     JS_FN("regexp_construct", regexp_construct_self_hosting, 2,0),
     JS_FN("regexp_construct_no_sticky", regexp_construct_no_sticky, 2,0),
 
-    JS_FN("IsMatchFlagsArgumentEnabled", IsMatchFlagsArgumentEnabled, 0,0),
-    JS_FN("WarnOnceAboutFlagsArgument", WarnOnceAboutFlagsArgument, 0,0),
-
     JS_FN("IsModule", intrinsic_IsInstanceOfBuiltin<ModuleObject>, 1, 0),
     JS_FN("CallModuleMethodIfWrapped",
           CallNonGenericSelfhostedMethod<Is<ModuleObject>>, 2, 0),
     JS_FN("HostResolveImportedModule", intrinsic_HostResolveImportedModule, 2, 0),
     JS_FN("GetModuleEnvironment", intrinsic_GetModuleEnvironment, 1, 0),
     JS_FN("CreateModuleEnvironment", intrinsic_CreateModuleEnvironment, 1, 0),
     JS_FN("CreateImportBinding", intrinsic_CreateImportBinding, 4, 0),
     JS_FN("CreateNamespaceBinding", intrinsic_CreateNamespaceBinding, 3, 0),
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -557,24 +557,24 @@
     "bug_numbers": [1255198],
     "description": "This metric is recorded every time a navigator.geolocation.watchPosition() request gets allowed/fulfilled. A false value is recorded if the owner is not visible according to document.isVisible."
   },
   "JS_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT": {
     "alert_emails": ["jdemooij@mozilla.com"],
     "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 10,
-    "description": "Use of SpiderMonkey's deprecated language extensions in web content: ForEach=0, DestructuringForIn=1 (obsolete), LegacyGenerator=2, ExpressionClosure=3, LetBlock=4 (obsolete), LetExpression=5 (obsolete), NoSuchMethod=6 (obsolete), FlagsArgument=7, RegExpSourceProp=8 (obsolete), RestoredRegExpStatics=9 (obsolete), BlockScopeFunRedecl=10"
+    "description": "Use of SpiderMonkey's deprecated language extensions in web content: ForEach=0, DestructuringForIn=1 (obsolete), LegacyGenerator=2, ExpressionClosure=3, LetBlock=4 (obsolete), LetExpression=5 (obsolete), NoSuchMethod=6 (obsolete), FlagsArgument=7 (obsolete), RegExpSourceProp=8 (obsolete), RestoredRegExpStatics=9 (obsolete), BlockScopeFunRedecl=10"
   },
   "JS_DEPRECATED_LANGUAGE_EXTENSIONS_IN_ADDONS": {
     "alert_emails": ["jdemooij@mozilla.com"],
     "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 10,
-    "description": "Use of SpiderMonkey's deprecated language extensions in add-ons: ForEach=0, DestructuringForIn=1 (obsolete), LegacyGenerator=2, ExpressionClosure=3, LetBlock=4 (obsolete), LetExpression=5 (obsolete), NoSuchMethod=6 (obsolete), FlagsArgument=7, RegExpSourceProp=8 (obsolete), RestoredRegExpStatics=9 (obsolete), BlockScopeFunRedecl=10"
+    "description": "Use of SpiderMonkey's deprecated language extensions in add-ons: ForEach=0, DestructuringForIn=1 (obsolete), LegacyGenerator=2, ExpressionClosure=3, LetBlock=4 (obsolete), LetExpression=5 (obsolete), NoSuchMethod=6 (obsolete), FlagsArgument=7 (obsolete), RegExpSourceProp=8 (obsolete), RestoredRegExpStatics=9 (obsolete), BlockScopeFunRedecl=10"
   },
   "JS_DEFINE_GETTER_SETTER_THIS_NULL_UNDEFINED": {
     "alert_emails": ["jdemooij@mozilla.com"],
     "bug_numbers": [1249123],
     "expires_in_version": "55",
     "kind": "boolean",
     "releaseChannelCollection": "opt-out",
     "description": "__defineGetter__ or __defineSetter__ invoked with 1 = null/undefined or 0 = everything else as |this| value"