| Index: src/builtins/builtins-callsite.cc
|
| diff --git a/src/builtins/builtins-callsite.cc b/src/builtins/builtins-callsite.cc
|
| index c7b273e8438c05c0b5fc8bb0400517eafc397d4f..2038f28f680aa215f15d220e44dcc1f6849f2a7a 100644
|
| --- a/src/builtins/builtins-callsite.cc
|
| +++ b/src/builtins/builtins-callsite.cc
|
| @@ -199,32 +199,39 @@ MaybeHandle<String> FormatEvalOrigin(Isolate* isolate, Handle<Script> script) {
|
| return result;
|
| }
|
|
|
| -} // namespace
|
| -
|
| -BUILTIN(CallSitePrototypeGetEvalOrigin) {
|
| - HandleScope scope(isolate);
|
| - CHECK_CALLSITE(recv, "getEvalOrigin");
|
| -
|
| - CallSite call_site(isolate, recv);
|
| - if (call_site.IsWasm()) return *isolate->factory()->undefined_value();
|
| +MaybeHandle<Object> GetEvalOrigin(Isolate* isolate, Handle<JSObject> object) {
|
| + CallSite call_site(isolate, object);
|
| + if (call_site.IsWasm()) return isolate->factory()->undefined_value();
|
|
|
| // Retrieve the function's script object.
|
|
|
| Handle<Object> function_obj;
|
| Handle<Symbol> symbol = isolate->factory()->call_site_function_symbol();
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, function_obj,
|
| - JSObject::GetProperty(recv, symbol));
|
| + ASSIGN_RETURN_ON_EXCEPTION(isolate, function_obj,
|
| + JSObject::GetProperty(object, symbol), Object);
|
|
|
| DCHECK(function_obj->IsJSFunction());
|
| Handle<JSFunction> function = Handle<JSFunction>::cast(function_obj);
|
| Handle<Object> script = handle(function->shared()->script(), isolate);
|
|
|
| if (!script->IsScript()) {
|
| - return *isolate->factory()->undefined_value();
|
| + return isolate->factory()->undefined_value();
|
| }
|
|
|
| - RETURN_RESULT_OR_FAILURE(
|
| - isolate, FormatEvalOrigin(isolate, Handle<Script>::cast(script)));
|
| + Handle<String> str;
|
| + ASSIGN_RETURN_ON_EXCEPTION(
|
| + isolate, str, FormatEvalOrigin(isolate, Handle<Script>::cast(script)),
|
| + String);
|
| +
|
| + return str;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +BUILTIN(CallSitePrototypeGetEvalOrigin) {
|
| + HandleScope scope(isolate);
|
| + CHECK_CALLSITE(recv, "getEvalOrigin");
|
| + RETURN_RESULT_OR_FAILURE(isolate, GetEvalOrigin(isolate, recv));
|
| }
|
|
|
| BUILTIN(CallSitePrototypeGetFileName) {
|
| @@ -324,25 +331,32 @@ BUILTIN(CallSitePrototypeGetThis) {
|
| return *receiver;
|
| }
|
|
|
| -BUILTIN(CallSitePrototypeGetTypeName) {
|
| - HandleScope scope(isolate);
|
| - CHECK_CALLSITE(recv, "getTypeName");
|
| +namespace {
|
|
|
| +MaybeHandle<Object> GetTypeName(Isolate* isolate, Handle<JSObject> object) {
|
| Handle<Object> receiver;
|
| Handle<Symbol> symbol = isolate->factory()->call_site_receiver_symbol();
|
| - ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
|
| - JSObject::GetProperty(recv, symbol));
|
| + ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
|
| + JSObject::GetProperty(object, symbol), Object);
|
|
|
| // TODO(jgruber): Check for strict/constructor here as above.
|
|
|
| if (receiver->IsNull(isolate) || receiver->IsUndefined(isolate))
|
| - return *isolate->factory()->null_value();
|
| + return isolate->factory()->null_value();
|
|
|
| - if (receiver->IsJSProxy()) return *isolate->factory()->Proxy_string();
|
| + if (receiver->IsJSProxy()) return isolate->factory()->Proxy_string();
|
|
|
| Handle<JSReceiver> receiver_object =
|
| Object::ToObject(isolate, receiver).ToHandleChecked();
|
| - return *JSReceiver::GetConstructorName(receiver_object);
|
| + return JSReceiver::GetConstructorName(receiver_object);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +BUILTIN(CallSitePrototypeGetTypeName) {
|
| + HandleScope scope(isolate);
|
| + CHECK_CALLSITE(recv, "getTypeName");
|
| + RETURN_RESULT_OR_FAILURE(isolate, GetTypeName(isolate, recv));
|
| }
|
|
|
| BUILTIN(CallSitePrototypeIsConstructor) {
|
| @@ -381,10 +395,217 @@ BUILTIN(CallSitePrototypeIsToplevel) {
|
| return isolate->heap()->ToBoolean(call_site.IsToplevel());
|
| }
|
|
|
| +namespace {
|
| +
|
| +bool IsNonEmptyString(Handle<Object> object) {
|
| + return (object->IsString() && String::cast(*object)->length() > 0);
|
| +}
|
| +
|
| +MaybeHandle<JSObject> AppendWasmToString(Isolate* isolate,
|
| + Handle<JSObject> recv,
|
| + CallSite* call_site,
|
| + IncrementalStringBuilder* builder) {
|
| + Handle<Object> name = call_site->GetFunctionName();
|
| + if (name->IsNull(isolate)) {
|
| + builder->AppendCString("<WASM UNNAMED>");
|
| + } else {
|
| + DCHECK(name->IsString());
|
| + builder->AppendString(Handle<String>::cast(name));
|
| + }
|
| +
|
| + builder->AppendCString(" (<WASM>[");
|
| +
|
| + Handle<String> ix = isolate->factory()->NumberToString(
|
| + handle(Smi::FromInt(call_site->wasm_func_index()), isolate));
|
| + builder->AppendString(ix);
|
| +
|
| + builder->AppendCString("]+");
|
| +
|
| + Handle<Object> pos;
|
| + ASSIGN_RETURN_ON_EXCEPTION(
|
| + isolate, pos, JSObject::GetProperty(
|
| + recv, isolate->factory()->call_site_position_symbol()),
|
| + JSObject);
|
| + DCHECK(pos->IsNumber());
|
| + builder->AppendString(isolate->factory()->NumberToString(pos));
|
| + builder->AppendCString(")");
|
| +
|
| + return recv;
|
| +}
|
| +
|
| +MaybeHandle<JSObject> AppendFileLocation(Isolate* isolate,
|
| + Handle<JSObject> recv,
|
| + CallSite* call_site,
|
| + IncrementalStringBuilder* builder) {
|
| + if (call_site->IsNative()) {
|
| + builder->AppendCString("native");
|
| + return recv;
|
| + }
|
| +
|
| + Handle<Object> file_name = call_site->GetScriptNameOrSourceUrl();
|
| + if (!file_name->IsString() && call_site->IsEval()) {
|
| + Handle<Object> eval_origin;
|
| + ASSIGN_RETURN_ON_EXCEPTION(isolate, eval_origin,
|
| + GetEvalOrigin(isolate, recv), JSObject);
|
| + DCHECK(eval_origin->IsString());
|
| + builder->AppendString(Handle<String>::cast(eval_origin));
|
| + builder->AppendCString(", "); // Expecting source position to follow.
|
| + }
|
| +
|
| + if (IsNonEmptyString(file_name)) {
|
| + builder->AppendString(Handle<String>::cast(file_name));
|
| + } else {
|
| + // Source code does not originate from a file and is not native, but we
|
| + // can still get the source position inside the source string, e.g. in
|
| + // an eval string.
|
| + builder->AppendCString("<anonymous>");
|
| + }
|
| +
|
| + int line_number = call_site->GetLineNumber();
|
| + if (line_number != -1) {
|
| + builder->AppendCharacter(':');
|
| + Handle<String> line_string = isolate->factory()->NumberToString(
|
| + handle(Smi::FromInt(line_number), isolate), isolate);
|
| + builder->AppendString(line_string);
|
| +
|
| + int column_number = call_site->GetColumnNumber();
|
| + if (column_number != -1) {
|
| + builder->AppendCharacter(':');
|
| + Handle<String> column_string = isolate->factory()->NumberToString(
|
| + handle(Smi::FromInt(column_number), isolate), isolate);
|
| + builder->AppendString(column_string);
|
| + }
|
| + }
|
| +
|
| + return recv;
|
| +}
|
| +
|
| +int StringIndexOf(Isolate* isolate, Handle<String> subject,
|
| + Handle<String> pattern) {
|
| + if (pattern->length() > subject->length()) return -1;
|
| + return String::IndexOf(isolate, subject, pattern, 0);
|
| +}
|
| +
|
| +// Returns true iff
|
| +// 1. the subject ends with '.' + pattern, or
|
| +// 2. subject == pattern.
|
| +bool StringEndsWithMethodName(Isolate* isolate, Handle<String> subject,
|
| + Handle<String> pattern) {
|
| + if (String::Equals(subject, pattern)) return true;
|
| +
|
| + FlatStringReader subject_reader(isolate, String::Flatten(subject));
|
| + FlatStringReader pattern_reader(isolate, String::Flatten(pattern));
|
| +
|
| + int pattern_index = pattern_reader.length() - 1;
|
| + int subject_index = subject_reader.length() - 1;
|
| + for (int i = 0; i <= pattern_reader.length(); i++) { // Iterate over len + 1.
|
| + if (subject_index < 0) {
|
| + return false;
|
| + }
|
| +
|
| + const uc32 subject_char = subject_reader.Get(subject_index);
|
| + if (i == pattern_reader.length()) {
|
| + if (subject_char != '.') return false;
|
| + } else if (subject_char != pattern_reader.Get(pattern_index)) {
|
| + return false;
|
| + }
|
| +
|
| + pattern_index--;
|
| + subject_index--;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +MaybeHandle<JSObject> AppendMethodCall(Isolate* isolate, Handle<JSObject> recv,
|
| + CallSite* call_site,
|
| + IncrementalStringBuilder* builder) {
|
| + Handle<Object> type_name;
|
| + ASSIGN_RETURN_ON_EXCEPTION(isolate, type_name, GetTypeName(isolate, recv),
|
| + JSObject);
|
| + Handle<Object> method_name = call_site->GetMethodName();
|
| + Handle<Object> function_name = call_site->GetFunctionName();
|
| +
|
| + if (IsNonEmptyString(function_name)) {
|
| + Handle<String> function_string = Handle<String>::cast(function_name);
|
| + if (type_name->IsString()) {
|
| + Handle<String> type_string = Handle<String>::cast(type_name);
|
| + bool starts_with_type_name =
|
| + (StringIndexOf(isolate, function_string, type_string) == 0);
|
| + if (!starts_with_type_name) {
|
| + builder->AppendString(type_string);
|
| + builder->AppendCharacter('.');
|
| + }
|
| + }
|
| + builder->AppendString(function_string);
|
| +
|
| + if (IsNonEmptyString(method_name)) {
|
| + Handle<String> method_string = Handle<String>::cast(method_name);
|
| + if (!StringEndsWithMethodName(isolate, function_string, method_string)) {
|
| + builder->AppendCString(" [as ");
|
| + builder->AppendString(method_string);
|
| + builder->AppendCharacter(']');
|
| + }
|
| + }
|
| + } else {
|
| + builder->AppendString(Handle<String>::cast(type_name));
|
| + builder->AppendCharacter('.');
|
| + if (IsNonEmptyString(method_name)) {
|
| + builder->AppendString(Handle<String>::cast(method_name));
|
| + } else {
|
| + builder->AppendCString("<anonymous>");
|
| + }
|
| + }
|
| +
|
| + return recv;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| BUILTIN(CallSitePrototypeToString) {
|
| HandleScope scope(isolate);
|
| - // TODO(jgruber)
|
| - return *isolate->factory()->undefined_value();
|
| + CHECK_CALLSITE(recv, "toString");
|
| +
|
| + IncrementalStringBuilder builder(isolate);
|
| +
|
| + CallSite call_site(isolate, recv);
|
| + if (call_site.IsWasm()) {
|
| + RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, AppendWasmToString(isolate, recv, &call_site, &builder));
|
| + RETURN_RESULT_OR_FAILURE(isolate, builder.Finish());
|
| + }
|
| +
|
| + DCHECK(!call_site.IsWasm());
|
| + Handle<Object> function_name = call_site.GetFunctionName();
|
| +
|
| + const bool is_toplevel = call_site.IsToplevel();
|
| + const bool is_constructor = call_site.IsConstructor();
|
| + const bool is_method_call = !(is_toplevel || is_constructor);
|
| +
|
| + if (is_method_call) {
|
| + RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, AppendMethodCall(isolate, recv, &call_site, &builder));
|
| + } else if (is_constructor) {
|
| + builder.AppendCString("new ");
|
| + if (IsNonEmptyString(function_name)) {
|
| + builder.AppendString(Handle<String>::cast(function_name));
|
| + } else {
|
| + builder.AppendCString("<anonymous>");
|
| + }
|
| + } else if (IsNonEmptyString(function_name)) {
|
| + builder.AppendString(Handle<String>::cast(function_name));
|
| + } else {
|
| + RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, AppendFileLocation(isolate, recv, &call_site, &builder));
|
| + RETURN_RESULT_OR_FAILURE(isolate, builder.Finish());
|
| + }
|
| +
|
| + builder.AppendCString(" (");
|
| + RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, AppendFileLocation(isolate, recv, &call_site, &builder));
|
| + builder.AppendCString(")");
|
| +
|
| + RETURN_RESULT_OR_FAILURE(isolate, builder.Finish());
|
| }
|
|
|
| #undef CHECK_CALLSITE
|
|
|