diff options
-rw-r--r-- | mojo/BUILD.gn | 2 | ||||
-rw-r--r-- | mojo/apps/js/BUILD.gn | 67 | ||||
-rw-r--r-- | mojo/apps/js/application_delegate_impl.cc | 27 | ||||
-rw-r--r-- | mojo/apps/js/application_delegate_impl.h | 45 | ||||
-rw-r--r-- | mojo/apps/js/content_handler_impl.cc | 56 | ||||
-rw-r--r-- | mojo/apps/js/content_handler_impl.h | 33 | ||||
-rw-r--r-- | mojo/apps/js/content_handler_main.cc | 42 | ||||
-rw-r--r-- | mojo/apps/js/js_app.cc | 46 | ||||
-rw-r--r-- | mojo/apps/js/js_app.h | 30 | ||||
-rw-r--r-- | mojo/apps/js/main.cc | 15 | ||||
-rw-r--r-- | mojo/apps/js/standalone_main.cc | 55 | ||||
-rw-r--r-- | mojo/mojo.gyp | 3 | ||||
-rw-r--r-- | mojo/mojo_apps.gypi | 39 |
13 files changed, 325 insertions, 135 deletions
diff --git a/mojo/BUILD.gn b/mojo/BUILD.gn index b980b6e..45d91fd 100644 --- a/mojo/BUILD.gn +++ b/mojo/BUILD.gn @@ -12,7 +12,7 @@ group("mojo") { } deps = [ ":tests", - "//mojo/apps/js:mojo_js", + "//mojo/apps/js", "//mojo/common", "//mojo/examples", "//mojo/public", diff --git a/mojo/apps/js/BUILD.gn b/mojo/apps/js/BUILD.gn index 60ec320..16f1907 100644 --- a/mojo/apps/js/BUILD.gn +++ b/mojo/apps/js/BUILD.gn @@ -2,43 +2,72 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -shared_library("mojo_js") { +# GYP version: part of mojo/mojo_apps.gypi:mojo_js_lib +source_set("js") { + sources = [ + "mojo_runner_delegate.cc", + "mojo_runner_delegate.h", + ] + + public_deps = [ + "//mojo/bindings/js", + ] + deps = [ + "//base", + "//gin", + "//mojo/apps/js/bindings", + "//mojo/apps/js/bindings/gl", + "//v8", + ] +} + +# GYP version: mojo/mojo_apps.gypi:mojo_js_apps_lib +source_set("js_apps") { sources = [ "application_delegate_impl.cc", "js_app.cc", "mojo_module.cc", - "main.cc" ] + public_deps = [ + "//mojo/bindings/js", + ] deps = [ ":js", - "//base", - "//base:i18n", - "//gin", "//mojo/application", "//mojo/public/c/system:for_shared_library", - "//mojo/public/cpp/application", - "//mojo/public/cpp/bindings", "//mojo/public/cpp/utility", - "//mojo/services/public/interfaces/content_handler", ] } -# GYP version: part of mojo/mojo_apps.gypi:mojo_js_lib -source_set("js") { +shared_library("mojo_js_content_handler") { sources = [ - "mojo_runner_delegate.cc", - "mojo_runner_delegate.h", + "content_handler_impl.cc", + "content_handler_main.cc", ] - public_deps = [ - "//mojo/bindings/js", + deps = [ + ":js_apps", + "//base:i18n", + "//mojo/application:application", + "//mojo/environment:chromium", + "//mojo/services/public/interfaces/content_handler", ] +} + +shared_library("mojo_js_standalone") { + sources = [ + "standalone_main.cc" + ] + deps = [ - "//base", - "//gin", - "//mojo/apps/js/bindings", - "//mojo/apps/js/bindings/gl", - "//v8", + ":js_apps", + "//base:i18n", + "//mojo/application:application", + "//mojo/environment:chromium", + "//mojo/public/cpp/application", ] } + + + diff --git a/mojo/apps/js/application_delegate_impl.cc b/mojo/apps/js/application_delegate_impl.cc index 81cff28..65c48ca 100644 --- a/mojo/apps/js/application_delegate_impl.cc +++ b/mojo/apps/js/application_delegate_impl.cc @@ -10,22 +10,8 @@ namespace mojo { namespace apps { -ContentHandlerImpl::ContentHandlerImpl(ApplicationDelegateImpl* app) - : content_handler_(app) { -} - -ContentHandlerImpl::~ContentHandlerImpl() { -} - -void ContentHandlerImpl::OnConnect( - const mojo::String& url, - URLResponsePtr content, - InterfaceRequest<ServiceProvider> service_provider) { - content_handler_->StartJSApp(url.To<std::string>(), content.Pass()); -} - ApplicationDelegateImpl::ApplicationDelegateImpl() - : application_impl_(NULL), content_handler_factory_(this) { + : application_impl_(nullptr) { } void ApplicationDelegateImpl::Initialize(ApplicationImpl* app) { @@ -35,15 +21,8 @@ void ApplicationDelegateImpl::Initialize(ApplicationImpl* app) { ApplicationDelegateImpl::~ApplicationDelegateImpl() { } -bool ApplicationDelegateImpl::ConfigureIncomingConnection( - ApplicationConnection* connection) { - connection->AddService(&content_handler_factory_); - return true; -} - -void ApplicationDelegateImpl::StartJSApp(const std::string& url, - URLResponsePtr content) { - JSApp* app = new JSApp(this, url, content.Pass()); +void ApplicationDelegateImpl::StartJSApp(scoped_ptr<JSApp> app_ptr) { + JSApp *app = app_ptr.release(); app_vector_.push_back(app); // TODO(hansmuller): deal with the Start() return value. app->Start(); diff --git a/mojo/apps/js/application_delegate_impl.h b/mojo/apps/js/application_delegate_impl.h index fc2500b..4c2f2e2 100644 --- a/mojo/apps/js/application_delegate_impl.h +++ b/mojo/apps/js/application_delegate_impl.h @@ -5,11 +5,10 @@ #ifndef MOJO_APPS_JS_CONTENT_HANDLER_H_ #define MOJO_APPS_JS_CONTENT_HANDLER_H_ -#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/interface_factory_impl.h" -#include "mojo/services/public/interfaces/content_handler/content_handler.mojom.h" +#include "mojo/public/cpp/system/message_pipe.h" namespace mojo { @@ -20,49 +19,35 @@ namespace apps { class ApplicationDelegateImpl; class JSApp; -// Starts a new JSApp for each OnConnect call(). - -class ContentHandlerImpl : public InterfaceImpl<ContentHandler> { - public: - ContentHandlerImpl(ApplicationDelegateImpl* content_handler); - virtual ~ContentHandlerImpl(); - - private: - virtual void OnConnect( - const mojo::String& url, - URLResponsePtr content, - InterfaceRequest<ServiceProvider> service_provider) override; - - ApplicationDelegateImpl* content_handler_; -}; - // Manages the JSApps started by this content handler. This class owns the one // reference to the Mojo shell. JSApps post a task to the content handler's -// thread to connect to a service or to quit.l +// thread to connect to a service or to quit. +// +// The lifetime each JSApp is defined by its entry in AppVector. When the entry +// is removed ("erased") by QuitJSApp(), the JSApp is destroyed. class ApplicationDelegateImpl : public ApplicationDelegate { public: ApplicationDelegateImpl(); virtual ~ApplicationDelegateImpl(); - void StartJSApp(const std::string& url, URLResponsePtr content); - void QuitJSApp(JSApp* app); + // Add app to the AppVector and call its Start() method. + void StartJSApp(scoped_ptr<JSApp> app); + + // Remove app from the AppVector; destroys the app. + void QuitJSApp(JSApp *app); void ConnectToService(ScopedMessagePipeHandle pipe_handle, const std::string& application_url, const std::string& interface_name); - private: - typedef ScopedVector<JSApp> AppVector; - - // ApplicationDelegate methods + protected: + // ApplicationDelegate: virtual void Initialize(ApplicationImpl* app) override; - virtual bool ConfigureIncomingConnection( - ApplicationConnection* connection) override; + private: + typedef ScopedVector<JSApp> AppVector; ApplicationImpl* application_impl_; - InterfaceFactoryImplWithContext<ContentHandlerImpl, ApplicationDelegateImpl> - content_handler_factory_; AppVector app_vector_; }; diff --git a/mojo/apps/js/content_handler_impl.cc b/mojo/apps/js/content_handler_impl.cc new file mode 100644 index 0000000..f3dffa7 --- /dev/null +++ b/mojo/apps/js/content_handler_impl.cc @@ -0,0 +1,56 @@ +// Copyright 2014 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 "mojo/apps/js/content_handler_impl.h" + +#include "mojo/apps/js/application_delegate_impl.h" +#include "mojo/apps/js/js_app.h" +#include "mojo/common/data_pipe_utils.h" + +namespace mojo { +namespace apps { + +class ContentHandlerJSApp : public JSApp { + public: + ContentHandlerJSApp(ApplicationDelegateImpl* app_delegate_impl, + const std::string& url, + URLResponsePtr content) + : JSApp(app_delegate_impl), + url_(url), + content_(content.Pass()) { + } + + virtual bool Load(std::string* source, std::string* file_name) override { + *file_name = url_; + if (content_.is_null()) + return false; + return common::BlockingCopyToString(content_->body.Pass(), source); + } + + private: + std::string url_; + URLResponsePtr content_; +}; + + +ContentHandlerImpl::ContentHandlerImpl(ApplicationDelegateImpl* app) + : app_delegate_impl_(app) { +} + +ContentHandlerImpl::~ContentHandlerImpl() { +} + +void ContentHandlerImpl::OnConnect( + const mojo::String& url, + URLResponsePtr content, + InterfaceRequest<ServiceProvider> service_provider) { + scoped_ptr<JSApp> js_app( + new ContentHandlerJSApp(app_delegate_impl_, + url.To<std::string>(), + content.Pass())); + app_delegate_impl_->StartJSApp(js_app.Pass()); +} + +} // namespace apps +} // namespace mojo diff --git a/mojo/apps/js/content_handler_impl.h b/mojo/apps/js/content_handler_impl.h new file mode 100644 index 0000000..04c2603 --- /dev/null +++ b/mojo/apps/js/content_handler_impl.h @@ -0,0 +1,33 @@ +// Copyright 2014 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 MOJO_APPS_JS_CONTENT_HANDLER_IMPL_H_ +#define MOJO_APPS_JS_CONTENT_HANDLER_IMPL_H_ + +#include "mojo/services/public/interfaces/content_handler/content_handler.mojom.h" + +namespace mojo { +namespace apps { + +class ApplicationDelegateImpl; + +// Starts a new JSApp for each OnConnect call(). +class ContentHandlerImpl : public InterfaceImpl<ContentHandler> { + public: + ContentHandlerImpl(ApplicationDelegateImpl* app_delegate_impl); + + private: + virtual ~ContentHandlerImpl(); + virtual void OnConnect( + const mojo::String& url, + URLResponsePtr content, + InterfaceRequest<ServiceProvider> service_provider) override; + + ApplicationDelegateImpl* app_delegate_impl_; +}; + +} // namespace apps +} // namespace mojo + +#endif // MOJO_APPS_JS_CONTENT_HANDLER_IMPL_H_ diff --git a/mojo/apps/js/content_handler_main.cc b/mojo/apps/js/content_handler_main.cc new file mode 100644 index 0000000..3ea9a3e --- /dev/null +++ b/mojo/apps/js/content_handler_main.cc @@ -0,0 +1,42 @@ +// Copyright 2014 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 "base/i18n/icu_util.h" +#include "mojo/application/application_runner_chromium.h" +#include "mojo/apps/js/application_delegate_impl.h" +#include "mojo/apps/js/content_handler_impl.h" +#include "mojo/public/c/system/main.h" +#include "mojo/public/cpp/application/application_impl.h" +#include "mojo/public/cpp/application/interface_factory_impl.h" +#include "mojo/services/public/interfaces/content_handler/content_handler.mojom.h" + +namespace mojo { +namespace apps { + +class ContentHandlerApplicationDelegateImpl : public ApplicationDelegateImpl { + public: + ContentHandlerApplicationDelegateImpl() : content_handler_factory_(this) { + } + + private: + virtual bool ConfigureIncomingConnection( + ApplicationConnection* connection) override { + connection->AddService(&content_handler_factory_); + return true; + } + + InterfaceFactoryImplWithContext<ContentHandlerImpl, ApplicationDelegateImpl> + content_handler_factory_; +}; + +} // namespace apps +} // namespace mojo + +MojoResult MojoMain(MojoHandle shell_handle) { + base::i18n::InitializeICU(); + mojo::ApplicationRunnerChromium runner( + new mojo::apps::ContentHandlerApplicationDelegateImpl()); + return runner.Run(shell_handle); +} diff --git a/mojo/apps/js/js_app.cc b/mojo/apps/js/js_app.cc index db51c09..877564d 100644 --- a/mojo/apps/js/js_app.cc +++ b/mojo/apps/js/js_app.cc @@ -9,21 +9,16 @@ #include "gin/converter.h" #include "mojo/apps/js/application_delegate_impl.h" #include "mojo/apps/js/mojo_module.h" -#include "mojo/common/data_pipe_utils.h" namespace mojo { namespace apps { -JSApp::JSApp(ApplicationDelegateImpl* content_handler_app, - const std::string& url, - URLResponsePtr content) - : content_handler_app_(content_handler_app), - url_(url), - content_(content.Pass()), - thread_("Mojo JS " + url), - content_handler_task_runner_( +JSApp::JSApp(ApplicationDelegateImpl* app_delegate_impl) + : app_delegate_impl_(app_delegate_impl), + thread_("Mojo JS"), + app_delegate_impl_task_runner_( base::MessageLoop::current()->task_runner()) { - CHECK(on_content_handler_thread()); + CHECK(on_app_delegate_impl_thread()); runner_delegate_.AddBuiltinModule(Mojo::kModuleName, base::Bind(Mojo::GetModule, this)); } @@ -32,7 +27,7 @@ JSApp::~JSApp() { } bool JSApp::Start() { - CHECK(!js_app_task_runner_.get() && on_content_handler_thread()); + CHECK(!js_app_task_runner_.get() && on_app_delegate_impl_thread()); base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0); thread_.StartWithOptions(thread_options); @@ -58,10 +53,10 @@ Handle JSApp::ConnectToService(const std::string& application_url, CHECK(on_js_app_thread()); MessagePipe pipe; - content_handler_task_runner_->PostTask( + app_delegate_impl_task_runner_->PostTask( FROM_HERE, base::Bind(&ApplicationDelegateImpl::ConnectToService, - base::Unretained(content_handler_app_), + base::Unretained(app_delegate_impl_), base::Passed(pipe.handle1.Pass()), application_url, interface_name)); @@ -70,12 +65,12 @@ Handle JSApp::ConnectToService(const std::string& application_url, } void JSApp::Run() { - CHECK(!js_app_task_runner_.get() && !on_content_handler_thread()); + CHECK(!js_app_task_runner_.get() && !on_app_delegate_impl_thread()); js_app_task_runner_ = base::MessageLoop::current()->task_runner(); - // TODO(hansmuller): check the return value and fail gracefully. - std::string module; - common::BlockingCopyToString(content_->body.Pass(), &module); + std::string source; + std::string file_name; + Load(&source, &file_name); // TODO(hansmuller): handle Load() failure. gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode, gin::ArrayBufferAllocator::SharedInstance()); @@ -85,28 +80,27 @@ void JSApp::Run() { shell_runner_.reset( new gin::ShellRunner(&runner_delegate_, isolate_holder_->isolate())); - // TODO(hansmuller): exiting this scope here is OK? gin::Runner::Scope scope(shell_runner_.get()); - shell_runner_->Run(module.c_str(), url_.c_str()); + shell_runner_->Run(source.c_str(), file_name.c_str()); } void JSApp::Terminate() { isolate_holder_->RemoveRunMicrotasksObserver(); - shell_runner_.reset(NULL); + shell_runner_.reset(nullptr); // This JSApp's thread must be stopped on the thread that started it. Ask the - // content_handler_app_ to erase its AppVector entry for this app, which + // app_delegate_impl_ to erase its AppVector entry for this app, which // implicitly destroys this JSApp and stops its thread. - content_handler_task_runner_->PostTask( + app_delegate_impl_task_runner_->PostTask( FROM_HERE, base::Bind(&ApplicationDelegateImpl::QuitJSApp, - base::Unretained(content_handler_app_), + base::Unretained(app_delegate_impl_), base::Unretained(this))); } -bool JSApp::on_content_handler_thread() const { - return content_handler_task_runner_.get() && - content_handler_task_runner_.get() == +bool JSApp::on_app_delegate_impl_thread() const { + return app_delegate_impl_task_runner_.get() && + app_delegate_impl_task_runner_.get() == base::MessageLoop::current()->task_runner().get(); } diff --git a/mojo/apps/js/js_app.h b/mojo/apps/js/js_app.h index 8662619..6bbaed4 100644 --- a/mojo/apps/js/js_app.h +++ b/mojo/apps/js/js_app.h @@ -6,7 +6,6 @@ #define MOJO_APPS_JS_JS_APP_H_ #include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" #include "base/threading/thread.h" #include "gin/public/isolate_holder.h" #include "gin/shell_runner.h" @@ -21,19 +20,26 @@ class ApplicationDelegateImpl; // Each JavaScript app started by content handler runs on its own thread and // in its own V8 isolate. This class represents one running JS app. -// -// The lifetime of this class is defined by the content handler's internal -// "app_vector" list. class JSApp { public: - JSApp(ApplicationDelegateImpl* content_handler_app, - const std::string& url, - URLResponsePtr content); - ~JSApp(); + JSApp(ApplicationDelegateImpl* app_delegate_impl); + virtual ~JSApp(); + // Launch this app on a new thread. This method can be called on any thread. + // This method causes Load() and then Run() to run on a new thread. bool Start(); + + + // Subclasses must return the JS source code for this app's main script and + // the filename or URL that identifies the script's origin. This method will + // be called from this app's thread. + virtual bool Load(std::string* source, std::string* file_name) = 0; + + // Called by the JS mojo module to quit this JS app. See mojo_module.cc. void Quit(); + + // Called by the JS mojo module to connect to a Mojo service. Handle ConnectToService(const std::string& application_url, const std::string& interface_name); @@ -42,14 +48,12 @@ class JSApp { void Terminate(); // Used to CHECK that we're running on the correct thread. - bool on_content_handler_thread() const; + bool on_app_delegate_impl_thread() const; bool on_js_app_thread() const; - ApplicationDelegateImpl* content_handler_app_; - std::string url_; - URLResponsePtr content_; + ApplicationDelegateImpl* app_delegate_impl_; base::Thread thread_; - scoped_refptr<base::SingleThreadTaskRunner> content_handler_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> app_delegate_impl_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> js_app_task_runner_; MojoRunnerDelegate runner_delegate_; scoped_ptr<gin::IsolateHolder> isolate_holder_; diff --git a/mojo/apps/js/main.cc b/mojo/apps/js/main.cc deleted file mode 100644 index 5ecf47d..0000000 --- a/mojo/apps/js/main.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 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 "base/i18n/icu_util.h" -#include "mojo/application/application_runner_chromium.h" -#include "mojo/apps/js/application_delegate_impl.h" -#include "mojo/public/c/system/main.h" - -MojoResult MojoMain(MojoHandle shell_handle) { - base::i18n::InitializeICU(); - mojo::ApplicationRunnerChromium runner( - new mojo::apps::ApplicationDelegateImpl()); - return runner.Run(shell_handle); -} diff --git a/mojo/apps/js/standalone_main.cc b/mojo/apps/js/standalone_main.cc new file mode 100644 index 0000000..eca936a --- /dev/null +++ b/mojo/apps/js/standalone_main.cc @@ -0,0 +1,55 @@ +// Copyright 2014 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 "base/files/file_util.h" +#include "base/i18n/icu_util.h" +#include "mojo/application/application_runner_chromium.h" +#include "mojo/apps/js/application_delegate_impl.h" +#include "mojo/apps/js/js_app.h" +#include "mojo/public/c/system/main.h" +#include "mojo/public/cpp/application/application_delegate.h" + +namespace mojo { +namespace apps { + +class StandaloneJSApp : public JSApp { + public: + StandaloneJSApp(ApplicationDelegateImpl* app_delegate_impl, + const base::FilePath& path) + : JSApp(app_delegate_impl), + path_(path) { + } + + virtual bool Load(std::string* source, std::string* file_name) override { + *file_name = path_.AsUTF8Unsafe(); + return ReadFileToString(path_, source); + } + + private: + base::FilePath path_; +}; + +class StandaloneApplicationDelegateImpl : public ApplicationDelegateImpl { + private: + virtual void Initialize(ApplicationImpl* app) override { + ApplicationDelegateImpl::Initialize(app); + + // TODO(hansmuller): Find the JS source code path in app->args(). + base::FilePath path(base::FilePath::FromUTF8Unsafe( + "/builds/dev/src/mojo/apps/js/main.js")); + + scoped_ptr<JSApp> js_app(new StandaloneJSApp(this, path)); + StartJSApp(js_app.Pass()); + } +}; + +} // namespace apps +} // namespace mojo + +MojoResult MojoMain(MojoHandle shell_handle) { + base::i18n::InitializeICU(); + mojo::ApplicationRunnerChromium runner( + new mojo::apps::StandaloneApplicationDelegateImpl()); + return runner.Run(shell_handle); +} diff --git a/mojo/mojo.gyp b/mojo/mojo.gyp index bca8aa6..a82e5ed 100644 --- a/mojo/mojo.gyp +++ b/mojo/mojo.gyp @@ -39,7 +39,8 @@ 'mojo_example_service', 'mojo_geometry_lib', 'mojo_html_viewer', - 'mojo_js', + 'mojo_js_content_handler', + 'mojo_js_standalone', 'mojo_native_viewport_service', 'mojo_network_service', 'mojo_pepper_container_app', diff --git a/mojo/mojo_apps.gypi b/mojo/mojo_apps.gypi index 631a5e9..de1919a 100644 --- a/mojo/mojo_apps.gypi +++ b/mojo/mojo_apps.gypi @@ -80,22 +80,49 @@ ], }, { - # GN version: //mojo/apps/js:mojo_js - 'target_name': 'mojo_js', - 'type': 'loadable_module', + # GN version: //mojo/apps/js/test:mojo_js_apps_lib + 'target_name': 'mojo_js_apps_lib', + 'type': 'static_library', + 'export_dependent_settings': [ + 'mojo_base.gyp:mojo_cpp_bindings', + ], 'dependencies': [ 'mojo_base.gyp:mojo_application_chromium', + 'mojo_apps_js_bindings', 'mojo_base.gyp:mojo_cpp_bindings', 'mojo_base.gyp:mojo_utility', - 'mojo_content_handler_bindings', 'mojo_js_lib', - '<(mojo_system_for_loadable_module)', ], 'sources': [ 'apps/js/application_delegate_impl.cc', 'apps/js/js_app.cc', 'apps/js/mojo_module.cc', - 'apps/js/main.cc', + ], + }, + { + # GN version: //mojo/apps/js:mojo_js_content_handler + 'target_name': 'mojo_js_content_handler', + 'type': 'loadable_module', + 'dependencies': [ + 'mojo_content_handler_bindings', + 'mojo_js_apps_lib', + '<(mojo_system_for_loadable_module)', + ], + 'sources': [ + 'apps/js/content_handler_impl.cc', + 'apps/js/content_handler_main.cc', + ], + }, + { + # GN version: //mojo/apps/js:mojo_js_standalone + 'target_name': 'mojo_js_standalone', + 'type': 'loadable_module', + 'dependencies': [ + 'mojo_js_apps_lib', + '<(mojo_system_for_loadable_module)', + ], + 'sources': [ + 'apps/js/standalone_main.cc', ], }, ], |