| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/builtins/builtins.h" | 5 #include "src/builtins/builtins.h" |
| 6 #include "src/builtins/builtins-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
| 7 | 7 |
| 8 #include "src/string-builder.h" | 8 #include "src/string-builder.h" |
| 9 #include "src/wasm/wasm-module.h" | 9 #include "src/wasm/wasm-module.h" |
| 10 | 10 |
| 11 namespace v8 { | 11 namespace v8 { |
| 12 namespace internal { | 12 namespace internal { |
| 13 | 13 |
| 14 #define CHECK_CALLSITE(recv, method) \ | 14 #define CHECK_CALLSITE(recv, method) \ |
| 15 CHECK_RECEIVER(JSObject, recv, method); \ | 15 CHECK_RECEIVER(JSObject, recv, method); \ |
| 16 if (!JSReceiver::HasOwnProperty( \ | 16 if (!JSReceiver::HasOwnProperty( \ |
| 17 recv, isolate->factory()->call_site_position_symbol()) \ | 17 recv, isolate->factory()->call_site_position_symbol()) \ |
| 18 .FromMaybe(false)) { \ | 18 .FromMaybe(false)) { \ |
| 19 THROW_NEW_ERROR_RETURN_FAILURE( \ | 19 THROW_NEW_ERROR_RETURN_FAILURE( \ |
| 20 isolate, \ | 20 isolate, \ |
| 21 NewTypeError(MessageTemplate::kCallSiteMethod, \ | 21 NewTypeError(MessageTemplate::kCallSiteMethod, \ |
| 22 isolate->factory()->NewStringFromAsciiChecked(method))); \ | 22 isolate->factory()->NewStringFromAsciiChecked(method))); \ |
| 23 } | 23 } |
| 24 | 24 |
| 25 #define SET_CALLSITE_PROPERTY(target, key, value) \ | |
| 26 RETURN_FAILURE_ON_EXCEPTION( \ | |
| 27 isolate, JSObject::SetOwnPropertyIgnoreAttributes( \ | |
| 28 target, isolate->factory()->key(), value, DONT_ENUM)) | |
| 29 | |
| 30 BUILTIN(CallSiteConstructor) { | 25 BUILTIN(CallSiteConstructor) { |
| 31 HandleScope scope(isolate); | 26 HandleScope scope(isolate); |
| 27 |
| 32 Handle<JSFunction> target = args.target<JSFunction>(); | 28 Handle<JSFunction> target = args.target<JSFunction>(); |
| 33 Handle<HeapObject> new_target_obj = args.new_target(); | 29 Handle<Object> new_target = Handle<Object>::cast(args.new_target()); |
| 34 Handle<Object> receiver = args.atOrUndefined(isolate, 1); | 30 Handle<Object> receiver = args.atOrUndefined(isolate, 1); |
| 35 Handle<Object> fun = args.atOrUndefined(isolate, 2); | 31 Handle<Object> fun = args.atOrUndefined(isolate, 2); |
| 36 Handle<Object> pos = args.atOrUndefined(isolate, 3); | 32 Handle<Object> pos = args.atOrUndefined(isolate, 3); |
| 37 Handle<Object> strict_mode = args.atOrUndefined(isolate, 4); | 33 Handle<Object> strict_mode = args.atOrUndefined(isolate, 4); |
| 38 | 34 |
| 39 // Create the JS object. | 35 RETURN_RESULT_OR_FAILURE( |
| 40 | 36 isolate, CallSiteUtils::Construct(isolate, target, new_target, receiver, |
| 41 Handle<JSReceiver> new_target = new_target_obj->IsJSReceiver() | 37 fun, pos, strict_mode)); |
| 42 ? Handle<JSReceiver>::cast(new_target_obj) | |
| 43 : Handle<JSReceiver>::cast(target); | |
| 44 | |
| 45 Handle<JSObject> obj; | |
| 46 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, obj, | |
| 47 JSObject::New(target, new_target)); | |
| 48 | |
| 49 // For wasm frames, receiver is the wasm object and fun is the function index | |
| 50 // instead of an actual function. | |
| 51 const bool is_wasm_object = | |
| 52 receiver->IsJSObject() && wasm::IsWasmObject(JSObject::cast(*receiver)); | |
| 53 if (!fun->IsJSFunction() && !is_wasm_object) { | |
| 54 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 55 isolate, NewTypeError(MessageTemplate::kCallSiteExpectsFunction, | |
| 56 Object::TypeOf(isolate, receiver), | |
| 57 Object::TypeOf(isolate, fun))); | |
| 58 } | |
| 59 | |
| 60 if (is_wasm_object) { | |
| 61 DCHECK(!fun->IsJSFunction()); | |
| 62 SET_CALLSITE_PROPERTY(obj, call_site_wasm_obj_symbol, receiver); | |
| 63 | |
| 64 Handle<Object> fun_index; | |
| 65 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, fun_index, | |
| 66 Object::ToUint32(isolate, fun)); | |
| 67 SET_CALLSITE_PROPERTY(obj, call_site_wasm_func_index_symbol, fun); | |
| 68 } else { | |
| 69 DCHECK(fun->IsJSFunction()); | |
| 70 SET_CALLSITE_PROPERTY(obj, call_site_receiver_symbol, receiver); | |
| 71 SET_CALLSITE_PROPERTY(obj, call_site_function_symbol, fun); | |
| 72 } | |
| 73 | |
| 74 Handle<Object> pos_int32; | |
| 75 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, pos_int32, | |
| 76 Object::ToInt32(isolate, pos)); | |
| 77 SET_CALLSITE_PROPERTY(obj, call_site_position_symbol, pos_int32); | |
| 78 SET_CALLSITE_PROPERTY( | |
| 79 obj, call_site_strict_symbol, | |
| 80 isolate->factory()->ToBoolean(strict_mode->BooleanValue())); | |
| 81 | |
| 82 return *obj; | |
| 83 } | 38 } |
| 84 | 39 |
| 85 #undef SET_CALLSITE_PROPERTY | |
| 86 | |
| 87 namespace { | 40 namespace { |
| 88 | 41 |
| 89 Object* PositiveNumberOrNull(int value, Isolate* isolate) { | 42 Object* PositiveNumberOrNull(int value, Isolate* isolate) { |
| 90 if (value >= 0) return *isolate->factory()->NewNumberFromInt(value); | 43 if (value >= 0) return *isolate->factory()->NewNumberFromInt(value); |
| 91 return isolate->heap()->null_value(); | 44 return isolate->heap()->null_value(); |
| 92 } | 45 } |
| 93 | 46 |
| 94 } // namespace | 47 } // namespace |
| 95 | 48 |
| 96 BUILTIN(CallSitePrototypeGetColumnNumber) { | 49 BUILTIN(CallSitePrototypeGetColumnNumber) { |
| 97 HandleScope scope(isolate); | 50 HandleScope scope(isolate); |
| 98 CHECK_CALLSITE(recv, "getColumnNumber"); | 51 CHECK_CALLSITE(recv, "getColumnNumber"); |
| 99 | 52 |
| 100 CallSite call_site(isolate, recv); | 53 CallSite call_site(isolate, recv); |
| 101 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); | 54 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); |
| 102 return PositiveNumberOrNull(call_site.GetColumnNumber(), isolate); | 55 return PositiveNumberOrNull(call_site.GetColumnNumber(), isolate); |
| 103 } | 56 } |
| 104 | 57 |
| 105 namespace { | |
| 106 | |
| 107 Object* EvalFromFunctionName(Isolate* isolate, Handle<Script> script) { | |
| 108 if (script->eval_from_shared()->IsUndefined(isolate)) | |
| 109 return *isolate->factory()->undefined_value(); | |
| 110 | |
| 111 Handle<SharedFunctionInfo> shared( | |
| 112 SharedFunctionInfo::cast(script->eval_from_shared())); | |
| 113 // Find the name of the function calling eval. | |
| 114 if (shared->name()->BooleanValue()) { | |
| 115 return shared->name(); | |
| 116 } | |
| 117 | |
| 118 return shared->inferred_name(); | |
| 119 } | |
| 120 | |
| 121 Object* EvalFromScript(Isolate* isolate, Handle<Script> script) { | |
| 122 if (script->eval_from_shared()->IsUndefined(isolate)) | |
| 123 return *isolate->factory()->undefined_value(); | |
| 124 | |
| 125 Handle<SharedFunctionInfo> eval_from_shared( | |
| 126 SharedFunctionInfo::cast(script->eval_from_shared())); | |
| 127 return eval_from_shared->script()->IsScript() | |
| 128 ? eval_from_shared->script() | |
| 129 : *isolate->factory()->undefined_value(); | |
| 130 } | |
| 131 | |
| 132 MaybeHandle<String> FormatEvalOrigin(Isolate* isolate, Handle<Script> script) { | |
| 133 Handle<Object> sourceURL = Script::GetNameOrSourceURL(script); | |
| 134 if (!sourceURL->IsUndefined(isolate)) { | |
| 135 DCHECK(sourceURL->IsString()); | |
| 136 return Handle<String>::cast(sourceURL); | |
| 137 } | |
| 138 | |
| 139 IncrementalStringBuilder builder(isolate); | |
| 140 builder.AppendCString("eval at "); | |
| 141 | |
| 142 Handle<Object> eval_from_function_name = | |
| 143 handle(EvalFromFunctionName(isolate, script), isolate); | |
| 144 if (eval_from_function_name->BooleanValue()) { | |
| 145 Handle<String> str; | |
| 146 ASSIGN_RETURN_ON_EXCEPTION( | |
| 147 isolate, str, Object::ToString(isolate, eval_from_function_name), | |
| 148 String); | |
| 149 builder.AppendString(str); | |
| 150 } else { | |
| 151 builder.AppendCString("<anonymous>"); | |
| 152 } | |
| 153 | |
| 154 Handle<Object> eval_from_script_obj = | |
| 155 handle(EvalFromScript(isolate, script), isolate); | |
| 156 if (eval_from_script_obj->IsScript()) { | |
| 157 Handle<Script> eval_from_script = | |
| 158 Handle<Script>::cast(eval_from_script_obj); | |
| 159 builder.AppendCString(" ("); | |
| 160 if (eval_from_script->compilation_type() == Script::COMPILATION_TYPE_EVAL) { | |
| 161 // Eval script originated from another eval. | |
| 162 Handle<String> str; | |
| 163 ASSIGN_RETURN_ON_EXCEPTION( | |
| 164 isolate, str, FormatEvalOrigin(isolate, eval_from_script), String); | |
| 165 builder.AppendString(str); | |
| 166 } else { | |
| 167 DCHECK(eval_from_script->compilation_type() != | |
| 168 Script::COMPILATION_TYPE_EVAL); | |
| 169 // eval script originated from "real" source. | |
| 170 Handle<Object> name_obj = handle(eval_from_script->name(), isolate); | |
| 171 if (eval_from_script->name()->IsString()) { | |
| 172 builder.AppendString(Handle<String>::cast(name_obj)); | |
| 173 | |
| 174 Script::PositionInfo info; | |
| 175 if (eval_from_script->GetPositionInfo(script->GetEvalPosition(), &info, | |
| 176 Script::NO_OFFSET)) { | |
| 177 builder.AppendCString(":"); | |
| 178 | |
| 179 Handle<String> str = isolate->factory()->NumberToString( | |
| 180 handle(Smi::FromInt(info.line + 1), isolate)); | |
| 181 builder.AppendString(str); | |
| 182 | |
| 183 builder.AppendCString(":"); | |
| 184 | |
| 185 str = isolate->factory()->NumberToString( | |
| 186 handle(Smi::FromInt(info.column + 1), isolate)); | |
| 187 builder.AppendString(str); | |
| 188 } | |
| 189 } else { | |
| 190 DCHECK(!eval_from_script->name()->IsString()); | |
| 191 builder.AppendCString("unknown source"); | |
| 192 } | |
| 193 } | |
| 194 builder.AppendCString(")"); | |
| 195 } | |
| 196 | |
| 197 Handle<String> result; | |
| 198 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String); | |
| 199 return result; | |
| 200 } | |
| 201 | |
| 202 MaybeHandle<Object> GetEvalOrigin(Isolate* isolate, Handle<JSObject> object) { | |
| 203 CallSite call_site(isolate, object); | |
| 204 if (call_site.IsWasm()) return isolate->factory()->undefined_value(); | |
| 205 | |
| 206 // Retrieve the function's script object. | |
| 207 | |
| 208 Handle<Object> function_obj; | |
| 209 Handle<Symbol> symbol = isolate->factory()->call_site_function_symbol(); | |
| 210 ASSIGN_RETURN_ON_EXCEPTION(isolate, function_obj, | |
| 211 JSObject::GetProperty(object, symbol), Object); | |
| 212 | |
| 213 DCHECK(function_obj->IsJSFunction()); | |
| 214 Handle<JSFunction> function = Handle<JSFunction>::cast(function_obj); | |
| 215 Handle<Object> script = handle(function->shared()->script(), isolate); | |
| 216 | |
| 217 if (!script->IsScript()) { | |
| 218 return isolate->factory()->undefined_value(); | |
| 219 } | |
| 220 | |
| 221 Handle<String> str; | |
| 222 ASSIGN_RETURN_ON_EXCEPTION( | |
| 223 isolate, str, FormatEvalOrigin(isolate, Handle<Script>::cast(script)), | |
| 224 String); | |
| 225 | |
| 226 return str; | |
| 227 } | |
| 228 | |
| 229 } // namespace | |
| 230 | |
| 231 BUILTIN(CallSitePrototypeGetEvalOrigin) { | 58 BUILTIN(CallSitePrototypeGetEvalOrigin) { |
| 232 HandleScope scope(isolate); | 59 HandleScope scope(isolate); |
| 233 CHECK_CALLSITE(recv, "getEvalOrigin"); | 60 CHECK_CALLSITE(recv, "getEvalOrigin"); |
| 234 RETURN_RESULT_OR_FAILURE(isolate, GetEvalOrigin(isolate, recv)); | 61 |
| 62 CallSite call_site(isolate, recv); |
| 63 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); |
| 64 return *call_site.GetEvalOrigin(); |
| 235 } | 65 } |
| 236 | 66 |
| 237 BUILTIN(CallSitePrototypeGetFileName) { | 67 BUILTIN(CallSitePrototypeGetFileName) { |
| 238 HandleScope scope(isolate); | 68 HandleScope scope(isolate); |
| 239 CHECK_CALLSITE(recv, "getFileName"); | 69 CHECK_CALLSITE(recv, "getFileName"); |
| 240 | 70 |
| 241 CallSite call_site(isolate, recv); | 71 CallSite call_site(isolate, recv); |
| 242 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); | 72 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); |
| 243 return *call_site.GetFileName(); | 73 return *call_site.GetFileName(); |
| 244 } | 74 } |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 Handle<Symbol> symbol = isolate->factory()->call_site_receiver_symbol(); | 154 Handle<Symbol> symbol = isolate->factory()->call_site_receiver_symbol(); |
| 325 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver, | 155 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver, |
| 326 JSObject::GetProperty(recv, symbol)); | 156 JSObject::GetProperty(recv, symbol)); |
| 327 | 157 |
| 328 if (*receiver == isolate->heap()->call_site_constructor_symbol()) | 158 if (*receiver == isolate->heap()->call_site_constructor_symbol()) |
| 329 return *isolate->factory()->undefined_value(); | 159 return *isolate->factory()->undefined_value(); |
| 330 | 160 |
| 331 return *receiver; | 161 return *receiver; |
| 332 } | 162 } |
| 333 | 163 |
| 334 namespace { | |
| 335 | |
| 336 MaybeHandle<Object> GetTypeName(Isolate* isolate, Handle<JSObject> object) { | |
| 337 Handle<Object> receiver; | |
| 338 Handle<Symbol> symbol = isolate->factory()->call_site_receiver_symbol(); | |
| 339 ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver, | |
| 340 JSObject::GetProperty(object, symbol), Object); | |
| 341 | |
| 342 // TODO(jgruber): Check for strict/constructor here as above. | |
| 343 | |
| 344 if (receiver->IsNull(isolate) || receiver->IsUndefined(isolate)) | |
| 345 return isolate->factory()->null_value(); | |
| 346 | |
| 347 if (receiver->IsJSProxy()) return isolate->factory()->Proxy_string(); | |
| 348 | |
| 349 Handle<JSReceiver> receiver_object = | |
| 350 Object::ToObject(isolate, receiver).ToHandleChecked(); | |
| 351 return JSReceiver::GetConstructorName(receiver_object); | |
| 352 } | |
| 353 | |
| 354 } // namespace | |
| 355 | |
| 356 BUILTIN(CallSitePrototypeGetTypeName) { | 164 BUILTIN(CallSitePrototypeGetTypeName) { |
| 357 HandleScope scope(isolate); | 165 HandleScope scope(isolate); |
| 358 CHECK_CALLSITE(recv, "getTypeName"); | 166 CHECK_CALLSITE(recv, "getTypeName"); |
| 359 RETURN_RESULT_OR_FAILURE(isolate, GetTypeName(isolate, recv)); | 167 |
| 168 CallSite call_site(isolate, recv); |
| 169 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); |
| 170 return *call_site.GetTypeName(); |
| 360 } | 171 } |
| 361 | 172 |
| 362 BUILTIN(CallSitePrototypeIsConstructor) { | 173 BUILTIN(CallSitePrototypeIsConstructor) { |
| 363 HandleScope scope(isolate); | 174 HandleScope scope(isolate); |
| 364 CHECK_CALLSITE(recv, "isConstructor"); | 175 CHECK_CALLSITE(recv, "isConstructor"); |
| 365 | 176 |
| 366 CallSite call_site(isolate, recv); | 177 CallSite call_site(isolate, recv); |
| 367 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); | 178 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); |
| 368 return isolate->heap()->ToBoolean(call_site.IsConstructor()); | 179 return isolate->heap()->ToBoolean(call_site.IsConstructor()); |
| 369 } | 180 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 388 | 199 |
| 389 BUILTIN(CallSitePrototypeIsToplevel) { | 200 BUILTIN(CallSitePrototypeIsToplevel) { |
| 390 HandleScope scope(isolate); | 201 HandleScope scope(isolate); |
| 391 CHECK_CALLSITE(recv, "isToplevel"); | 202 CHECK_CALLSITE(recv, "isToplevel"); |
| 392 | 203 |
| 393 CallSite call_site(isolate, recv); | 204 CallSite call_site(isolate, recv); |
| 394 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); | 205 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); |
| 395 return isolate->heap()->ToBoolean(call_site.IsToplevel()); | 206 return isolate->heap()->ToBoolean(call_site.IsToplevel()); |
| 396 } | 207 } |
| 397 | 208 |
| 398 namespace { | |
| 399 | |
| 400 bool IsNonEmptyString(Handle<Object> object) { | |
| 401 return (object->IsString() && String::cast(*object)->length() > 0); | |
| 402 } | |
| 403 | |
| 404 MaybeHandle<JSObject> AppendWasmToString(Isolate* isolate, | |
| 405 Handle<JSObject> recv, | |
| 406 CallSite* call_site, | |
| 407 IncrementalStringBuilder* builder) { | |
| 408 Handle<Object> name = call_site->GetFunctionName(); | |
| 409 if (name->IsNull(isolate)) { | |
| 410 builder->AppendCString("<WASM UNNAMED>"); | |
| 411 } else { | |
| 412 DCHECK(name->IsString()); | |
| 413 builder->AppendString(Handle<String>::cast(name)); | |
| 414 } | |
| 415 | |
| 416 builder->AppendCString(" (<WASM>["); | |
| 417 | |
| 418 Handle<String> ix = isolate->factory()->NumberToString( | |
| 419 handle(Smi::FromInt(call_site->wasm_func_index()), isolate)); | |
| 420 builder->AppendString(ix); | |
| 421 | |
| 422 builder->AppendCString("]+"); | |
| 423 | |
| 424 Handle<Object> pos; | |
| 425 ASSIGN_RETURN_ON_EXCEPTION( | |
| 426 isolate, pos, JSObject::GetProperty( | |
| 427 recv, isolate->factory()->call_site_position_symbol()), | |
| 428 JSObject); | |
| 429 DCHECK(pos->IsNumber()); | |
| 430 builder->AppendString(isolate->factory()->NumberToString(pos)); | |
| 431 builder->AppendCString(")"); | |
| 432 | |
| 433 return recv; | |
| 434 } | |
| 435 | |
| 436 MaybeHandle<JSObject> AppendFileLocation(Isolate* isolate, | |
| 437 Handle<JSObject> recv, | |
| 438 CallSite* call_site, | |
| 439 IncrementalStringBuilder* builder) { | |
| 440 if (call_site->IsNative()) { | |
| 441 builder->AppendCString("native"); | |
| 442 return recv; | |
| 443 } | |
| 444 | |
| 445 Handle<Object> file_name = call_site->GetScriptNameOrSourceUrl(); | |
| 446 if (!file_name->IsString() && call_site->IsEval()) { | |
| 447 Handle<Object> eval_origin; | |
| 448 ASSIGN_RETURN_ON_EXCEPTION(isolate, eval_origin, | |
| 449 GetEvalOrigin(isolate, recv), JSObject); | |
| 450 DCHECK(eval_origin->IsString()); | |
| 451 builder->AppendString(Handle<String>::cast(eval_origin)); | |
| 452 builder->AppendCString(", "); // Expecting source position to follow. | |
| 453 } | |
| 454 | |
| 455 if (IsNonEmptyString(file_name)) { | |
| 456 builder->AppendString(Handle<String>::cast(file_name)); | |
| 457 } else { | |
| 458 // Source code does not originate from a file and is not native, but we | |
| 459 // can still get the source position inside the source string, e.g. in | |
| 460 // an eval string. | |
| 461 builder->AppendCString("<anonymous>"); | |
| 462 } | |
| 463 | |
| 464 int line_number = call_site->GetLineNumber(); | |
| 465 if (line_number != -1) { | |
| 466 builder->AppendCharacter(':'); | |
| 467 Handle<String> line_string = isolate->factory()->NumberToString( | |
| 468 handle(Smi::FromInt(line_number), isolate), isolate); | |
| 469 builder->AppendString(line_string); | |
| 470 | |
| 471 int column_number = call_site->GetColumnNumber(); | |
| 472 if (column_number != -1) { | |
| 473 builder->AppendCharacter(':'); | |
| 474 Handle<String> column_string = isolate->factory()->NumberToString( | |
| 475 handle(Smi::FromInt(column_number), isolate), isolate); | |
| 476 builder->AppendString(column_string); | |
| 477 } | |
| 478 } | |
| 479 | |
| 480 return recv; | |
| 481 } | |
| 482 | |
| 483 int StringIndexOf(Isolate* isolate, Handle<String> subject, | |
| 484 Handle<String> pattern) { | |
| 485 if (pattern->length() > subject->length()) return -1; | |
| 486 return String::IndexOf(isolate, subject, pattern, 0); | |
| 487 } | |
| 488 | |
| 489 // Returns true iff | |
| 490 // 1. the subject ends with '.' + pattern, or | |
| 491 // 2. subject == pattern. | |
| 492 bool StringEndsWithMethodName(Isolate* isolate, Handle<String> subject, | |
| 493 Handle<String> pattern) { | |
| 494 if (String::Equals(subject, pattern)) return true; | |
| 495 | |
| 496 FlatStringReader subject_reader(isolate, String::Flatten(subject)); | |
| 497 FlatStringReader pattern_reader(isolate, String::Flatten(pattern)); | |
| 498 | |
| 499 int pattern_index = pattern_reader.length() - 1; | |
| 500 int subject_index = subject_reader.length() - 1; | |
| 501 for (int i = 0; i <= pattern_reader.length(); i++) { // Iterate over len + 1. | |
| 502 if (subject_index < 0) { | |
| 503 return false; | |
| 504 } | |
| 505 | |
| 506 const uc32 subject_char = subject_reader.Get(subject_index); | |
| 507 if (i == pattern_reader.length()) { | |
| 508 if (subject_char != '.') return false; | |
| 509 } else if (subject_char != pattern_reader.Get(pattern_index)) { | |
| 510 return false; | |
| 511 } | |
| 512 | |
| 513 pattern_index--; | |
| 514 subject_index--; | |
| 515 } | |
| 516 | |
| 517 return true; | |
| 518 } | |
| 519 | |
| 520 MaybeHandle<JSObject> AppendMethodCall(Isolate* isolate, Handle<JSObject> recv, | |
| 521 CallSite* call_site, | |
| 522 IncrementalStringBuilder* builder) { | |
| 523 Handle<Object> type_name; | |
| 524 ASSIGN_RETURN_ON_EXCEPTION(isolate, type_name, GetTypeName(isolate, recv), | |
| 525 JSObject); | |
| 526 Handle<Object> method_name = call_site->GetMethodName(); | |
| 527 Handle<Object> function_name = call_site->GetFunctionName(); | |
| 528 | |
| 529 if (IsNonEmptyString(function_name)) { | |
| 530 Handle<String> function_string = Handle<String>::cast(function_name); | |
| 531 if (type_name->IsString()) { | |
| 532 Handle<String> type_string = Handle<String>::cast(type_name); | |
| 533 bool starts_with_type_name = | |
| 534 (StringIndexOf(isolate, function_string, type_string) == 0); | |
| 535 if (!starts_with_type_name) { | |
| 536 builder->AppendString(type_string); | |
| 537 builder->AppendCharacter('.'); | |
| 538 } | |
| 539 } | |
| 540 builder->AppendString(function_string); | |
| 541 | |
| 542 if (IsNonEmptyString(method_name)) { | |
| 543 Handle<String> method_string = Handle<String>::cast(method_name); | |
| 544 if (!StringEndsWithMethodName(isolate, function_string, method_string)) { | |
| 545 builder->AppendCString(" [as "); | |
| 546 builder->AppendString(method_string); | |
| 547 builder->AppendCharacter(']'); | |
| 548 } | |
| 549 } | |
| 550 } else { | |
| 551 builder->AppendString(Handle<String>::cast(type_name)); | |
| 552 builder->AppendCharacter('.'); | |
| 553 if (IsNonEmptyString(method_name)) { | |
| 554 builder->AppendString(Handle<String>::cast(method_name)); | |
| 555 } else { | |
| 556 builder->AppendCString("<anonymous>"); | |
| 557 } | |
| 558 } | |
| 559 | |
| 560 return recv; | |
| 561 } | |
| 562 | |
| 563 } // namespace | |
| 564 | |
| 565 BUILTIN(CallSitePrototypeToString) { | 209 BUILTIN(CallSitePrototypeToString) { |
| 566 HandleScope scope(isolate); | 210 HandleScope scope(isolate); |
| 567 CHECK_CALLSITE(recv, "toString"); | 211 CHECK_CALLSITE(recv, "toString"); |
| 568 | 212 RETURN_RESULT_OR_FAILURE(isolate, CallSiteUtils::ToString(isolate, recv)); |
| 569 IncrementalStringBuilder builder(isolate); | |
| 570 | |
| 571 CallSite call_site(isolate, recv); | |
| 572 if (call_site.IsWasm()) { | |
| 573 RETURN_FAILURE_ON_EXCEPTION( | |
| 574 isolate, AppendWasmToString(isolate, recv, &call_site, &builder)); | |
| 575 RETURN_RESULT_OR_FAILURE(isolate, builder.Finish()); | |
| 576 } | |
| 577 | |
| 578 DCHECK(!call_site.IsWasm()); | |
| 579 Handle<Object> function_name = call_site.GetFunctionName(); | |
| 580 | |
| 581 const bool is_toplevel = call_site.IsToplevel(); | |
| 582 const bool is_constructor = call_site.IsConstructor(); | |
| 583 const bool is_method_call = !(is_toplevel || is_constructor); | |
| 584 | |
| 585 if (is_method_call) { | |
| 586 RETURN_FAILURE_ON_EXCEPTION( | |
| 587 isolate, AppendMethodCall(isolate, recv, &call_site, &builder)); | |
| 588 } else if (is_constructor) { | |
| 589 builder.AppendCString("new "); | |
| 590 if (IsNonEmptyString(function_name)) { | |
| 591 builder.AppendString(Handle<String>::cast(function_name)); | |
| 592 } else { | |
| 593 builder.AppendCString("<anonymous>"); | |
| 594 } | |
| 595 } else if (IsNonEmptyString(function_name)) { | |
| 596 builder.AppendString(Handle<String>::cast(function_name)); | |
| 597 } else { | |
| 598 RETURN_FAILURE_ON_EXCEPTION( | |
| 599 isolate, AppendFileLocation(isolate, recv, &call_site, &builder)); | |
| 600 RETURN_RESULT_OR_FAILURE(isolate, builder.Finish()); | |
| 601 } | |
| 602 | |
| 603 builder.AppendCString(" ("); | |
| 604 RETURN_FAILURE_ON_EXCEPTION( | |
| 605 isolate, AppendFileLocation(isolate, recv, &call_site, &builder)); | |
| 606 builder.AppendCString(")"); | |
| 607 | |
| 608 RETURN_RESULT_OR_FAILURE(isolate, builder.Finish()); | |
| 609 } | 213 } |
| 610 | 214 |
| 611 #undef CHECK_CALLSITE | 215 #undef CHECK_CALLSITE |
| 612 | 216 |
| 613 } // namespace internal | 217 } // namespace internal |
| 614 } // namespace v8 | 218 } // namespace v8 |
| OLD | NEW |