blob: 5b7807ed4a9e50ca4648180e7194e33b854937af [file] [log] [blame]
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/builtins/builtins-utils-inl.h"
#include "src/builtins/builtins.h"
#include "src/heap/heap-inl.h" // For ToBoolean.
#include "src/logging/counters.h"
#include "src/objects/frame-array-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/stack-frame-info.h"
namespace v8 {
namespace internal {
#define CHECK_CALLSITE(recv, method) \
CHECK_RECEIVER(JSObject, recv, method); \
if (!JSReceiver::HasOwnProperty( \
recv, isolate->factory()->call_site_frame_array_symbol()) \
.FromMaybe(false)) { \
THROW_NEW_ERROR_RETURN_FAILURE( \
isolate, \
NewTypeError(MessageTemplate::kCallSiteMethod, \
isolate->factory()->NewStringFromAsciiChecked(method))); \
}
namespace {
Object PositiveNumberOrNull(int value, Isolate* isolate) {
if (value >= 0) return *isolate->factory()->NewNumberFromInt(value);
return ReadOnlyRoots(isolate).null_value();
}
Handle<FrameArray> GetFrameArray(Isolate* isolate, Handle<JSObject> object) {
Handle<Object> frame_array_obj = JSObject::GetDataProperty(
object, isolate->factory()->call_site_frame_array_symbol());
return Handle<FrameArray>::cast(frame_array_obj);
}
int GetFrameIndex(Isolate* isolate, Handle<JSObject> object) {
Handle<Object> frame_index_obj = JSObject::GetDataProperty(
object, isolate->factory()->call_site_frame_index_symbol());
return Smi::ToInt(*frame_index_obj);
}
} // namespace
BUILTIN(CallSitePrototypeGetColumnNumber) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getColumnNumber");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return PositiveNumberOrNull(it.Frame()->GetColumnNumber(), isolate);
}
BUILTIN(CallSitePrototypeGetEvalOrigin) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getEvalOrigin");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return *it.Frame()->GetEvalOrigin();
}
BUILTIN(CallSitePrototypeGetFileName) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getFileName");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return *it.Frame()->GetFileName();
}
BUILTIN(CallSitePrototypeGetFunction) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getFunction");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
StackFrameBase* frame = it.Frame();
if (frame->IsStrict() ||
(frame->GetFunction()->IsJSFunction() &&
JSFunction::cast(*frame->GetFunction()).shared().is_toplevel())) {
return ReadOnlyRoots(isolate).undefined_value();
}
isolate->CountUsage(v8::Isolate::kCallSiteAPIGetFunctionSloppyCall);
return *frame->GetFunction();
}
BUILTIN(CallSitePrototypeGetFunctionName) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getFunctionName");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return *it.Frame()->GetFunctionName();
}
BUILTIN(CallSitePrototypeGetLineNumber) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getLineNumber");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return PositiveNumberOrNull(it.Frame()->GetLineNumber(), isolate);
}
BUILTIN(CallSitePrototypeGetMethodName) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getMethodName");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return *it.Frame()->GetMethodName();
}
BUILTIN(CallSitePrototypeGetPosition) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getPosition");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return Smi::FromInt(it.Frame()->GetPosition());
}
BUILTIN(CallSitePrototypeGetPromiseIndex) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getPromiseIndex");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return PositiveNumberOrNull(it.Frame()->GetPromiseIndex(), isolate);
}
BUILTIN(CallSitePrototypeGetScriptNameOrSourceURL) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getScriptNameOrSourceUrl");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return *it.Frame()->GetScriptNameOrSourceUrl();
}
BUILTIN(CallSitePrototypeGetThis) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getThis");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
StackFrameBase* frame = it.Frame();
if (frame->IsStrict()) return ReadOnlyRoots(isolate).undefined_value();
isolate->CountUsage(v8::Isolate::kCallSiteAPIGetThisSloppyCall);
return *frame->GetReceiver();
}
BUILTIN(CallSitePrototypeGetTypeName) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getTypeName");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return *it.Frame()->GetTypeName();
}
BUILTIN(CallSitePrototypeIsAsync) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "isAsync");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return isolate->heap()->ToBoolean(it.Frame()->IsAsync());
}
BUILTIN(CallSitePrototypeIsConstructor) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "isConstructor");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return isolate->heap()->ToBoolean(it.Frame()->IsConstructor());
}
BUILTIN(CallSitePrototypeIsEval) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "isEval");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return isolate->heap()->ToBoolean(it.Frame()->IsEval());
}
BUILTIN(CallSitePrototypeIsNative) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "isNative");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return isolate->heap()->ToBoolean(it.Frame()->IsNative());
}
BUILTIN(CallSitePrototypeIsPromiseAll) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "isPromiseAll");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return isolate->heap()->ToBoolean(it.Frame()->IsPromiseAll());
}
BUILTIN(CallSitePrototypeIsToplevel) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "isToplevel");
FrameArrayIterator it(isolate, GetFrameArray(isolate, recv),
GetFrameIndex(isolate, recv));
return isolate->heap()->ToBoolean(it.Frame()->IsToplevel());
}
BUILTIN(CallSitePrototypeToString) {
HandleScope scope(isolate);
CHECK_CALLSITE(recv, "toString");
Handle<StackTraceFrame> frame = isolate->factory()->NewStackTraceFrame(
GetFrameArray(isolate, recv), GetFrameIndex(isolate, recv));
RETURN_RESULT_OR_FAILURE(isolate, SerializeStackTraceFrame(isolate, frame));
}
#undef CHECK_CALLSITE
} // namespace internal
} // namespace v8