blob: a3c08bca8aac199fdd9dbb93703e562c11d4058a [file] [log] [blame]
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/script/v8c/v8c_global_environment.h"
#include <algorithm>
#include <utility>
#include "base/lazy_instance.h"
#include "base/stringprintf.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/script/v8c/v8c_source_code.h"
#include "nb/memory_scope.h"
namespace cobalt {
namespace script {
namespace v8c {
V8cGlobalEnvironment::V8cGlobalEnvironment(v8::Isolate* isolate)
: garbage_collection_count_(0),
environment_settings_(nullptr),
last_error_message_(nullptr),
eval_enabled_(false),
isolate_(isolate) {
TRACK_MEMORY_SCOPE("Javascript");
v8::Isolate::Scope isolate_scope(isolate_);
v8::HandleScope handle_scope(isolate_);
v8::Local<v8::ObjectTemplate> global_object_template;
v8::Local<v8::Context> context =
v8::Context::New(isolate_, nullptr, global_object_template);
context_.Reset(isolate_, context);
}
V8cGlobalEnvironment::~V8cGlobalEnvironment() {
DCHECK(thread_checker_.CalledOnValidThread());
}
void V8cGlobalEnvironment::CreateGlobalObject() {
TRACK_MEMORY_SCOPE("Javascript");
DCHECK(thread_checker_.CalledOnValidThread());
// TODO: Global object creation happens with context creation in V8.
// Strongly consider removing this from the interface.
EvaluateAutomatics();
}
bool V8cGlobalEnvironment::EvaluateScript(
const scoped_refptr<SourceCode>& source_code, bool mute_errors,
std::string* out_result_utf8) {
TRACK_MEMORY_SCOPE("Javascript");
DCHECK(thread_checker_.CalledOnValidThread());
v8::Isolate::Scope isolate_scope(isolate_);
v8::HandleScope handle_scope(isolate_);
v8::Local<v8::Context> context = context_.Get(isolate_);
v8::Context::Scope scope(context);
V8cSourceCode* v8c_source_code =
base::polymorphic_downcast<V8cSourceCode*>(source_code.get());
const base::SourceLocation& source_location = v8c_source_code->location();
v8::TryCatch try_catch(isolate_);
v8::ScriptOrigin script_origin(
v8::String::NewFromUtf8(isolate_, source_location.file_path.c_str(),
v8::NewStringType::kNormal)
.ToLocalChecked(),
v8::Integer::New(isolate_, source_location.line_number),
v8::Integer::New(isolate_, source_location.column_number),
v8::Boolean::New(isolate_, !mute_errors));
v8::Local<v8::String> source =
v8::String::NewFromUtf8(isolate_, v8c_source_code->source_utf8().c_str(),
v8::NewStringType::kNormal)
.ToLocalChecked();
v8::MaybeLocal<v8::Script> maybe_script =
v8::Script::Compile(context, source);
v8::Local<v8::Script> script;
if (!maybe_script.ToLocal(&script)) {
return false;
}
v8::MaybeLocal<v8::Value> maybe_result = script->Run(context);
v8::Local<v8::Value> result;
if (!maybe_result.ToLocal(&result)) {
return false;
}
if (out_result_utf8) {
*out_result_utf8 = *v8::String::Utf8Value(isolate_, result);
}
return true;
}
bool V8cGlobalEnvironment::EvaluateScript(
const scoped_refptr<SourceCode>& source_code,
const scoped_refptr<Wrappable>& owning_object, bool mute_errors,
base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle) {
TRACK_MEMORY_SCOPE("Javascript");
DCHECK(thread_checker_.CalledOnValidThread());
// TODO: Implement this once we have |V8cObjectHandleHolder|.
NOTIMPLEMENTED();
return false;
}
std::vector<StackFrame> V8cGlobalEnvironment::GetStackTrace(int max_frames) {
DCHECK(thread_checker_.CalledOnValidThread());
NOTIMPLEMENTED();
return {};
}
void V8cGlobalEnvironment::PreventGarbageCollection(
const scoped_refptr<Wrappable>& wrappable) {
DCHECK(thread_checker_.CalledOnValidThread());
NOTIMPLEMENTED();
}
void V8cGlobalEnvironment::AllowGarbageCollection(
const scoped_refptr<Wrappable>& wrappable) {
TRACK_MEMORY_SCOPE("Javascript");
DCHECK(thread_checker_.CalledOnValidThread());
NOTIMPLEMENTED();
}
void V8cGlobalEnvironment::DisableEval(const std::string& message) {
DCHECK(thread_checker_.CalledOnValidThread());
eval_disabled_message_.emplace(message);
eval_enabled_ = false;
}
void V8cGlobalEnvironment::EnableEval() {
DCHECK(thread_checker_.CalledOnValidThread());
eval_disabled_message_ = base::nullopt;
eval_enabled_ = true;
}
void V8cGlobalEnvironment::DisableJit() {
DCHECK(thread_checker_.CalledOnValidThread());
SB_DLOG(INFO)
<< "V8 can only be run with JIT enabled, ignoring |DisableJit| call.";
}
void V8cGlobalEnvironment::SetReportEvalCallback(
const base::Closure& report_eval) {
DCHECK(thread_checker_.CalledOnValidThread());
report_eval_ = report_eval;
}
void V8cGlobalEnvironment::SetReportErrorCallback(
const ReportErrorCallback& report_error_callback) {
DCHECK(thread_checker_.CalledOnValidThread());
report_error_callback_ = report_error_callback;
}
void V8cGlobalEnvironment::Bind(const std::string& identifier,
const scoped_refptr<Wrappable>& impl) {
TRACK_MEMORY_SCOPE("Javascript");
NOTIMPLEMENTED();
}
ScriptValueFactory* V8cGlobalEnvironment::script_value_factory() {
NOTIMPLEMENTED();
return nullptr;
}
void V8cGlobalEnvironment::EvaluateAutomatics() {
// TODO: Maybe add fetch, stream, and promise polyfills. Investigate what
// V8 has to natively offer first.
NOTIMPLEMENTED();
}
} // namespace v8c
} // namespace script
} // namespace cobalt