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, ConstructCallSite(isolate, target, new_target, receiver, fun, |
41 Handle<JSReceiver> new_target = new_target_obj->IsJSReceiver() | 37 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, CallSiteToString(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 |