OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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/messages.h" | 5 #include "src/messages.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/execution.h" | 10 #include "src/execution.h" |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 Handle<Object> arg = Handle<Object>(message->argument(), isolate); | 157 Handle<Object> arg = Handle<Object>(message->argument(), isolate); |
158 return MessageTemplate::FormatMessage(isolate, message->type(), arg); | 158 return MessageTemplate::FormatMessage(isolate, message->type(), arg); |
159 } | 159 } |
160 | 160 |
161 std::unique_ptr<char[]> MessageHandler::GetLocalizedMessage( | 161 std::unique_ptr<char[]> MessageHandler::GetLocalizedMessage( |
162 Isolate* isolate, Handle<Object> data) { | 162 Isolate* isolate, Handle<Object> data) { |
163 HandleScope scope(isolate); | 163 HandleScope scope(isolate); |
164 return GetMessage(isolate, data)->ToCString(DISALLOW_NULLS); | 164 return GetMessage(isolate, data)->ToCString(DISALLOW_NULLS); |
165 } | 165 } |
166 | 166 |
| 167 void JSStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array, |
| 168 int frame_ix) { |
| 169 DCHECK(!array->IsWasmFrame(frame_ix)); |
| 170 isolate_ = isolate; |
| 171 receiver_ = handle(array->Receiver(frame_ix), isolate); |
| 172 function_ = handle(array->Function(frame_ix), isolate); |
| 173 code_ = handle(array->Code(frame_ix), isolate); |
| 174 offset_ = array->Offset(frame_ix)->value(); |
167 | 175 |
168 CallSite::CallSite(Isolate* isolate, Handle<JSObject> call_site_obj) | 176 const int flags = array->Flags(frame_ix)->value(); |
169 : isolate_(isolate) { | 177 force_constructor_ = (flags & FrameArray::kForceConstructor) != 0; |
170 Handle<Object> maybe_function = JSObject::GetDataProperty( | 178 is_strict_ = (flags & FrameArray::kIsStrict) != 0; |
171 call_site_obj, isolate->factory()->call_site_function_symbol()); | |
172 if (maybe_function->IsJSFunction()) { | |
173 // javascript | |
174 fun_ = Handle<JSFunction>::cast(maybe_function); | |
175 receiver_ = JSObject::GetDataProperty( | |
176 call_site_obj, isolate->factory()->call_site_receiver_symbol()); | |
177 } else { | |
178 Handle<Object> maybe_wasm_func_index = JSObject::GetDataProperty( | |
179 call_site_obj, isolate->factory()->call_site_wasm_func_index_symbol()); | |
180 if (!maybe_wasm_func_index->IsSmi()) { | |
181 // invalid: neither javascript nor wasm | |
182 return; | |
183 } | |
184 // wasm | |
185 wasm_obj_ = Handle<JSObject>::cast(JSObject::GetDataProperty( | |
186 call_site_obj, isolate->factory()->call_site_wasm_obj_symbol())); | |
187 wasm_func_index_ = Smi::cast(*maybe_wasm_func_index)->value(); | |
188 DCHECK(static_cast<int>(wasm_func_index_) >= 0); | |
189 } | |
190 | |
191 CHECK(JSObject::GetDataProperty( | |
192 call_site_obj, isolate->factory()->call_site_position_symbol()) | |
193 ->ToInt32(&pos_)); | |
194 } | 179 } |
195 | 180 |
| 181 JSStackFrame::JSStackFrame(Isolate* isolate, Handle<Object> receiver, |
| 182 Handle<JSFunction> function, |
| 183 Handle<AbstractCode> code, int offset) |
| 184 : isolate_(isolate), |
| 185 receiver_(receiver), |
| 186 function_(function), |
| 187 code_(code), |
| 188 offset_(offset), |
| 189 force_constructor_(false), |
| 190 is_strict_(false) {} |
196 | 191 |
197 Handle<Object> CallSite::GetFileName() { | 192 JSStackFrame::JSStackFrame() {} |
198 if (!IsJavaScript()) return isolate_->factory()->null_value(); | 193 |
199 Object* script = fun_->shared()->script(); | 194 Handle<Object> JSStackFrame::GetFunction() const { |
200 if (!script->IsScript()) return isolate_->factory()->null_value(); | 195 return Handle<Object>::cast(function_); |
201 return Handle<Object>(Script::cast(script)->name(), isolate_); | |
202 } | 196 } |
203 | 197 |
| 198 Handle<Object> JSStackFrame::GetFileName() { |
| 199 if (!HasScript()) return isolate_->factory()->null_value(); |
| 200 return handle(GetScript()->name(), isolate_); |
| 201 } |
204 | 202 |
205 Handle<Object> CallSite::GetFunctionName() { | 203 Handle<Object> JSStackFrame::GetFunctionName() { |
206 if (IsWasm()) { | 204 Handle<String> result = JSFunction::GetName(function_); |
207 return wasm::GetWasmFunctionNameOrNull(isolate_, wasm_obj_, | |
208 wasm_func_index_); | |
209 } | |
210 Handle<String> result = JSFunction::GetName(fun_); | |
211 if (result->length() != 0) return result; | 205 if (result->length() != 0) return result; |
212 | 206 |
213 Handle<Object> script(fun_->shared()->script(), isolate_); | 207 if (HasScript() && |
214 if (script->IsScript() && | 208 GetScript()->compilation_type() == Script::COMPILATION_TYPE_EVAL) { |
215 Handle<Script>::cast(script)->compilation_type() == | |
216 Script::COMPILATION_TYPE_EVAL) { | |
217 return isolate_->factory()->eval_string(); | 209 return isolate_->factory()->eval_string(); |
218 } | 210 } |
219 return isolate_->factory()->null_value(); | 211 return isolate_->factory()->null_value(); |
220 } | 212 } |
221 | 213 |
222 Handle<Object> CallSite::GetScriptNameOrSourceUrl() { | 214 Handle<Object> JSStackFrame::GetScriptNameOrSourceUrl() { |
223 if (!IsJavaScript()) return isolate_->factory()->null_value(); | 215 if (!HasScript()) return isolate_->factory()->null_value(); |
224 Object* script_obj = fun_->shared()->script(); | 216 Handle<Script> script = GetScript(); |
225 if (!script_obj->IsScript()) return isolate_->factory()->null_value(); | |
226 Handle<Script> script(Script::cast(script_obj), isolate_); | |
227 Object* source_url = script->source_url(); | 217 Object* source_url = script->source_url(); |
228 if (source_url->IsString()) return Handle<Object>(source_url, isolate_); | 218 return (source_url->IsString()) ? handle(source_url, isolate_) |
229 return Handle<Object>(script->name(), isolate_); | 219 : handle(script->name(), isolate_); |
230 } | 220 } |
231 | 221 |
| 222 namespace { |
| 223 |
232 bool CheckMethodName(Isolate* isolate, Handle<JSObject> obj, Handle<Name> name, | 224 bool CheckMethodName(Isolate* isolate, Handle<JSObject> obj, Handle<Name> name, |
233 Handle<JSFunction> fun, | 225 Handle<JSFunction> fun, |
234 LookupIterator::Configuration config) { | 226 LookupIterator::Configuration config) { |
235 LookupIterator iter = | 227 LookupIterator iter = |
236 LookupIterator::PropertyOrElement(isolate, obj, name, config); | 228 LookupIterator::PropertyOrElement(isolate, obj, name, config); |
237 if (iter.state() == LookupIterator::DATA) { | 229 if (iter.state() == LookupIterator::DATA) { |
238 return iter.GetDataValue().is_identical_to(fun); | 230 return iter.GetDataValue().is_identical_to(fun); |
239 } else if (iter.state() == LookupIterator::ACCESSOR) { | 231 } else if (iter.state() == LookupIterator::ACCESSOR) { |
240 Handle<Object> accessors = iter.GetAccessors(); | 232 Handle<Object> accessors = iter.GetAccessors(); |
241 if (accessors->IsAccessorPair()) { | 233 if (accessors->IsAccessorPair()) { |
242 Handle<AccessorPair> pair = Handle<AccessorPair>::cast(accessors); | 234 Handle<AccessorPair> pair = Handle<AccessorPair>::cast(accessors); |
243 return pair->getter() == *fun || pair->setter() == *fun; | 235 return pair->getter() == *fun || pair->setter() == *fun; |
244 } | 236 } |
245 } | 237 } |
246 return false; | 238 return false; |
247 } | 239 } |
248 | 240 |
| 241 } // namespace |
249 | 242 |
250 Handle<Object> CallSite::GetMethodName() { | 243 Handle<Object> JSStackFrame::GetMethodName() { |
251 if (!IsJavaScript() || receiver_->IsNull(isolate_) || | 244 if (receiver_->IsNull(isolate_) || receiver_->IsUndefined(isolate_)) { |
252 receiver_->IsUndefined(isolate_)) { | |
253 return isolate_->factory()->null_value(); | 245 return isolate_->factory()->null_value(); |
254 } | 246 } |
| 247 |
255 Handle<JSReceiver> receiver = | 248 Handle<JSReceiver> receiver = |
256 Object::ToObject(isolate_, receiver_).ToHandleChecked(); | 249 Object::ToObject(isolate_, receiver_).ToHandleChecked(); |
257 if (!receiver->IsJSObject()) { | 250 if (!receiver->IsJSObject()) { |
258 return isolate_->factory()->null_value(); | 251 return isolate_->factory()->null_value(); |
259 } | 252 } |
260 | 253 |
261 Handle<JSObject> obj = Handle<JSObject>::cast(receiver); | 254 Handle<JSObject> obj = Handle<JSObject>::cast(receiver); |
262 Handle<Object> function_name(fun_->shared()->name(), isolate_); | 255 Handle<Object> function_name(function_->shared()->name(), isolate_); |
263 if (function_name->IsString()) { | 256 if (function_name->IsString()) { |
264 Handle<String> name = Handle<String>::cast(function_name); | 257 Handle<String> name = Handle<String>::cast(function_name); |
265 // ES2015 gives getters and setters name prefixes which must | 258 // ES2015 gives getters and setters name prefixes which must |
266 // be stripped to find the property name. | 259 // be stripped to find the property name. |
267 if (name->IsUtf8EqualTo(CStrVector("get "), true) || | 260 if (name->IsUtf8EqualTo(CStrVector("get "), true) || |
268 name->IsUtf8EqualTo(CStrVector("set "), true)) { | 261 name->IsUtf8EqualTo(CStrVector("set "), true)) { |
269 name = isolate_->factory()->NewProperSubString(name, 4, name->length()); | 262 name = isolate_->factory()->NewProperSubString(name, 4, name->length()); |
270 } | 263 } |
271 if (CheckMethodName(isolate_, obj, name, fun_, | 264 if (CheckMethodName(isolate_, obj, name, function_, |
272 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR)) { | 265 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR)) { |
273 return name; | 266 return name; |
274 } | 267 } |
275 } | 268 } |
276 | 269 |
277 HandleScope outer_scope(isolate_); | 270 HandleScope outer_scope(isolate_); |
278 Handle<Object> result; | 271 Handle<Object> result; |
279 for (PrototypeIterator iter(isolate_, obj, kStartAtReceiver); !iter.IsAtEnd(); | 272 for (PrototypeIterator iter(isolate_, obj, kStartAtReceiver); !iter.IsAtEnd(); |
280 iter.Advance()) { | 273 iter.Advance()) { |
281 Handle<Object> current = PrototypeIterator::GetCurrent(iter); | 274 Handle<Object> current = PrototypeIterator::GetCurrent(iter); |
282 if (!current->IsJSObject()) break; | 275 if (!current->IsJSObject()) break; |
283 Handle<JSObject> current_obj = Handle<JSObject>::cast(current); | 276 Handle<JSObject> current_obj = Handle<JSObject>::cast(current); |
284 if (current_obj->IsAccessCheckNeeded()) break; | 277 if (current_obj->IsAccessCheckNeeded()) break; |
285 Handle<FixedArray> keys = | 278 Handle<FixedArray> keys = |
286 KeyAccumulator::GetOwnEnumPropertyKeys(isolate_, current_obj); | 279 KeyAccumulator::GetOwnEnumPropertyKeys(isolate_, current_obj); |
287 for (int i = 0; i < keys->length(); i++) { | 280 for (int i = 0; i < keys->length(); i++) { |
288 HandleScope inner_scope(isolate_); | 281 HandleScope inner_scope(isolate_); |
289 if (!keys->get(i)->IsName()) continue; | 282 if (!keys->get(i)->IsName()) continue; |
290 Handle<Name> name_key(Name::cast(keys->get(i)), isolate_); | 283 Handle<Name> name_key(Name::cast(keys->get(i)), isolate_); |
291 if (!CheckMethodName(isolate_, current_obj, name_key, fun_, | 284 if (!CheckMethodName(isolate_, current_obj, name_key, function_, |
292 LookupIterator::OWN_SKIP_INTERCEPTOR)) | 285 LookupIterator::OWN_SKIP_INTERCEPTOR)) |
293 continue; | 286 continue; |
294 // Return null in case of duplicates to avoid confusion. | 287 // Return null in case of duplicates to avoid confusion. |
295 if (!result.is_null()) return isolate_->factory()->null_value(); | 288 if (!result.is_null()) return isolate_->factory()->null_value(); |
296 result = inner_scope.CloseAndEscape(name_key); | 289 result = inner_scope.CloseAndEscape(name_key); |
297 } | 290 } |
298 } | 291 } |
299 | 292 |
300 if (!result.is_null()) return outer_scope.CloseAndEscape(result); | 293 if (!result.is_null()) return outer_scope.CloseAndEscape(result); |
301 return isolate_->factory()->null_value(); | 294 return isolate_->factory()->null_value(); |
302 } | 295 } |
303 | 296 |
304 Handle<Object> CallSite::GetTypeName() { | |
305 // TODO(jgruber): Check for strict/constructor here as in | |
306 // CallSitePrototypeGetThis. | |
307 | |
308 if (receiver_->IsNull(isolate_) || receiver_->IsUndefined(isolate_)) | |
309 return isolate_->factory()->null_value(); | |
310 | |
311 if (receiver_->IsJSProxy()) return isolate_->factory()->Proxy_string(); | |
312 | |
313 Handle<JSReceiver> receiver_object = | |
314 Object::ToObject(isolate_, receiver_).ToHandleChecked(); | |
315 return JSReceiver::GetConstructorName(receiver_object); | |
316 } | |
317 | |
318 namespace { | 297 namespace { |
319 | 298 |
320 Object* EvalFromFunctionName(Isolate* isolate, Handle<Script> script) { | 299 Object* EvalFromFunctionName(Isolate* isolate, Handle<Script> script) { |
321 if (script->eval_from_shared()->IsUndefined(isolate)) | 300 if (script->eval_from_shared()->IsUndefined(isolate)) |
322 return *isolate->factory()->undefined_value(); | 301 return *isolate->factory()->undefined_value(); |
323 | 302 |
324 Handle<SharedFunctionInfo> shared( | 303 Handle<SharedFunctionInfo> shared( |
325 SharedFunctionInfo::cast(script->eval_from_shared())); | 304 SharedFunctionInfo::cast(script->eval_from_shared())); |
326 // Find the name of the function calling eval. | 305 // Find the name of the function calling eval. |
327 if (shared->name()->BooleanValue()) { | 306 if (shared->name()->BooleanValue()) { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 builder.AppendCString(")"); | 386 builder.AppendCString(")"); |
408 } | 387 } |
409 | 388 |
410 Handle<String> result; | 389 Handle<String> result; |
411 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String); | 390 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String); |
412 return result; | 391 return result; |
413 } | 392 } |
414 | 393 |
415 } // namespace | 394 } // namespace |
416 | 395 |
417 Handle<Object> CallSite::GetEvalOrigin() { | 396 Handle<Object> JSStackFrame::GetTypeName() { |
418 if (IsWasm()) return isolate_->factory()->undefined_value(); | 397 // TODO(jgruber): Check for strict/constructor here as in |
419 DCHECK(IsJavaScript()); | 398 // CallSitePrototypeGetThis. |
420 | 399 |
421 Handle<Object> script = handle(fun_->shared()->script(), isolate_); | 400 if (receiver_->IsNull(isolate_) || receiver_->IsUndefined(isolate_)) |
422 if (!script->IsScript()) return isolate_->factory()->undefined_value(); | 401 return isolate_->factory()->null_value(); |
423 | 402 |
424 return FormatEvalOrigin(isolate_, Handle<Script>::cast(script)) | 403 if (receiver_->IsJSProxy()) return isolate_->factory()->Proxy_string(); |
425 .ToHandleChecked(); | 404 |
426 } | 405 Handle<JSReceiver> receiver_object = |
427 | 406 Object::ToObject(isolate_, receiver_).ToHandleChecked(); |
428 int CallSite::GetLineNumber() { | 407 return JSReceiver::GetConstructorName(receiver_object); |
429 if (pos_ >= 0 && IsJavaScript()) { | 408 } |
430 Handle<Object> script_obj(fun_->shared()->script(), isolate_); | 409 |
431 if (script_obj->IsScript()) { | 410 Handle<Object> JSStackFrame::GetEvalOrigin() { |
432 Handle<Script> script = Handle<Script>::cast(script_obj); | 411 if (!HasScript()) return isolate_->factory()->undefined_value(); |
433 return Script::GetLineNumber(script, pos_) + 1; | 412 return FormatEvalOrigin(isolate_, GetScript()).ToHandleChecked(); |
434 } | 413 } |
435 } | 414 |
| 415 int JSStackFrame::GetLineNumber() { |
| 416 DCHECK_LE(0, GetPosition()); |
| 417 if (HasScript()) return Script::GetLineNumber(GetScript(), GetPosition()) + 1; |
436 return -1; | 418 return -1; |
437 } | 419 } |
438 | 420 |
439 | 421 int JSStackFrame::GetColumnNumber() { |
440 int CallSite::GetColumnNumber() { | 422 DCHECK_LE(0, GetPosition()); |
441 if (pos_ >= 0 && IsJavaScript()) { | 423 if (HasScript()) { |
442 Handle<Object> script_obj(fun_->shared()->script(), isolate_); | 424 return Script::GetColumnNumber(GetScript(), GetPosition()) + 1; |
443 if (script_obj->IsScript()) { | |
444 Handle<Script> script = Handle<Script>::cast(script_obj); | |
445 return Script::GetColumnNumber(script, pos_) + 1; | |
446 } | |
447 } | 425 } |
448 return -1; | 426 return -1; |
449 } | 427 } |
450 | 428 |
451 | 429 bool JSStackFrame::IsNative() { |
452 bool CallSite::IsNative() { | 430 return HasScript() && GetScript()->type() == Script::TYPE_NATIVE; |
453 if (!IsJavaScript()) return false; | 431 } |
454 Handle<Object> script(fun_->shared()->script(), isolate_); | 432 |
455 return script->IsScript() && | 433 bool JSStackFrame::IsToplevel() { |
456 Handle<Script>::cast(script)->type() == Script::TYPE_NATIVE; | |
457 } | |
458 | |
459 | |
460 bool CallSite::IsToplevel() { | |
461 if (IsWasm()) return false; | |
462 return receiver_->IsJSGlobalProxy() || receiver_->IsNull(isolate_) || | 434 return receiver_->IsJSGlobalProxy() || receiver_->IsNull(isolate_) || |
463 receiver_->IsUndefined(isolate_); | 435 receiver_->IsUndefined(isolate_); |
464 } | 436 } |
465 | 437 |
466 | 438 bool JSStackFrame::IsEval() { |
467 bool CallSite::IsEval() { | 439 return HasScript() && |
468 if (!IsJavaScript()) return false; | 440 GetScript()->compilation_type() == Script::COMPILATION_TYPE_EVAL; |
469 Handle<Object> script(fun_->shared()->script(), isolate_); | 441 } |
470 return script->IsScript() && | 442 |
471 Handle<Script>::cast(script)->compilation_type() == | 443 bool JSStackFrame::IsConstructor() { |
472 Script::COMPILATION_TYPE_EVAL; | 444 if (force_constructor_) return true; |
473 } | 445 if (!receiver_->IsJSObject()) return false; |
474 | |
475 | |
476 bool CallSite::IsConstructor() { | |
477 // Builtin exit frames mark constructors by passing a special symbol as the | |
478 // receiver. | |
479 Object* ctor_symbol = isolate_->heap()->call_site_constructor_symbol(); | |
480 if (*receiver_ == ctor_symbol) return true; | |
481 if (!IsJavaScript() || !receiver_->IsJSObject()) return false; | |
482 Handle<Object> constructor = | 446 Handle<Object> constructor = |
483 JSReceiver::GetDataProperty(Handle<JSObject>::cast(receiver_), | 447 JSReceiver::GetDataProperty(Handle<JSObject>::cast(receiver_), |
484 isolate_->factory()->constructor_string()); | 448 isolate_->factory()->constructor_string()); |
485 return constructor.is_identical_to(fun_); | 449 return constructor.is_identical_to(function_); |
486 } | 450 } |
487 | 451 |
488 namespace { | 452 namespace { |
489 | 453 |
| 454 bool IsNonEmptyString(Handle<Object> object) { |
| 455 return (object->IsString() && String::cast(*object)->length() > 0); |
| 456 } |
| 457 |
| 458 void AppendFileLocation(Isolate* isolate, JSStackFrame* call_site, |
| 459 IncrementalStringBuilder* builder) { |
| 460 if (call_site->IsNative()) { |
| 461 builder->AppendCString("native"); |
| 462 return; |
| 463 } |
| 464 |
| 465 Handle<Object> file_name = call_site->GetScriptNameOrSourceUrl(); |
| 466 if (!file_name->IsString() && call_site->IsEval()) { |
| 467 Handle<Object> eval_origin = call_site->GetEvalOrigin(); |
| 468 DCHECK(eval_origin->IsString()); |
| 469 builder->AppendString(Handle<String>::cast(eval_origin)); |
| 470 builder->AppendCString(", "); // Expecting source position to follow. |
| 471 } |
| 472 |
| 473 if (IsNonEmptyString(file_name)) { |
| 474 builder->AppendString(Handle<String>::cast(file_name)); |
| 475 } else { |
| 476 // Source code does not originate from a file and is not native, but we |
| 477 // can still get the source position inside the source string, e.g. in |
| 478 // an eval string. |
| 479 builder->AppendCString("<anonymous>"); |
| 480 } |
| 481 |
| 482 int line_number = call_site->GetLineNumber(); |
| 483 if (line_number != -1) { |
| 484 builder->AppendCharacter(':'); |
| 485 Handle<String> line_string = isolate->factory()->NumberToString( |
| 486 handle(Smi::FromInt(line_number), isolate), isolate); |
| 487 builder->AppendString(line_string); |
| 488 |
| 489 int column_number = call_site->GetColumnNumber(); |
| 490 if (column_number != -1) { |
| 491 builder->AppendCharacter(':'); |
| 492 Handle<String> column_string = isolate->factory()->NumberToString( |
| 493 handle(Smi::FromInt(column_number), isolate), isolate); |
| 494 builder->AppendString(column_string); |
| 495 } |
| 496 } |
| 497 } |
| 498 |
| 499 int StringIndexOf(Isolate* isolate, Handle<String> subject, |
| 500 Handle<String> pattern) { |
| 501 if (pattern->length() > subject->length()) return -1; |
| 502 return String::IndexOf(isolate, subject, pattern, 0); |
| 503 } |
| 504 |
| 505 // Returns true iff |
| 506 // 1. the subject ends with '.' + pattern, or |
| 507 // 2. subject == pattern. |
| 508 bool StringEndsWithMethodName(Isolate* isolate, Handle<String> subject, |
| 509 Handle<String> pattern) { |
| 510 if (String::Equals(subject, pattern)) return true; |
| 511 |
| 512 FlatStringReader subject_reader(isolate, String::Flatten(subject)); |
| 513 FlatStringReader pattern_reader(isolate, String::Flatten(pattern)); |
| 514 |
| 515 int pattern_index = pattern_reader.length() - 1; |
| 516 int subject_index = subject_reader.length() - 1; |
| 517 for (int i = 0; i <= pattern_reader.length(); i++) { // Iterate over len + 1. |
| 518 if (subject_index < 0) { |
| 519 return false; |
| 520 } |
| 521 |
| 522 const uc32 subject_char = subject_reader.Get(subject_index); |
| 523 if (i == pattern_reader.length()) { |
| 524 if (subject_char != '.') return false; |
| 525 } else if (subject_char != pattern_reader.Get(pattern_index)) { |
| 526 return false; |
| 527 } |
| 528 |
| 529 pattern_index--; |
| 530 subject_index--; |
| 531 } |
| 532 |
| 533 return true; |
| 534 } |
| 535 |
| 536 void AppendMethodCall(Isolate* isolate, JSStackFrame* call_site, |
| 537 IncrementalStringBuilder* builder) { |
| 538 Handle<Object> type_name = call_site->GetTypeName(); |
| 539 Handle<Object> method_name = call_site->GetMethodName(); |
| 540 Handle<Object> function_name = call_site->GetFunctionName(); |
| 541 |
| 542 if (IsNonEmptyString(function_name)) { |
| 543 Handle<String> function_string = Handle<String>::cast(function_name); |
| 544 if (IsNonEmptyString(type_name)) { |
| 545 Handle<String> type_string = Handle<String>::cast(type_name); |
| 546 bool starts_with_type_name = |
| 547 (StringIndexOf(isolate, function_string, type_string) == 0); |
| 548 if (!starts_with_type_name) { |
| 549 builder->AppendString(type_string); |
| 550 builder->AppendCharacter('.'); |
| 551 } |
| 552 } |
| 553 builder->AppendString(function_string); |
| 554 |
| 555 if (IsNonEmptyString(method_name)) { |
| 556 Handle<String> method_string = Handle<String>::cast(method_name); |
| 557 if (!StringEndsWithMethodName(isolate, function_string, method_string)) { |
| 558 builder->AppendCString(" [as "); |
| 559 builder->AppendString(method_string); |
| 560 builder->AppendCharacter(']'); |
| 561 } |
| 562 } |
| 563 } else { |
| 564 builder->AppendString(Handle<String>::cast(type_name)); |
| 565 builder->AppendCharacter('.'); |
| 566 if (IsNonEmptyString(method_name)) { |
| 567 builder->AppendString(Handle<String>::cast(method_name)); |
| 568 } else { |
| 569 builder->AppendCString("<anonymous>"); |
| 570 } |
| 571 } |
| 572 } |
| 573 |
| 574 } // namespace |
| 575 |
| 576 MaybeHandle<String> JSStackFrame::ToString() { |
| 577 IncrementalStringBuilder builder(isolate_); |
| 578 |
| 579 Handle<Object> function_name = GetFunctionName(); |
| 580 |
| 581 const bool is_toplevel = IsToplevel(); |
| 582 const bool is_constructor = IsConstructor(); |
| 583 const bool is_method_call = !(is_toplevel || is_constructor); |
| 584 |
| 585 if (is_method_call) { |
| 586 AppendMethodCall(isolate_, this, &builder); |
| 587 } else if (is_constructor) { |
| 588 builder.AppendCString("new "); |
| 589 if (IsNonEmptyString(function_name)) { |
| 590 builder.AppendString(Handle<String>::cast(function_name)); |
| 591 } else { |
| 592 builder.AppendCString("<anonymous>"); |
| 593 } |
| 594 } else if (IsNonEmptyString(function_name)) { |
| 595 builder.AppendString(Handle<String>::cast(function_name)); |
| 596 } else { |
| 597 AppendFileLocation(isolate_, this, &builder); |
| 598 RETURN_RESULT(isolate_, builder.Finish(), String); |
| 599 } |
| 600 |
| 601 builder.AppendCString(" ("); |
| 602 AppendFileLocation(isolate_, this, &builder); |
| 603 builder.AppendCString(")"); |
| 604 |
| 605 RETURN_RESULT(isolate_, builder.Finish(), String); |
| 606 } |
| 607 |
| 608 int JSStackFrame::GetPosition() const { return code_->SourcePosition(offset_); } |
| 609 |
| 610 bool JSStackFrame::HasScript() const { |
| 611 return function_->shared()->script()->IsScript(); |
| 612 } |
| 613 |
| 614 Handle<Script> JSStackFrame::GetScript() const { |
| 615 return handle(Script::cast(function_->shared()->script()), isolate_); |
| 616 } |
| 617 |
| 618 void WasmStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array, |
| 619 int frame_ix) { |
| 620 DCHECK(array->IsWasmFrame(frame_ix)); |
| 621 isolate_ = isolate; |
| 622 wasm_obj_ = handle(array->WasmObject(frame_ix), isolate); |
| 623 wasm_func_index_ = array->WasmFunctionIndex(frame_ix)->value(); |
| 624 code_ = handle(array->Code(frame_ix), isolate); |
| 625 offset_ = array->Offset(frame_ix)->value(); |
| 626 } |
| 627 |
| 628 Handle<Object> WasmStackFrame::GetFunction() const { |
| 629 Handle<Object> obj(Smi::FromInt(wasm_func_index_), isolate_); |
| 630 return obj; |
| 631 } |
| 632 |
| 633 Handle<Object> WasmStackFrame::GetFunctionName() { |
| 634 return wasm::GetWasmFunctionNameOrNull(isolate_, wasm_obj_, wasm_func_index_); |
| 635 } |
| 636 |
| 637 MaybeHandle<String> WasmStackFrame::ToString() { |
| 638 IncrementalStringBuilder builder(isolate_); |
| 639 |
| 640 Handle<Object> name = GetFunctionName(); |
| 641 if (name->IsNull(isolate_)) { |
| 642 builder.AppendCString("<WASM UNNAMED>"); |
| 643 } else { |
| 644 DCHECK(name->IsString()); |
| 645 builder.AppendString(Handle<String>::cast(name)); |
| 646 } |
| 647 |
| 648 builder.AppendCString(" (<WASM>["); |
| 649 |
| 650 Handle<Smi> ix(Smi::FromInt(wasm_func_index_), isolate_); |
| 651 builder.AppendString(isolate_->factory()->NumberToString(ix)); |
| 652 |
| 653 builder.AppendCString("]+"); |
| 654 |
| 655 Handle<Object> pos(Smi::FromInt(GetPosition()), isolate_); |
| 656 builder.AppendString(isolate_->factory()->NumberToString(pos)); |
| 657 builder.AppendCString(")"); |
| 658 |
| 659 return builder.Finish(); |
| 660 } |
| 661 |
| 662 int WasmStackFrame::GetPosition() const { |
| 663 return (offset_ < 0) ? (-1 - offset_) : code_->SourcePosition(offset_); |
| 664 } |
| 665 |
| 666 Handle<Object> WasmStackFrame::Null() const { |
| 667 return isolate_->factory()->null_value(); |
| 668 } |
| 669 |
| 670 FrameArrayIterator::FrameArrayIterator(Isolate* isolate, |
| 671 Handle<FrameArray> array, int frame_ix) |
| 672 : isolate_(isolate), array_(array), next_frame_ix_(frame_ix) {} |
| 673 |
| 674 bool FrameArrayIterator::HasNext() const { |
| 675 return (next_frame_ix_ < array_->FrameCount()); |
| 676 } |
| 677 |
| 678 void FrameArrayIterator::Next() { next_frame_ix_++; } |
| 679 |
| 680 StackFrameBase* FrameArrayIterator::Frame() { |
| 681 DCHECK(HasNext()); |
| 682 const int flags = array_->Flags(next_frame_ix_)->value(); |
| 683 const bool is_js_frame = (flags & FrameArray::kIsWasmFrame) == 0; |
| 684 if (is_js_frame) { |
| 685 js_frame_.FromFrameArray(isolate_, array_, next_frame_ix_); |
| 686 return &js_frame_; |
| 687 } else { |
| 688 wasm_frame_.FromFrameArray(isolate_, array_, next_frame_ix_); |
| 689 return &wasm_frame_; |
| 690 } |
| 691 } |
| 692 |
| 693 namespace { |
| 694 |
| 695 MaybeHandle<Object> ConstructCallSite(Isolate* isolate, |
| 696 Handle<FrameArray> frame_array, |
| 697 int frame_index) { |
| 698 Handle<JSFunction> target = |
| 699 handle(isolate->native_context()->callsite_function(), isolate); |
| 700 |
| 701 Handle<JSObject> obj; |
| 702 ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, JSObject::New(target, target), |
| 703 Object); |
| 704 |
| 705 Handle<Symbol> key = isolate->factory()->call_site_frame_array_symbol(); |
| 706 RETURN_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes( |
| 707 obj, key, frame_array, DONT_ENUM), |
| 708 Object); |
| 709 |
| 710 key = isolate->factory()->call_site_frame_index_symbol(); |
| 711 Handle<Object> value(Smi::FromInt(frame_index), isolate); |
| 712 RETURN_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes( |
| 713 obj, key, value, DONT_ENUM), |
| 714 Object); |
| 715 |
| 716 return obj; |
| 717 } |
| 718 |
490 // Convert the raw frames as written by Isolate::CaptureSimpleStackTrace into | 719 // Convert the raw frames as written by Isolate::CaptureSimpleStackTrace into |
491 // a vector of JS CallSite objects. | 720 // a JSArray of JSCallSite objects. |
492 MaybeHandle<FixedArray> GetStackFrames(Isolate* isolate, | 721 MaybeHandle<JSArray> GetStackFrames(Isolate* isolate, |
493 Handle<Object> raw_stack) { | 722 Handle<FrameArray> elems) { |
494 DCHECK(raw_stack->IsJSArray()); | |
495 Handle<JSArray> raw_stack_array = Handle<JSArray>::cast(raw_stack); | |
496 | |
497 DCHECK(raw_stack_array->elements()->IsFixedArray()); | |
498 Handle<FrameArray> elems(FrameArray::cast(raw_stack_array->elements())); | |
499 | |
500 const int frame_count = elems->FrameCount(); | 723 const int frame_count = elems->FrameCount(); |
501 | 724 |
502 Handle<FixedArray> frames = isolate->factory()->NewFixedArray(frame_count); | 725 Handle<FixedArray> frames = isolate->factory()->NewFixedArray(frame_count); |
503 for (int i = 0; i < frame_count; i++) { | 726 for (int i = 0; i < frame_count; i++) { |
504 const int flags = elems->Flags(i)->value(); | 727 Handle<Object> site; |
505 Handle<AbstractCode> code(elems->Code(i), isolate); | 728 ASSIGN_RETURN_ON_EXCEPTION(isolate, site, |
506 Handle<Smi> pc(elems->Offset(i), isolate); | 729 ConstructCallSite(isolate, elems, i), JSArray); |
507 Handle<Object> strict = | 730 frames->set(i, *site); |
508 isolate->factory()->ToBoolean(flags & FrameArray::kIsStrict); | 731 } |
509 | 732 |
510 if (elems->IsWasmFrame(i)) { | 733 return isolate->factory()->NewJSArrayWithElements(frames); |
511 Handle<Object> wasm_obj(elems->WasmObject(i), isolate); | |
512 Handle<Smi> wasm_fun_ix(elems->WasmFunctionIndex(i), isolate); | |
513 | |
514 Handle<Object> pos((pc->value() < 0) | |
515 ? Smi::FromInt(-1 - pc->value()) | |
516 : Smi::FromInt(code->SourcePosition(pc->value())), | |
517 isolate); | |
518 | |
519 Handle<Object> callsite; | |
520 ASSIGN_RETURN_ON_EXCEPTION( | |
521 isolate, callsite, | |
522 CallSiteUtils::Construct(isolate, wasm_obj, wasm_fun_ix, pos, strict), | |
523 FixedArray); | |
524 | |
525 frames->set(i, *callsite); | |
526 } else { | |
527 Handle<Object> recv(elems->Receiver(i), isolate); | |
528 Handle<Object> fun(elems->Function(i), isolate); | |
529 Handle<Object> pos(Smi::FromInt(code->SourcePosition(pc->value())), | |
530 isolate); | |
531 | |
532 if (flags & FrameArray::kForceConstructor) { | |
533 recv = handle(isolate->heap()->call_site_constructor_symbol()); | |
534 } | |
535 | |
536 Handle<Object> callsite; | |
537 ASSIGN_RETURN_ON_EXCEPTION( | |
538 isolate, callsite, | |
539 CallSiteUtils::Construct(isolate, recv, fun, pos, strict), | |
540 FixedArray); | |
541 | |
542 frames->set(i, *callsite); | |
543 } | |
544 } | |
545 | |
546 return frames; | |
547 } | 734 } |
548 | 735 |
549 MaybeHandle<Object> AppendErrorString(Isolate* isolate, Handle<Object> error, | 736 MaybeHandle<Object> AppendErrorString(Isolate* isolate, Handle<Object> error, |
550 IncrementalStringBuilder* builder) { | 737 IncrementalStringBuilder* builder) { |
551 MaybeHandle<String> err_str = | 738 MaybeHandle<String> err_str = |
552 ErrorUtils::ToString(isolate, Handle<Object>::cast(error)); | 739 ErrorUtils::ToString(isolate, Handle<Object>::cast(error)); |
553 if (err_str.is_null()) { | 740 if (err_str.is_null()) { |
554 // Error.toString threw. Try to return a string representation of the thrown | 741 // Error.toString threw. Try to return a string representation of the thrown |
555 // exception instead. | 742 // exception instead. |
556 | 743 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 | 780 |
594 DISALLOW_COPY_AND_ASSIGN(PrepareStackTraceScope); | 781 DISALLOW_COPY_AND_ASSIGN(PrepareStackTraceScope); |
595 }; | 782 }; |
596 | 783 |
597 } // namespace | 784 } // namespace |
598 | 785 |
599 // static | 786 // static |
600 MaybeHandle<Object> ErrorUtils::FormatStackTrace(Isolate* isolate, | 787 MaybeHandle<Object> ErrorUtils::FormatStackTrace(Isolate* isolate, |
601 Handle<JSObject> error, | 788 Handle<JSObject> error, |
602 Handle<Object> raw_stack) { | 789 Handle<Object> raw_stack) { |
603 // Create JS CallSite objects from the raw stack frame array. | 790 DCHECK(raw_stack->IsJSArray()); |
| 791 Handle<JSArray> raw_stack_array = Handle<JSArray>::cast(raw_stack); |
604 | 792 |
605 Handle<FixedArray> frames; | 793 DCHECK(raw_stack_array->elements()->IsFixedArray()); |
606 ASSIGN_RETURN_ON_EXCEPTION(isolate, frames, | 794 Handle<FrameArray> elems(FrameArray::cast(raw_stack_array->elements())); |
607 GetStackFrames(isolate, raw_stack), Object); | |
608 | 795 |
609 // If there's a user-specified "prepareStackFrames" function, call it on the | 796 // If there's a user-specified "prepareStackFrames" function, call it on the |
610 // frames and use its result. | 797 // frames and use its result. |
611 | 798 |
612 Handle<JSFunction> global_error = isolate->error_function(); | 799 Handle<JSFunction> global_error = isolate->error_function(); |
613 Handle<Object> prepare_stack_trace; | 800 Handle<Object> prepare_stack_trace; |
614 ASSIGN_RETURN_ON_EXCEPTION( | 801 ASSIGN_RETURN_ON_EXCEPTION( |
615 isolate, prepare_stack_trace, | 802 isolate, prepare_stack_trace, |
616 JSFunction::GetProperty(isolate, global_error, "prepareStackTrace"), | 803 JSFunction::GetProperty(isolate, global_error, "prepareStackTrace"), |
617 Object); | 804 Object); |
618 | 805 |
619 const bool in_recursion = isolate->formatting_stack_trace(); | 806 const bool in_recursion = isolate->formatting_stack_trace(); |
620 if (prepare_stack_trace->IsJSFunction() && !in_recursion) { | 807 if (prepare_stack_trace->IsJSFunction() && !in_recursion) { |
621 PrepareStackTraceScope scope(isolate); | 808 PrepareStackTraceScope scope(isolate); |
622 Handle<JSArray> array = isolate->factory()->NewJSArrayWithElements(frames); | 809 |
| 810 Handle<JSArray> sites; |
| 811 ASSIGN_RETURN_ON_EXCEPTION(isolate, sites, GetStackFrames(isolate, elems), |
| 812 Object); |
623 | 813 |
624 const int argc = 2; | 814 const int argc = 2; |
625 ScopedVector<Handle<Object>> argv(argc); | 815 ScopedVector<Handle<Object>> argv(argc); |
| 816 |
626 argv[0] = error; | 817 argv[0] = error; |
627 argv[1] = array; | 818 argv[1] = sites; |
628 | 819 |
629 Handle<Object> result; | 820 Handle<Object> result; |
630 ASSIGN_RETURN_ON_EXCEPTION( | 821 ASSIGN_RETURN_ON_EXCEPTION( |
631 isolate, result, Execution::Call(isolate, prepare_stack_trace, | 822 isolate, result, Execution::Call(isolate, prepare_stack_trace, |
632 global_error, argc, argv.start()), | 823 global_error, argc, argv.start()), |
633 Object); | 824 Object); |
634 | 825 |
635 return result; | 826 return result; |
636 } | 827 } |
637 | 828 |
| 829 // Otherwise, run our internal formatting logic. |
| 830 |
638 IncrementalStringBuilder builder(isolate); | 831 IncrementalStringBuilder builder(isolate); |
639 | 832 |
640 RETURN_ON_EXCEPTION(isolate, AppendErrorString(isolate, error, &builder), | 833 RETURN_ON_EXCEPTION(isolate, AppendErrorString(isolate, error, &builder), |
641 Object); | 834 Object); |
642 | 835 |
643 for (int i = 0; i < frames->length(); i++) { | 836 for (FrameArrayIterator it(isolate, elems); it.HasNext(); it.Next()) { |
644 builder.AppendCString("\n at "); | 837 builder.AppendCString("\n at "); |
645 | 838 |
646 Handle<Object> frame = FixedArray::get(*frames, i, isolate); | 839 StackFrameBase* frame = it.Frame(); |
647 MaybeHandle<String> maybe_frame_string = | 840 MaybeHandle<String> maybe_frame_string = frame->ToString(); |
648 CallSiteUtils::ToString(isolate, frame); | |
649 if (maybe_frame_string.is_null()) { | 841 if (maybe_frame_string.is_null()) { |
650 // CallSite.toString threw. Try to return a string representation of the | 842 // CallSite.toString threw. Try to return a string representation of the |
651 // thrown exception instead. | 843 // thrown exception instead. |
652 | 844 |
653 DCHECK(isolate->has_pending_exception()); | 845 DCHECK(isolate->has_pending_exception()); |
654 Handle<Object> pending_exception = | 846 Handle<Object> pending_exception = |
655 handle(isolate->pending_exception(), isolate); | 847 handle(isolate->pending_exception(), isolate); |
656 isolate->clear_pending_exception(); | 848 isolate->clear_pending_exception(); |
657 | 849 |
658 maybe_frame_string = ErrorUtils::ToString(isolate, pending_exception); | 850 maybe_frame_string = ErrorUtils::ToString(isolate, pending_exception); |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 } | 1097 } |
906 | 1098 |
907 DCHECK(mode != SKIP_UNTIL_SEEN); | 1099 DCHECK(mode != SKIP_UNTIL_SEEN); |
908 | 1100 |
909 Handle<Object> no_caller; | 1101 Handle<Object> no_caller; |
910 Handle<String> msg = FormatMessage(isolate, template_index, arg0, arg1, arg2); | 1102 Handle<String> msg = FormatMessage(isolate, template_index, arg0, arg1, arg2); |
911 return ErrorUtils::Construct(isolate, constructor, constructor, msg, mode, | 1103 return ErrorUtils::Construct(isolate, constructor, constructor, msg, mode, |
912 no_caller, false); | 1104 no_caller, false); |
913 } | 1105 } |
914 | 1106 |
915 #define SET_CALLSITE_PROPERTY(target, key, value) \ | |
916 RETURN_ON_EXCEPTION( \ | |
917 isolate, JSObject::SetOwnPropertyIgnoreAttributes( \ | |
918 target, isolate->factory()->key(), value, DONT_ENUM), \ | |
919 Object) | |
920 | |
921 MaybeHandle<Object> CallSiteUtils::Construct(Isolate* isolate, | |
922 Handle<Object> receiver, | |
923 Handle<Object> fun, | |
924 Handle<Object> pos, | |
925 Handle<Object> strict_mode) { | |
926 // Create the JS object. | |
927 | |
928 Handle<JSFunction> target = | |
929 handle(isolate->native_context()->callsite_function(), isolate); | |
930 | |
931 Handle<JSObject> obj; | |
932 ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, JSObject::New(target, target), | |
933 Object); | |
934 | |
935 // For wasm frames, receiver is the wasm object and fun is the function index | |
936 // instead of an actual function. | |
937 const bool is_wasm_object = | |
938 receiver->IsJSObject() && wasm::IsWasmObject(JSObject::cast(*receiver)); | |
939 if (!fun->IsJSFunction() && !is_wasm_object) { | |
940 THROW_NEW_ERROR(isolate, | |
941 NewTypeError(MessageTemplate::kCallSiteExpectsFunction, | |
942 Object::TypeOf(isolate, receiver), | |
943 Object::TypeOf(isolate, fun)), | |
944 Object); | |
945 } | |
946 | |
947 if (is_wasm_object) { | |
948 DCHECK(fun->IsSmi()); | |
949 DCHECK(wasm::GetNumberOfFunctions(JSObject::cast(*receiver)) > | |
950 Smi::cast(*fun)->value()); | |
951 | |
952 SET_CALLSITE_PROPERTY(obj, call_site_wasm_obj_symbol, receiver); | |
953 SET_CALLSITE_PROPERTY(obj, call_site_wasm_func_index_symbol, fun); | |
954 } else { | |
955 DCHECK(fun->IsJSFunction()); | |
956 SET_CALLSITE_PROPERTY(obj, call_site_receiver_symbol, receiver); | |
957 SET_CALLSITE_PROPERTY(obj, call_site_function_symbol, fun); | |
958 } | |
959 | |
960 DCHECK(pos->IsSmi()); | |
961 SET_CALLSITE_PROPERTY(obj, call_site_position_symbol, pos); | |
962 SET_CALLSITE_PROPERTY( | |
963 obj, call_site_strict_symbol, | |
964 isolate->factory()->ToBoolean(strict_mode->BooleanValue())); | |
965 | |
966 return obj; | |
967 } | |
968 | |
969 #undef SET_CALLSITE_PROPERTY | |
970 | |
971 namespace { | |
972 | |
973 bool IsNonEmptyString(Handle<Object> object) { | |
974 return (object->IsString() && String::cast(*object)->length() > 0); | |
975 } | |
976 | |
977 MaybeHandle<JSObject> AppendWasmToString(Isolate* isolate, | |
978 Handle<JSObject> recv, | |
979 CallSite* call_site, | |
980 IncrementalStringBuilder* builder) { | |
981 Handle<Object> name = call_site->GetFunctionName(); | |
982 if (name->IsNull(isolate)) { | |
983 builder->AppendCString("<WASM UNNAMED>"); | |
984 } else { | |
985 DCHECK(name->IsString()); | |
986 builder->AppendString(Handle<String>::cast(name)); | |
987 } | |
988 | |
989 builder->AppendCString(" (<WASM>["); | |
990 | |
991 Handle<String> ix = isolate->factory()->NumberToString( | |
992 handle(Smi::FromInt(call_site->wasm_func_index()), isolate)); | |
993 builder->AppendString(ix); | |
994 | |
995 builder->AppendCString("]+"); | |
996 | |
997 Handle<Object> pos; | |
998 ASSIGN_RETURN_ON_EXCEPTION( | |
999 isolate, pos, JSObject::GetProperty( | |
1000 recv, isolate->factory()->call_site_position_symbol()), | |
1001 JSObject); | |
1002 DCHECK(pos->IsNumber()); | |
1003 builder->AppendString(isolate->factory()->NumberToString(pos)); | |
1004 builder->AppendCString(")"); | |
1005 | |
1006 return recv; | |
1007 } | |
1008 | |
1009 MaybeHandle<JSObject> AppendFileLocation(Isolate* isolate, | |
1010 Handle<JSObject> recv, | |
1011 CallSite* call_site, | |
1012 IncrementalStringBuilder* builder) { | |
1013 if (call_site->IsNative()) { | |
1014 builder->AppendCString("native"); | |
1015 return recv; | |
1016 } | |
1017 | |
1018 Handle<Object> file_name = call_site->GetScriptNameOrSourceUrl(); | |
1019 if (!file_name->IsString() && call_site->IsEval()) { | |
1020 Handle<Object> eval_origin = call_site->GetEvalOrigin(); | |
1021 DCHECK(eval_origin->IsString()); | |
1022 builder->AppendString(Handle<String>::cast(eval_origin)); | |
1023 builder->AppendCString(", "); // Expecting source position to follow. | |
1024 } | |
1025 | |
1026 if (IsNonEmptyString(file_name)) { | |
1027 builder->AppendString(Handle<String>::cast(file_name)); | |
1028 } else { | |
1029 // Source code does not originate from a file and is not native, but we | |
1030 // can still get the source position inside the source string, e.g. in | |
1031 // an eval string. | |
1032 builder->AppendCString("<anonymous>"); | |
1033 } | |
1034 | |
1035 int line_number = call_site->GetLineNumber(); | |
1036 if (line_number != -1) { | |
1037 builder->AppendCharacter(':'); | |
1038 Handle<String> line_string = isolate->factory()->NumberToString( | |
1039 handle(Smi::FromInt(line_number), isolate), isolate); | |
1040 builder->AppendString(line_string); | |
1041 | |
1042 int column_number = call_site->GetColumnNumber(); | |
1043 if (column_number != -1) { | |
1044 builder->AppendCharacter(':'); | |
1045 Handle<String> column_string = isolate->factory()->NumberToString( | |
1046 handle(Smi::FromInt(column_number), isolate), isolate); | |
1047 builder->AppendString(column_string); | |
1048 } | |
1049 } | |
1050 | |
1051 return recv; | |
1052 } | |
1053 | |
1054 int StringIndexOf(Isolate* isolate, Handle<String> subject, | |
1055 Handle<String> pattern) { | |
1056 if (pattern->length() > subject->length()) return -1; | |
1057 return String::IndexOf(isolate, subject, pattern, 0); | |
1058 } | |
1059 | |
1060 // Returns true iff | |
1061 // 1. the subject ends with '.' + pattern, or | |
1062 // 2. subject == pattern. | |
1063 bool StringEndsWithMethodName(Isolate* isolate, Handle<String> subject, | |
1064 Handle<String> pattern) { | |
1065 if (String::Equals(subject, pattern)) return true; | |
1066 | |
1067 FlatStringReader subject_reader(isolate, String::Flatten(subject)); | |
1068 FlatStringReader pattern_reader(isolate, String::Flatten(pattern)); | |
1069 | |
1070 int pattern_index = pattern_reader.length() - 1; | |
1071 int subject_index = subject_reader.length() - 1; | |
1072 for (int i = 0; i <= pattern_reader.length(); i++) { // Iterate over len + 1. | |
1073 if (subject_index < 0) { | |
1074 return false; | |
1075 } | |
1076 | |
1077 const uc32 subject_char = subject_reader.Get(subject_index); | |
1078 if (i == pattern_reader.length()) { | |
1079 if (subject_char != '.') return false; | |
1080 } else if (subject_char != pattern_reader.Get(pattern_index)) { | |
1081 return false; | |
1082 } | |
1083 | |
1084 pattern_index--; | |
1085 subject_index--; | |
1086 } | |
1087 | |
1088 return true; | |
1089 } | |
1090 | |
1091 MaybeHandle<JSObject> AppendMethodCall(Isolate* isolate, Handle<JSObject> recv, | |
1092 CallSite* call_site, | |
1093 IncrementalStringBuilder* builder) { | |
1094 Handle<Object> type_name = call_site->GetTypeName(); | |
1095 Handle<Object> method_name = call_site->GetMethodName(); | |
1096 Handle<Object> function_name = call_site->GetFunctionName(); | |
1097 | |
1098 if (IsNonEmptyString(function_name)) { | |
1099 Handle<String> function_string = Handle<String>::cast(function_name); | |
1100 if (IsNonEmptyString(type_name)) { | |
1101 Handle<String> type_string = Handle<String>::cast(type_name); | |
1102 bool starts_with_type_name = | |
1103 (StringIndexOf(isolate, function_string, type_string) == 0); | |
1104 if (!starts_with_type_name) { | |
1105 builder->AppendString(type_string); | |
1106 builder->AppendCharacter('.'); | |
1107 } | |
1108 } | |
1109 builder->AppendString(function_string); | |
1110 | |
1111 if (IsNonEmptyString(method_name)) { | |
1112 Handle<String> method_string = Handle<String>::cast(method_name); | |
1113 if (!StringEndsWithMethodName(isolate, function_string, method_string)) { | |
1114 builder->AppendCString(" [as "); | |
1115 builder->AppendString(method_string); | |
1116 builder->AppendCharacter(']'); | |
1117 } | |
1118 } | |
1119 } else { | |
1120 builder->AppendString(Handle<String>::cast(type_name)); | |
1121 builder->AppendCharacter('.'); | |
1122 if (IsNonEmptyString(method_name)) { | |
1123 builder->AppendString(Handle<String>::cast(method_name)); | |
1124 } else { | |
1125 builder->AppendCString("<anonymous>"); | |
1126 } | |
1127 } | |
1128 | |
1129 return recv; | |
1130 } | |
1131 | |
1132 } // namespace | |
1133 | |
1134 MaybeHandle<String> CallSiteUtils::ToString(Isolate* isolate, | |
1135 Handle<Object> receiver) { | |
1136 if (!receiver->IsJSObject()) { | |
1137 THROW_NEW_ERROR( | |
1138 isolate, | |
1139 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, | |
1140 isolate->factory()->NewStringFromAsciiChecked("toString"), | |
1141 receiver), | |
1142 String); | |
1143 } | |
1144 Handle<JSObject> recv = Handle<JSObject>::cast(receiver); | |
1145 | |
1146 if (!JSReceiver::HasOwnProperty( | |
1147 recv, isolate->factory()->call_site_position_symbol()) | |
1148 .FromMaybe(false)) { | |
1149 THROW_NEW_ERROR( | |
1150 isolate, | |
1151 NewTypeError(MessageTemplate::kCallSiteMethod, | |
1152 isolate->factory()->NewStringFromAsciiChecked("toString")), | |
1153 String); | |
1154 } | |
1155 | |
1156 IncrementalStringBuilder builder(isolate); | |
1157 | |
1158 CallSite call_site(isolate, recv); | |
1159 if (call_site.IsWasm()) { | |
1160 RETURN_ON_EXCEPTION(isolate, | |
1161 AppendWasmToString(isolate, recv, &call_site, &builder), | |
1162 String); | |
1163 RETURN_RESULT(isolate, builder.Finish(), String); | |
1164 } | |
1165 | |
1166 DCHECK(!call_site.IsWasm()); | |
1167 Handle<Object> function_name = call_site.GetFunctionName(); | |
1168 | |
1169 const bool is_toplevel = call_site.IsToplevel(); | |
1170 const bool is_constructor = call_site.IsConstructor(); | |
1171 const bool is_method_call = !(is_toplevel || is_constructor); | |
1172 | |
1173 if (is_method_call) { | |
1174 RETURN_ON_EXCEPTION( | |
1175 isolate, AppendMethodCall(isolate, recv, &call_site, &builder), String); | |
1176 } else if (is_constructor) { | |
1177 builder.AppendCString("new "); | |
1178 if (IsNonEmptyString(function_name)) { | |
1179 builder.AppendString(Handle<String>::cast(function_name)); | |
1180 } else { | |
1181 builder.AppendCString("<anonymous>"); | |
1182 } | |
1183 } else if (IsNonEmptyString(function_name)) { | |
1184 builder.AppendString(Handle<String>::cast(function_name)); | |
1185 } else { | |
1186 RETURN_ON_EXCEPTION(isolate, | |
1187 AppendFileLocation(isolate, recv, &call_site, &builder), | |
1188 String); | |
1189 RETURN_RESULT(isolate, builder.Finish(), String); | |
1190 } | |
1191 | |
1192 builder.AppendCString(" ("); | |
1193 RETURN_ON_EXCEPTION( | |
1194 isolate, AppendFileLocation(isolate, recv, &call_site, &builder), String); | |
1195 builder.AppendCString(")"); | |
1196 | |
1197 RETURN_RESULT(isolate, builder.Finish(), String); | |
1198 } | |
1199 | |
1200 } // namespace internal | 1107 } // namespace internal |
1201 } // namespace v8 | 1108 } // namespace v8 |
OLD | NEW |