1// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// Check that message and name are not enumerable on Error objects.
29var desc = Object.getOwnPropertyDescriptor(Error.prototype, 'name');
30assertFalse(desc['enumerable']);
31desc = Object.getOwnPropertyDescriptor(Error.prototype, 'message');
32assertFalse(desc['enumerable']);
33
34var e = new Error("foobar");
35desc = Object.getOwnPropertyDescriptor(e, 'message');
36assertFalse(desc['enumerable']);
37desc = Object.getOwnPropertyDescriptor(e, 'stack');
38assertFalse(desc['enumerable']);
39
40var e = new Error();
41assertFalse(e.hasOwnProperty('message'));
42
43// name is not tested above, but in addition we should have no enumerable
44// properties, so we simply assert that.
45for (var v in e) {
46  assertUnreachable();
47}
48
49// Check that error construction does not call setters for the
50// properties on error objects in prototypes.
51function fail() { assertUnreachable(); };
52ReferenceError.prototype.__defineSetter__('name', fail);
53ReferenceError.prototype.__defineSetter__('message', fail);
54ReferenceError.prototype.__defineSetter__('stack', fail);
55
56var e = new ReferenceError();
57assertTrue(e.hasOwnProperty('stack'));
58
59var e = new ReferenceError('123');
60assertTrue(e.hasOwnProperty('message'));
61assertTrue(e.hasOwnProperty('stack'));
62
63try {
64  eval("var error = reference");
65} catch (error) {
66  e = error;
67}
68
69assertTrue(e.hasOwnProperty('stack'));
70
71// Check that intercepting property access from toString is prevented for
72// compiler errors. This is not specified, but allowing interception through a
73// getter can leak error objects from different script tags in the same context
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.
77var errors = [SyntaxError, ReferenceError, TypeError, RangeError, URIError];
78var error_triggers = ["syntax error",
79                      "var error = reference",
80                      "undefined()",
81                      "String.fromCodePoint(0xFFFFFF)",
82                      "decodeURI('%F')"];
83for (var i in errors) {
84  // Monkey-patch prototype.
85  for (var prop of ["name", "message", "stack"]) {
86    errors[i].prototype.__defineGetter__(prop, fail);
87  }
88  // String conversion should not invoke monkey-patched getters on prototype.
89  assertThrows(()=>Realm.eval(0, error_triggers[i]));
90}
91
92// Monkey-patching non-internal errors should still be observable.
93function MyError() {}
94MyError.prototype = new Error;
95var errors = [Error, RangeError, EvalError, URIError,
96              SyntaxError, ReferenceError, TypeError, MyError];
97for (var i in errors) {
98  errors[i].prototype.__defineGetter__("name", function() { return "my"; });
99  errors[i].prototype.__defineGetter__("message", function() { return "moo"; });
100  var e = new errors[i];
101  assertEquals("my: moo", e.toString());
102}
103
104
105Error.prototype.toString = Object.prototype.toString;
106assertEquals("[object Object]", Error.prototype.toString());
107assertEquals(Object.prototype, Error.prototype.__proto__);
108var e = new Error("foo");
109assertEquals("[object Error]", e.toString());
110