2017-04-18 20:50:30 +00:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
#include "src/builtins/builtins-utils.h"
|
|
|
|
#include "src/builtins/builtins.h"
|
|
|
|
|
2017-09-11 11:40:20 +00:00
|
|
|
#include "src/api.h"
|
2017-04-18 20:50:30 +00:00
|
|
|
#include "src/debug/interface-types.h"
|
|
|
|
#include "src/objects-inl.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Console
|
|
|
|
|
2017-06-12 10:01:19 +00:00
|
|
|
#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) \
|
|
|
|
V(Assert, assert) \
|
|
|
|
V(MarkTimeline, markTimeline) \
|
|
|
|
V(Profile, profile) \
|
|
|
|
V(ProfileEnd, profileEnd) \
|
|
|
|
V(Timeline, timeline) \
|
2017-10-13 07:13:19 +00:00
|
|
|
V(TimelineEnd, timelineEnd)
|
2017-06-12 10:01:19 +00:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
void ConsoleCall(
|
|
|
|
Isolate* isolate, internal::BuiltinArguments& args,
|
|
|
|
void (debug::ConsoleDelegate::*func)(const v8::debug::ConsoleCallArguments&,
|
|
|
|
const v8::debug::ConsoleContext&)) {
|
2017-08-15 17:13:43 +00:00
|
|
|
CHECK(!isolate->has_pending_exception());
|
|
|
|
CHECK(!isolate->has_scheduled_exception());
|
2017-06-12 10:01:19 +00:00
|
|
|
if (!isolate->console_delegate()) return;
|
2017-08-15 17:13:43 +00:00
|
|
|
HandleScope scope(isolate);
|
2017-06-12 10:01:19 +00:00
|
|
|
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)));
|
|
|
|
}
|
2017-10-13 07:13:19 +00:00
|
|
|
|
|
|
|
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";
|
|
|
|
if (args.length() > 1 && args[1]->IsString()) {
|
|
|
|
// Try converting the first argument to a string.
|
|
|
|
name = args.at<String>(1)->ToCString();
|
|
|
|
raw_name = name.get();
|
|
|
|
}
|
|
|
|
LOG(isolate, TimerEvent(se, raw_name));
|
|
|
|
}
|
2017-06-12 10:01:19 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
#define CONSOLE_BUILTIN_IMPLEMENTATION(call, name) \
|
|
|
|
BUILTIN(Console##call) { \
|
|
|
|
ConsoleCall(isolate, args, &debug::ConsoleDelegate::call); \
|
2017-08-31 12:26:27 +00:00
|
|
|
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); \
|
2017-06-12 10:01:19 +00:00
|
|
|
return isolate->heap()->undefined_value(); \
|
2017-04-18 20:50:30 +00:00
|
|
|
}
|
|
|
|
CONSOLE_METHOD_LIST(CONSOLE_BUILTIN_IMPLEMENTATION)
|
|
|
|
#undef CONSOLE_BUILTIN_IMPLEMENTATION
|
|
|
|
|
2017-10-13 07:13:19 +00:00
|
|
|
BUILTIN(ConsoleTime) {
|
|
|
|
LogTimerEvent(isolate, args, Logger::START);
|
|
|
|
ConsoleCall(isolate, args, &debug::ConsoleDelegate::Time);
|
|
|
|
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
|
|
|
|
return isolate->heap()->undefined_value();
|
|
|
|
}
|
|
|
|
|
|
|
|
BUILTIN(ConsoleTimeEnd) {
|
|
|
|
LogTimerEvent(isolate, args, Logger::END);
|
|
|
|
ConsoleCall(isolate, args, &debug::ConsoleDelegate::TimeEnd);
|
|
|
|
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
|
|
|
|
return isolate->heap()->undefined_value();
|
|
|
|
}
|
|
|
|
|
|
|
|
BUILTIN(ConsoleTimeStamp) {
|
|
|
|
LogTimerEvent(isolate, args, Logger::STAMP);
|
|
|
|
ConsoleCall(isolate, args, &debug::ConsoleDelegate::TimeStamp);
|
|
|
|
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
|
|
|
|
return isolate->heap()->undefined_value();
|
|
|
|
}
|
|
|
|
|
2017-06-12 10:01:19 +00:00
|
|
|
namespace {
|
|
|
|
void InstallContextFunction(Handle<JSObject> target, const char* name,
|
2017-11-08 12:56:08 +00:00
|
|
|
Builtins::Name builtin_id, int context_id,
|
2017-06-13 10:08:50 +00:00
|
|
|
Handle<Object> context_name) {
|
2017-06-12 10:01:19 +00:00
|
|
|
Factory* const factory = target->GetIsolate()->factory();
|
|
|
|
|
2017-11-08 12:56:08 +00:00
|
|
|
Handle<Code> code(target->GetIsolate()->builtins()->builtin(builtin_id));
|
2017-06-12 10:01:19 +00:00
|
|
|
|
|
|
|
Handle<String> name_string =
|
|
|
|
Name::ToFunctionName(factory->InternalizeUtf8String(name))
|
|
|
|
.ToHandleChecked();
|
2017-11-08 12:56:08 +00:00
|
|
|
NewFunctionArgs args = NewFunctionArgs::ForBuiltinWithoutPrototype(
|
|
|
|
name_string, code, builtin_id, i::LanguageMode::kSloppy);
|
|
|
|
Handle<JSFunction> fun = factory->NewFunction(args);
|
|
|
|
|
2017-06-12 10:01:19 +00:00
|
|
|
fun->shared()->set_native(true);
|
|
|
|
fun->shared()->DontAdaptArguments();
|
|
|
|
fun->shared()->set_length(1);
|
|
|
|
|
|
|
|
JSObject::AddProperty(fun, factory->console_context_id_symbol(),
|
|
|
|
handle(Smi::FromInt(context_id), target->GetIsolate()),
|
|
|
|
NONE);
|
|
|
|
if (context_name->IsString()) {
|
|
|
|
JSObject::AddProperty(fun, factory->console_context_name_symbol(),
|
2017-06-13 10:08:50 +00:00
|
|
|
context_name, NONE);
|
2017-06-12 10:01:19 +00:00
|
|
|
}
|
|
|
|
JSObject::AddProperty(target, name_string, fun, NONE);
|
|
|
|
}
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
BUILTIN(ConsoleContext) {
|
|
|
|
HandleScope scope(isolate);
|
|
|
|
|
|
|
|
Factory* const factory = isolate->factory();
|
|
|
|
Handle<String> name = factory->InternalizeUtf8String("Context");
|
2017-11-08 12:56:08 +00:00
|
|
|
NewFunctionArgs arguments = NewFunctionArgs::ForFunctionWithoutCode(
|
|
|
|
name, isolate->sloppy_function_map(), LanguageMode::kSloppy);
|
|
|
|
Handle<JSFunction> cons = factory->NewFunction(arguments);
|
|
|
|
|
|
|
|
Handle<JSObject> prototype = factory->NewJSObject(isolate->object_function());
|
|
|
|
JSFunction::SetPrototype(cons, prototype);
|
|
|
|
|
2017-06-12 10:01:19 +00:00
|
|
|
Handle<JSObject> context = factory->NewJSObject(cons, TENURED);
|
|
|
|
DCHECK(context->IsJSObject());
|
|
|
|
int id = isolate->last_console_context_id() + 1;
|
|
|
|
isolate->set_last_console_context_id(id);
|
|
|
|
|
2017-06-13 10:08:50 +00:00
|
|
|
#define CONSOLE_BUILTIN_SETUP(call, name) \
|
|
|
|
InstallContextFunction(context, #name, Builtins::kConsole##call, id, \
|
|
|
|
args.at(1));
|
2017-06-12 10:01:19 +00:00
|
|
|
CONSOLE_METHOD_LIST(CONSOLE_BUILTIN_SETUP)
|
|
|
|
#undef CONSOLE_BUILTIN_SETUP
|
2017-10-13 07:13:19 +00:00
|
|
|
InstallContextFunction(context, "time", Builtins::kConsoleTime, id,
|
|
|
|
args.at(1));
|
|
|
|
InstallContextFunction(context, "timeEnd", Builtins::kConsoleTimeEnd, id,
|
|
|
|
args.at(1));
|
|
|
|
InstallContextFunction(context, "timeStamp", Builtins::kConsoleTimeStamp, id,
|
|
|
|
args.at(1));
|
2017-06-12 10:01:19 +00:00
|
|
|
|
|
|
|
return *context;
|
|
|
|
}
|
|
|
|
|
2017-04-18 20:50:30 +00:00
|
|
|
#undef CONSOLE_METHOD_LIST
|
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|