OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 library mojo_builtin; | 5 library mojo_builtin; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:convert'; | 8 import 'dart:convert'; |
9 //import 'dart:_internal'; | 9 //import 'dart:_internal'; |
10 import 'dart:mojo.core'; | 10 import 'dart:mojo.internal'; |
11 // import 'root_library'; happens here from C Code | 11 // import 'root_library'; happens here from C Code |
12 | 12 |
13 // The root library (aka the script) is imported into this library. The | 13 // The root library (aka the script) is imported into this library. The |
14 // embedder uses this to lookup the main entrypoint in the root library's | 14 // embedder uses this to lookup the main entrypoint in the root library's |
15 // namespace. | 15 // namespace. |
16 Function _getMainClosure() => main; | 16 Function _getMainClosure() => main; |
17 | 17 |
18 | |
19 // Corelib 'print' implementation. | 18 // Corelib 'print' implementation. |
20 void _print(arg) { | 19 void _print(arg) { |
21 _Logger._printString(arg.toString()); | 20 _Logger._printString(arg.toString()); |
22 } | 21 } |
23 | 22 |
24 | |
25 class _Logger { | 23 class _Logger { |
26 static void _printString(String s) native "Logger_PrintString"; | 24 static void _printString(String s) native "Logger_PrintString"; |
27 } | 25 } |
28 | 26 |
29 | |
30 _getPrintClosure() => _print; | 27 _getPrintClosure() => _print; |
31 | 28 |
32 const _logBuiltin = false; | 29 const _logBuiltin = false; |
33 | 30 |
34 | |
35 Uri _uriBase() { | 31 Uri _uriBase() { |
36 return _entryPointScript.resolve('.'); | 32 return _entryPointScript.resolve('.'); |
37 } | 33 } |
38 _getUriBaseClosure() => _uriBase; | 34 _getUriBaseClosure() => _uriBase; |
39 | 35 |
40 // The current working directory | 36 // The current working directory |
41 var _workingDirectoryUri; | 37 var _workingDirectoryUri; |
42 // The URI that the entry point script was loaded from. Remembered so that | 38 // The URI that the entry point script was loaded from. Remembered so that |
43 // package imports can be resolved relative to it. | 39 // package imports can be resolved relative to it. |
44 var _entryPointScript; | 40 var _entryPointScript; |
45 // The directory to look in to resolve "package:" scheme URIs. | 41 // The directory to look in to resolve "package:" scheme URIs. |
46 var _packageRoot; | 42 var _packageRoot; |
47 | 43 |
48 _setupHooks() { | 44 _setupHooks() { |
49 VMLibraryHooks.eventHandlerSendData = MojoHandleWatcher.timer; | 45 VMLibraryHooks.eventHandlerSendData = MojoHandleWatcher.timer; |
50 } | 46 } |
51 | 47 |
52 | |
53 _enforceTrailingSlash(uri) { | 48 _enforceTrailingSlash(uri) { |
54 // Ensure we have a trailing slash character. | 49 // Ensure we have a trailing slash character. |
55 if (!uri.endsWith('/')) { | 50 if (!uri.endsWith('/')) { |
56 return '$uri/'; | 51 return '$uri/'; |
57 } | 52 } |
58 return uri; | 53 return uri; |
59 } | 54 } |
60 | 55 |
61 | |
62 void _setWorkingDirectory(cwd) { | 56 void _setWorkingDirectory(cwd) { |
63 cwd = _enforceTrailingSlash(cwd); | 57 cwd = _enforceTrailingSlash(cwd); |
64 _workingDirectoryUri = new Uri(scheme: 'file', path: cwd); | 58 _workingDirectoryUri = new Uri(scheme: 'file', path: cwd); |
65 if (_logBuiltin) { | 59 if (_logBuiltin) { |
66 _print('# Working Directory: $cwd'); | 60 _print('# Working Directory: $cwd'); |
67 } | 61 } |
68 } | 62 } |
69 | 63 |
70 | |
71 _setPackageRoot(String packageRoot) { | 64 _setPackageRoot(String packageRoot) { |
72 packageRoot = _enforceTrailingSlash(packageRoot); | 65 packageRoot = _enforceTrailingSlash(packageRoot); |
73 if (packageRoot.startsWith('file:') || | 66 if (packageRoot.startsWith('file:') || |
74 packageRoot.startsWith('http:') || | 67 packageRoot.startsWith('http:') || |
75 packageRoot.startsWith('https:')) { | 68 packageRoot.startsWith('https:')) { |
76 _packageRoot = _workingDirectoryUri.resolve(packageRoot); | 69 _packageRoot = _workingDirectoryUri.resolve(packageRoot); |
77 } else { | 70 } else { |
78 _packageRoot = _workingDirectoryUri.resolveUri(new Uri.file(packageRoot)); | 71 _packageRoot = _workingDirectoryUri.resolveUri(new Uri.file(packageRoot)); |
79 } | 72 } |
80 if (_logBuiltin) { | 73 if (_logBuiltin) { |
81 _print('# Package root: $packageRoot -> $_packageRoot'); | 74 _print('# Package root: $packageRoot -> $_packageRoot'); |
82 } | 75 } |
83 } | 76 } |
84 | 77 |
85 | |
86 String _resolveScriptUri(String scriptName) { | 78 String _resolveScriptUri(String scriptName) { |
87 if (_workingDirectoryUri == null) { | 79 if (_workingDirectoryUri == null) { |
88 throw 'No current working directory set.'; | 80 throw 'No current working directory set.'; |
89 } | 81 } |
90 | 82 |
91 var scriptUri = Uri.parse(scriptName); | 83 var scriptUri = Uri.parse(scriptName); |
92 if (scriptUri.scheme != '') { | 84 if (scriptUri.scheme != '') { |
93 // Script has a scheme, assume that it is fully formed. | 85 // Script has a scheme, assume that it is fully formed. |
94 _entryPointScript = scriptUri; | 86 _entryPointScript = scriptUri; |
95 } else { | 87 } else { |
(...skipping 15 matching lines...) Expand all Loading... |
111 } | 103 } |
112 var baseUri = Uri.parse(base); | 104 var baseUri = Uri.parse(base); |
113 if (userString.startsWith(_DART_EXT)) { | 105 if (userString.startsWith(_DART_EXT)) { |
114 var uri = userString.substring(_DART_EXT.length); | 106 var uri = userString.substring(_DART_EXT.length); |
115 return '$_DART_EXT${baseUri.resolve(uri)}'; | 107 return '$_DART_EXT${baseUri.resolve(uri)}'; |
116 } else { | 108 } else { |
117 return baseUri.resolve(userString).toString(); | 109 return baseUri.resolve(userString).toString(); |
118 } | 110 } |
119 } | 111 } |
120 | 112 |
121 | |
122 Uri _resolvePackageUri(Uri uri) { | 113 Uri _resolvePackageUri(Uri uri) { |
123 if (!uri.host.isEmpty) { | 114 if (!uri.host.isEmpty) { |
124 var path = '${uri.host}${uri.path}'; | 115 var path = '${uri.host}${uri.path}'; |
125 var right = 'package:$path'; | 116 var right = 'package:$path'; |
126 var wrong = 'package://$path'; | 117 var wrong = 'package://$path'; |
127 | 118 |
128 throw "URIs using the 'package:' scheme should look like " | 119 throw "URIs using the 'package:' scheme should look like " |
129 "'$right', not '$wrong'."; | 120 "'$right', not '$wrong'."; |
130 } | 121 } |
131 | 122 |
132 var packageRoot = _packageRoot == null ? | 123 var packageRoot = _packageRoot == null |
133 _entryPointScript.resolve('packages/') : | 124 ? _entryPointScript.resolve('packages/') |
134 _packageRoot; | 125 : _packageRoot; |
135 return packageRoot.resolve(uri.path); | 126 return packageRoot.resolve(uri.path); |
136 } | 127 } |
137 | 128 |
138 | |
139 int _numOutstandingLoadRequests = 0; | 129 int _numOutstandingLoadRequests = 0; |
140 | 130 |
141 // TODO(zra): Enable loading libraries over http. | 131 // TODO(zra): Enable loading libraries over http. |
142 // void _httpGet(Uri uri, String libraryUri, loadCallback(List<int> data)) { | 132 // void _httpGet(Uri uri, String libraryUri, loadCallback(List<int> data)) { |
143 // } | 133 // } |
144 | 134 |
145 | |
146 void _signalDoneLoading() native "Builtin_DoneLoading"; | 135 void _signalDoneLoading() native "Builtin_DoneLoading"; |
147 | 136 |
148 | 137 void _loadScriptCallback(int tag, String uri, String libraryUri, |
149 void _loadScriptCallback(int tag, String uri, String libraryUri, List<int> data) | 138 List<int> data) native "Builtin_LoadScript"; |
150 native "Builtin_LoadScript"; | |
151 | |
152 | 139 |
153 void _loadScript(int tag, String uri, String libraryUri, List<int> data) { | 140 void _loadScript(int tag, String uri, String libraryUri, List<int> data) { |
154 _loadScriptCallback(tag, uri, libraryUri, data); | 141 _loadScriptCallback(tag, uri, libraryUri, data); |
155 assert(_numOutstandingLoadRequests > 0); | 142 assert(_numOutstandingLoadRequests > 0); |
156 _numOutstandingLoadRequests--; | 143 _numOutstandingLoadRequests--; |
157 if (_logBuiltin) { | 144 if (_logBuiltin) { |
158 _print("native Builtin_LoadScript($uri) completed, " | 145 _print("native Builtin_LoadScript($uri) completed, " |
159 "${_numOutstandingLoadRequests} requests remaining"); | 146 "${_numOutstandingLoadRequests} requests remaining"); |
160 } | 147 } |
161 if (_numOutstandingLoadRequests == 0) { | 148 if (_numOutstandingLoadRequests == 0) { |
162 _signalDoneLoading(); | 149 _signalDoneLoading(); |
163 } | 150 } |
164 } | 151 } |
165 | 152 |
166 | 153 void _asyncLoadErrorCallback( |
167 void _asyncLoadErrorCallback(uri, libraryUri, error) | 154 uri, libraryUri, error) native "Builtin_AsyncLoadError"; |
168 native "Builtin_AsyncLoadError"; | |
169 | 155 |
170 void _asyncLoadError(uri, libraryUri, error) { | 156 void _asyncLoadError(uri, libraryUri, error) { |
171 assert(_numOutstandingLoadRequests > 0); | 157 assert(_numOutstandingLoadRequests > 0); |
172 if (_logBuiltin) { | 158 if (_logBuiltin) { |
173 _print("_asyncLoadError($uri), error: $error"); | 159 _print("_asyncLoadError($uri), error: $error"); |
174 } | 160 } |
175 _numOutstandingLoadRequests--; | 161 _numOutstandingLoadRequests--; |
176 _asyncLoadErrorCallback(uri, libraryUri, error); | 162 _asyncLoadErrorCallback(uri, libraryUri, error); |
177 if (_numOutstandingLoadRequests == 0) { | 163 if (_numOutstandingLoadRequests == 0) { |
178 _signalDoneLoading(); | 164 _signalDoneLoading(); |
179 } | 165 } |
180 } | 166 } |
181 | 167 |
182 | |
183 // Create a Uri of 'userUri'. If the input uri is a package uri, then the | 168 // Create a Uri of 'userUri'. If the input uri is a package uri, then the |
184 // package uri is resolved. | 169 // package uri is resolved. |
185 Uri _createUri(String userUri) { | 170 Uri _createUri(String userUri) { |
186 var uri = Uri.parse(userUri); | 171 var uri = Uri.parse(userUri); |
187 if (_logBuiltin) { | 172 if (_logBuiltin) { |
188 _print('# Creating uri for: $uri'); | 173 _print('# Creating uri for: $uri'); |
189 } | 174 } |
190 | 175 |
191 // TODO(zra): Except for the special handling for package:, URI's should just | 176 // TODO(zra): Except for the special handling for package:, URI's should just |
192 // be sent to the network stack to resolve. | 177 // be sent to the network stack to resolve. |
193 switch (uri.scheme) { | 178 switch (uri.scheme) { |
194 case '': | 179 case '': |
195 case 'file': | 180 case 'file': |
196 case 'http': | 181 case 'http': |
197 case 'https': | 182 case 'https': |
198 return uri; | 183 return uri; |
199 case 'package': | 184 case 'package': |
200 return _resolvePackageUri(uri); | 185 return _resolvePackageUri(uri); |
201 default: | 186 default: |
202 // Only handling file, http[s], and package URIs | 187 // Only handling file, http[s], and package URIs |
203 // in standalone binary. | 188 // in standalone binary. |
204 if (_logBuiltin) { | 189 if (_logBuiltin) { |
205 _print('# Unknown scheme (${uri.scheme}) in $uri.'); | 190 _print('# Unknown scheme (${uri.scheme}) in $uri.'); |
206 } | 191 } |
207 throw 'Not a known scheme: $uri'; | 192 throw 'Not a known scheme: $uri'; |
208 } | 193 } |
209 } | 194 } |
210 | 195 |
211 | |
212 // TODO(zra): readSync and enumerateFiles are exposed for testing purposes only. | 196 // TODO(zra): readSync and enumerateFiles are exposed for testing purposes only. |
213 // Eventually, there will be different builtin libraries for testing and | 197 // Eventually, there will be different builtin libraries for testing and |
214 // production(i.e. the content handler). In the content handler's builtin | 198 // production(i.e. the content handler). In the content handler's builtin |
215 // library, File IO capabilities will be removed. | 199 // library, File IO capabilities will be removed. |
216 // This uses the synchronous base::ReadFileToString exposed by Mojo. | 200 // This uses the synchronous base::ReadFileToString exposed by Mojo. |
217 List<int> readSync(String uri) native "Builtin_ReadSync"; | 201 List<int> readSync(String uri) native "Builtin_ReadSync"; |
218 | 202 |
219 // This uses base::FileEnumerator. | 203 // This uses base::FileEnumerator. |
220 List<String> enumerateFiles(String path) native "Builtin_EnumerateFiles"; | 204 List<String> enumerateFiles(String path) native "Builtin_EnumerateFiles"; |
221 | 205 |
222 // Asynchronously loads script data through a http[s] or file uri. | 206 // Asynchronously loads script data through a http[s] or file uri. |
223 _loadDataAsync(int tag, String uri, String libraryUri, List<int> source) { | 207 _loadDataAsync(int tag, String uri, String libraryUri, List<int> source) { |
224 if (tag == null) { | 208 if (tag == null) { |
225 uri = _resolveScriptUri(uri); | 209 uri = _resolveScriptUri(uri); |
226 } | 210 } |
227 Uri resourceUri = _createUri(uri); | 211 Uri resourceUri = _createUri(uri); |
228 _numOutstandingLoadRequests++; | 212 _numOutstandingLoadRequests++; |
229 if (_logBuiltin) { | 213 if (_logBuiltin) { |
230 _print("_loadDataAsync($uri), " | 214 _print("_loadDataAsync($uri), " |
231 "${_numOutstandingLoadRequests} requests outstanding"); | 215 "${_numOutstandingLoadRequests} requests outstanding"); |
232 } | 216 } |
233 if (source != null) { | 217 if (source != null) { |
234 _loadScript(tag, uri, libraryUri, source); | 218 _loadScript(tag, uri, libraryUri, source); |
235 return; | 219 return; |
236 } | 220 } |
237 if ((resourceUri.scheme == 'http') || (resourceUri.scheme == 'https')) { | 221 if ((resourceUri.scheme == 'http') || (resourceUri.scheme == 'https')) { |
238 // TODO(zra): Enable library loading over http. | 222 // TODO(zra): Enable library loading over http. |
239 // _httpGet(resourceUri, libraryUri, (data) { | 223 // _httpGet(resourceUri, libraryUri, (data) { |
240 // _loadScript(tag, uri, libraryUri, data); | 224 // _loadScript(tag, uri, libraryUri, data); |
241 // }); | 225 // }); |
242 throw 'Cannot load http, yet.'; | 226 throw 'Cannot load http, yet.'; |
243 } else { | 227 } else { |
244 // Mojo does not expose any asynchronous file IO calls, but we'll maintain | 228 // Mojo does not expose any asynchronous file IO calls, but we'll maintain |
245 // the same structure as the standalone embedder here in case it ever does. | 229 // the same structure as the standalone embedder here in case it ever does. |
246 var data = readSync(resourceUri.toFilePath()); | 230 var data = readSync(resourceUri.toFilePath()); |
247 _loadScript(tag, uri, libraryUri, data); | 231 _loadScript(tag, uri, libraryUri, data); |
248 } | 232 } |
249 } | 233 } |
OLD | NEW |