blob: 59757a52422df59c55f69b5337bf3b688e59eda2 [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/call-site-info-inl.h"
#include "src/objects/objects-inl.h"
namespace v8 {
namespace internal {
#define CHECK_CALLSITE(frame, method) \
CHECK_RECEIVER(JSObject, receiver, method); \
LookupIterator it(isolate, receiver, \
isolate->factory()->call_site_info_symbol(), \
LookupIterator::OWN_SKIP_INTERCEPTOR); \
if (it.state() != LookupIterator::DATA) { \
THROW_NEW_ERROR_RETURN_FAILURE( \
isolate, \
NewTypeError(MessageTemplate::kCallSiteMethod, \
isolate->factory()->NewStringFromAsciiChecked(method))); \
} \
auto frame = Cast<CallSiteInfo>(it.GetDataValue())
namespace {
Tagged<Object> PositiveNumberOrNull(int value, Isolate* isolate) {
if (value > 0) return *isolate->factory()->NewNumberFromInt(value);
return ReadOnlyRoots(isolate).null_value();
}
bool NativeContextIsForShadowRealm(Tagged<NativeContext> native_context) {
return native_context->scope_info()->scope_type() == SHADOW_REALM_SCOPE;
}
} // namespace
BUILTIN(CallSitePrototypeGetColumnNumber) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "getColumnNumber");
return PositiveNumberOrNull(CallSiteInfo::GetColumnNumber(frame), isolate);
}
BUILTIN(CallSitePrototypeGetEnclosingColumnNumber) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "getEnclosingColumnNumber");
return PositiveNumberOrNull(CallSiteInfo::GetEnclosingColumnNumber(frame),
isolate);
}
BUILTIN(CallSitePrototypeGetEnclosingLineNumber) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "getEnclosingLineNumber");
return PositiveNumberOrNull(CallSiteInfo::GetEnclosingLineNumber(frame),
isolate);
}
BUILTIN(CallSitePrototypeGetEvalOrigin) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "getEvalOrigin");
return *CallSiteInfo::GetEvalOrigin(frame);
}
BUILTIN(CallSitePrototypeGetFileName) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "getFileName");
return frame->GetScriptName();
}
BUILTIN(CallSitePrototypeGetFunction) {
static const char method_name[] = "getFunction";
HandleScope scope(isolate);
CHECK_CALLSITE(frame, method_name);
// ShadowRealms have a boundary: references to outside objects must not exist
// in the ShadowRealm, and references to ShadowRealm objects must not exist
// outside the ShadowRealm.
if (NativeContextIsForShadowRealm(isolate->raw_native_context()) ||
(IsJSFunction(frame->function()) &&
NativeContextIsForShadowRealm(
Cast<JSFunction>(frame->function())->native_context()))) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewTypeError(
MessageTemplate::kCallSiteMethodUnsupportedInShadowRealm,
isolate->factory()->NewStringFromAsciiChecked(method_name)));
}
if (frame->IsStrict() ||
(IsJSFunction(frame->function()) &&
Cast<JSFunction>(frame->function())->shared()->is_toplevel())) {
return ReadOnlyRoots(isolate).undefined_value();
}
isolate->CountUsage(v8::Isolate::kCallSiteAPIGetFunctionSloppyCall);
return frame->function();
}
BUILTIN(CallSitePrototypeGetFunctionName) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "getFunctionName");
return *CallSiteInfo::GetFunctionName(frame);
}
BUILTIN(CallSitePrototypeGetLineNumber) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "getLineNumber");
return PositiveNumberOrNull(CallSiteInfo::GetLineNumber(frame), isolate);
}
BUILTIN(CallSitePrototypeGetMethodName) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "getMethodName");
return *CallSiteInfo::GetMethodName(frame);
}
BUILTIN(CallSitePrototypeGetPosition) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "getPosition");
return Smi::FromInt(CallSiteInfo::GetSourcePosition(frame));
}
BUILTIN(CallSitePrototypeGetPromiseIndex) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "getPromiseIndex");
if (!frame->IsPromiseAll() && !frame->IsPromiseAny() &&
!frame->IsPromiseAllSettled()) {
return ReadOnlyRoots(isolate).null_value();
}
return Smi::FromInt(CallSiteInfo::GetSourcePosition(frame));
}
BUILTIN(CallSitePrototypeGetScriptHash) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "getScriptHash");
return *CallSiteInfo::GetScriptHash(frame);
}
BUILTIN(CallSitePrototypeGetScriptNameOrSourceURL) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "getScriptNameOrSourceUrl");
return frame->GetScriptNameOrSourceURL();
}
BUILTIN(CallSitePrototypeGetThis) {
static const char method_name[] = "getThis";
HandleScope scope(isolate);
CHECK_CALLSITE(frame, method_name);
// ShadowRealms have a boundary: references to outside objects must not exist
// in the ShadowRealm, and references to ShadowRealm objects must not exist
// outside the ShadowRealm.
if (NativeContextIsForShadowRealm(isolate->raw_native_context()) ||
(IsJSFunction(frame->function()) &&
NativeContextIsForShadowRealm(
Cast<JSFunction>(frame->function())->native_context()))) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewTypeError(
MessageTemplate::kCallSiteMethodUnsupportedInShadowRealm,
isolate->factory()->NewStringFromAsciiChecked(method_name)));
}
if (frame->IsStrict()) return ReadOnlyRoots(isolate).undefined_value();
isolate->CountUsage(v8::Isolate::kCallSiteAPIGetThisSloppyCall);
#if V8_ENABLE_WEBASSEMBLY
if (frame->IsAsmJsWasm()) {
return frame->GetWasmInstance()
->trusted_data(isolate)
->native_context()
->global_proxy();
}
#endif // V8_ENABLE_WEBASSEMBLY
return frame->receiver_or_instance();
}
BUILTIN(CallSitePrototypeGetTypeName) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "getTypeName");
return *CallSiteInfo::GetTypeName(frame);
}
BUILTIN(CallSitePrototypeIsAsync) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "isAsync");
return isolate->heap()->ToBoolean(frame->IsAsync());
}
BUILTIN(CallSitePrototypeIsConstructor) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "isConstructor");
return isolate->heap()->ToBoolean(frame->IsConstructor());
}
BUILTIN(CallSitePrototypeIsEval) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "isEval");
return isolate->heap()->ToBoolean(frame->IsEval());
}
BUILTIN(CallSitePrototypeIsNative) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "isNative");
return isolate->heap()->ToBoolean(frame->IsNative());
}
BUILTIN(CallSitePrototypeIsPromiseAll) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "isPromiseAll");
return isolate->heap()->ToBoolean(frame->IsPromiseAll());
}
BUILTIN(CallSitePrototypeIsToplevel) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "isToplevel");
return isolate->heap()->ToBoolean(frame->IsToplevel());
}
BUILTIN(CallSitePrototypeToString) {
HandleScope scope(isolate);
CHECK_CALLSITE(frame, "toString");
RETURN_RESULT_OR_FAILURE(isolate, SerializeCallSiteInfo(isolate, frame));
}
#undef CHECK_CALLSITE
} // namespace internal
} // namespace v8