From 5a9a0b20e74b1ffc88141fe3e86a1df6d6773685 Mon Sep 17 00:00:00 2001 From: yangguo Date: Fri, 17 Apr 2015 06:27:41 -0700 Subject: [PATCH] Migrate error messages, part 3 (runtime.js). Motivation for this is reducing the size of the native context. R=mvstanton@chromium.org Review URL: https://codereview.chromium.org/1089303003 Cr-Commit-Position: refs/heads/master@{#27917} --- src/messages.h | 18 ++++++++++ src/messages.js | 16 +-------- src/runtime.js | 49 +++++++++++--------------- src/runtime/runtime-object.cc | 11 +++--- src/symbol.js | 4 +-- test/mjsunit/messages.js | 81 ++++++++++++++++++++++++++++++++++++++++++- tools/js2c.py | 2 +- 7 files changed, 127 insertions(+), 54 deletions(-) diff --git a/src/messages.h b/src/messages.h index fb3e50c..9a31a2d 100644 --- a/src/messages.h +++ b/src/messages.h @@ -92,11 +92,29 @@ class MessageHandler { /* Error */ \ T(CyclicProto, "Cyclic __proto__ value") \ /* TypeError */ \ + T(ApplyNonFunction, \ + "Function.prototype.apply was called on %, which is a % and not a " \ + "function") \ T(CalledNonCallable, "% is not a function") \ + T(CannotConvertToPrimitive, "Cannot convert object to primitive value") \ T(GeneratorRunning, "Generator is already running") \ T(IncompatibleMethodReceiver, "Method % called on incompatible receiver %") \ + T(InstanceofFunctionExpected, \ + "Expecting a function in instanceof check, but got %") \ + T(InstanceofNonobjectProto, \ + "Function has non-object prototype '%' in instanceof check") \ + T(InvalidInOperatorUse, "Cannot use 'in' operator to search for '%' in %") \ + T(NotConstructor, "% is not a constructor") \ T(PropertyNotFunction, "Property '%' of object % is not a function") \ + T(SymbolToPrimitive, \ + "Cannot convert a Symbol wrapper object to a primitive value") \ + T(SymbolToNumber, "Cannot convert a Symbol value to a number") \ + T(SymbolToString, "Cannot convert a Symbol value to a string") \ + T(UndefinedOrNullToObject, "Cannot convert undefined or null to object") \ T(WithExpression, "% has no properties") \ + T(WrongArgs, "%: Arguments list has wrong type") \ + /* RangeError */ \ + T(StackOverflow, "Maximum call stack size exceeded") \ /* EvalError */ \ T(CodeGenFromStrings, "%") diff --git a/src/messages.js b/src/messages.js index 7f576bc..5d8ff65 100644 --- a/src/messages.js +++ b/src/messages.js @@ -33,8 +33,6 @@ var kMessages = { unknown_label: ["Undefined label '", "%0", "'"], uncaught_exception: ["Uncaught ", "%0"], undefined_method: ["Object ", "%1", " has no method '", "%0", "'"], - cannot_convert_to_primitive: ["Cannot convert object to primitive value"], - not_constructor: ["%0", " is not a constructor"], not_defined: ["%0", " is not defined"], non_method: ["'super' is referenced from non-method"], unsupported_super: ["Unsupported reference to 'super'"], @@ -42,15 +40,7 @@ var kMessages = { non_object_property_store: ["Cannot set property '", "%0", "' of ", "%1"], illegal_invocation: ["Illegal invocation"], no_setter_in_callback: ["Cannot set property ", "%0", " of ", "%1", " which has only a getter"], - apply_non_function: ["Function.prototype.apply was called on ", "%0", ", which is a ", "%1", " and not a function"], - apply_wrong_args: ["Function.prototype.apply: Arguments list has wrong type"], - reflect_apply_wrong_args: ["Reflect.apply: Arguments list has wrong type"], - reflect_construct_wrong_args: ["Reflect.construct: Arguments list has wrong type"], flags_getter_non_object: ["RegExp.prototype.flags getter called on non-object ", "%0"], - invalid_in_operator_use: ["Cannot use 'in' operator to search for '", "%0", "' in ", "%1"], - instanceof_function_expected: ["Expecting a function in instanceof check, but got ", "%0"], - instanceof_nonobject_proto: ["Function has non-object prototype '", "%0", "' in instanceof check"], - undefined_or_null_to_object: ["Cannot convert undefined or null to object"], reduce_no_initial: ["Reduce of empty array with no initial value"], getter_must_be_callable: ["Getter must be a function: ", "%0"], setter_must_be_callable: ["Setter must be a function: ", "%0"], @@ -113,7 +103,6 @@ var kMessages = { invalid_data_view_accessor_offset: ["Offset is outside the bounds of the DataView"], - stack_overflow: ["Maximum call stack size exceeded"], invalid_time_value: ["Invalid time value"], invalid_count_value: ["Invalid count value"], invalid_code_point: ["Invalid code point ", "%0"], @@ -179,9 +168,6 @@ var kMessages = { cant_prevent_ext_external_array_elements: ["Cannot prevent extension of an object with external array elements"], redef_external_array_element: ["Cannot redefine a property of an object with external array elements"], const_assign: ["Assignment to constant variable."], - symbol_to_string: ["Cannot convert a Symbol value to a string"], - symbol_to_primitive: ["Cannot convert a Symbol wrapper object to a primitive value"], - symbol_to_number: ["Cannot convert a Symbol value to a number"], module_export_undefined: ["Export '", "%0", "' is not defined in module"], duplicate_export: ["Duplicate export of '", "%0", "'"], unexpected_super: ["'super' keyword unexpected here"], @@ -1287,7 +1273,7 @@ InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]); // Boilerplate for exceptions for stack overflows. Used from // Isolate::StackOverflow(). function SetUpStackOverflowBoilerplate() { - var boilerplate = MakeRangeError('stack_overflow', []); + var boilerplate = MakeRangeError(kStackOverflow); %DefineAccessorPropertyUnchecked( boilerplate, 'stack', StackTraceGetter, StackTraceSetter, DONT_ENUM); diff --git a/src/runtime.js b/src/runtime.js index b20639c..aaaa4fe 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -320,7 +320,7 @@ function DELETE(key, language_mode) { // ECMA-262, section 11.8.7, page 54. function IN(x) { if (!IS_SPEC_OBJECT(x)) { - throw %MakeTypeError('invalid_in_operator_use', [this, x]); + throw %MakeTypeError(kInvalidInOperatorUse, this, x); } if (%_IsNonNegativeSmi(this)) { if (IS_ARRAY(x) && %_HasFastPackedElements(x)) { @@ -339,7 +339,7 @@ function IN(x) { function INSTANCE_OF(F) { var V = this; if (!IS_SPEC_FUNCTION(F)) { - throw %MakeTypeError('instanceof_function_expected', [F]); + throw %MakeTypeError(kInstanceofFunctionExpected, F); } // If V is not an object, return false. @@ -356,7 +356,7 @@ function INSTANCE_OF(F) { // Get the prototype of F; if it is not an object, throw an error. var O = F.prototype; if (!IS_SPEC_OBJECT(O)) { - throw %MakeTypeError('instanceof_nonobject_proto', [O]); + throw %MakeTypeError(kInstanceofNonobjectProto, O); } // Return whether or not O is in the prototype chain of V. @@ -429,18 +429,15 @@ function APPLY_PREPARE(args) { // We can handle any number of apply arguments if the stack is // big enough, but sanity check the value to avoid overflow when // multiplying with pointer size. - if (length > kSafeArgumentsLength) { - throw %MakeRangeError('stack_overflow', []); - } + if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow); if (!IS_SPEC_FUNCTION(this)) { - throw %MakeTypeError('apply_non_function', - [ %ToString(this), typeof this ]); + throw %MakeTypeError(kApplyNonFunction, %ToString(this), typeof this); } // Make sure the arguments list has the right type. if (args != null && !IS_SPEC_OBJECT(args)) { - throw %MakeTypeError('apply_wrong_args', []); + throw %MakeTypeError(kWrongArgs, "Function.prototype.apply"); } // Return the length which is the number of arguments to copy to the @@ -467,7 +464,7 @@ function REFLECT_APPLY_PREPARE(args) { } if (!IS_SPEC_OBJECT(args)) { - throw %MakeTypeError('reflect_apply_wrong_args', [ ]); + throw %MakeTypeError(kWrongArgs, "Reflect.apply"); } length = %ToLength(args.length); @@ -475,9 +472,7 @@ function REFLECT_APPLY_PREPARE(args) { // We can handle any number of apply arguments if the stack is // big enough, but sanity check the value to avoid overflow when // multiplying with pointer size. - if (length > kSafeArgumentsLength) { - throw %MakeRangeError('stack_overflow', []); - } + if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow); // Return the length which is the number of arguments to copy to the // stack. It is guaranteed to be a small integer at this point. @@ -505,7 +500,7 @@ function REFLECT_CONSTRUCT_PREPARE(args, newTarget) { if (!IS_SPEC_FUNCTION(this)) { throw %MakeTypeError(kCalledNonCallable, %ToString(this)); } else { - throw %MakeTypeError('not_constructor', [ %ToString(this) ]); + throw %MakeTypeError(kNotConstructor, %ToString(this)); } } @@ -513,12 +508,12 @@ function REFLECT_CONSTRUCT_PREPARE(args, newTarget) { if (!IS_SPEC_FUNCTION(newTarget)) { throw %MakeTypeError(kCalledNonCallable, %ToString(newTarget)); } else { - throw %MakeTypeError('not_constructor', [ %ToString(newTarget) ]); + throw %MakeTypeError(kNotConstructor, %ToString(newTarget)); } } if (!IS_SPEC_OBJECT(args)) { - throw %MakeTypeError('reflect_construct_wrong_args', [ ]); + throw %MakeTypeError(kWrongArgs, "Reflect.construct"); } length = %ToLength(args.length); @@ -526,9 +521,7 @@ function REFLECT_CONSTRUCT_PREPARE(args, newTarget) { // We can handle any number of apply arguments if the stack is // big enough, but sanity check the value to avoid overflow when // multiplying with pointer size. - if (length > kSafeArgumentsLength) { - throw %MakeRangeError('stack_overflow', []); - } + if (length > kSafeArgumentsLength) throw %MakeRangeError(kStackOverflow); // Return the length which is the number of arguments to copy to the // stack. It is guaranteed to be a small integer at this point. @@ -537,7 +530,7 @@ function REFLECT_CONSTRUCT_PREPARE(args, newTarget) { function STACK_OVERFLOW(length) { - throw %MakeRangeError('stack_overflow', []); + throw %MakeRangeError(kStackOverflow); } @@ -577,7 +570,7 @@ function ToPrimitive(x, hint) { if (IS_STRING(x)) return x; // Normal behavior. if (!IS_SPEC_OBJECT(x)) return x; - if (IS_SYMBOL_WRAPPER(x)) throw MakeTypeError('symbol_to_primitive', []); + if (IS_SYMBOL_WRAPPER(x)) throw MakeTypeError(kSymbolToPrimitive); if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT; return (hint == NUMBER_HINT) ? %DefaultNumber(x) : %DefaultString(x); } @@ -602,7 +595,7 @@ function ToNumber(x) { } if (IS_BOOLEAN(x)) return x ? 1 : 0; if (IS_UNDEFINED(x)) return NAN; - if (IS_SYMBOL(x)) throw MakeTypeError('symbol_to_number', []); + if (IS_SYMBOL(x)) throw MakeTypeError(kSymbolToNumber); return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x)); } @@ -613,7 +606,7 @@ function NonNumberToNumber(x) { } if (IS_BOOLEAN(x)) return x ? 1 : 0; if (IS_UNDEFINED(x)) return NAN; - if (IS_SYMBOL(x)) throw MakeTypeError('symbol_to_number', []); + if (IS_SYMBOL(x)) throw MakeTypeError(kSymbolToNumber); return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x)); } @@ -624,7 +617,7 @@ function ToString(x) { if (IS_NUMBER(x)) return %_NumberToString(x); if (IS_BOOLEAN(x)) return x ? 'true' : 'false'; if (IS_UNDEFINED(x)) return 'undefined'; - if (IS_SYMBOL(x)) throw %MakeTypeError('symbol_to_string', []); + if (IS_SYMBOL(x)) throw %MakeTypeError(kSymbolToString); return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x)); } @@ -632,7 +625,7 @@ function NonStringToString(x) { if (IS_NUMBER(x)) return %_NumberToString(x); if (IS_BOOLEAN(x)) return x ? 'true' : 'false'; if (IS_UNDEFINED(x)) return 'undefined'; - if (IS_SYMBOL(x)) throw %MakeTypeError('symbol_to_string', []); + if (IS_SYMBOL(x)) throw %MakeTypeError(kSymbolToString); return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x)); } @@ -650,7 +643,7 @@ function ToObject(x) { if (IS_BOOLEAN(x)) return new $Boolean(x); if (IS_SYMBOL(x)) return %NewSymbolWrapper(x); if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) { - throw %MakeTypeError('undefined_or_null_to_object', []); + throw %MakeTypeError(kUndefinedOrNullToObject); } return x; } @@ -747,7 +740,7 @@ function DefaultNumber(x) { if (%IsPrimitive(s)) return s; } } - throw %MakeTypeError('cannot_convert_to_primitive', []); + throw %MakeTypeError(kCannotConvertToPrimitive); } // ECMA-262, section 8.6.2.6, page 28. @@ -765,7 +758,7 @@ function DefaultString(x) { if (%IsPrimitive(v)) return v; } } - throw %MakeTypeError('cannot_convert_to_primitive', []); + throw %MakeTypeError(kCannotConvertToPrimitive); } function ToPositiveInteger(x, rangeErrorName) { diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc index c387b37..d3e3313 100644 --- a/src/runtime/runtime-object.cc +++ b/src/runtime/runtime-object.cc @@ -7,6 +7,7 @@ #include "src/arguments.h" #include "src/bootstrapper.h" #include "src/debug.h" +#include "src/messages.h" #include "src/runtime/runtime.h" #include "src/runtime/runtime-utils.h" @@ -1208,9 +1209,8 @@ static Object* Runtime_NewObjectHelper(Isolate* isolate, Handle site) { // If the constructor isn't a proper function we throw a type error. if (!constructor->IsJSFunction()) { - Vector > arguments = HandleVector(&constructor, 1); - THROW_NEW_ERROR_RETURN_FAILURE(isolate, - NewTypeError("not_constructor", arguments)); + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewTypeError(MessageTemplate::kNotConstructor, constructor)); } Handle function = Handle::cast(constructor); @@ -1223,9 +1223,8 @@ static Object* Runtime_NewObjectHelper(Isolate* isolate, // If function should not have prototype, construction is not allowed. In this // case generated code bailouts here, since function has no initial_map. if (!function->should_have_prototype() && !function->shared()->bound()) { - Vector > arguments = HandleVector(&constructor, 1); - THROW_NEW_ERROR_RETURN_FAILURE(isolate, - NewTypeError("not_constructor", arguments)); + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewTypeError(MessageTemplate::kNotConstructor, constructor)); } Debug* debug = isolate->debug(); diff --git a/src/symbol.js b/src/symbol.js index 0f5ecb7..3a582f8 100644 --- a/src/symbol.js +++ b/src/symbol.js @@ -24,9 +24,7 @@ var GlobalSymbol = global.Symbol; // ------------------------------------------------------------------- function SymbolConstructor(x) { - if (%_IsConstructCall()) { - throw MakeTypeError('not_constructor', ["Symbol"]); - } + if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Symbol"); // NOTE: Passing in a Symbol value will throw on ToString(). return %CreateSymbol(IS_UNDEFINED(x) ? x : ToString(x)); } diff --git a/test/mjsunit/messages.js b/test/mjsunit/messages.js index c2ba736..4162255 100644 --- a/test/mjsunit/messages.js +++ b/test/mjsunit/messages.js @@ -2,14 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Flags: --stack-size=100 --harmony --harmony-reflect + function test(f, expected, type) { try { f(); - assertUnreachable(); } catch (e) { assertInstanceof(e, type); assertEquals(expected, e.message); + return; } + assertUnreachable(); } // === Error === @@ -23,6 +26,17 @@ test(function() { // === TypeError === +// kApplyNonFunction +test(function() { + Function.prototype.apply.call(1, []); +}, "Function.prototype.apply was called on 1, which is a number " + + "and not a function", TypeError); + +// kCannotConvertToPrimitive +test(function() { + [].join(Object(Symbol(1))); +}, "Cannot convert object to primitive value", TypeError); + // kGeneratorRunning test(function() { var iter; @@ -42,13 +56,78 @@ test(function() { }, "Method RegExp.prototype.compile called on incompatible receiver " + "[object RegExp]", TypeError); +// kInstanceofFunctionExpected +test(function() { + 1 instanceof 1; +}, "Expecting a function in instanceof check, but got 1", TypeError); + +// kInstanceofNonobjectProto +test(function() { + function f() {} + var o = new f(); + f.prototype = 1; + o instanceof f; +}, "Function has non-object prototype '1' in instanceof check", TypeError); + +// kInvalidInOperatorUse +test(function() { + 1 in 1; +}, "Cannot use 'in' operator to search for '1' in 1", TypeError); + +// kNotConstructor +test(function() { + new Symbol(); +}, "Symbol is not a constructor", TypeError); + // kPropertyNotFunction test(function() { Set.prototype.add = 0; new Set(1); }, "Property 'add' of object # is not a function", TypeError); +// kSymbolToPrimitive +test(function() { + 1 + Object(Symbol()); +}, "Cannot convert a Symbol wrapper object to a primitive value", TypeError); + +// kSymbolToString +test(function() { + "" + Symbol(); +}, "Cannot convert a Symbol value to a string", TypeError); + +// kSymbolToNumber +test(function() { + 1 + Symbol(); +}, "Cannot convert a Symbol value to a number", TypeError); + +// kUndefinedOrNullToObject +test(function() { + Array.prototype.toString.call(null); +}, "Cannot convert undefined or null to object", TypeError); + // kWithExpression test(function() { with (null) {} }, "null has no properties", TypeError); + +// kWrongArgs +test(function() { + (function() {}).apply({}, 1); +}, "Function.prototype.apply: Arguments list has wrong type", TypeError); + +test(function() { + Reflect.apply(function() {}, {}, 1); +}, "Reflect.apply: Arguments list has wrong type", TypeError); + +test(function() { + Reflect.construct(function() {}, 1); +}, "Reflect.construct: Arguments list has wrong type", TypeError); + + +// === RangeError === + +// kStackOverflow +test(function() { + function f() { f(Array(1000)); } + f(); +}, "Maximum call stack size exceeded", RangeError); diff --git a/tools/js2c.py b/tools/js2c.py index c72afbc..d0484b5 100755 --- a/tools/js2c.py +++ b/tools/js2c.py @@ -192,7 +192,7 @@ def ReadMacros(lines): return (constants, macros) -TEMPLATE_PATTERN = re.compile(r'^\s+T\(([a-zA-Z]+), ".+"\)') +TEMPLATE_PATTERN = re.compile(r'^\s+T\(([A-Z][a-zA-Z]*),') def ReadMessageTemplates(lines): templates = [] -- 2.7.4