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 | 72 // compiler errors. This is not specified, but allowing interception through a |
73 // through a getter can leak error objects from different | 73 // getter can leak error objects from different script tags in the same context |
74 // script tags in the same context in a browser setting. | 74 // in a browser setting. Use Realm.eval as a proxy for loading scripts. We |
| 75 // ignore the exception thrown from it since that would not be catchable from |
| 76 // user-land code. |
75 var errors = [SyntaxError, ReferenceError, TypeError, RangeError, URIError]; | 77 var errors = [SyntaxError, ReferenceError, TypeError, RangeError, URIError]; |
76 var error_triggers = ["syntax error", | 78 var error_triggers = ["syntax error", |
77 "var error = reference", | 79 "var error = reference", |
78 "undefined()", | 80 "undefined()", |
79 "String.fromCodePoint(0xFFFFFF)", | 81 "String.fromCodePoint(0xFFFFFF)", |
80 "decodeURI('%F')"]; | 82 "decodeURI('%F')"]; |
81 for (var i in errors) { | 83 for (var i in errors) { |
82 var name = errors[i].name; | |
83 | |
84 // Monkey-patch prototype. | 84 // Monkey-patch prototype. |
85 var props = ["name", "message", "stack"]; | 85 for (var prop of ["name", "message", "stack"]) { |
86 for (var j in props) { | 86 errors[i].prototype.__defineGetter__(prop, fail); |
87 errors[i].prototype.__defineGetter__(props[j], fail); | |
88 } | 87 } |
89 // String conversion should not invoke monkey-patched getters on prototype. | 88 // String conversion should not invoke monkey-patched getters on prototype. |
90 var error; | 89 assertThrows(()=>Realm.eval(0, error_triggers[i])); |
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()); | |
115 } | 90 } |
116 | 91 |
117 // Monkey-patching non-internal errors should still be observable. | 92 // Monkey-patching non-internal errors should still be observable. |
118 function MyError() {} | 93 function MyError() {} |
119 MyError.prototype = new Error; | 94 MyError.prototype = new Error; |
120 var errors = [Error, RangeError, EvalError, URIError, | 95 var errors = [Error, RangeError, EvalError, URIError, |
121 SyntaxError, ReferenceError, TypeError, MyError]; | 96 SyntaxError, ReferenceError, TypeError, MyError]; |
122 for (var i in errors) { | 97 for (var i in errors) { |
123 errors[i].prototype.__defineGetter__("name", function() { return "my"; }); | 98 errors[i].prototype.__defineGetter__("name", function() { return "my"; }); |
124 errors[i].prototype.__defineGetter__("message", function() { return "moo"; }); | 99 errors[i].prototype.__defineGetter__("message", function() { return "moo"; }); |
125 var e = new errors[i]; | 100 var e = new errors[i]; |
126 assertEquals("my: moo", e.toString()); | 101 assertEquals("my: moo", e.toString()); |
127 } | 102 } |
128 | 103 |
129 | 104 |
130 Error.prototype.toString = Object.prototype.toString; | 105 Error.prototype.toString = Object.prototype.toString; |
131 assertEquals("[object Object]", Error.prototype.toString()); | 106 assertEquals("[object Object]", Error.prototype.toString()); |
132 assertEquals(Object.prototype, Error.prototype.__proto__); | 107 assertEquals(Object.prototype, Error.prototype.__proto__); |
133 var e = new Error("foo"); | 108 var e = new Error("foo"); |
134 assertEquals("[object Error]", e.toString()); | 109 assertEquals("[object Error]", e.toString()); |
OLD | NEW |