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