| // 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 |