Skip to content

Commit

Permalink
Introduce gin_shell
Browse files Browse the repository at this point in the history
This CL adds a simple shell program for Gin to make edit/test/debug cycle
faster. The shell excutes a list of scripts from the command line and loads any
requested AMD modules relative to the current working directory.

This CL will also let us remove the ugly code in
https://codereview.chromium.org/69843003/diff/240001/mojo/public/bindings/js/test/run_js_tests.cc
because we now know how to file modules via the file system. Eventually for
Mojo, we'll want to use a net_module_provider (instead of the
file_module_provider included in this CL) to load additional AMD modules off
the network.

BUG=317398
R=jochen@chromium.org

Review URL: https://codereview.chromium.org/74753002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@235750 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
abarth@chromium.org committed Nov 18, 2013
1 parent a29e465 commit 855ab43
Show file tree
Hide file tree
Showing 24 changed files with 568 additions and 164 deletions.
5 changes: 1 addition & 4 deletions gin/DEPS
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
include_rules = [
"+v8",

# Use of base is allowed in tests. We can also use base in production code
# as long as we don't introduce a link-time dependency.
"+base",
"+v8",
]
7 changes: 3 additions & 4 deletions gin/arguments.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include "gin/arguments.h"

#include <sstream>
#include "base/strings/stringprintf.h"
#include "gin/converter.h"

namespace gin {
Expand All @@ -29,9 +29,8 @@ void Arguments::ThrowError() {
if (insufficient_arguments_)
return ThrowTypeError("Insufficient number of arguments.");

std::stringstream stream;
stream << "Error processing argument " << next_ - 1 << ".";
ThrowTypeError(stream.str());
ThrowTypeError(base::StringPrintf(
"Error processing argument %d.", next_ - 1));
}

void Arguments::ThrowTypeError(const std::string& message) {
Expand Down
26 changes: 7 additions & 19 deletions gin/array_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,26 +53,25 @@ ArrayBufferAllocator* ArrayBufferAllocator::SharedInstance() {
// a pointer to the ArrayBuffer::Private object in an internal field of the
// ArrayBuffer object.
//
class ArrayBuffer::Private {
class ArrayBuffer::Private : public base::RefCounted<ArrayBuffer::Private> {
public:
static scoped_refptr<Private> From(v8::Isolate* isolate,
v8::Handle<v8::ArrayBuffer> array);

void AddRef();
void Release();

void* buffer() const { return buffer_; }
size_t length() const { return length_; }

private:
friend class base::RefCounted<Private>;

Private(v8::Isolate* isolate, v8::Handle<v8::ArrayBuffer> array);
~Private();

static void WeakCallback(
const v8::WeakCallbackData<v8::ArrayBuffer, Private>& data);

size_t ref_count_;
v8::Persistent<v8::ArrayBuffer> array_buffer_;
scoped_refptr<Private> self_reference_;
void* buffer_;
size_t length_;
};
Expand All @@ -86,28 +85,17 @@ scoped_refptr<ArrayBuffer::Private> ArrayBuffer::Private::From(
return make_scoped_refptr(new Private(isolate, array));
}

void ArrayBuffer::Private::AddRef() {
++ref_count_;
}

void ArrayBuffer::Private::Release() {
if (--ref_count_)
return;
delete this;
}

ArrayBuffer::Private::Private(v8::Isolate* isolate,
v8::Handle<v8::ArrayBuffer> array)
: ref_count_(0),
array_buffer_(isolate, array) {
: array_buffer_(isolate, array) {
// Take ownership of the array buffer.
v8::ArrayBuffer::Contents contents = array->Externalize();
buffer_ = contents.Data();
length_ = contents.ByteLength();

array->SetAlignedPointerInInternalField(kBufferViewPrivateIndex, this);

AddRef(); // Balanced in WeakCallback.
self_reference_ = this; // Cleared in WeakCallback.
array_buffer_.SetWeak(this, WeakCallback);
}

Expand All @@ -119,7 +107,7 @@ void ArrayBuffer::Private::WeakCallback(
const v8::WeakCallbackData<v8::ArrayBuffer, Private>& data) {
Private* parameter = data.GetParameter();
parameter->array_buffer_.Reset();
parameter->Release(); // Balanced in ArrayBuffer::Private::Private.
// parameter->self_reference_.clear();
}

// ArrayBuffer ----------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion gin/array_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h" // For scoped_refptr only!
#include "base/memory/ref_counted.h"
#include "gin/converter.h"
#include "v8/include/v8.h"

Expand Down
11 changes: 5 additions & 6 deletions gin/context_holder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include "gin/context_holder.h"

#include <assert.h>
#include "base/logging.h"
#include "gin/per_context_data.h"

namespace gin {
Expand All @@ -17,18 +17,17 @@ ContextHolder::~ContextHolder() {
v8::HandleScope handle_scope(isolate());
v8::Handle<v8::Context> context = this->context();

PerContextData* data = PerContextData::From(context);
data->Detach(context);
delete data;
data_->Detach(context);
data_.reset();

// TODO(abarth): Figure out how to set kResetInDestructor to true.
context_.Reset();
}

void ContextHolder::SetContext(v8::Handle<v8::Context> context) {
assert(context_.IsEmpty());
DCHECK(context_.IsEmpty());
context_.Reset(isolate_, context);
new PerContextData(context); // Deleted in ~ContextHolder.
data_.reset(new PerContextData(context));
}

} // namespace gin
5 changes: 5 additions & 0 deletions gin/context_holder.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
#define GIN_CONTEXT_HOLDER_H_

#include <list>

#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "v8/include/v8.h"

namespace gin {

class PerContextData;

class ContextHolder {
public:
explicit ContextHolder(v8::Isolate* isolate);
Expand All @@ -27,6 +31,7 @@ class ContextHolder {
private:
v8::Isolate* isolate_;
v8::Persistent<v8::Context> context_;
scoped_ptr<PerContextData> data_;

DISALLOW_COPY_AND_ASSIGN(ContextHolder);
};
Expand Down
32 changes: 25 additions & 7 deletions gin/gin.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,29 @@
{
'target_name': 'gin',
'type': 'static_library',
'include_dirs': [
'..'
],
'dependencies': [
'../base/base.gyp:base',
'../v8/tools/gyp/v8.gyp:v8',
],
'export_dependent_settings': [
'../base/base.gyp:base',
'../v8/tools/gyp/v8.gyp:v8',
],
'sources': [
'modules/file_module_provider.cc',
'modules/file_module_provider.h',
'modules/module_registry.cc',
'modules/module_registry.h',
'modules/module_runner_delegate.cc',
'modules/module_runner_delegate.h',
'arguments.cc',
'arguments.h',
'array_buffer.cc',
'array_buffer.h',
'converter.cc',
'converter.h',
'context_holder.cc',
'context_holder.h',
'converter.cc',
'converter.h',
'dictionary.cc',
'dictionary.h',
'initialize.cc',
Expand All @@ -40,20 +43,35 @@
'per_isolate_data.h',
'runner.cc',
'runner.h',
'try_catch.cc',
'try_catch.h',
'wrapper_info.cc',
'wrapper_info.h',
],
},
{
'target_name': 'gin_shell',
'type': 'executable',
'dependencies': [
'gin',
],
'sources': [
'shell/gin_main.cc',
],
'msvs_settings': {
'VCLinkerTool': {
'SubSystem': '1', # /SUBSYSTEM:CONSOLE
},
},
},
{
'target_name': 'gin_test',
'type': 'static_library',
'dependencies': [
'../base/base.gyp:base',
'../testing/gtest.gyp:gtest',
'gin',
],
'export_dependent_settings': [
'../base/base.gyp:base',
'../testing/gtest.gyp:gtest',
'gin',
],
Expand Down
2 changes: 1 addition & 1 deletion gin/initialize.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ void Initialize() {
v8::V8::SetArrayBufferAllocator(ArrayBufferAllocator::SharedInstance());
v8::V8::InitializeICU();
v8::V8::SetFlagsFromString(kFlags,
static_cast<uint32_t>(sizeof(kFlags) / sizeof(kFlags[0])) - 1);
static_cast<uint32_t>(arraysize(kFlags)) - 1);
v8::V8::SetEntropySource(&GenerateEntropy);
v8::V8::Initialize();

Expand Down
67 changes: 67 additions & 0 deletions gin/modules/file_module_provider.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2013 The Chromium 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 "gin/modules/file_module_provider.h"

#include "base/bind.h"
#include "base/file_util.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_split.h"
#include "gin/converter.h"

namespace gin {

namespace {

void AttempToLoadModule(const base::WeakPtr<Runner>& runner,
const base::FilePath& base,
const std::string& id) {
if (!runner)
return;

std::vector<std::string> components;
base::SplitString(id, '/', &components);
base::FilePath path = base;
for (size_t i = 0; i < components.size(); ++i) {
// TODO(abarth): Technically the path components can be UTF-8. We don't
// handle that case correctly yet.
path = path.AppendASCII(components[i]);
}
path = path.AddExtension(FILE_PATH_LITERAL("js"));

std::string source;
if (!ReadFileToString(path, &source))
return;

Runner::Scope scope(runner.get());
v8::Handle<v8::Script> script = v8::Script::New(
StringToV8(runner->isolate(), source),
StringToV8(runner->isolate(), id));
runner->Run(script);
}

} // namespace

FileModuleProvider::FileModuleProvider(const base::FilePath& base)
: base_(base) {
}

FileModuleProvider::~FileModuleProvider() {
}

void FileModuleProvider::AttempToLoadModules(
Runner* runner, const std::set<std::string>& ids) {
std::set<std::string> modules = ids;
for (std::set<std::string>::const_iterator it = modules.begin();
it != modules.end(); ++it) {
const std::string& id = *it;
if (attempted_ids_.count(id))
continue;
attempted_ids_.insert(id);
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(AttempToLoadModule, runner->GetWeakPtr(), base_, id));
}
}

} // namespace gin
32 changes: 32 additions & 0 deletions gin/modules/file_module_provider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef GIN_MODULES_FILE_MODULE_PROVIDER_H_
#define GIN_MODULES_FILE_MODULE_PROVIDER_H_

#include <set>
#include <string>

#include "base/files/file_path.h"
#include "gin/runner.h"

namespace gin {

class FileModuleProvider {
public:
explicit FileModuleProvider(const base::FilePath& base);
~FileModuleProvider();

void AttempToLoadModules(Runner* runner, const std::set<std::string>& ids);

private:
base::FilePath base_;
std::set<std::string> attempted_ids_;

DISALLOW_COPY_AND_ASSIGN(FileModuleProvider);
};

} // namespace gin

#endif // GIN_MODULES_FILE_MODULE_PROVIDER_H_
Loading

0 comments on commit 855ab43

Please sign in to comment.