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 |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 } | 192 } |
193 } | 193 } |
194 builder.AppendCString(")"); | 194 builder.AppendCString(")"); |
195 } | 195 } |
196 | 196 |
197 Handle<String> result; | 197 Handle<String> result; |
198 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String); | 198 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String); |
199 return result; | 199 return result; |
200 } | 200 } |
201 | 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 |
202 } // namespace | 229 } // namespace |
203 | 230 |
204 BUILTIN(CallSitePrototypeGetEvalOrigin) { | 231 BUILTIN(CallSitePrototypeGetEvalOrigin) { |
205 HandleScope scope(isolate); | 232 HandleScope scope(isolate); |
206 CHECK_CALLSITE(recv, "getEvalOrigin"); | 233 CHECK_CALLSITE(recv, "getEvalOrigin"); |
207 | 234 RETURN_RESULT_OR_FAILURE(isolate, GetEvalOrigin(isolate, recv)); |
208 CallSite call_site(isolate, recv); | |
209 if (call_site.IsWasm()) return *isolate->factory()->undefined_value(); | |
210 | |
211 // Retrieve the function's script object. | |
212 | |
213 Handle<Object> function_obj; | |
214 Handle<Symbol> symbol = isolate->factory()->call_site_function_symbol(); | |
215 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, function_obj, | |
216 JSObject::GetProperty(recv, symbol)); | |
217 | |
218 DCHECK(function_obj->IsJSFunction()); | |
219 Handle<JSFunction> function = Handle<JSFunction>::cast(function_obj); | |
220 Handle<Object> script = handle(function->shared()->script(), isolate); | |
221 | |
222 if (!script->IsScript()) { | |
223 return *isolate->factory()->undefined_value(); | |
224 } | |
225 | |
226 RETURN_RESULT_OR_FAILURE( | |
227 isolate, FormatEvalOrigin(isolate, Handle<Script>::cast(script))); | |
228 } | 235 } |
229 | 236 |
230 BUILTIN(CallSitePrototypeGetFileName) { | 237 BUILTIN(CallSitePrototypeGetFileName) { |
231 HandleScope scope(isolate); | 238 HandleScope scope(isolate); |
232 CHECK_CALLSITE(recv, "getFileName"); | 239 CHECK_CALLSITE(recv, "getFileName"); |
233 | 240 |
234 CallSite call_site(isolate, recv); | 241 CallSite call_site(isolate, recv); |
235 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); | 242 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); |
236 return *call_site.GetFileName(); | 243 return *call_site.GetFileName(); |
237 } | 244 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 Handle<Symbol> symbol = isolate->factory()->call_site_receiver_symbol(); | 324 Handle<Symbol> symbol = isolate->factory()->call_site_receiver_symbol(); |
318 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver, | 325 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver, |
319 JSObject::GetProperty(recv, symbol)); | 326 JSObject::GetProperty(recv, symbol)); |
320 | 327 |
321 if (*receiver == isolate->heap()->call_site_constructor_symbol()) | 328 if (*receiver == isolate->heap()->call_site_constructor_symbol()) |
322 return *isolate->factory()->undefined_value(); | 329 return *isolate->factory()->undefined_value(); |
323 | 330 |
324 return *receiver; | 331 return *receiver; |
325 } | 332 } |
326 | 333 |
| 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 |
327 BUILTIN(CallSitePrototypeGetTypeName) { | 356 BUILTIN(CallSitePrototypeGetTypeName) { |
328 HandleScope scope(isolate); | 357 HandleScope scope(isolate); |
329 CHECK_CALLSITE(recv, "getTypeName"); | 358 CHECK_CALLSITE(recv, "getTypeName"); |
330 | 359 RETURN_RESULT_OR_FAILURE(isolate, GetTypeName(isolate, recv)); |
331 Handle<Object> receiver; | |
332 Handle<Symbol> symbol = isolate->factory()->call_site_receiver_symbol(); | |
333 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver, | |
334 JSObject::GetProperty(recv, symbol)); | |
335 | |
336 // TODO(jgruber): Check for strict/constructor here as above. | |
337 | |
338 if (receiver->IsNull(isolate) || receiver->IsUndefined(isolate)) | |
339 return *isolate->factory()->null_value(); | |
340 | |
341 if (receiver->IsJSProxy()) return *isolate->factory()->Proxy_string(); | |
342 | |
343 Handle<JSReceiver> receiver_object = | |
344 Object::ToObject(isolate, receiver).ToHandleChecked(); | |
345 return *JSReceiver::GetConstructorName(receiver_object); | |
346 } | 360 } |
347 | 361 |
348 BUILTIN(CallSitePrototypeIsConstructor) { | 362 BUILTIN(CallSitePrototypeIsConstructor) { |
349 HandleScope scope(isolate); | 363 HandleScope scope(isolate); |
350 CHECK_CALLSITE(recv, "isConstructor"); | 364 CHECK_CALLSITE(recv, "isConstructor"); |
351 | 365 |
352 CallSite call_site(isolate, recv); | 366 CallSite call_site(isolate, recv); |
353 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); | 367 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); |
354 return isolate->heap()->ToBoolean(call_site.IsConstructor()); | 368 return isolate->heap()->ToBoolean(call_site.IsConstructor()); |
355 } | 369 } |
(...skipping 18 matching lines...) Expand all Loading... |
374 | 388 |
375 BUILTIN(CallSitePrototypeIsToplevel) { | 389 BUILTIN(CallSitePrototypeIsToplevel) { |
376 HandleScope scope(isolate); | 390 HandleScope scope(isolate); |
377 CHECK_CALLSITE(recv, "isToplevel"); | 391 CHECK_CALLSITE(recv, "isToplevel"); |
378 | 392 |
379 CallSite call_site(isolate, recv); | 393 CallSite call_site(isolate, recv); |
380 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); | 394 CHECK(call_site.IsJavaScript() || call_site.IsWasm()); |
381 return isolate->heap()->ToBoolean(call_site.IsToplevel()); | 395 return isolate->heap()->ToBoolean(call_site.IsToplevel()); |
382 } | 396 } |
383 | 397 |
| 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 |
384 BUILTIN(CallSitePrototypeToString) { | 565 BUILTIN(CallSitePrototypeToString) { |
385 HandleScope scope(isolate); | 566 HandleScope scope(isolate); |
386 // TODO(jgruber) | 567 CHECK_CALLSITE(recv, "toString"); |
387 return *isolate->factory()->undefined_value(); | 568 |
| 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()); |
388 } | 609 } |
389 | 610 |
390 #undef CHECK_CALLSITE | 611 #undef CHECK_CALLSITE |
391 | 612 |
392 } // namespace internal | 613 } // namespace internal |
393 } // namespace v8 | 614 } // namespace v8 |
OLD | NEW |