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 |