builtins-console.cc 7.37 KB
Newer Older
1 2 3 4
// Copyright 2017 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.

5
#include "src/api/api-inl.h"
6 7
#include "src/builtins/builtins-utils-inl.h"
#include "src/builtins/builtins.h"
8
#include "src/debug/interface-types.h"
9 10
#include "src/logging/counters.h"
#include "src/logging/log.h"
11
#include "src/objects/objects-inl.h"
12 13 14 15 16 17 18

namespace v8 {
namespace internal {

// -----------------------------------------------------------------------------
// Console

19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
#define CONSOLE_METHOD_LIST(V)      \
  V(Debug, debug)                   \
  V(Error, error)                   \
  V(Info, info)                     \
  V(Log, log)                       \
  V(Warn, warn)                     \
  V(Dir, dir)                       \
  V(DirXml, dirXml)                 \
  V(Table, table)                   \
  V(Trace, trace)                   \
  V(Group, group)                   \
  V(GroupCollapsed, groupCollapsed) \
  V(GroupEnd, groupEnd)             \
  V(Clear, clear)                   \
  V(Count, count)                   \
34
  V(CountReset, countReset)         \
35 36
  V(Assert, assert)                 \
  V(Profile, profile)               \
37 38
  V(ProfileEnd, profileEnd)         \
  V(TimeLog, timeLog)
39 40 41

namespace {
void ConsoleCall(
42
    Isolate* isolate, const internal::BuiltinArguments& args,
43 44
    void (debug::ConsoleDelegate::*func)(const v8::debug::ConsoleCallArguments&,
                                         const v8::debug::ConsoleContext&)) {
45 46
  CHECK(!isolate->has_pending_exception());
  CHECK(!isolate->has_scheduled_exception());
47
  if (!isolate->console_delegate()) return;
48
  HandleScope scope(isolate);
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

  // Access check. The current context has to match the context of all
  // arguments, otherwise the inspector might leak objects across contexts.
  Handle<Context> context = handle(isolate->context(), isolate);
  for (int i = 0; i < args.length(); ++i) {
    Handle<Object> argument = args.at<Object>(i);
    if (!argument->IsJSObject()) continue;

    Handle<JSObject> argument_obj = Handle<JSObject>::cast(argument);
    if (argument->IsAccessCheckNeeded(isolate) &&
        !isolate->MayAccess(context, argument_obj)) {
      isolate->ReportFailedAccessCheck(argument_obj);
      return;
    }
  }

65 66 67 68 69 70 71 72 73 74 75 76 77 78
  debug::ConsoleCallArguments wrapper(args);
  Handle<Object> context_id_obj = JSObject::GetDataProperty(
      args.target(), isolate->factory()->console_context_id_symbol());
  int context_id =
      context_id_obj->IsSmi() ? Handle<Smi>::cast(context_id_obj)->value() : 0;
  Handle<Object> context_name_obj = JSObject::GetDataProperty(
      args.target(), isolate->factory()->console_context_name_symbol());
  Handle<String> context_name = context_name_obj->IsString()
                                    ? Handle<String>::cast(context_name_obj)
                                    : isolate->factory()->anonymous_string();
  (isolate->console_delegate()->*func)(
      wrapper,
      v8::debug::ConsoleContext(context_id, Utils::ToLocal(context_name)));
}
79 80 81 82 83 84 85

void LogTimerEvent(Isolate* isolate, BuiltinArguments args,
                   Logger::StartEnd se) {
  if (!isolate->logger()->is_logging()) return;
  HandleScope scope(isolate);
  std::unique_ptr<char[]> name;
  const char* raw_name = "default";
86
  if (args.length() > 1 && args[1].IsString()) {
87 88 89 90 91 92
    // Try converting the first argument to a string.
    name = args.at<String>(1)->ToCString();
    raw_name = name.get();
  }
  LOG(isolate, TimerEvent(se, raw_name));
}
93 94 95 96 97
}  // namespace

#define CONSOLE_BUILTIN_IMPLEMENTATION(call, name)             \
  BUILTIN(Console##call) {                                     \
    ConsoleCall(isolate, args, &debug::ConsoleDelegate::call); \
98
    RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);            \
99
    return ReadOnlyRoots(isolate).undefined_value();           \
100 101 102 103
  }
CONSOLE_METHOD_LIST(CONSOLE_BUILTIN_IMPLEMENTATION)
#undef CONSOLE_BUILTIN_IMPLEMENTATION

104 105 106 107
BUILTIN(ConsoleTime) {
  LogTimerEvent(isolate, args, Logger::START);
  ConsoleCall(isolate, args, &debug::ConsoleDelegate::Time);
  RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
108
  return ReadOnlyRoots(isolate).undefined_value();
109 110 111 112 113 114
}

BUILTIN(ConsoleTimeEnd) {
  LogTimerEvent(isolate, args, Logger::END);
  ConsoleCall(isolate, args, &debug::ConsoleDelegate::TimeEnd);
  RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
115
  return ReadOnlyRoots(isolate).undefined_value();
116 117 118 119 120 121
}

BUILTIN(ConsoleTimeStamp) {
  LogTimerEvent(isolate, args, Logger::STAMP);
  ConsoleCall(isolate, args, &debug::ConsoleDelegate::TimeStamp);
  RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
122
  return ReadOnlyRoots(isolate).undefined_value();
123 124
}

125
namespace {
126

127 128 129 130
void InstallContextFunction(Isolate* isolate, Handle<JSObject> target,
                            const char* name, Builtins::Name builtin_id,
                            int context_id, Handle<Object> context_name) {
  Factory* const factory = isolate->factory();
131

132 133 134
  Handle<NativeContext> context(isolate->native_context());
  Handle<Map> map = isolate->sloppy_function_without_prototype_map();

135
  Handle<String> name_string =
136
      Name::ToFunctionName(isolate, factory->InternalizeUtf8String(name))
137
          .ToHandleChecked();
138 139 140 141 142 143
  Handle<SharedFunctionInfo> info =
      factory->NewSharedFunctionInfoForBuiltin(name_string, builtin_id);
  info->set_language_mode(LanguageMode::kSloppy);

  Handle<JSFunction> fun =
      Factory::JSFunctionBuilder{isolate, info, context}.set_map(map).Build();
144

145 146 147
  fun->shared().set_native(true);
  fun->shared().DontAdaptArguments();
  fun->shared().set_length(1);
148

149
  JSObject::AddProperty(isolate, fun, factory->console_context_id_symbol(),
150
                        handle(Smi::FromInt(context_id), isolate), NONE);
151
  if (context_name->IsString()) {
152
    JSObject::AddProperty(isolate, fun, factory->console_context_name_symbol(),
153
                          context_name, NONE);
154
  }
155
  JSObject::AddProperty(isolate, target, name_string, fun, NONE);
156
}
157

158 159 160 161 162 163 164
}  // namespace

BUILTIN(ConsoleContext) {
  HandleScope scope(isolate);

  Factory* const factory = isolate->factory();
  Handle<String> name = factory->InternalizeUtf8String("Context");
165 166 167 168 169 170 171
  Handle<SharedFunctionInfo> info =
      factory->NewSharedFunctionInfoForBuiltin(name, Builtins::kIllegal);
  info->set_language_mode(LanguageMode::kSloppy);

  Handle<JSFunction> cons =
      Factory::JSFunctionBuilder{isolate, info, isolate->native_context()}
          .Build();
172 173 174 175

  Handle<JSObject> prototype = factory->NewJSObject(isolate->object_function());
  JSFunction::SetPrototype(cons, prototype);

176
  Handle<JSObject> context = factory->NewJSObject(cons, AllocationType::kOld);
177 178 179 180
  DCHECK(context->IsJSObject());
  int id = isolate->last_console_context_id() + 1;
  isolate->set_last_console_context_id(id);

181 182 183
#define CONSOLE_BUILTIN_SETUP(call, name)                                   \
  InstallContextFunction(isolate, context, #name, Builtins::kConsole##call, \
                         id, args.at(1));
184 185
  CONSOLE_METHOD_LIST(CONSOLE_BUILTIN_SETUP)
#undef CONSOLE_BUILTIN_SETUP
186
  InstallContextFunction(isolate, context, "time", Builtins::kConsoleTime, id,
187
                         args.at(1));
188 189 190 191
  InstallContextFunction(isolate, context, "timeEnd", Builtins::kConsoleTimeEnd,
                         id, args.at(1));
  InstallContextFunction(isolate, context, "timeStamp",
                         Builtins::kConsoleTimeStamp, id, args.at(1));
192 193 194 195

  return *context;
}

196 197 198 199
#undef CONSOLE_METHOD_LIST

}  // namespace internal
}  // namespace v8