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