OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 | 62 |
63 try { | 63 try { |
64 eval("var error = reference"); | 64 eval("var error = reference"); |
65 } catch (error) { | 65 } catch (error) { |
66 e = error; | 66 e = error; |
67 } | 67 } |
68 | 68 |
69 assertTrue(e.hasOwnProperty('stack')); | 69 assertTrue(e.hasOwnProperty('stack')); |
70 | 70 |
71 // Check that intercepting property access from toString is prevented for | 71 // Check that intercepting property access from toString is prevented for |
72 // compiler errors. This is not specified, but allowing interception through a | 72 // compiler errors. This is not specified, but allowing interception |
73 // getter can leak error objects from different script tags in the same context | 73 // through a getter can leak error objects from different |
74 // in a browser setting. Use Realm.eval as a proxy for loading scripts. We | 74 // script tags in the same context in a browser setting. |
75 // ignore the exception thrown from it since that would not be catchable from | |
76 // user-land code. | |
77 var errors = [SyntaxError, ReferenceError, TypeError, RangeError, URIError]; | 75 var errors = [SyntaxError, ReferenceError, TypeError, RangeError, URIError]; |
78 var error_triggers = ["syntax error", | 76 var error_triggers = ["syntax error", |
79 "var error = reference", | 77 "var error = reference", |
80 "undefined()", | 78 "undefined()", |
81 "String.fromCodePoint(0xFFFFFF)", | 79 "String.fromCodePoint(0xFFFFFF)", |
82 "decodeURI('%F')"]; | 80 "decodeURI('%F')"]; |
83 for (var i in errors) { | 81 for (var i in errors) { |
| 82 var name = errors[i].name; |
| 83 |
84 // Monkey-patch prototype. | 84 // Monkey-patch prototype. |
85 for (var prop of ["name", "message", "stack"]) { | 85 var props = ["name", "message", "stack"]; |
86 errors[i].prototype.__defineGetter__(prop, fail); | 86 for (var j in props) { |
| 87 errors[i].prototype.__defineGetter__(props[j], fail); |
87 } | 88 } |
88 // String conversion should not invoke monkey-patched getters on prototype. | 89 // String conversion should not invoke monkey-patched getters on prototype. |
89 assertThrows(()=>Realm.eval(0, error_triggers[i])); | 90 var error; |
| 91 try { |
| 92 eval(error_triggers[i]); |
| 93 } catch (e) { |
| 94 error = e; |
| 95 } |
| 96 assertTrue(error.toString().startsWith(name)); |
| 97 |
| 98 // Deleting message on the error (exposing the getter) is fine. |
| 99 delete error.message; |
| 100 assertEquals(name, error.toString()); |
| 101 |
| 102 // Custom properties shadowing the name are fine. |
| 103 var myerror = { name: "myerror", message: "mymessage"}; |
| 104 myerror.__proto__ = error; |
| 105 assertEquals("myerror: mymessage", myerror.toString()); |
| 106 |
| 107 // Custom getters in actual objects are welcome. |
| 108 error.__defineGetter__("name", function() { return "mine"; }); |
| 109 assertEquals("mine", error.toString()); |
| 110 |
| 111 // Custom properties shadowing the name are fine. |
| 112 var myerror2 = { message: "mymessage"}; |
| 113 myerror2.__proto__ = error; |
| 114 assertEquals("mine: mymessage", myerror2.toString()); |
90 } | 115 } |
91 | 116 |
92 // Monkey-patching non-internal errors should still be observable. | 117 // Monkey-patching non-internal errors should still be observable. |
93 function MyError() {} | 118 function MyError() {} |
94 MyError.prototype = new Error; | 119 MyError.prototype = new Error; |
95 var errors = [Error, RangeError, EvalError, URIError, | 120 var errors = [Error, RangeError, EvalError, URIError, |
96 SyntaxError, ReferenceError, TypeError, MyError]; | 121 SyntaxError, ReferenceError, TypeError, MyError]; |
97 for (var i in errors) { | 122 for (var i in errors) { |
98 errors[i].prototype.__defineGetter__("name", function() { return "my"; }); | 123 errors[i].prototype.__defineGetter__("name", function() { return "my"; }); |
99 errors[i].prototype.__defineGetter__("message", function() { return "moo"; }); | 124 errors[i].prototype.__defineGetter__("message", function() { return "moo"; }); |
100 var e = new errors[i]; | 125 var e = new errors[i]; |
101 assertEquals("my: moo", e.toString()); | 126 assertEquals("my: moo", e.toString()); |
102 } | 127 } |
103 | 128 |
104 | 129 |
105 Error.prototype.toString = Object.prototype.toString; | 130 Error.prototype.toString = Object.prototype.toString; |
106 assertEquals("[object Object]", Error.prototype.toString()); | 131 assertEquals("[object Object]", Error.prototype.toString()); |
107 assertEquals(Object.prototype, Error.prototype.__proto__); | 132 assertEquals(Object.prototype, Error.prototype.__proto__); |
108 var e = new Error("foo"); | 133 var e = new Error("foo"); |
109 assertEquals("[object Error]", e.toString()); | 134 assertEquals("[object Error]", e.toString()); |
OLD | NEW |