| 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 |