1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/api-inl.h"
6 #include "src/builtins/builtins-utils-inl.h"
7 #include "src/builtins/builtins.h"
8 #include "src/debug/interface-types.h"
9 #include "src/objects-inl.h"
10
11 namespace v8 {
12 namespace internal {
13
14 // -----------------------------------------------------------------------------
15 // Console
16
17 #define CONSOLE_METHOD_LIST(V) \
18 V(Debug, debug) \
19 V(Error, error) \
20 V(Info, info) \
21 V(Log, log) \
22 V(Warn, warn) \
23 V(Dir, dir) \
24 V(DirXml, dirXml) \
25 V(Table, table) \
26 V(Trace, trace) \
27 V(Group, group) \
28 V(GroupCollapsed, groupCollapsed) \
29 V(GroupEnd, groupEnd) \
30 V(Clear, clear) \
31 V(Count, count) \
32 V(CountReset, countReset) \
33 V(Assert, assert) \
34 V(Profile, profile) \
35 V(ProfileEnd, profileEnd)
36
37 namespace {
ConsoleCall(Isolate * isolate,internal::BuiltinArguments & args,void (debug::ConsoleDelegate::* func)(const v8::debug::ConsoleCallArguments &,const v8::debug::ConsoleContext &))38 void ConsoleCall(
39 Isolate* isolate, internal::BuiltinArguments& args,
40 void (debug::ConsoleDelegate::*func)(const v8::debug::ConsoleCallArguments&,
41 const v8::debug::ConsoleContext&)) {
42 CHECK(!isolate->has_pending_exception());
43 CHECK(!isolate->has_scheduled_exception());
44 if (!isolate->console_delegate()) return;
45 HandleScope scope(isolate);
46 debug::ConsoleCallArguments wrapper(args);
47 Handle<Object> context_id_obj = JSObject::GetDataProperty(
48 args.target(), isolate->factory()->console_context_id_symbol());
49 int context_id =
50 context_id_obj->IsSmi() ? Handle<Smi>::cast(context_id_obj)->value() : 0;
51 Handle<Object> context_name_obj = JSObject::GetDataProperty(
52 args.target(), isolate->factory()->console_context_name_symbol());
53 Handle<String> context_name = context_name_obj->IsString()
54 ? Handle<String>::cast(context_name_obj)
55 : isolate->factory()->anonymous_string();
56 (isolate->console_delegate()->*func)(
57 wrapper,
58 v8::debug::ConsoleContext(context_id, Utils::ToLocal(context_name)));
59 }
60
LogTimerEvent(Isolate * isolate,BuiltinArguments args,Logger::StartEnd se)61 void LogTimerEvent(Isolate* isolate, BuiltinArguments args,
62 Logger::StartEnd se) {
63 if (!isolate->logger()->is_logging()) return;
64 HandleScope scope(isolate);
65 std::unique_ptr<char[]> name;
66 const char* raw_name = "default";
67 if (args.length() > 1 && args[1]->IsString()) {
68 // Try converting the first argument to a string.
69 name = args.at<String>(1)->ToCString();
70 raw_name = name.get();
71 }
72 LOG(isolate, TimerEvent(se, raw_name));
73 }
74 } // namespace
75
76 #define CONSOLE_BUILTIN_IMPLEMENTATION(call, name) \
77 BUILTIN(Console##call) { \
78 ConsoleCall(isolate, args, &debug::ConsoleDelegate::call); \
79 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); \
80 return ReadOnlyRoots(isolate).undefined_value(); \
81 }
82 CONSOLE_METHOD_LIST(CONSOLE_BUILTIN_IMPLEMENTATION)
83 #undef CONSOLE_BUILTIN_IMPLEMENTATION
84
BUILTIN(ConsoleTime)85 BUILTIN(ConsoleTime) {
86 LogTimerEvent(isolate, args, Logger::START);
87 ConsoleCall(isolate, args, &debug::ConsoleDelegate::Time);
88 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
89 return ReadOnlyRoots(isolate).undefined_value();
90 }
91
BUILTIN(ConsoleTimeEnd)92 BUILTIN(ConsoleTimeEnd) {
93 LogTimerEvent(isolate, args, Logger::END);
94 ConsoleCall(isolate, args, &debug::ConsoleDelegate::TimeEnd);
95 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
96 return ReadOnlyRoots(isolate).undefined_value();
97 }
98
BUILTIN(ConsoleTimeStamp)99 BUILTIN(ConsoleTimeStamp) {
100 LogTimerEvent(isolate, args, Logger::STAMP);
101 ConsoleCall(isolate, args, &debug::ConsoleDelegate::TimeStamp);
102 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
103 return ReadOnlyRoots(isolate).undefined_value();
104 }
105
106 namespace {
InstallContextFunction(Isolate * isolate,Handle<JSObject> target,const char * name,Builtins::Name builtin_id,int context_id,Handle<Object> context_name)107 void InstallContextFunction(Isolate* isolate, Handle<JSObject> target,
108 const char* name, Builtins::Name builtin_id,
109 int context_id, Handle<Object> context_name) {
110 Factory* const factory = isolate->factory();
111
112 Handle<String> name_string =
113 Name::ToFunctionName(isolate, factory->InternalizeUtf8String(name))
114 .ToHandleChecked();
115 NewFunctionArgs args = NewFunctionArgs::ForBuiltinWithoutPrototype(
116 name_string, builtin_id, i::LanguageMode::kSloppy);
117 Handle<JSFunction> fun = factory->NewFunction(args);
118
119 fun->shared()->set_native(true);
120 fun->shared()->DontAdaptArguments();
121 fun->shared()->set_length(1);
122
123 JSObject::AddProperty(isolate, fun, factory->console_context_id_symbol(),
124 handle(Smi::FromInt(context_id), isolate), NONE);
125 if (context_name->IsString()) {
126 JSObject::AddProperty(isolate, fun, factory->console_context_name_symbol(),
127 context_name, NONE);
128 }
129 JSObject::AddProperty(isolate, target, name_string, fun, NONE);
130 }
131 } // namespace
132
BUILTIN(ConsoleContext)133 BUILTIN(ConsoleContext) {
134 HandleScope scope(isolate);
135
136 Factory* const factory = isolate->factory();
137 Handle<String> name = factory->InternalizeUtf8String("Context");
138 NewFunctionArgs arguments = NewFunctionArgs::ForFunctionWithoutCode(
139 name, isolate->sloppy_function_map(), LanguageMode::kSloppy);
140 Handle<JSFunction> cons = factory->NewFunction(arguments);
141
142 Handle<JSObject> prototype = factory->NewJSObject(isolate->object_function());
143 JSFunction::SetPrototype(cons, prototype);
144
145 Handle<JSObject> context = factory->NewJSObject(cons, TENURED);
146 DCHECK(context->IsJSObject());
147 int id = isolate->last_console_context_id() + 1;
148 isolate->set_last_console_context_id(id);
149
150 #define CONSOLE_BUILTIN_SETUP(call, name) \
151 InstallContextFunction(isolate, context, #name, Builtins::kConsole##call, \
152 id, args.at(1));
153 CONSOLE_METHOD_LIST(CONSOLE_BUILTIN_SETUP)
154 #undef CONSOLE_BUILTIN_SETUP
155 InstallContextFunction(isolate, context, "time", Builtins::kConsoleTime, id,
156 args.at(1));
157 InstallContextFunction(isolate, context, "timeEnd", Builtins::kConsoleTimeEnd,
158 id, args.at(1));
159 InstallContextFunction(isolate, context, "timeStamp",
160 Builtins::kConsoleTimeStamp, id, args.at(1));
161
162 return *context;
163 }
164
165 #undef CONSOLE_METHOD_LIST
166
167 } // namespace internal
168 } // namespace v8
169