OLD | NEW |
| (Empty) |
1 // Copyright 2016 the V8 project authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "src/builtins/builtins.h" | |
6 #include "src/builtins/builtins-utils.h" | |
7 | |
8 #include "src/accessors.h" | |
9 #include "src/bootstrapper.h" | |
10 #include "src/property-descriptor.h" | |
11 #include "src/string-builder.h" | |
12 | |
13 namespace v8 { | |
14 namespace internal { | |
15 | |
16 // ES6 section 19.5.1.1 Error ( message ) | |
17 BUILTIN(ErrorConstructor) { | |
18 HandleScope scope(isolate); | |
19 | |
20 // 1. If NewTarget is undefined, let newTarget be the active function object, | |
21 // else let newTarget be NewTarget. | |
22 | |
23 Handle<JSFunction> target = args.target<JSFunction>(); | |
24 Handle<JSReceiver> new_target; | |
25 if (args.new_target()->IsJSReceiver()) { | |
26 new_target = Handle<JSReceiver>::cast(args.new_target()); | |
27 } else { | |
28 new_target = target; | |
29 } | |
30 | |
31 // 2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%ErrorPrototype%", | |
32 // « [[ErrorData]] »). | |
33 Handle<JSObject> err; | |
34 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, err, | |
35 JSObject::New(target, new_target)); | |
36 | |
37 // 3. If message is not undefined, then | |
38 // a. Let msg be ? ToString(message). | |
39 // b. Let msgDesc be the PropertyDescriptor{[[Value]]: msg, [[Writable]]: | |
40 // true, [[Enumerable]]: false, [[Configurable]]: true}. | |
41 // c. Perform ! DefinePropertyOrThrow(O, "message", msgDesc). | |
42 // 4. Return O. | |
43 | |
44 Handle<Object> msg = args.atOrUndefined(isolate, 1); | |
45 if (!msg->IsUndefined(isolate)) { | |
46 Handle<String> msg_string; | |
47 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, msg_string, | |
48 Object::ToString(isolate, msg)); | |
49 RETURN_FAILURE_ON_EXCEPTION( | |
50 isolate, | |
51 JSObject::SetOwnPropertyIgnoreAttributes( | |
52 err, isolate->factory()->message_string(), msg_string, DONT_ENUM)); | |
53 } | |
54 | |
55 // Capture the stack trace unless we're setting up. | |
56 if (!isolate->bootstrapper()->IsActive()) { | |
57 // Optionally capture a more detailed stack trace for the message. | |
58 RETURN_FAILURE_ON_EXCEPTION(isolate, | |
59 isolate->CaptureAndSetDetailedStackTrace(err)); | |
60 // Capture a simple stack trace for the stack property. | |
61 RETURN_FAILURE_ON_EXCEPTION(isolate, | |
62 isolate->CaptureAndSetSimpleStackTrace(err)); | |
63 } | |
64 | |
65 return *err; | |
66 } | |
67 | |
68 // static | |
69 BUILTIN(ErrorCaptureStackTrace) { | |
70 HandleScope scope(isolate); | |
71 Handle<Object> object_obj = args.atOrUndefined(isolate, 1); | |
72 if (!object_obj->IsJSObject()) { | |
73 THROW_NEW_ERROR_RETURN_FAILURE( | |
74 isolate, NewTypeError(MessageTemplate::kInvalidArgument, object_obj)); | |
75 } | |
76 Handle<JSObject> object = Handle<JSObject>::cast(object_obj); | |
77 Handle<Object> caller = args.atOrUndefined(isolate, 2); | |
78 | |
79 // TODO(jgruber): Eagerly format the stack trace and remove accessors.h | |
80 // include. | |
81 | |
82 // Handle writes to the global object. | |
83 | |
84 if (object->IsJSGlobalProxy()) { | |
85 Map* map = object->map(); | |
86 if (map->has_hidden_prototype()) { | |
87 object = handle(JSGlobalObject::cast(map->prototype()), isolate); | |
88 } | |
89 } | |
90 | |
91 // Check if the stack property is read-only. | |
92 | |
93 bool is_extensible = true; | |
94 if (!JSObject::IsExtensible(object)) { | |
95 is_extensible = false; | |
96 } | |
97 | |
98 PropertyDescriptor desc; | |
99 Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor( | |
100 isolate, object, isolate->factory()->stack_string(), &desc); | |
101 if (owned.FromMaybe(false)) { | |
102 if (!desc.configurable() || !desc.writable()) { | |
103 is_extensible = false; | |
104 } | |
105 } | |
106 | |
107 if (!is_extensible) { | |
108 THROW_NEW_ERROR_RETURN_FAILURE( | |
109 isolate, NewTypeError(MessageTemplate::kDefineDisallowed, | |
110 isolate->factory()->stack_string(), object)); | |
111 } | |
112 | |
113 // Add stack accessors to the given object | |
114 | |
115 Handle<Map> map(object->map()); | |
116 PropertyAttributes attribs = DONT_ENUM; | |
117 Handle<AccessorInfo> error_stack = | |
118 Accessors::ErrorStackInfo(isolate, attribs); | |
119 { | |
120 AccessorConstantDescriptor d(Handle<Name>(Name::cast(error_stack->name())), | |
121 error_stack, attribs); | |
122 Handle<Map> new_map = Map::CopyInsertDescriptor(map, &d, INSERT_TRANSITION); | |
123 JSObject::MigrateToMap(object, new_map, 1); | |
124 } | |
125 | |
126 // Collect the stack trace. | |
127 | |
128 RETURN_FAILURE_ON_EXCEPTION(isolate, | |
129 isolate->CaptureAndSetDetailedStackTrace(object)); | |
130 RETURN_FAILURE_ON_EXCEPTION( | |
131 isolate, isolate->CaptureAndSetSimpleStackTrace(object, caller)); | |
132 | |
133 return *isolate->factory()->undefined_value(); | |
134 } | |
135 | |
136 namespace { | |
137 | |
138 MaybeHandle<String> GetStringPropertyOrDefault(Isolate* isolate, | |
139 Handle<JSReceiver> recv, | |
140 Handle<String> key, | |
141 Handle<String> default_str) { | |
142 Handle<Object> obj; | |
143 ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, JSObject::GetProperty(recv, key), | |
144 String); | |
145 | |
146 Handle<String> str; | |
147 if (obj->IsUndefined(isolate)) { | |
148 str = default_str; | |
149 } else { | |
150 ASSIGN_RETURN_ON_EXCEPTION(isolate, str, Object::ToString(isolate, obj), | |
151 String); | |
152 } | |
153 | |
154 return str; | |
155 } | |
156 | |
157 } // namespace | |
158 | |
159 // ES6 section 19.5.3.4 Error.prototype.toString ( ) | |
160 BUILTIN(ErrorPrototypeToString) { | |
161 HandleScope scope(isolate); | |
162 | |
163 // 1. Let O be the this value. | |
164 // 2. If Type(O) is not Object, throw a TypeError exception. | |
165 CHECK_RECEIVER(JSReceiver, receiver, "Error.prototype.toString"); | |
166 | |
167 // 3. Let name be ? Get(O, "name"). | |
168 // 4. If name is undefined, let name be "Error"; otherwise let name be | |
169 // ? ToString(name). | |
170 Handle<String> name_key = isolate->factory()->name_string(); | |
171 Handle<String> name_default = isolate->factory()->Error_string(); | |
172 Handle<String> name; | |
173 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
174 isolate, name, | |
175 GetStringPropertyOrDefault(isolate, receiver, name_key, name_default)); | |
176 | |
177 // 5. Let msg be ? Get(O, "message"). | |
178 // 6. If msg is undefined, let msg be the empty String; otherwise let msg be | |
179 // ? ToString(msg). | |
180 Handle<String> msg_key = isolate->factory()->message_string(); | |
181 Handle<String> msg_default = isolate->factory()->empty_string(); | |
182 Handle<String> msg; | |
183 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
184 isolate, msg, | |
185 GetStringPropertyOrDefault(isolate, receiver, msg_key, msg_default)); | |
186 | |
187 // 7. If name is the empty String, return msg. | |
188 // 8. If msg is the empty String, return name. | |
189 if (name->length() == 0) return *msg; | |
190 if (msg->length() == 0) return *name; | |
191 | |
192 // 9. Return the result of concatenating name, the code unit 0x003A (COLON), | |
193 // the code unit 0x0020 (SPACE), and msg. | |
194 IncrementalStringBuilder builder(isolate); | |
195 builder.AppendString(name); | |
196 builder.AppendCString(": "); | |
197 builder.AppendString(msg); | |
198 RETURN_RESULT_OR_FAILURE(isolate, builder.Finish()); | |
199 } | |
200 | |
201 } // namespace internal | |
202 } // namespace v8 | |
OLD | NEW |