Bug 1223916 - Prohibit direct method calls at the parser level in self-hosted code. (r=till)
authorEric Faust <efaustbmo@gmail.com>
Fri, 13 Nov 2015 18:26:00 -0800
changeset 309807 677cbf860ff298a4147e628f4dcab418d9a6db01
parent 309806 582d73c412f687f2ce682e3cf13b21bf179ac315
child 309808 3c50e66165d5f4160872e13e0f5d99281cb4fef3
push id7649
push usermartin.thomson@gmail.com
push dateThu, 19 Nov 2015 00:06:17 +0000
reviewerstill
bugs1223916
milestone45.0a1
Bug 1223916 - Prohibit direct method calls at the parser level in self-hosted code. (r=till)
js/src/builtin/Array.js
js/src/builtin/Intl.js
js/src/builtin/Iterator.js
js/src/builtin/Module.js
js/src/builtin/Object.js
js/src/builtin/String.js
js/src/builtin/TypedArray.js
js/src/builtin/Utilities.js
js/src/frontend/Parser.cpp
js/src/js.msg
js/src/vm/Xdr.h
--- a/js/src/builtin/Array.js
+++ b/js/src/builtin/Array.js
@@ -769,17 +769,17 @@ function ArrayFrom(items, mapfn=undefine
         // Step 6.f.
         var k = 0;
 
         // Step 6.g.
         // These steps cannot be implemented using a for-of loop.
         // See <https://bugs.ecmascript.org/show_bug.cgi?id=2883>.
         while (true) {
             // Steps 6.g.i-iii.
-            var next = iterator.next();
+            var next = callFunction(iterator.next, iterator);
             if (!IsObject(next))
                 ThrowTypeError(JSMSG_NEXT_RETURNED_PRIMITIVE);
 
             // Step 6.g.iv.
             if (next.done) {
                 A.length = k;
                 return A;
             }
--- a/js/src/builtin/Intl.js
+++ b/js/src/builtin/Intl.js
@@ -438,29 +438,29 @@ function CanonicalizeLanguageTag(locale)
     // "u-ca-chinese-t-zh-latn" -> "t-zh-latn-u-ca-chinese"
     var extensions = new List();
     while (i < subtags.length && subtags[i] !== "x") {
         var extensionStart = i;
         i++;
         while (i < subtags.length && subtags[i].length > 1)
             i++;
         var extension = callFunction(std_Array_join, callFunction(std_Array_slice, subtags, extensionStart, i), "-");
-        extensions.push(extension);
+        callFunction(std_Array_push, extensions, extension);
     }
-    extensions.sort();
+    callFunction(std_Array_sort, extensions);
 
     // Private use sequences are left as is. "x-private"
     var privateUse = "";
     if (i < subtags.length)
         privateUse = callFunction(std_Array_join, callFunction(std_Array_slice, subtags, i), "-");
 
     // Put everything back together.
     var canonical = normal;
     if (extensions.length > 0)
-        canonical += "-" + extensions.join("-");
+        canonical += "-" + callFunction(std_Array_join, extensions, "-");
     if (privateUse.length > 0) {
         // Be careful of a Language-Tag that is entirely privateuse.
         if (canonical.length > 0)
             canonical += "-" + privateUse;
         else
             canonical = privateUse;
     }
 
@@ -573,21 +573,24 @@ function DefaultLocale() {
     if (runtimeDefaultLocale === localeCache.runtimeDefaultLocale)
         return localeCache.defaultLocale;
 
     // If we didn't have a cache hit, compute the candidate default locale.
     // Then use it as the actual default locale if ICU supports that locale
     // (perhaps via fallback).  Otherwise use the last-ditch locale.
     var candidate = DefaultLocaleIgnoringAvailableLocales();
     var locale;
-    if (BestAvailableLocaleIgnoringDefault(collatorInternalProperties.availableLocales(),
+    if (BestAvailableLocaleIgnoringDefault(callFunction(collatorInternalProperties.availableLocales,
+                                                        collatorInternalProperties),
                                            candidate) &&
-        BestAvailableLocaleIgnoringDefault(numberFormatInternalProperties.availableLocales(),
+        BestAvailableLocaleIgnoringDefault(callFunction(numberFormatInternalProperties.availableLocales,
+                                                        numberFormatInternalProperties),
                                            candidate) &&
-        BestAvailableLocaleIgnoringDefault(dateTimeFormatInternalProperties.availableLocales(),
+        BestAvailableLocaleIgnoringDefault(callFunction(dateTimeFormatInternalProperties.availableLocales,
+                                                        dateTimeFormatInternalProperties),
                                            candidate))
     {
         locale = candidate;
     } else {
         locale = lastDitchLocale();
     }
 
     assert(IsStructurallyValidLanguageTag(locale),
@@ -670,18 +673,18 @@ function CanonicalizeLocaleList(locales)
         if (kPresent) {
             var kValue = O[k];
             if (!(typeof kValue === "string" || IsObject(kValue)))
                 ThrowTypeError(JSMSG_INVALID_LOCALES_ELEMENT);
             var tag = ToString(kValue);
             if (!IsStructurallyValidLanguageTag(tag))
                 ThrowRangeError(JSMSG_INVALID_LANGUAGE_TAG, tag);
             tag = CanonicalizeLanguageTag(tag);
-            if (seen.indexOf(tag) === -1)
-                seen.push(tag);
+            if (callFunction(std_Array_indexOf, seen, tag) === -1)
+                callFunction(std_Array_push, seen, tag);
         }
         k++;
     }
     return seen;
 }
 
 
 function BestAvailableLocaleHelper(availableLocales, locale, considerDefaultLocale) {
@@ -963,24 +966,24 @@ function LookupSupportedLocales(availabl
     while (k < len) {
         // Steps 4.a-b.
         var locale = requestedLocales[k];
         var noExtensionsLocale = removeUnicodeExtensions(locale);
 
         // Step 4.c-d.
         var availableLocale = BestAvailableLocale(availableLocales, noExtensionsLocale);
         if (availableLocale !== undefined)
-            subset.push(locale);
+            callFunction(std_Array_push, subset, locale);
 
         // Step 4.e.
         k++;
     }
 
     // Steps 5-6.
-    return subset.slice(0);
+    return callFunction(std_Array_slice, subset, 0);
 }
 
 
 /**
  * Returns the subset of requestedLocales for which availableLocales has a
  * matching (possibly fallback) locale. Locales appear in the same order in the
  * returned list as in the input list.
  *
@@ -1312,17 +1315,17 @@ function resolveCollatorInternals(lazyCo
                      ? Collator.sortLocaleData
                      : Collator.searchLocaleData;
 
     // Compute effective locale.
     // Step 14.
     var relevantExtensionKeys = Collator.relevantExtensionKeys;
 
     // Step 15.
-    var r = ResolveLocale(Collator.availableLocales(),
+    var r = ResolveLocale(callFunction(Collator.availableLocales, Collator),
                           lazyCollatorData.requestedLocales,
                           lazyCollatorData.opt,
                           relevantExtensionKeys,
                           localeData);
 
     // Step 16.
     internalProps.locale = r.locale;
 
@@ -1502,17 +1505,18 @@ function InitializeCollator(collator, lo
  * matching (possibly fallback) locale. Locales appear in the same order in the
  * returned list as in the input list.
  *
  * Spec: ECMAScript Internationalization API Specification, 10.2.2.
  */
 function Intl_Collator_supportedLocalesOf(locales /*, options*/) {
     var options = arguments.length > 1 ? arguments[1] : undefined;
 
-    var availableLocales = collatorInternalProperties.availableLocales();
+    var availableLocales = callFunction(collatorInternalProperties.availableLocales,
+                                        collatorInternalProperties);
     var requestedLocales = CanonicalizeLocaleList(locales);
     return SupportedLocales(availableLocales, requestedLocales, options);
 }
 
 
 /**
  * Collator internal properties.
  *
@@ -1670,17 +1674,17 @@ function resolveNumberFormatInternals(la
     // Compute effective locale.
     // Step 9.
     var NumberFormat = numberFormatInternalProperties;
 
     // Step 10.
     var localeData = NumberFormat.localeData;
 
     // Step 11.
-    var r = ResolveLocale(NumberFormat.availableLocales(),
+    var r = ResolveLocale(callFunction(NumberFormat.availableLocales, NumberFormat),
                           lazyNumberFormatData.requestedLocales,
                           lazyNumberFormatData.opt,
                           NumberFormat.relevantExtensionKeys,
                           localeData);
 
     // Steps 12-13.  (Step 14 is not relevant to our implementation.)
     internalProps.locale = r.locale;
     internalProps.numberingSystem = r.nu;
@@ -1954,17 +1958,18 @@ function CurrencyDigits(currency) {
  * matching (possibly fallback) locale. Locales appear in the same order in the
  * returned list as in the input list.
  *
  * Spec: ECMAScript Internationalization API Specification, 11.2.2.
  */
 function Intl_NumberFormat_supportedLocalesOf(locales /*, options*/) {
     var options = arguments.length > 1 ? arguments[1] : undefined;
 
-    var availableLocales = numberFormatInternalProperties.availableLocales();
+    var availableLocales = callFunction(numberFormatInternalProperties.availableLocales,
+                                        numberFormatInternalProperties);
     var requestedLocales = CanonicalizeLocaleList(locales);
     return SupportedLocales(availableLocales, requestedLocales, options);
 }
 
 
 function getNumberingSystems(locale) {
     // ICU doesn't have an API to determine the set of numbering systems
     // supported for a locale; it generally pretends that any numbering system
@@ -2113,17 +2118,17 @@ function resolveDateTimeFormatInternals(
     // Compute effective locale.
     // Step 8.
     var DateTimeFormat = dateTimeFormatInternalProperties;
 
     // Step 9.
     var localeData = DateTimeFormat.localeData;
 
     // Step 10.
-    var r = ResolveLocale(DateTimeFormat.availableLocales(),
+    var r = ResolveLocale(callFunction(DateTimeFormat.availableLocales, DateTimeFormat),
                           lazyDateTimeFormatData.requestedLocales,
                           lazyDateTimeFormatData.localeOpt,
                           DateTimeFormat.relevantExtensionKeys,
                           localeData);
 
     // Steps 11-13.
     internalProps.locale = r.locale;
     internalProps.calendar = r.ca;
@@ -2654,17 +2659,18 @@ function BestFitFormatMatcher(options, f
  * matching (possibly fallback) locale. Locales appear in the same order in the
  * returned list as in the input list.
  *
  * Spec: ECMAScript Internationalization API Specification, 12.2.2.
  */
 function Intl_DateTimeFormat_supportedLocalesOf(locales /*, options*/) {
     var options = arguments.length > 1 ? arguments[1] : undefined;
 
-    var availableLocales = dateTimeFormatInternalProperties.availableLocales();
+    var availableLocales = callFunction(dateTimeFormatInternalProperties.availableLocales,
+                                        dateTimeFormatInternalProperties);
     var requestedLocales = CanonicalizeLocaleList(locales);
     return SupportedLocales(availableLocales, requestedLocales, options);
 }
 
 
 /**
  * DateTimeFormat internal properties.
  *
--- a/js/src/builtin/Iterator.js
+++ b/js/src/builtin/Iterator.js
@@ -6,28 +6,28 @@ function IteratorIdentity() {
     return this;
 }
 
 var LegacyIteratorWrapperMap = new std_WeakMap();
 
 function LegacyIteratorNext(arg) {
     var iter = callFunction(std_WeakMap_get, LegacyIteratorWrapperMap, this);
     try {
-        return { value: iter.next(arg), done: false };
+        return { value: callFunction(iter.next, iter, arg), done: false };
     } catch (e) {
         if (e instanceof std_StopIteration)
             return { value: undefined, done: true };
         throw e;
     }
 }
 
 function LegacyIteratorThrow(exn) {
     var iter = callFunction(std_WeakMap_get, LegacyIteratorWrapperMap, this);
     try {
-        return { value: iter.throw(exn), done: false };
+        return { value: callFunction(iter.throw, iter, exn), done: false };
     } catch (e) {
         if (e instanceof std_StopIteration)
             return { value: undefined, done: true };
         throw e;
     }
 }
 
 function LegacyIterator(iter) {
--- a/js/src/builtin/Module.js
+++ b/js/src/builtin/Module.js
@@ -38,17 +38,18 @@ function ModuleGetExportedNames(exportSt
         _DefineDataProperty(exportedNames, namesCount++, e.exportName);
     }
 
     // Step 7
     let starExportEntries = module.starExportEntries;
     for (let i = 0; i < starExportEntries.length; i++) {
         let e = starExportEntries[i];
         let requestedModule = HostResolveImportedModule(module, e.moduleRequest);
-        let starNames = requestedModule.getExportedNames(exportStarSet);
+        let starNames = callFunction(requestedModule.getExportedNames, requestedModule,
+                                     exportStarSet);
         for (let j = 0; j < starNames.length; j++) {
             let n = starNames[j];
             if (n !== "default" && !(n in exportedNames))
                 _DefineDataProperty(exportedNames, namesCount++, n);
         }
     }
 
     return exportedNames;
@@ -84,19 +85,18 @@ function ModuleResolveExport(exportName,
     }
 
     // Step 5
     let indirectExportEntries = module.indirectExportEntries;
     for (let i = 0; i < indirectExportEntries.length; i++) {
         let e = indirectExportEntries[i];
         if (exportName === e.exportName) {
             let importedModule = HostResolveImportedModule(module, e.moduleRequest);
-            let indirectResolution = importedModule.resolveExport(e.importName,
-                                                                  resolveSet,
-                                                                  exportStarSet);
+            let indirectResolution = callFunction(importedModule.resolveExport, importedModule,
+                                                  e.importName, resolveSet, exportStarSet);
             if (indirectResolution !== null)
                 return indirectResolution;
         }
     }
 
     // Step 6
     if (exportName === "default") {
         // A default export cannot be provided by an export *.
@@ -113,17 +113,18 @@ function ModuleResolveExport(exportName,
     // Step 9
     let starResolution = null;
 
     // Step 10
     let starExportEntries = module.starExportEntries;
     for (let i = 0; i < starExportEntries.length; i++) {
         let e = starExportEntries[i];
         let importedModule = HostResolveImportedModule(module, e.moduleRequest);
-        let resolution = importedModule.resolveExport(exportName, resolveSet, exportStarSet);
+        let resolution = callFunction(importedModule.resolveExport, importedModule,
+                                      exportName, resolveSet, exportStarSet);
         if (resolution === "ambiguous")
             return resolution;
 
         if (resolution !== null) {
             if (starResolution === null) {
                 starResolution = resolution;
             } else {
                 if (resolution.module !== starResolution.module ||
@@ -141,45 +142,45 @@ function ModuleResolveExport(exportName,
 // 15.2.1.18 GetModuleNamespace(module)
 function GetModuleNamespace(module)
 {
     // Step 2
     let namespace = module.namespace;
 
     // Step 3
     if (typeof namespace === "undefined") {
-        let exportedNames = module.getExportedNames();
+        let exportedNames = callFunction(module.getExportedNames, module);
         let unambiguousNames = [];
         for (let i = 0; i < exportedNames.length; i++) {
             let name = exportedNames[i];
-            let resolution = module.resolveExport(name);
+            let resolution = callFunction(module.resolveExport, module, name);
             if (resolution === null)
                 ThrowSyntaxError(JSMSG_MISSING_NAMESPACE_EXPORT);
             if (resolution !== "ambiguous")
                 _DefineDataProperty(unambiguousNames, unambiguousNames.length, name);
         }
         namespace = ModuleNamespaceCreate(module, unambiguousNames);
     }
 
     // Step 4
     return namespace;
 }
 
 // 9.4.6.13 ModuleNamespaceCreate(module, exports)
 function ModuleNamespaceCreate(module, exports)
 {
-    exports.sort();
+    callFunction(std_Array_sort, exports);
 
     let ns = NewModuleNamespace(module, exports);
 
     // Pre-compute all bindings now rather than calling ResolveExport() on every
     // access.
     for (let i = 0; i < exports.length; i++) {
         let name = exports[i];
-        let binding = module.resolveExport(name);
+        let binding = callFunction(module.resolveExport, module, name);
         assert(binding !== null && binding !== "ambiguous", "Failed to resolve binding");
         AddModuleNamespaceBinding(ns, name, binding.module, binding.bindingName);
     }
 
     return ns;
 }
 
 // 15.2.1.16.4 ModuleDeclarationInstantiation()
@@ -199,40 +200,41 @@ function ModuleDeclarationInstantiation(
     CreateModuleEnvironment(module);
     let env = GetModuleEnvironment(module);
 
     // Step 8
     let requestedModules = module.requestedModules;
     for (let i = 0; i < requestedModules.length; i++) {
         let required = requestedModules[i];
         let requiredModule = HostResolveImportedModule(module, required);
-        requiredModule.declarationInstantiation();
+        callFunction(requiredModule.declarationInstantiation, requiredModule);
     }
 
     // Step 9
     let indirectExportEntries = module.indirectExportEntries;
     for (let i = 0; i < indirectExportEntries.length; i++) {
         let e = indirectExportEntries[i];
-        let resolution = module.resolveExport(e.exportName);
+        let resolution = callFunction(module.resolveExport, module, e.exportName);
         if (resolution === null)
             ThrowSyntaxError(JSMSG_MISSING_INDIRECT_EXPORT);
         if (resolution === "ambiguous")
             ThrowSyntaxError(JSMSG_AMBIGUOUS_INDIRECT_EXPORT);
     }
 
     // Step 12
     let importEntries = module.importEntries;
     for (let i = 0; i < importEntries.length; i++) {
         let imp = importEntries[i];
         let importedModule = HostResolveImportedModule(module, imp.moduleRequest);
         if (imp.importName === "*") {
             let namespace = GetModuleNamespace(importedModule);
             CreateNamespaceBinding(env, imp.localName, namespace);
         } else {
-            let resolution = importedModule.resolveExport(imp.importName);
+            let resolution = callFunction(importedModule.resolveExport, importedModule,
+                                          imp.importName);
             if (resolution === null)
                 ThrowSyntaxError(JSMSG_MISSING_IMPORT);
             if (resolution === "ambiguous")
                 ThrowSyntaxError(JSMSG_AMBIGUOUS_IMPORT);
             CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
         }
     }
 
@@ -256,17 +258,17 @@ function ModuleEvaluation()
     // Step 5
     SetModuleEvaluated(this);
 
     // Step 6
     let requestedModules = module.requestedModules;
     for (let i = 0; i < requestedModules.length; i++) {
         let required = requestedModules[i];
         let requiredModule = HostResolveImportedModule(module, required);
-        requiredModule.evaluation();
+        callFunction(requiredModule.evaluation, requiredModule);
     }
 
     return EvaluateModule(module);
 }
 
 function ModuleNamespaceEnumerate()
 {
     if (!IsObject(this) || !IsModuleNamespace(this))
--- a/js/src/builtin/Object.js
+++ b/js/src/builtin/Object.js
@@ -52,17 +52,17 @@ function ObjectIsExtensible(obj) {
 }
 
 /* ES2015 19.1.3.5 Object.prototype.toLocaleString */
 function Object_toLocaleString() {
     // Step 1.
     var O = this;
 
     // Step 2.
-    return O.toString();
+    return callFunction(O.toString, O);
 }
 
 function ObjectDefineSetter(name, setter) {
     var object;
     if (this === null || this === undefined)
         object = global;
     else
         object = ToObject(this);
--- a/js/src/builtin/String.js
+++ b/js/src/builtin/String.js
@@ -291,22 +291,22 @@ function String_static_fromCodePoint(cod
 
         // Step 5e.
         if (nextCP < 0 || nextCP > 0x10FFFF)
             ThrowRangeError(JSMSG_NOT_A_CODEPOINT, ToString(nextCP));
 
         // Step 5f.
         // Inlined UTF-16 Encoding
         if (nextCP <= 0xFFFF) {
-            elements.push(nextCP);
+            callFunction(std_Array_push, elements, nextCP);
             continue;
         }
 
-        elements.push((((nextCP - 0x10000) / 0x400) | 0) + 0xD800);
-        elements.push((nextCP - 0x10000) % 0x400 + 0xDC00);
+        callFunction(std_Array_push, elements, (((nextCP - 0x10000) / 0x400) | 0) + 0xD800);
+        callFunction(std_Array_push, elements, (nextCP - 0x10000) % 0x400 + 0xDC00);
     }
 
     // Step 6.
     return callFunction(std_Function_apply, std_String_fromCharCode, null, elements);
 }
 
 /* ES6 Draft May 22, 2014 21.1.2.4 */
 function String_static_raw(callSite, ...substitutions) {
--- a/js/src/builtin/TypedArray.js
+++ b/js/src/builtin/TypedArray.js
@@ -211,17 +211,17 @@ function TypedArrayFilter(callbackfn, th
     for (var k = 0; k < len; k++) {
         // Steps 13.b-c.
         var kValue = O[k];
         // Steps 13.d-e.
         var selected = ToBoolean(callFunction(callbackfn, T, kValue, k, O));
         // Step 13.f.
         if (selected) {
             // Step 13.f.i.
-            kept.push(kValue);
+            callFunction(std_Array_push, kept, kValue);
             // Step 13.f.ii.
             captured++;
         }
     }
 
     // Steps 14-15.
     var A = new C(captured);
 
@@ -1053,24 +1053,24 @@ function TypedArrayFrom(constructor, tar
         var iterator = GetIterator(items, usingIterator);
 
         // Step 10.c.
         var values = new List();
 
         // Steps 10.d-e.
         while (true) {
             // Steps 10.e.i-ii.
-            var next = iterator.next();
+            var next = callFunction(iterator.next, iterator);
             if (!IsObject(next))
                 ThrowTypeError(JSMSG_NEXT_RETURNED_PRIMITIVE);
 
             // Steps 10.e.iii-vi.
             if (next.done)
                 break;
-            values.push(next.value);
+            callFunction(std_Array_push, values, next.value);
         }
 
         // Step 10.f.
         var len = values.length;
 
         // Steps 10.g-h.
         // There is no need to implement the 22.2.2.1.2 - TypedArrayAllocOrInit() method,
         // since `%TypedArray%(object)` currently doesn't call this self-hosted TypedArrayFrom().
--- a/js/src/builtin/Utilities.js
+++ b/js/src/builtin/Utilities.js
@@ -48,26 +48,17 @@ var std_Map_iterator_next = MapIteratorN
 
 
 /********** List specification type **********/
 
 /* Spec: ECMAScript Language Specification, 5.1 edition, 8.8 */
 function List() {
     this.length = 0;
 }
-
-{
-  let ListProto = std_Object_create(null);
-  ListProto.indexOf = std_Array_indexOf;
-  ListProto.join = std_Array_join;
-  ListProto.push = std_Array_push;
-  ListProto.slice = std_Array_slice;
-  ListProto.sort = std_Array_sort;
-  MakeConstructible(List, ListProto);
-}
+MakeConstructible(List, {__proto__: null});
 
 
 /********** Record specification type **********/
 
 
 /* Spec: ECMAScript Internationalization API Specification, draft, 5 */
 function Record() {
     return std_Object_create(null);
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -8636,16 +8636,21 @@ Parser<ParseHandler>::memberExpr(YieldHa
                     return null();
 
                 if (isSpread)
                     handler.setOp(nextMember, JSOP_SPREADSUPERCALL);
 
                 return nextMember;
             }
 
+            if (options().selfHostingMode && handler.isPropertyAccess(lhs)) {
+                report(ParseError, false, null(), JSMSG_SELFHOSTED_METHOD_CALL);
+                return null();
+            }
+
             nextMember = tt == TOK_LP ? handler.newCall() : handler.newTaggedTemplate();
             if (!nextMember)
                 return null();
 
             JSOp op = JSOP_CALL;
             if (PropertyName* name = handler.maybeNameAnyParentheses(lhs)) {
                 if (tt == TOK_LP && name == context->names().eval) {
                     /* Select JSOP_EVAL and flag pc as needsCallObject. */
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -308,16 +308,17 @@ MSG_DEF(JSMSG_PAREN_IN_PAREN,          0
 MSG_DEF(JSMSG_RC_AFTER_EXPORT_SPEC_LIST, 0, JSEXN_SYNTAXERR, "missing '}' after export specifier list")
 MSG_DEF(JSMSG_RC_AFTER_IMPORT_SPEC_LIST, 0, JSEXN_SYNTAXERR, "missing '}' after module specifier list")
 MSG_DEF(JSMSG_REDECLARED_CATCH_IDENTIFIER, 1, JSEXN_TYPEERR, "redeclaration of identifier '{0}' in catch")
 MSG_DEF(JSMSG_REDECLARED_PARAM,        1, JSEXN_TYPEERR, "redeclaration of formal parameter {0}")
 MSG_DEF(JSMSG_RESERVED_ID,             1, JSEXN_SYNTAXERR, "{0} is a reserved identifier")
 MSG_DEF(JSMSG_REST_WITH_DEFAULT,       0, JSEXN_SYNTAXERR, "rest parameter may not have a default")
 MSG_DEF(JSMSG_SELFHOSTED_TOP_LEVEL_LEXICAL, 1, JSEXN_SYNTAXERR, "self-hosted code cannot contain top-level {0} declarations")
 MSG_DEF(JSMSG_SELFHOSTED_UNBOUND_NAME, 0, JSEXN_TYPEERR, "self-hosted code may not contain unbound name lookups")
+MSG_DEF(JSMSG_SELFHOSTED_METHOD_CALL,  0, JSEXN_SYNTAXERR, "self-hosted code may not contain direct method calls")
 MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND,     0, JSEXN_SYNTAXERR, "missing ; after for-loop condition")
 MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT,     0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer")
 MSG_DEF(JSMSG_SEMI_BEFORE_STMNT,       0, JSEXN_SYNTAXERR, "missing ; before statement")
 MSG_DEF(JSMSG_SOURCE_TOO_LONG,         0, JSEXN_RANGEERR, "source is too long")
 MSG_DEF(JSMSG_STMT_AFTER_RETURN,       0, JSEXN_NONE, "unreachable code after return statement")
 MSG_DEF(JSMSG_STRICT_CODE_WITH,        0, JSEXN_SYNTAXERR, "strict mode code may not contain 'with' statements")
 MSG_DEF(JSMSG_STRICT_FUNCTION_STATEMENT, 0, JSEXN_SYNTAXERR, "in strict mode code, functions may be declared only at top level or immediately within another function")
 MSG_DEF(JSMSG_TEMPLSTR_UNTERM_EXPR,    0, JSEXN_SYNTAXERR, "missing } in template string")
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -24,21 +24,21 @@ namespace js {
  * versions.  If deserialization fails, the data should be invalidated if
  * possible.
  *
  * When you change this, run make_opcode_doc.py and copy the new output into
  * this wiki page:
  *
  *  https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
  */
-static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 320;
+static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 321;
 static const uint32_t XDR_BYTECODE_VERSION =
     uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
 
-static_assert(JSErr_Limit == 419,
+static_assert(JSErr_Limit == 420,
               "GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
               "removed MSG_DEFs from js.msg, you should increment "
               "XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "
               "expected JSErr_Limit value.");
 
 class XDRBuffer {
   public:
     explicit XDRBuffer(JSContext* cx)