| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "sky/engine/config.h" |
| 6 #include "sky/engine/core/script/dart_controller.h" |
| 7 |
| 8 #include "base/bind.h" |
| 9 #include "base/logging.h" |
| 10 #include "base/single_thread_task_runner.h" |
| 11 #include "sky/engine/bindings2/builtin.h" |
| 12 #include "sky/engine/bindings2/builtin_natives.h" |
| 13 #include "sky/engine/bindings2/builtin_sky.h" |
| 14 #include "sky/engine/core/app/AbstractModule.h" |
| 15 #include "sky/engine/core/app/Module.h" |
| 16 #include "sky/engine/core/dom/Element.h" |
| 17 #include "sky/engine/core/frame/LocalFrame.h" |
| 18 #include "sky/engine/core/html/imports/HTMLImport.h" |
| 19 #include "sky/engine/core/html/imports/HTMLImportChild.h" |
| 20 #include "sky/engine/core/loader/FrameLoaderClient.h" |
| 21 #include "sky/engine/core/script/dart_dependency_catcher.h" |
| 22 #include "sky/engine/core/script/dart_loader.h" |
| 23 #include "sky/engine/core/script/dom_dart_state.h" |
| 24 #include "sky/engine/public/platform/Platform.h" |
| 25 #include "sky/engine/tonic/dart_api_scope.h" |
| 26 #include "sky/engine/tonic/dart_class_library.h" |
| 27 #include "sky/engine/tonic/dart_error.h" |
| 28 #include "sky/engine/tonic/dart_gc_controller.h" |
| 29 #include "sky/engine/tonic/dart_isolate_scope.h" |
| 30 #include "sky/engine/tonic/dart_state.h" |
| 31 #include "sky/engine/wtf/text/TextPosition.h" |
| 32 |
| 33 namespace blink { |
| 34 |
| 35 #if ENABLE(ASSERT) |
| 36 static const char* kCheckedModeArgs[] = { |
| 37 "--enable_asserts", |
| 38 "--enable_type_checks", |
| 39 "--error_on_bad_type", |
| 40 "--error_on_bad_override", |
| 41 }; |
| 42 #endif |
| 43 |
| 44 extern const uint8_t* kDartSnapshotBuffer; |
| 45 |
| 46 DartController::DartController() : weak_factory_(this) { |
| 47 } |
| 48 |
| 49 DartController::~DartController() { |
| 50 } |
| 51 |
| 52 void DartController::LoadModule(RefPtr<AbstractModule> module, |
| 53 const String& source, |
| 54 const TextPosition& textPosition) { |
| 55 DartIsolateScope isolate_scope(dart_state()->isolate()); |
| 56 DartApiScope dart_api_scope; |
| 57 |
| 58 DartDependencyCatcher dependency_catcher(dart_state()->loader()); |
| 59 |
| 60 Dart_Handle library = Dart_LoadLibrary( |
| 61 StringToDart(dart_state(), module->url()), |
| 62 StringToDart(dart_state(), source), textPosition.m_line.zeroBasedInt(), |
| 63 textPosition.m_column.zeroBasedInt()); |
| 64 |
| 65 if (LogIfError(library)) |
| 66 return; |
| 67 |
| 68 if (HTMLImport* parent = module->document()->import()) { |
| 69 for (HTMLImportChild* child = static_cast<HTMLImportChild*>(parent->firstChi
ld()); |
| 70 child; child = static_cast<HTMLImportChild*>(child->next())) { |
| 71 if (Element* link = child->link()) { |
| 72 String name = link->getAttribute(HTMLNames::asAttr); |
| 73 |
| 74 Module* childModule = child->module(); |
| 75 if (childModule |
| 76 && childModule->library() |
| 77 && !childModule->library()->is_empty()) { |
| 78 if (LogIfError(Dart_LibraryImportLibrary( |
| 79 library, childModule->library()->dart_value(), |
| 80 StringToDart(dart_state(), name)))) |
| 81 return; |
| 82 } |
| 83 } |
| 84 } |
| 85 } |
| 86 |
| 87 module->set_library(DartValue::Create(dart_state(), library)); |
| 88 const auto& dependencies = dependency_catcher.dependencies(); |
| 89 |
| 90 if (dependencies.isEmpty()) { |
| 91 ExecuteModule(module); |
| 92 } else { |
| 93 dart_state()->loader().WaitForDependencies( |
| 94 dependencies, base::Bind(&DartController::ExecuteModule, |
| 95 weak_factory_.GetWeakPtr(), module)); |
| 96 } |
| 97 } |
| 98 |
| 99 void DartController::ExecuteModule(RefPtr<AbstractModule> module) { |
| 100 DCHECK(Dart_CurrentIsolate() == dart_state()->isolate()); |
| 101 DartApiScope dart_api_scope; |
| 102 |
| 103 LogIfError(Dart_FinalizeLoading(true)); |
| 104 Dart_Handle library = module->library()->dart_value(); |
| 105 const char* name = module->isApplication() ? "main" : "init"; |
| 106 Dart_Handle closure_name = Dart_NewStringFromCString(name); |
| 107 Dart_Handle result = Dart_Invoke(library, closure_name, 0, nullptr); |
| 108 |
| 109 if (module->isApplication()) { |
| 110 // TODO(dart): This will throw an API error if main() is absent. It would be |
| 111 // better to test whether main() is present first, then attempt to invoke it |
| 112 // so as to capture & report other errors. |
| 113 LogIfError(result); |
| 114 } |
| 115 } |
| 116 |
| 117 static void UnhandledExceptionCallback(Dart_Handle error) { |
| 118 DCHECK(!Dart_IsError(error)); |
| 119 LOG(ERROR) << Dart_GetError(error); |
| 120 } |
| 121 |
| 122 static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, |
| 123 Dart_Handle library, |
| 124 Dart_Handle url) { |
| 125 return DartLoader::HandleLibraryTag(tag, library, url); |
| 126 } |
| 127 |
| 128 static void IsolateShutdownCallback(void* callback_data) { |
| 129 // TODO(dart) |
| 130 } |
| 131 |
| 132 static bool IsServiceIsolateURL(const char* url_name) { |
| 133 return url_name != nullptr && |
| 134 String(url_name) == DART_VM_SERVICE_ISOLATE_NAME; |
| 135 } |
| 136 |
| 137 // TODO(rafaelw): Right now this only supports the creation of the handle |
| 138 // watcher isolate. Presumably, we'll want application isolates to spawn their |
| 139 // own isolates. |
| 140 static Dart_Isolate IsolateCreateCallback(const char* script_uri, |
| 141 const char* main, |
| 142 const char* package_root, |
| 143 void* callback_data, |
| 144 char** error) { |
| 145 |
| 146 if (IsServiceIsolateURL(script_uri)) { |
| 147 return Dart_CreateIsolate(script_uri, "main", kDartSnapshotBuffer, nullptr, |
| 148 error); |
| 149 } |
| 150 |
| 151 // Create & start the handle watcher isolate |
| 152 CHECK(kDartSnapshotBuffer); |
| 153 DartState* dart_state = new DartState(); |
| 154 Dart_Isolate isolate = Dart_CreateIsolate("sky:handle_watcher", "", |
| 155 kDartSnapshotBuffer, dart_state, error); |
| 156 CHECK(isolate) << error; |
| 157 dart_state->set_isolate(isolate); |
| 158 |
| 159 CHECK(!LogIfError(Dart_SetLibraryTagHandler(LibraryTagHandler))); |
| 160 |
| 161 { |
| 162 DartApiScope apiScope; |
| 163 Builtin::SetNativeResolver(Builtin::kBuiltinLibrary); |
| 164 Builtin::SetNativeResolver(Builtin::kMojoCoreLibrary); |
| 165 } |
| 166 |
| 167 Dart_ExitIsolate(); |
| 168 |
| 169 CHECK(Dart_IsolateMakeRunnable(isolate)); |
| 170 return isolate; |
| 171 } |
| 172 |
| 173 static void CallHandleMessage(base::WeakPtr<DartState> dart_state) { |
| 174 if (!dart_state) |
| 175 return; |
| 176 |
| 177 DartIsolateScope scope(dart_state->isolate()); |
| 178 DartApiScope api_scope; |
| 179 LogIfError(Dart_HandleMessage()); |
| 180 } |
| 181 |
| 182 static void MessageNotifyCallback(Dart_Isolate dest_isolate) { |
| 183 DCHECK(Platform::current()); |
| 184 Platform::current()->mainThreadTaskRunner()->PostTask(FROM_HERE, |
| 185 base::Bind(&CallHandleMessage, DartState::From(dest_isolate)->GetWeakPtr()
)); |
| 186 } |
| 187 |
| 188 static void EnsureHandleWatcherStarted() { |
| 189 static bool handle_watcher_started = false; |
| 190 if (handle_watcher_started) |
| 191 return; |
| 192 |
| 193 // TODO(dart): Call Dart_Cleanup (ensure the handle watcher isolate is closed) |
| 194 // during shutdown. |
| 195 Dart_Handle mojo_core_lib = |
| 196 Builtin::LoadAndCheckLibrary(Builtin::kMojoCoreLibrary); |
| 197 CHECK(!LogIfError((mojo_core_lib))); |
| 198 Dart_Handle handle_watcher_type = Dart_GetType( |
| 199 mojo_core_lib, |
| 200 Dart_NewStringFromCString("MojoHandleWatcher"), |
| 201 0, |
| 202 nullptr); |
| 203 CHECK(!LogIfError(handle_watcher_type)); |
| 204 CHECK(!LogIfError(Dart_Invoke( |
| 205 handle_watcher_type, |
| 206 Dart_NewStringFromCString("_start"), |
| 207 0, |
| 208 nullptr))); |
| 209 |
| 210 // RunLoop until the handle watcher isolate is spun-up. |
| 211 CHECK(!LogIfError(Dart_RunLoop())); |
| 212 handle_watcher_started = true; |
| 213 } |
| 214 |
| 215 void DartController::CreateIsolateFor(Document* document) { |
| 216 DCHECK(document); |
| 217 CHECK(kDartSnapshotBuffer); |
| 218 char* error = nullptr; |
| 219 dom_dart_state_ = adoptPtr(new DOMDartState(document)); |
| 220 Dart_Isolate isolate = Dart_CreateIsolate( |
| 221 document->url().string().utf8().data(), "main", kDartSnapshotBuffer, |
| 222 static_cast<DartState*>(dom_dart_state_.get()), &error); |
| 223 Dart_SetMessageNotifyCallback(MessageNotifyCallback); |
| 224 CHECK(isolate) << error; |
| 225 dom_dart_state_->set_isolate(isolate); |
| 226 Dart_SetGcCallbacks(DartGCPrologue, DartGCEpilogue); |
| 227 CHECK(!LogIfError(Dart_SetLibraryTagHandler(LibraryTagHandler))); |
| 228 |
| 229 { |
| 230 DartApiScope apiScope; |
| 231 |
| 232 Builtin::SetNativeResolver(Builtin::kBuiltinLibrary); |
| 233 Builtin::SetNativeResolver(Builtin::kMojoCoreLibrary); |
| 234 BuiltinNatives::Init(); |
| 235 |
| 236 builtin_sky_ = adoptPtr(new BuiltinSky(dart_state())); |
| 237 dart_state()->class_library().set_provider(builtin_sky_.get()); |
| 238 builtin_sky_->InstallWindow(dart_state()); |
| 239 |
| 240 document->frame()->loaderClient()->didCreateIsolate(isolate); |
| 241 |
| 242 EnsureHandleWatcherStarted(); |
| 243 } |
| 244 Dart_ExitIsolate(); |
| 245 } |
| 246 |
| 247 void DartController::ClearForClose() { |
| 248 DartIsolateScope scope(dom_dart_state_->isolate()); |
| 249 Dart_ShutdownIsolate(); |
| 250 dom_dart_state_.clear(); |
| 251 } |
| 252 |
| 253 void DartController::InitVM() { |
| 254 int argc = 0; |
| 255 const char** argv = nullptr; |
| 256 |
| 257 #if ENABLE(ASSERT) |
| 258 argc = arraysize(kCheckedModeArgs); |
| 259 argv = kCheckedModeArgs; |
| 260 #endif |
| 261 |
| 262 CHECK(Dart_SetVMFlags(argc, argv)); |
| 263 CHECK(Dart_Initialize(IsolateCreateCallback, |
| 264 nullptr, // Isolate interrupt callback. |
| 265 UnhandledExceptionCallback, IsolateShutdownCallback, |
| 266 // File IO callbacks. |
| 267 nullptr, nullptr, nullptr, nullptr, nullptr)); |
| 268 } |
| 269 |
| 270 } // namespace blink |
| OLD | NEW |