Commit ea09c9dc authored by jgruber's avatar jgruber Committed by Commit bot

Move CallSite.toString to C++

BUG=

Review-Url: https://codereview.chromium.org/2174723002
Cr-Commit-Position: refs/heads/master@{#38136}
parent b8229434
......@@ -2671,7 +2671,8 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
{"isConstructor", Builtins::kCallSitePrototypeIsConstructor},
{"isEval", Builtins::kCallSitePrototypeIsEval},
{"isNative", Builtins::kCallSitePrototypeIsNative},
{"isToplevel", Builtins::kCallSitePrototypeIsToplevel}};
{"isToplevel", Builtins::kCallSitePrototypeIsToplevel},
{"toString", Builtins::kCallSitePrototypeToString}};
PropertyAttributes attrs =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
......
......@@ -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
......
......@@ -16,20 +16,6 @@ var Bool16x8ToString;
var Bool32x4ToString;
var Bool8x16ToString;
var CallSite = utils.ImportNow("CallSite");
var callSiteConstructorSymbol =
utils.ImportNow("call_site_constructor_symbol");
var callSiteReceiverSymbol =
utils.ImportNow("call_site_receiver_symbol");
var callSiteFunctionSymbol =
utils.ImportNow("call_site_function_symbol");
var callSitePositionSymbol =
utils.ImportNow("call_site_position_symbol");
var callSiteStrictSymbol =
utils.ImportNow("call_site_strict_symbol");
var callSiteWasmObjectSymbol =
utils.ImportNow("call_site_wasm_obj_symbol");
var callSiteWasmFunctionIndexSymbol =
utils.ImportNow("call_site_wasm_func_index_symbol");
var Float32x4ToString;
var GlobalObject = global.Object;
var GlobalError = global.Error;
......@@ -48,7 +34,6 @@ var ObjectHasOwnProperty;
var ObjectToString = utils.ImportNow("object_to_string");
var Script = utils.ImportNow("Script");
var stackTraceSymbol = utils.ImportNow("stack_trace_symbol");
var StringIndexOf;
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
var Uint16x8ToString;
var Uint32x4ToString;
......@@ -64,7 +49,6 @@ utils.Import(function(from) {
Int32x4ToString = from.Int32x4ToString;
Int8x16ToString = from.Int8x16ToString;
ObjectHasOwnProperty = from.ObjectHasOwnProperty;
StringIndexOf = from.StringIndexOf;
Uint16x8ToString = from.Uint16x8ToString;
Uint32x4ToString = from.Uint32x4ToString;
Uint8x16ToString = from.Uint8x16ToString;
......@@ -272,83 +256,6 @@ function GetStackTraceLine(recv, fun, pos, isGlobal) {
// ----------------------------------------------------------------------------
// Error implementation
function CallSiteToString() {
if (HAS_PRIVATE(this, callSiteWasmObjectSymbol)) {
var funName = this.getFunctionName();
var funcIndex = GET_PRIVATE(this, callSiteWasmFunctionIndexSymbol);
var pos = this.getPosition();
if (IS_NULL(funName)) funName = "<WASM UNNAMED>";
return funName + " (<WASM>[" + funcIndex + "]+" + pos + ")";
}
var fileName;
var fileLocation = "";
if (this.isNative()) {
fileLocation = "native";
} else {
fileName = this.getScriptNameOrSourceURL();
if (!fileName && this.isEval()) {
fileLocation = this.getEvalOrigin();
fileLocation += ", "; // Expecting source position to follow.
}
if (fileName) {
fileLocation += fileName;
} 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.
fileLocation += "<anonymous>";
}
var lineNumber = this.getLineNumber();
if (lineNumber != null) {
fileLocation += ":" + lineNumber;
var columnNumber = this.getColumnNumber();
if (columnNumber) {
fileLocation += ":" + columnNumber;
}
}
}
var line = "";
var functionName = this.getFunctionName();
var addSuffix = true;
var isConstructor = this.isConstructor();
var isMethodCall = !(this.isToplevel() || isConstructor);
if (isMethodCall) {
var typeName = GetTypeName(GET_PRIVATE(this, callSiteReceiverSymbol), true);
var methodName = this.getMethodName();
if (functionName) {
if (typeName && %_Call(StringIndexOf, functionName, typeName) != 0) {
line += typeName + ".";
}
line += functionName;
if (methodName &&
(%_Call(StringIndexOf, functionName, "." + methodName) !=
functionName.length - methodName.length - 1)) {
line += " [as " + methodName + "]";
}
} else {
line += typeName + "." + (methodName || "<anonymous>");
}
} else if (isConstructor) {
line += "new " + (functionName || "<anonymous>");
} else if (functionName) {
line += functionName;
} else {
line += fileLocation;
addSuffix = false;
}
if (addSuffix) {
line += " (" + fileLocation + ")";
}
return line;
}
%AddNamedProperty(CallSite.prototype, "toString", CallSiteToString,
DONT_ENUM | DONT_DELETE | READ_ONLY);
%SetNativeFlag(CallSiteToString);
function FormatErrorString(error) {
try {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment