提交 341495d5 编写于 作者: J John McCutchan 提交者: GitHub

Support for hot source reloading in the Linux glfw sky_shell (#2755)

- [x] Wire up synchronous script reloading in the library tag handler.
- [x] Allow glfw sky_shell to start from dart source as well as bundle.
上级 f13875ca
......@@ -200,19 +200,88 @@ DartLibraryLoader::DartLibraryLoader(DartState* dart_state)
DartLibraryLoader::~DartLibraryLoader() {
}
static void BlockWaitingForDependencies(
DartLibraryLoader* loader,
const std::unordered_set<DartDependency*>& dependencies) {
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
base::MessageLoop::current()->task_runner();
base::RunLoop run_loop;
task_runner->PostTask(
FROM_HERE,
base::Bind(
&DartLibraryLoader::WaitForDependencies,
base::Unretained(loader),
dependencies,
base::Bind(
base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask),
task_runner.get(), FROM_HERE,
run_loop.QuitClosure())));
run_loop.Run();
}
static void InnerLoadScript(
const std::string& script_uri,
DartLibraryLoader* library_loader) {
// When spawning isolates, Dart expects the script loading to be completed
// before returning from the isolate creation callback. The mojo dart
// controller also expects the isolate to be finished loading a script
// before the isolate creation callback returns.
// We block here by creating a nested message pump and waiting for the load
// to complete.
DCHECK(base::MessageLoop::current() != nullptr);
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
// Initiate the load.
DartLibraryLoader& loader = *library_loader;
std::unordered_set<DartDependency*> dependencies;
{
DartDependencyCatcher dependency_catcher(loader);
loader.LoadScript(script_uri);
// Copy dependencies before dependency_catcher goes out of scope.
dependencies = std::unordered_set<DartDependency*>(
dependency_catcher.dependencies());
}
// Run inner message loop.
BlockWaitingForDependencies(&loader, dependencies);
// Finalize loading.
LogIfError(Dart_FinalizeLoading(true));
}
static void LoadScriptSync(
const std::string& script_uri,
DartLibraryLoader* library_loader) {
CHECK(base::MessageLoop::current() != nullptr);
// Thread has a message loop, use it.
InnerLoadScript(script_uri, library_loader);
}
Dart_Handle DartLibraryLoader::HandleLibraryTag(Dart_LibraryTag tag,
Dart_Handle library,
Dart_Handle url) {
DCHECK(Dart_IsLibrary(library));
DCHECK(Dart_IsLibrary(library) || Dart_IsNull(library));
DCHECK(Dart_IsString(url));
if (tag == Dart_kCanonicalizeUrl)
if (tag == Dart_kCanonicalizeUrl) {
return DartState::Current()->library_loader().CanonicalizeURL(library, url);
}
if (tag == Dart_kImportTag) {
return DartState::Current()->library_loader().Import(library, url);
}
if (tag == Dart_kSourceTag) {
return DartState::Current()->library_loader().Source(library, url);
}
if (tag == Dart_kScriptTag) {
LoadScriptSync(StdStringFromDart(url),
&DartState::Current()->library_loader());
return Dart_Null();
}
DCHECK(false);
return Dart_NewApiError("Unknown library tag.");
}
......
......@@ -17,11 +17,27 @@
namespace sky {
namespace shell {
static bool IsDartFile(const std::string& script_uri) {
std::string dart_extension = ".dart";
return script_uri.rfind(dart_extension) ==
(script_uri.size() - dart_extension.size());
}
bool InitInteractive() {
base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
auto args = command_line.GetArgs();
if (args.empty())
return false;
std::string bundle_path =
command_line.GetSwitchValueASCII(sky::shell::switches::kFLX);
if (bundle_path.empty()) {
// Alternatively, use the first positional argument.
bundle_path = args[0];
}
if (bundle_path.empty())
return false;
......@@ -38,10 +54,16 @@ bool InitInteractive() {
CHECK(gfx::GLSurface::InitializeOneOff());
glfwMakeContextCurrent(NULL);
std::string script_uri = std::string("file://") + bundle_path;
// TODO(abarth): Listen for a GLFW callback to delete this window.
(new WindowImpl(window))->RunFromBundle(script_uri, bundle_path);
if (IsDartFile(bundle_path)) {
// Load directly from source.
// TODO(abarth): Listen for a GLFW callback to delete this window.
(new WindowImpl(window))->RunFromFile(bundle_path);
} else {
std::string script_uri = std::string("file://") + bundle_path;
// Load from a bundle.
// TODO(abarth): Listen for a GLFW callback to delete this window.
(new WindowImpl(window))->RunFromBundle(script_uri, bundle_path);
}
return true;
}
......
......@@ -99,6 +99,12 @@ void WindowImpl::RunFromBundle(const std::string& script_uri,
engine_->RunFromBundle(script_uri, bundle_path);
}
void WindowImpl::RunFromFile(const std::string& file) {
// TODO(johnmccutchan): Wire up support for asset bundles when running
// from source.
engine_->RunFromFile(file, "", "");
}
void WindowImpl::UpdateViewportMetrics(int width, int height) {
auto metrics = sky::ViewportMetrics::New();
metrics->physical_width = width;
......
......@@ -26,6 +26,8 @@ class WindowImpl : public mojo::ServiceProvider,
void RunFromBundle(const std::string& script_uri,
const std::string& bundle_path);
void RunFromFile(const std::string& file);
void UpdateViewportMetrics(int width, int height);
void DispatchMouseButtonEvent(int button, int action, int mods);
void DispatchMouseMoveEvent(double x, double y);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册