Bug 1485066 - Part 3: Replace calls to JS_EncodeString for string comparison with StringEqualsAscii. r=Waldo
☠☠ backed out by 3d23c2f43b8a ☠ ☠
authorAndré Bargull <andre.bargull@gmail.com>
Wed, 05 Sep 2018 01:25:09 -0700
changeset 434759 4f89260d5e30f7b77ddd05e15414be8036b1937e
parent 434758 c22fc17c9d87281c0c074ccb2c2f21fb9a3bf4dd
child 434760 bf167b0a3af38a895690054de642027af9aafef3
push id107490
push usercsabou@mozilla.com
push dateWed, 05 Sep 2018 12:25:08 +0000
treeherdermozilla-inbound@e40f67f15bf1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1485066
milestone64.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 1485066 - Part 3: Replace calls to JS_EncodeString for string comparison with StringEqualsAscii. r=Waldo
js/src/builtin/TestingFunctions.cpp
js/src/shell/js.cpp
js/xpconnect/src/Sandbox.cpp
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2910,27 +2910,27 @@ const JSPropertySpec CloneBufferObject::
     JS_PS_END
 };
 
 static mozilla::Maybe<JS::StructuredCloneScope>
 ParseCloneScope(JSContext* cx, HandleString str)
 {
     mozilla::Maybe<JS::StructuredCloneScope> scope;
 
-    UniqueChars scopeStr = JS_EncodeString(cx, str);
+    JSLinearString* scopeStr = str->ensureLinear(cx);
     if (!scopeStr)
         return scope;
 
-    if (strcmp(scopeStr.get(), "SameProcessSameThread") == 0)
+    if (StringEqualsAscii(scopeStr, "SameProcessSameThread"))
         scope.emplace(JS::StructuredCloneScope::SameProcessSameThread);
-    else if (strcmp(scopeStr.get(), "SameProcessDifferentThread") == 0)
+    else if (StringEqualsAscii(scopeStr, "SameProcessDifferentThread"))
         scope.emplace(JS::StructuredCloneScope::SameProcessDifferentThread);
-    else if (strcmp(scopeStr.get(), "DifferentProcess") == 0)
+    else if (StringEqualsAscii(scopeStr, "DifferentProcess"))
         scope.emplace(JS::StructuredCloneScope::DifferentProcess);
-    else if (strcmp(scopeStr.get(), "DifferentProcessForIndexedDB") == 0)
+    else if (StringEqualsAscii(scopeStr, "DifferentProcessForIndexedDB"))
         scope.emplace(JS::StructuredCloneScope::DifferentProcessForIndexedDB);
 
     return scope;
 }
 
 static bool
 Serialize(JSContext* cx, unsigned argc, Value* vp)
 {
@@ -2947,23 +2947,23 @@ Serialize(JSContext* cx, unsigned argc, 
         RootedValue v(cx);
         if (!JS_GetProperty(cx, opts, "SharedArrayBuffer", &v))
             return false;
 
         if (!v.isUndefined()) {
             JSString* str = JS::ToString(cx, v);
             if (!str)
                 return false;
-            UniqueChars poli = JS_EncodeString(cx, str);
+            JSLinearString* poli = str->ensureLinear(cx);
             if (!poli)
                 return false;
 
-            if (strcmp(poli.get(), "allow") == 0) {
+            if (StringEqualsAscii(poli, "allow")) {
                 // default
-            } else if (strcmp(poli.get(), "deny") == 0) {
+            } else if (StringEqualsAscii(poli, "deny")) {
                 policy.denySharedArrayBuffer();
             } else {
                 JS_ReportErrorASCII(cx, "Invalid policy value for 'SharedArrayBuffer'");
                 return false;
             }
         }
 
         if (!JS_GetProperty(cx, opts, "scope", &v))
@@ -4117,41 +4117,41 @@ SetGCCallback(JSContext* cx, unsigned ar
 
     RootedValue v(cx);
     if (!JS_GetProperty(cx, opts, "action", &v))
         return false;
 
     JSString* str = JS::ToString(cx, v);
     if (!str)
         return false;
-    UniqueChars action = JS_EncodeString(cx, str);
+    RootedLinearString action(cx, str->ensureLinear(cx));
     if (!action)
         return false;
 
     int32_t phases = 0;
-    if ((strcmp(action.get(), "minorGC") == 0) || (strcmp(action.get(), "majorGC") == 0)) {
+    if (StringEqualsAscii(action, "minorGC") || StringEqualsAscii(action, "majorGC")) {
         if (!JS_GetProperty(cx, opts, "phases", &v))
             return false;
         if (v.isUndefined()) {
             phases = (1 << JSGC_END);
         } else {
             JSString* str = JS::ToString(cx, v);
             if (!str)
                 return false;
-            UniqueChars phasesStr = JS_EncodeString(cx, str);
+            JSLinearString* phasesStr = str->ensureLinear(cx);
             if (!phasesStr)
                 return false;
 
-            if (strcmp(phasesStr.get(), "begin") == 0)
+            if (StringEqualsAscii(phasesStr, "begin")) {
                 phases = (1 << JSGC_BEGIN);
-            else if (strcmp(phasesStr.get(), "end") == 0)
+            } else if (StringEqualsAscii(phasesStr, "end")) {
                 phases = (1 << JSGC_END);
-            else if (strcmp(phasesStr.get(), "both") == 0)
+            } else if (StringEqualsAscii(phasesStr, "both")) {
                 phases = (1 << JSGC_BEGIN) | (1 << JSGC_END);
-            else {
+            } else {
                 JS_ReportErrorASCII(cx, "Invalid callback phase");
                 return false;
             }
         }
     }
 
     if (gcCallback::prevMajorGC) {
         JS_SetGCCallback(cx, nullptr, nullptr);
@@ -4160,27 +4160,27 @@ SetGCCallback(JSContext* cx, unsigned ar
     }
 
     if (gcCallback::prevMinorGC) {
         JS_SetGCCallback(cx, nullptr, nullptr);
         js_delete<gcCallback::MinorGC>(gcCallback::prevMinorGC);
         gcCallback::prevMinorGC = nullptr;
     }
 
-    if (strcmp(action.get(), "minorGC") == 0) {
+    if (StringEqualsAscii(action, "minorGC")) {
         auto info = js_new<gcCallback::MinorGC>();
         if (!info) {
             ReportOutOfMemory(cx);
             return false;
         }
 
         info->phases = phases;
         info->active = true;
         JS_SetGCCallback(cx, gcCallback::minorGC, info);
-    } else if (strcmp(action.get(), "majorGC") == 0) {
+    } else if (StringEqualsAscii(action, "majorGC")) {
         if (!JS_GetProperty(cx, opts, "depth", &v))
             return false;
         int32_t depth = 1;
         if (!v.isUndefined()) {
             if (!ToInt32(cx, v, &depth))
                 return false;
         }
         if (depth < 0) {
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1467,43 +1467,46 @@ Options(JSContext* cx, unsigned argc, Va
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     JS::ContextOptions oldContextOptions = JS::ContextOptionsRef(cx);
     for (unsigned i = 0; i < args.length(); i++) {
         RootedString str(cx, JS::ToString(cx, args[i]));
         if (!str)
             return false;
-        args[i].setString(str);
-
-        UniqueChars opt = JS_EncodeStringToUTF8(cx, str);
+
+        RootedLinearString opt(cx, str->ensureLinear(cx));
         if (!opt)
             return false;
 
-        if (strcmp(opt.get(), "strict") == 0) {
+        if (StringEqualsAscii(opt, "strict")) {
             JS::ContextOptionsRef(cx).toggleExtraWarnings();
-        } else if (strcmp(opt.get(), "werror") == 0) {
+        } else if (StringEqualsAscii(opt, "werror")) {
             // Disallow toggling werror when there are off-thread jobs, to avoid
             // confusing CompileError::throwError.
             ShellContext* sc = GetShellContext(cx);
             if (!sc->offThreadJobs.empty()) {
                 JS_ReportErrorASCII(cx, "can't toggle werror when there are off-thread jobs");
                 return false;
             }
             JS::ContextOptionsRef(cx).toggleWerror();
-        } else if (strcmp(opt.get(), "throw_on_asmjs_validation_failure") == 0) {
+        } else if (StringEqualsAscii(opt, "throw_on_asmjs_validation_failure")) {
             JS::ContextOptionsRef(cx).toggleThrowOnAsmJSValidationFailure();
-        } else if (strcmp(opt.get(), "strict_mode") == 0) {
+        } else if (StringEqualsAscii(opt, "strict_mode")) {
             JS::ContextOptionsRef(cx).toggleStrictMode();
         } else {
+            UniqueChars optChars = JS_EncodeStringToUTF8(cx, opt);
+            if (!optChars)
+                return false;
+
             JS_ReportErrorUTF8(cx,
                                "unknown option name '%s'."
                                " The valid names are strict,"
                                " werror, and strict_mode.",
-                               opt.get());
+                               optChars.get());
             return false;
         }
     }
 
     UniqueChars names = DuplicateString("");
     bool found = false;
     if (names && oldContextOptions.extraWarnings()) {
         names = JS_sprintf_append(std::move(names), "%s%s", found ? "," : "", "strict");
@@ -5327,23 +5330,16 @@ class AutoCStringVector
     }
     char* operator[](size_t i) const {
         return argv_[i];
     }
     void replace(size_t i, UniqueChars arg) {
         js_free(argv_[i]);
         argv_[i] = arg.release();
     }
-    const char* back() const {
-        return argv_.back();
-    }
-    void replaceBack(UniqueChars arg) {
-        js_free(argv_.back());
-        argv_.back() = arg.release();
-    }
 };
 
 #if defined(XP_WIN)
 static bool
 EscapeForShell(JSContext* cx, AutoCStringVector& argv)
 {
     // Windows will break arguments in argv by various spaces, so we wrap each
     // argument in quotes and escape quotes within. Even with quotes, \ will be
@@ -5412,36 +5408,42 @@ NestedShell(JSContext* cx, unsigned argc
     // Propagate selected flags from the current shell
     for (unsigned i = 0; i < sPropagatedFlags.length(); i++) {
         UniqueChars flags = DuplicateString(cx, sPropagatedFlags[i]);
         if (!flags || !argv.append(std::move(flags)))
             return false;
     }
 
     // The arguments to nestedShell are stringified and append to argv.
-    RootedString str(cx);
     for (unsigned i = 0; i < args.length(); i++) {
-        str = ToString(cx, args[i]);
+        JSString* str = ToString(cx, args[i]);
         if (!str)
             return false;
 
-        UniqueChars arg = JS_EncodeString(cx, str);
-        if (!arg || !argv.append(std::move(arg)))
-            return false;
-
-        // As a special case, if the caller passes "--js-cache", replace that
-        // with "--js-cache=$(jsCacheDir)"
-        if (!strcmp(argv.back(), "--js-cache") && jsCacheDir) {
-            UniqueChars newArg = JS_smprintf("--js-cache=%s", jsCacheDir);
-            if (!newArg) {
+        JSLinearString* linear = str->ensureLinear(cx);
+        if (!linear)
+            return false;
+
+        UniqueChars arg;
+        if (StringEqualsAscii(linear, "--js-cache") && jsCacheDir) {
+            // As a special case, if the caller passes "--js-cache", use
+            // "--js-cache=$(jsCacheDir)" instead.
+            arg = JS_smprintf("--js-cache=%s", jsCacheDir);
+            if (!arg) {
                 JS_ReportOutOfMemory(cx);
                 return false;
             }
-            argv.replaceBack(std::move(newArg));
-        }
+        } else {
+            arg = JS_EncodeString(cx, str);
+            if (!arg)
+                return false;
+        }
+
+        if (!argv.append(std::move(arg)))
+            return false;
     }
 
     // execv assumes argv is null-terminated
     if (!argv.append(nullptr))
         return false;
 
     int status = 0;
 #if defined(XP_WIN)
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -849,79 +849,83 @@ xpc::GlobalProperties::Parse(JSContext* 
     for (uint32_t i = 0; i < length; i++) {
         RootedValue nameValue(cx);
         ok = JS_GetElement(cx, obj, i, &nameValue);
         NS_ENSURE_TRUE(ok, false);
         if (!nameValue.isString()) {
             JS_ReportErrorASCII(cx, "Property names must be strings");
             return false;
         }
-        RootedString nameStr(cx, nameValue.toString());
-        JS::UniqueChars name = JS_EncodeStringToUTF8(cx, nameStr);
-        if (!name)
+        JSFlatString* nameStr = JS_FlattenString(cx, nameValue.toString());
+        if (!nameStr)
             return false;
-        if (!strcmp(name.get(), "Blob")) {
+        if (JS_FlatStringEqualsAscii(nameStr, "Blob")) {
             Blob = true;
-        } else if (!strcmp(name.get(), "ChromeUtils")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "ChromeUtils")) {
             ChromeUtils = true;
-        } else if (!strcmp(name.get(), "CSS")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "CSS")) {
             CSS = true;
-        } else if (!strcmp(name.get(), "CSSRule")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "CSSRule")) {
             CSSRule = true;
-        } else if (!strcmp(name.get(), "Directory")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "Directory")) {
             Directory = true;
-        } else if (!strcmp(name.get(), "DOMParser")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "DOMParser")) {
             DOMParser = true;
-        } else if (!strcmp(name.get(), "Element")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "Element")) {
             Element = true;
-        } else if (!strcmp(name.get(), "Event")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "Event")) {
             Event = true;
-        } else if (!strcmp(name.get(), "File")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "File")) {
             File = true;
-        } else if (!strcmp(name.get(), "FileReader")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "FileReader")) {
             FileReader = true;
-        } else if (!strcmp(name.get(), "FormData")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "FormData")) {
             FormData = true;
-        } else if (!strcmp(name.get(), "InspectorUtils")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "InspectorUtils")) {
             InspectorUtils = true;
-        } else if (!strcmp(name.get(), "MessageChannel")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "MessageChannel")) {
             MessageChannel = true;
-        } else if (!strcmp(name.get(), "Node")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "Node")) {
             Node = true;
-        } else if (!strcmp(name.get(), "NodeFilter")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "NodeFilter")) {
             NodeFilter = true;
-        } else if (!strcmp(name.get(), "TextDecoder")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "TextDecoder")) {
             TextDecoder = true;
-        } else if (!strcmp(name.get(), "TextEncoder")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "TextEncoder")) {
             TextEncoder = true;
-        } else if (!strcmp(name.get(), "URL")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "URL")) {
             URL = true;
-        } else if (!strcmp(name.get(), "URLSearchParams")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "URLSearchParams")) {
             URLSearchParams = true;
-        } else if (!strcmp(name.get(), "XMLHttpRequest")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "XMLHttpRequest")) {
             XMLHttpRequest = true;
-        } else if (!strcmp(name.get(), "XMLSerializer")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "XMLSerializer")) {
             XMLSerializer = true;
-        } else if (!strcmp(name.get(), "atob")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "atob")) {
             atob = true;
-        } else if (!strcmp(name.get(), "btoa")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "btoa")) {
             btoa = true;
-        } else if (!strcmp(name.get(), "caches")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "caches")) {
             caches = true;
-        } else if (!strcmp(name.get(), "crypto")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "crypto")) {
             crypto = true;
-        } else if (!strcmp(name.get(), "fetch")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "fetch")) {
             fetch = true;
-        } else if (!strcmp(name.get(), "indexedDB")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "indexedDB")) {
             indexedDB = true;
 #ifdef MOZ_WEBRTC
-        } else if (!strcmp(name.get(), "rtcIdentityProvider")) {
+        } else if (JS_FlatStringEqualsAscii(nameStr, "rtcIdentityProvider")) {
             rtcIdentityProvider = true;
 #endif
         } else {
+            RootedString nameStr(cx, nameValue.toString());
+            JS::UniqueChars name = JS_EncodeStringToUTF8(cx, nameStr);
+            if (!name)
+                return false;
+
             JS_ReportErrorUTF8(cx, "Unknown property name: %s", name.get());
             return false;
         }
     }
     return true;
 }
 
 bool