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