• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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/logging/counters.h"
10 #include "src/logging/log.h"
11 #include "src/objects/objects-inl.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 // -----------------------------------------------------------------------------
17 // Console
18 
19 #define CONSOLE_METHOD_LIST(V)      \
20   V(Debug, debug)                   \
21   V(Error, error)                   \
22   V(Info, info)                     \
23   V(Log, log)                       \
24   V(Warn, warn)                     \
25   V(Dir, dir)                       \
26   V(DirXml, dirXml)                 \
27   V(Table, table)                   \
28   V(Trace, trace)                   \
29   V(Group, group)                   \
30   V(GroupCollapsed, groupCollapsed) \
31   V(GroupEnd, groupEnd)             \
32   V(Clear, clear)                   \
33   V(Count, count)                   \
34   V(CountReset, countReset)         \
35   V(Assert, assert)                 \
36   V(Profile, profile)               \
37   V(ProfileEnd, profileEnd)         \
38   V(TimeLog, timeLog)
39 
40 namespace {
ConsoleCall(Isolate * isolate,const internal::BuiltinArguments & args,void (debug::ConsoleDelegate::* func)(const v8::debug::ConsoleCallArguments &,const v8::debug::ConsoleContext &))41 void ConsoleCall(
42     Isolate* isolate, const internal::BuiltinArguments& args,
43     void (debug::ConsoleDelegate::*func)(const v8::debug::ConsoleCallArguments&,
44                                          const v8::debug::ConsoleContext&)) {
45   CHECK(!isolate->has_pending_exception());
46   CHECK(!isolate->has_scheduled_exception());
47   if (!isolate->console_delegate()) return;
48   HandleScope scope(isolate);
49 
50   // Access check. The current context has to match the context of all
51   // arguments, otherwise the inspector might leak objects across contexts.
52   Handle<Context> context = handle(isolate->context(), isolate);
53   for (int i = 0; i < args.length(); ++i) {
54     Handle<Object> argument = args.at<Object>(i);
55     if (!argument->IsJSObject()) continue;
56 
57     Handle<JSObject> argument_obj = Handle<JSObject>::cast(argument);
58     if (argument->IsAccessCheckNeeded(isolate) &&
59         !isolate->MayAccess(context, argument_obj)) {
60       isolate->ReportFailedAccessCheck(argument_obj);
61       return;
62     }
63   }
64 
65   debug::ConsoleCallArguments wrapper(args);
66   Handle<Object> context_id_obj = JSObject::GetDataProperty(
67       args.target(), isolate->factory()->console_context_id_symbol());
68   int context_id =
69       context_id_obj->IsSmi() ? Handle<Smi>::cast(context_id_obj)->value() : 0;
70   Handle<Object> context_name_obj = JSObject::GetDataProperty(
71       args.target(), isolate->factory()->console_context_name_symbol());
72   Handle<String> context_name = context_name_obj->IsString()
73                                     ? Handle<String>::cast(context_name_obj)
74                                     : isolate->factory()->anonymous_string();
75   (isolate->console_delegate()->*func)(
76       wrapper,
77       v8::debug::ConsoleContext(context_id, Utils::ToLocal(context_name)));
78 }
79 
LogTimerEvent(Isolate * isolate,BuiltinArguments args,Logger::StartEnd se)80 void LogTimerEvent(Isolate* isolate, BuiltinArguments args,
81                    Logger::StartEnd se) {
82   if (!isolate->logger()->is_logging()) return;
83   HandleScope scope(isolate);
84   std::unique_ptr<char[]> name;
85   const char* raw_name = "default";
86   if (args.length() > 1 && args[1].IsString()) {
87     // Try converting the first argument to a string.
88     name = args.at<String>(1)->ToCString();
89     raw_name = name.get();
90   }
91   LOG(isolate, TimerEvent(se, raw_name));
92 }
93 }  // namespace
94 
95 #define CONSOLE_BUILTIN_IMPLEMENTATION(call, name)             \
96   BUILTIN(Console##call) {                                     \
97     ConsoleCall(isolate, args, &debug::ConsoleDelegate::call); \
98     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);            \
99     return ReadOnlyRoots(isolate).undefined_value();           \
100   }
101 CONSOLE_METHOD_LIST(CONSOLE_BUILTIN_IMPLEMENTATION)
102 #undef CONSOLE_BUILTIN_IMPLEMENTATION
103 
BUILTIN(ConsoleTime)104 BUILTIN(ConsoleTime) {
105   LogTimerEvent(isolate, args, Logger::START);
106   ConsoleCall(isolate, args, &debug::ConsoleDelegate::Time);
107   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
108   return ReadOnlyRoots(isolate).undefined_value();
109 }
110 
BUILTIN(ConsoleTimeEnd)111 BUILTIN(ConsoleTimeEnd) {
112   LogTimerEvent(isolate, args, Logger::END);
113   ConsoleCall(isolate, args, &debug::ConsoleDelegate::TimeEnd);
114   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
115   return ReadOnlyRoots(isolate).undefined_value();
116 }
117 
BUILTIN(ConsoleTimeStamp)118 BUILTIN(ConsoleTimeStamp) {
119   LogTimerEvent(isolate, args, Logger::STAMP);
120   ConsoleCall(isolate, args, &debug::ConsoleDelegate::TimeStamp);
121   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
122   return ReadOnlyRoots(isolate).undefined_value();
123 }
124 
125 namespace {
InstallContextFunction(Isolate * isolate,Handle<JSObject> target,const char * name,Builtins::Name builtin_id,int context_id,Handle<Object> context_name)126 void InstallContextFunction(Isolate* isolate, Handle<JSObject> target,
127                             const char* name, Builtins::Name builtin_id,
128                             int context_id, Handle<Object> context_name) {
129   Factory* const factory = isolate->factory();
130 
131   Handle<String> name_string =
132       Name::ToFunctionName(isolate, factory->InternalizeUtf8String(name))
133           .ToHandleChecked();
134   NewFunctionArgs args = NewFunctionArgs::ForBuiltinWithoutPrototype(
135       name_string, builtin_id, i::LanguageMode::kSloppy);
136   Handle<JSFunction> fun = factory->NewFunction(args);
137 
138   fun->shared().set_native(true);
139   fun->shared().DontAdaptArguments();
140   fun->shared().set_length(1);
141 
142   JSObject::AddProperty(isolate, fun, factory->console_context_id_symbol(),
143                         handle(Smi::FromInt(context_id), isolate), NONE);
144   if (context_name->IsString()) {
145     JSObject::AddProperty(isolate, fun, factory->console_context_name_symbol(),
146                           context_name, NONE);
147   }
148   JSObject::AddProperty(isolate, target, name_string, fun, NONE);
149 }
150 }  // namespace
151 
BUILTIN(ConsoleContext)152 BUILTIN(ConsoleContext) {
153   HandleScope scope(isolate);
154 
155   Factory* const factory = isolate->factory();
156   Handle<String> name = factory->InternalizeUtf8String("Context");
157   NewFunctionArgs arguments = NewFunctionArgs::ForFunctionWithoutCode(
158       name, isolate->sloppy_function_map(), LanguageMode::kSloppy);
159   Handle<JSFunction> cons = factory->NewFunction(arguments);
160 
161   Handle<JSObject> prototype = factory->NewJSObject(isolate->object_function());
162   JSFunction::SetPrototype(cons, prototype);
163 
164   Handle<JSObject> context = factory->NewJSObject(cons, AllocationType::kOld);
165   DCHECK(context->IsJSObject());
166   int id = isolate->last_console_context_id() + 1;
167   isolate->set_last_console_context_id(id);
168 
169 #define CONSOLE_BUILTIN_SETUP(call, name)                                   \
170   InstallContextFunction(isolate, context, #name, Builtins::kConsole##call, \
171                          id, args.at(1));
172   CONSOLE_METHOD_LIST(CONSOLE_BUILTIN_SETUP)
173 #undef CONSOLE_BUILTIN_SETUP
174   InstallContextFunction(isolate, context, "time", Builtins::kConsoleTime, id,
175                          args.at(1));
176   InstallContextFunction(isolate, context, "timeEnd", Builtins::kConsoleTimeEnd,
177                          id, args.at(1));
178   InstallContextFunction(isolate, context, "timeStamp",
179                          Builtins::kConsoleTimeStamp, id, args.at(1));
180 
181   return *context;
182 }
183 
184 #undef CONSOLE_METHOD_LIST
185 
186 }  // namespace internal
187 }  // namespace v8
188