Revision: 6552
Author: [email protected]
Date: Tue Feb  1 04:31:16 2011
Log: Avoid callbacks to user code during error formatting in a couple of
other situations.

Do not use overwritten Object.prototype.hasOwnProperty and
Array.prototype.pop. Do not use split and join in the error formatting
implementation. They are too big to control and their generality is
not needed.

Review URL: http://codereview.chromium.org/6287041
http://code.google.com/p/v8/source/detail?r=6552

Modified:
 /branches/bleeding_edge/src/array.js
 /branches/bleeding_edge/src/messages.js
 /branches/bleeding_edge/src/mirror-debugger.js
 /branches/bleeding_edge/test/cctest/test-api.cc
 /branches/bleeding_edge/test/mjsunit/mirror-error.js

=======================================
--- /branches/bleeding_edge/src/array.js        Mon Jan 31 06:54:53 2011
+++ /branches/bleeding_edge/src/array.js        Tue Feb  1 04:31:16 2011
@@ -171,8 +171,9 @@
     }
     return %StringBuilderConcat(elements, length2, '');
   } finally {
-    // Make sure to pop the visited array no matter what happens.
-    if (is_array) visited_arrays.pop();
+    // Make sure to remove the last element of the visited array no
+    // matter what happens.
+    if (is_array) visited_arrays.length = visited_arrays.length - 1;
   }
 }

=======================================
--- /branches/bleeding_edge/src/messages.js     Fri Jan 28 02:33:10 2011
+++ /branches/bleeding_edge/src/messages.js     Tue Feb  1 04:31:16 2011
@@ -53,20 +53,22 @@
 var kMessages = 0;

 var kReplacementMarkers =
-    [ "%0", "%1", "%2", "%3", "%4", "%5", "%6", "%7", "%8", "%9", "%10" ];
+    [ "%0", "%1", "%2", "%3" ]

 function FormatString(format, args) {
-  var result = format;
-  for (var i = 0; i < args.length; i++) {
-    var str;
-    try {
-      str = ToDetailString(args[i]);
-    } catch (e) {
-      str = "#<error>";
-    }
-    var replacement_marker = kReplacementMarkers[i];
-    var split = %_CallFunction(result, replacement_marker, StringSplit);
-    result = %_CallFunction(split, str, ArrayJoin);
+  var result = "";
+  var arg_num = 0;
+  for (var i = 0; i < format.length; i++) {
+    var str = format[i];
+    for (arg_num = 0; arg_num < kReplacementMarkers.length; arg_num++) {
+      if (format[i] !== kReplacementMarkers[arg_num]) continue;
+      try {
+        str = ToDetailString(args[arg_num]);
+      } catch (e) {
+        str = "#<error>";
+      }
+    }
+    result += str;
   }
   return result;
 }
@@ -143,86 +145,86 @@
   if (kMessages === 0) {
     kMessages = {
       // Error
-      cyclic_proto:                 "Cyclic __proto__ value",
+      cyclic_proto:                 ["Cyclic __proto__ value"],
       // TypeError
-      unexpected_token:             "Unexpected token %0",
-      unexpected_token_number:      "Unexpected number",
-      unexpected_token_string:      "Unexpected string",
-      unexpected_token_identifier:  "Unexpected identifier",
-      unexpected_eos:               "Unexpected end of input",
-      malformed_regexp:             "Invalid regular expression: /%0/: %1",
- unterminated_regexp: "Invalid regular expression: missing /", - regexp_flags: "Cannot supply flags when constructing one RegExp from another", - incompatible_method_receiver: "Method %0 called on incompatible receiver %1",
-      invalid_lhs_in_assignment:    "Invalid left-hand side in assignment",
-      invalid_lhs_in_for_in:        "Invalid left-hand side in for-in",
- invalid_lhs_in_postfix_op: "Invalid left-hand side expression in postfix operation", - invalid_lhs_in_prefix_op: "Invalid left-hand side expression in prefix operation", - multiple_defaults_in_switch: "More than one default clause in switch statement",
-      newline_after_throw:          "Illegal newline after throw",
-      redeclaration:                "%0 '%1' has already been declared",
-      no_catch_or_finally:          "Missing catch or finally after try",
-      unknown_label:                "Undefined label '%0'",
-      uncaught_exception:           "Uncaught %0",
-      stack_trace:                  "Stack Trace:\n%0",
-      called_non_callable:          "%0 is not a function",
-      undefined_method:             "Object %1 has no method '%0'",
- property_not_function: "Property '%0' of object %1 is not a function", - cannot_convert_to_primitive: "Cannot convert object to primitive value",
-      not_constructor:              "%0 is not a constructor",
-      not_defined:                  "%0 is not defined",
-      non_object_property_load:     "Cannot read property '%0' of %1",
-      non_object_property_store:    "Cannot set property '%0' of %1",
-      non_object_property_call:     "Cannot call method '%0' of %1",
-      with_expression:              "%0 has no properties",
-      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", - 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",
-      null_to_object:               "Cannot convert 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",
- value_and_accessor: "Invalid property. A property cannot both have accessors and be writable or have a value: %0", - proto_object_or_null: "Object prototype may only be an Object or null", - property_desc_object: "Property description must be an object: %0",
-      redefine_disallowed:          "Cannot redefine property: %0",
- define_disallowed: "Cannot define property, object is not extensible: %0",
+      unexpected_token:             ["Unexpected token ", "%0"],
+      unexpected_token_number:      ["Unexpected number"],
+      unexpected_token_string:      ["Unexpected string"],
+      unexpected_token_identifier:  ["Unexpected identifier"],
+      unexpected_eos:               ["Unexpected end of input"],
+ malformed_regexp: ["Invalid regular expression: /", "%0", "/: ", "%1"], + unterminated_regexp: ["Invalid regular expression: missing /"], + regexp_flags: ["Cannot supply flags when constructing one RegExp from another"], + incompatible_method_receiver: ["Method ", "%0", " called on incompatible receiver ", "%1"], + invalid_lhs_in_assignment: ["Invalid left-hand side in assignment"],
+      invalid_lhs_in_for_in:        ["Invalid left-hand side in for-in"],
+ invalid_lhs_in_postfix_op: ["Invalid left-hand side expression in postfix operation"], + invalid_lhs_in_prefix_op: ["Invalid left-hand side expression in prefix operation"], + multiple_defaults_in_switch: ["More than one default clause in switch statement"],
+      newline_after_throw:          ["Illegal newline after throw"],
+ redeclaration: ["%0", " '", "%1", "' has already been declared"],
+      no_catch_or_finally:          ["Missing catch or finally after try"],
+      unknown_label:                ["Undefined label '", "%0", "'"],
+      uncaught_exception:           ["Uncaught ", "%0"],
+      stack_trace:                  ["Stack Trace:\n", "%0"],
+      called_non_callable:          ["%0", " is not a function"],
+ undefined_method: ["Object ", "%1", " has no method '", "%0", "'"], + property_not_function: ["Property '", "%0", "' of object ", "%1", " is not a function"], + cannot_convert_to_primitive: ["Cannot convert object to primitive value"],
+      not_constructor:              ["%0", " is not a constructor"],
+      not_defined:                  ["%0", " is not defined"],
+ non_object_property_load: ["Cannot read property '", "%0", "' of ", "%1"], + non_object_property_store: ["Cannot set property '", "%0", "' of ", "%1"], + non_object_property_call: ["Cannot call method '", "%0", "' of ", "%1"],
+      with_expression:              ["%0", " has no properties"],
+      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"], + 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"],
+      null_to_object:               ["Cannot convert 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"],
+ value_and_accessor: ["Invalid property. A property cannot both have accessors and be writable or have a value: ", "%0"], + proto_object_or_null: ["Object prototype may only be an Object or null"], + property_desc_object: ["Property description must be an object: ", "%0"],
+      redefine_disallowed:          ["Cannot redefine property: ", "%0"],
+ define_disallowed: ["Cannot define property, object is not extensible: ", "%0"],
       // RangeError
-      invalid_array_length:         "Invalid array length",
-      stack_overflow:               "Maximum call stack size exceeded",
+      invalid_array_length:         ["Invalid array length"],
+      stack_overflow:               ["Maximum call stack size exceeded"],
       // SyntaxError
-      unable_to_parse:              "Parse error",
-      duplicate_regexp_flag:        "Duplicate RegExp flag %0",
-      invalid_regexp:               "Invalid RegExp pattern /%0/",
-      illegal_break:                "Illegal break statement",
-      illegal_continue:             "Illegal continue statement",
-      illegal_return:               "Illegal return statement",
-      error_loading_debugger:       "Error loading debugger",
-      no_input_to_regexp:           "No input to %0",
-      invalid_json:                 "String '%0' is not valid JSON",
- circular_structure: "Converting circular structure to JSON",
-      obj_ctor_property_non_object: "Object.%0 called on non-object",
-      array_indexof_not_defined:    "Array.getIndexOf: Argument undefined",
- object_not_extensible: "Can't add property %0, object is not extensible",
-      illegal_access:               "Illegal access",
- invalid_preparser_data: "Invalid preparser data for function %0", - strict_mode_with: "Strict mode code may not include a with statement", - strict_catch_variable: "Catch variable may not be eval or arguments in strict mode", - strict_param_name: "Parameter name eval or arguments is not allowed in strict mode", - strict_param_dupe: "Strict mode function may not have duplicate parameter names", - strict_var_name: "Variable name may not be eval or arguments in strict mode", - strict_function_name: "Function name may not be eval or arguments in strict mode", - strict_octal_literal: "Octal literals are not allowed in strict mode.", - strict_duplicate_property: "Duplicate data property in object literal not allowed in strict mode", - accessor_data_property: "Object literal may not have data and accessor property with the same name", - accessor_get_set: "Object literal may not have multiple get/set accessors with the same name", - strict_lhs_eval_assignment: "Assignment to eval or arguments is not allowed in strict mode", - strict_lhs_postfix: "Postfix increment/decrement may not have eval or arguments operand in strict mode", - strict_lhs_prefix: "Prefix increment/decrement may not have eval or arguments operand in strict mode",
+      unable_to_parse:              ["Parse error"],
+      duplicate_regexp_flag:        ["Duplicate RegExp flag ", "%0"],
+ invalid_regexp: ["Invalid RegExp pattern /", "%0", "/"],
+      illegal_break:                ["Illegal break statement"],
+      illegal_continue:             ["Illegal continue statement"],
+      illegal_return:               ["Illegal return statement"],
+      error_loading_debugger:       ["Error loading debugger"],
+      no_input_to_regexp:           ["No input to ", "%0"],
+ invalid_json: ["String '", "%0", "' is not valid JSON"], + circular_structure: ["Converting circular structure to JSON"], + obj_ctor_property_non_object: ["Object.", "%0", " called on non-object"], + array_indexof_not_defined: ["Array.getIndexOf: Argument undefined"], + object_not_extensible: ["Can't add property ", "%0", ", object is not extensible"],
+      illegal_access:               ["Illegal access"],
+ invalid_preparser_data: ["Invalid preparser data for function ", "%0"], + strict_mode_with: ["Strict mode code may not include a with statement"], + strict_catch_variable: ["Catch variable may not be eval or arguments in strict mode"], + strict_param_name: ["Parameter name eval or arguments is not allowed in strict mode"], + strict_param_dupe: ["Strict mode function may not have duplicate parameter names"], + strict_var_name: ["Variable name may not be eval or arguments in strict mode"], + strict_function_name: ["Function name may not be eval or arguments in strict mode"], + strict_octal_literal: ["Octal literals are not allowed in strict mode."], + strict_duplicate_property: ["Duplicate data property in object literal not allowed in strict mode"], + accessor_data_property: ["Object literal may not have data and accessor property with the same name"], + accessor_get_set: ["Object literal may not have multiple get/set accessors with the same name"], + strict_lhs_eval_assignment: ["Assignment to eval or arguments is not allowed in strict mode"], + strict_lhs_postfix: ["Postfix increment/decrement may not have eval or arguments operand in strict mode"], + strict_lhs_prefix: ["Prefix increment/decrement may not have eval or arguments operand in strict mode"],
     };
   }
   var format = kMessages[message.type];
@@ -1038,14 +1040,16 @@
   if (!%PushIfAbsent(visited_errors, this)) throw cyclic_error_marker;
   try {
     var type = this.type;
-    if (type && !this.hasOwnProperty("message")) {
+    if (type && !%_CallFunction(this, "message", ObjectHasOwnProperty)) {
       var formatted = FormatMessage({ type: type, args: this.arguments });
       return this.name + ": " + formatted;
     }
- var message = this.hasOwnProperty("message") ? (": " + this.message) : "";
+    var message = %_CallFunction(this, "message", ObjectHasOwnProperty)
+        ? (": " + this.message)
+        : "";
     return this.name + message;
   } finally {
-    visited_errors.pop();
+    visited_errors.length = visited_errors.length - 1;
   }
 }

=======================================
--- /branches/bleeding_edge/src/mirror-debugger.js      Fri Jan 28 02:33:10 2011
+++ /branches/bleeding_edge/src/mirror-debugger.js      Tue Feb  1 04:31:16 2011
@@ -1084,9 +1084,9 @@
   // Use the same text representation as in messages.js.
   var text;
   try {
-    str = builtins.ToDetailString(this.value_);
+    str = %_CallFunction(this.value_, builtins.errorToString);
   } catch (e) {
-    str = '#<an Error>';
+    str = '#<Error>';
   }
   return str;
 }
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc     Mon Jan 31 05:49:15 2011
+++ /branches/bleeding_edge/test/cctest/test-api.cc     Tue Feb  1 04:31:16 2011
@@ -2369,13 +2369,25 @@
 }


-// Test that overwritten toString methods are not invoked on uncaught
-// exception formatting. However, they are invoked when performing
-// normal error string conversions.
+static v8::Handle<Value> Fail(const v8::Arguments& args) {
+  ApiTestFuzzer::Fuzz();
+  CHECK(false);
+  return v8::Undefined();
+}
+
+
+// Test that overwritten methods are not invoked on uncaught exception
+// formatting. However, they are invoked when performing normal error
+// string conversions.
 TEST(APIThrowMessageOverwrittenToString) {
   v8::HandleScope scope;
   v8::V8::AddMessageListener(check_reference_error_message);
-  LocalContext context;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("fail"), v8::FunctionTemplate::New(Fail));
+  LocalContext context(NULL, templ);
+  CompileRun("Array.prototype.pop = fail;");
+  CompileRun("Object.prototype.hasOwnProperty = fail;");
+ CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }"); CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }"); CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
   CompileRun("ReferenceError.prototype.toString ="
=======================================
--- /branches/bleeding_edge/test/mjsunit/mirror-error.js Tue Dec 7 03:01:02 2010 +++ /branches/bleeding_edge/test/mjsunit/mirror-error.js Tue Feb 1 04:31:16 2011
@@ -76,7 +76,7 @@
     }
     assertTrue(found_message, 'Property message not found');
   }
-
+
   // Check the formatted text (regress 1231579).
   assertEquals(fromJSON.text, e.toString(), 'toString');
 }

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to