Skip to content

Commit f63db49

Browse files
committed
- Implement resource loading via the Resource class.
R=asiva@google.com Review URL: https://codereview.chromium.org//1264413002 .
1 parent ba88435 commit f63db49

File tree

5 files changed

+177
-77
lines changed

5 files changed

+177
-77
lines changed

runtime/bin/builtin.dart

Lines changed: 106 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,18 @@
44

55
library builtin;
66
// NOTE: Do not import 'dart:io' in builtin.
7+
import 'dart:async';
78
import 'dart:collection';
9+
import 'dart:_internal';
810
import 'dart:isolate';
911
import 'dart:typed_data';
1012

13+
14+
// Before handling an embedder entrypoint we finalize the setup of the
15+
// dart:_builtin library.
16+
bool _setupCompleted = false;
17+
18+
1119
// The root library (aka the script) is imported into this library. The
1220
// standalone embedder uses this to lookup the main entrypoint in the
1321
// root library's namespace.
@@ -49,10 +57,11 @@ _getUriBaseClosure() => _uriBase;
4957
// The embedder forwards most loading requests to this library.
5058

5159
// See Dart_LibraryTag in dart_api.h
52-
const Dart_kScriptTag = null;
53-
const Dart_kImportTag = 0;
54-
const Dart_kSourceTag = 1;
55-
const Dart_kCanonicalizeUrl = 2;
60+
const _Dart_kScriptTag = null;
61+
const _Dart_kImportTag = 0;
62+
const _Dart_kSourceTag = 1;
63+
const _Dart_kCanonicalizeUrl = 2;
64+
const _Dart_kResourceLoad = 3;
5665

5766
// Embedder sets this to true if the --trace-loading flag was passed on the
5867
// command line.
@@ -119,16 +128,16 @@ class _LoadRequest {
119128
final int _id;
120129
final int _tag;
121130
final String _uri;
122-
final String _libraryUri;
123131
final Uri _resourceUri;
132+
final _context;
124133

125134
_LoadRequest(this._id,
126135
this._tag,
127136
this._uri,
128-
this._libraryUri,
129-
this._resourceUri);
137+
this._resourceUri,
138+
this._context);
130139

131-
toString() => "LoadRequest($_id, $_tag, $_uri, $_libraryUri, $_resourceUri)";
140+
toString() => "LoadRequest($_id, $_tag, $_uri, $_resourceUri, $_context)";
132141
}
133142

134143

@@ -195,6 +204,9 @@ _enforceTrailingSlash(uri) {
195204
// Embedder Entrypoint:
196205
// The embedder calls this method with the current working directory.
197206
void _setWorkingDirectory(cwd) {
207+
if (!_setupCompleted) {
208+
_setupHooks();
209+
}
198210
if (_traceLoading) {
199211
_log('Setting working directory: $cwd');
200212
}
@@ -208,6 +220,9 @@ void _setWorkingDirectory(cwd) {
208220
// Embedder Entrypoint:
209221
// The embedder calls this method with a custom package root.
210222
_setPackageRoot(String packageRoot) {
223+
if (!_setupCompleted) {
224+
_setupHooks();
225+
}
211226
if (_traceLoading) {
212227
_log('Setting package root: $packageRoot');
213228
}
@@ -323,26 +338,33 @@ void _handleLoaderReply(msg) {
323338
var req = _reqMap[id];
324339
try {
325340
if (dataOrError is Uint8List) {
326-
_loadScript(req, dataOrError);
341+
// Successfully loaded the data.
342+
if (req._tag == _Dart_kResourceLoad) {
343+
Completer c = req._context;
344+
c.complete(dataOrError);
345+
} else {
346+
// TODO: Currently a compilation error while loading the script is
347+
// fatal for the isolate. _loadScriptCallback() does not return and
348+
// the number of requests remains out of sync.
349+
_loadScriptCallback(req._tag, req._uri, req._context, dataOrError);
350+
}
351+
_finishLoadRequest(req);
327352
} else {
328353
assert(dataOrError is String);
329354
var error = new _LoadError(req._uri, dataOrError.toString());
330-
_asyncLoadError(req, error);
355+
_asyncLoadError(req, error, null);
331356
}
332357
} catch(e, s) {
333358
// Wrap inside a _LoadError unless we are already propagating a
334359
// previous _LoadError.
335360
var error = (e is _LoadError) ? e : new _LoadError(req._uri, e.toString());
336361
assert(req != null);
337-
_asyncLoadError(req, error);
362+
_asyncLoadError(req, error, s);
338363
}
339364
}
340365

341366

342-
void _startLoadRequest(int tag,
343-
String uri,
344-
String libraryUri,
345-
Uri resourceUri) {
367+
void _startLoadRequest(int tag, String uri, Uri resourceUri, context) {
346368
if (_receivePort == null) {
347369
if (_traceLoading) {
348370
_log("Initializing load port.");
@@ -356,7 +378,7 @@ void _startLoadRequest(int tag,
356378
var curId = _reqId++;
357379

358380
assert(_reqMap[curId] == null);
359-
_reqMap[curId] = new _LoadRequest(curId, tag, uri, libraryUri, resourceUri);
381+
_reqMap[curId] = new _LoadRequest(curId, tag, uri, resourceUri, context);
360382

361383
assert(_receivePort != null);
362384
assert(_sendPort != null);
@@ -369,8 +391,9 @@ void _startLoadRequest(int tag,
369391
_loadPort.send(msg);
370392

371393
if (_traceLoading) {
372-
_log("Loading of $resourceUri for $uri started with id: $curId, "
373-
"${_reqMap.length} requests outstanding");
394+
_log("Loading of $resourceUri for $uri started with id: $curId. "
395+
"${_reqMap.length} requests remaining, "
396+
"${_pendingPackageLoads.length} packages pending.");
374397
}
375398
}
376399

@@ -408,13 +431,17 @@ void _handlePackagesReply(msg) {
408431
}
409432

410433
// Resolve all pending package loads now that we know how to resolve them.
411-
for (var i = 0; i < _pendingPackageLoads.length; i++) {
412-
var req = _pendingPackageLoads[i];
434+
while (_pendingPackageLoads.length > 0) {
435+
var req = _pendingPackageLoads.removeLast();
413436
if (req != null) {
414437
if (_traceLoading) {
415438
_log("Handling deferred load request: $req");
416439
}
417-
_loadPackage(req._tag, req._uri, req._libraryUri, req._resourceUri);
440+
_loadPackage(req._tag, req._uri, req._resourceUri, req._context);
441+
} else {
442+
if (_traceLoading) {
443+
_log("Skipping dummy deferred request.");
444+
}
418445
}
419446
}
420447
// Reset the pending package loads to empty. So that we eventually can
@@ -446,6 +473,9 @@ void _requestPackagesMap() {
446473
// Embedder Entrypoint:
447474
// Request the load of a particular packages map.
448475
void _loadPackagesMap(String packagesParam) {
476+
if (!_setupCompleted) {
477+
_setupHooks();
478+
}
449479
// First convert the packages parameter from the command line to a URI which
450480
// can be handled by the loader code.
451481
// TODO(iposva): Consider refactoring the common code below which is almost
@@ -490,60 +520,53 @@ void _loadPackagesMap(String packagesParam) {
490520
}
491521

492522

493-
void _loadScript(_LoadRequest req, Uint8List data) {
494-
// TODO: Currently a compilation error while loading the script is
495-
// fatal for the isolate. _loadScriptCallback() does not return and
496-
// the number of requests remains out of sync.
497-
_loadScriptCallback(req._tag, req._uri, req._libraryUri, data);
498-
_finishLoadRequest(req);
499-
}
500-
501-
502-
void _asyncLoadError(_LoadRequest req, _LoadError error) {
523+
void _asyncLoadError(_LoadRequest req, _LoadError error, StackTrace stack) {
503524
if (_traceLoading) {
504-
_log("_asyncLoadError(${req._uri}), error: $error");
525+
_log("_asyncLoadError(${req._uri}), error: $error\nstack: $stack");
505526
}
506-
var libraryUri = req._libraryUri;
507-
if (req._tag == Dart_kImportTag) {
508-
// When importing a library, the libraryUri is the imported
509-
// uri.
510-
libraryUri = req._uri;
527+
if (req._tag == _Dart_kResourceLoad) {
528+
Completer c = req._context;
529+
c.completeError(error, stack);
530+
} else {
531+
Uri libraryUri = req._context;
532+
if (req._tag == _Dart_kImportTag) {
533+
// When importing a library, the libraryUri is the imported
534+
// uri.
535+
libraryUri = req._uri;
536+
}
537+
_asyncLoadErrorCallback(req._uri, libraryUri, error);
511538
}
512-
_asyncLoadErrorCallback(req._uri, libraryUri, error);
513539
_finishLoadRequest(req);
514540
}
515541

516542

517-
_loadDataFromLoadPort(int tag,
518-
String uri,
519-
String libraryUri,
520-
Uri resourceUri) {
543+
_loadDataFromLoadPort(int tag, String uri, Uri resourceUri, context) {
521544
try {
522-
_startLoadRequest(tag, uri, libraryUri, resourceUri);
523-
} catch (e) {
545+
_startLoadRequest(tag, uri, resourceUri, context);
546+
} catch (e, s) {
524547
if (_traceLoading) {
525548
_log("Exception when communicating with service isolate: $e");
526549
}
527550
// Wrap inside a _LoadError unless we are already propagating a previously
528551
// seen _LoadError.
529552
var error = (e is _LoadError) ? e : new _LoadError(e.toString());
530-
_asyncLoadError(tag, uri, libraryUri, error);
553+
_asyncLoadError(tag, uri, context, error, s);
531554
}
532555
}
533556

534557

535558
// Loading a package URI needs to first map the package name to a loadable
536559
// URI.
537-
_loadPackage(int tag, String uri, String libraryUri, Uri resourceUri) {
560+
_loadPackage(int tag, String uri, Uri resourceUri, context) {
538561
if (_packagesReady()) {
539-
_loadData(tag, uri, libraryUri, _resolvePackageUri(resourceUri));
562+
_loadData(tag, uri, _resolvePackageUri(resourceUri), context);
540563
} else {
541564
if (_pendingPackageLoads.isEmpty) {
542565
// Package resolution has not been setup yet, and this is the first
543566
// request for package resolution & loading.
544567
_requestPackagesMap();
545568
}
546-
var req = new _LoadRequest(-1, tag, uri, libraryUri, resourceUri);
569+
var req = new _LoadRequest(-1, tag, uri, resourceUri, context);
547570
_pendingPackageLoads.add(req);
548571
if (_traceLoading) {
549572
_log("Pending package load of '$uri': "
@@ -554,36 +577,42 @@ _loadPackage(int tag, String uri, String libraryUri, Uri resourceUri) {
554577

555578

556579
// Load the data associated with the resourceUri.
557-
_loadData(int tag, String uri, String libraryUri, Uri resourceUri) {
580+
_loadData(int tag, String uri, Uri resourceUri, context) {
558581
if (resourceUri.scheme == 'package') {
559582
// package based uris need to be resolved to the correct loadable location.
560583
// The logic of which is handled seperately, and then _loadData is called
561584
// recursively.
562-
_loadPackage(tag, uri, libraryUri, resourceUri);
585+
_loadPackage(tag, uri, resourceUri, context);
563586
} else {
564-
_loadDataFromLoadPort(tag, uri, libraryUri, resourceUri);
587+
_loadDataFromLoadPort(tag, uri, resourceUri, context);
565588
}
566589
}
567590

568591

569592
// Embedder Entrypoint:
570593
// Asynchronously loads script data through a http[s] or file uri.
571594
_loadDataAsync(int tag, String uri, String libraryUri) {
595+
if (!_setupCompleted) {
596+
_setupHooks();
597+
}
572598
var resourceUri;
573-
if (tag == Dart_kScriptTag) {
599+
if (tag == _Dart_kScriptTag) {
574600
resourceUri = _resolveScriptUri(uri);
575601
uri = resourceUri.toString();
576602
} else {
577603
resourceUri = Uri.parse(uri);
578604
}
579-
_loadData(tag, uri, libraryUri, resourceUri);
605+
_loadData(tag, uri, resourceUri, libraryUri);
580606
}
581607

582608

583609
// Embedder Entrypoint:
584610
// Function called by standalone embedder to resolve uris when the VM requests
585611
// Dart_kCanonicalizeUrl from the tag handler.
586612
String _resolveUri(String base, String userString) {
613+
if (!_setupCompleted) {
614+
_setupHooks();
615+
}
587616
if (_traceLoading) {
588617
_log('Resolving: $userString from $base');
589618
}
@@ -602,9 +631,23 @@ String _resolveUri(String base, String userString) {
602631
}
603632

604633

634+
// Handling of Resource class by dispatching to the load port.
635+
Future<List<int>> _resourceReadAsBytes(Uri uri) {
636+
var completer = new Completer<List<int>>();
637+
// Request the load of the resource associating the completer as the context
638+
// for the load.
639+
_loadData(_Dart_kResourceLoad, uri.toString(), uri, completer);
640+
// Return the future that will be triggered once the resource has been loaded.
641+
return completer.future;
642+
}
643+
644+
605645
// Embedder Entrypoint (gen_snapshot):
606646
// Resolve relative paths relative to working directory.
607647
String _resolveInWorkingDirectory(String fileName) {
648+
if (!_setupCompleted) {
649+
_setupHooks();
650+
}
608651
if (_workingDirectory == null) {
609652
throw 'No current working directory set.';
610653
}
@@ -679,6 +722,9 @@ String _filePathFromUri(String userUri) {
679722
// The filename part is the extension name, with the platform-dependent
680723
// prefixes and extensions added.
681724
_extensionPathFromUri(String userUri) {
725+
if (!_setupCompleted) {
726+
_setupHooks();
727+
}
682728
if (!userUri.startsWith(_DART_EXT)) {
683729
throw 'Unexpected internal error: Extension URI $userUri missing dart-ext:';
684730
}
@@ -706,3 +752,10 @@ _extensionPathFromUri(String userUri) {
706752

707753
return [path, filename, name];
708754
}
755+
756+
757+
// Register callbacks and hooks with the rest of the core libraries.
758+
_setupHooks() {
759+
_setupCompleted = true;
760+
VMLibraryHooks.resourceReadAsBytes = _resourceReadAsBytes;
761+
}

runtime/lib/core_patch.dart

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -205,27 +205,3 @@ class _SyncIterator implements Iterator {
205205
}
206206
}
207207
}
208-
209-
patch class Resource {
210-
/* patch */ const factory Resource(String uri) = _Resource;
211-
}
212-
213-
class _Resource implements Resource {
214-
final String _location;
215-
216-
const _Resource(String uri) : _location = uri;
217-
218-
Uri get uri => Uri.base.resolve(_location);
219-
220-
Stream<List<int>> openRead() {
221-
throw new UnimplementedError("openRead");
222-
}
223-
224-
Future<List<int>> readAsBytes() {
225-
throw new UnimplementedError("readAsBytes");
226-
}
227-
228-
Future<String> readAsString({Encoding encoding}) {
229-
throw new UnimplementedError("readAsString");
230-
}
231-
}

runtime/lib/core_sources.gypi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
'object_patch.dart',
4545
'regexp.cc',
4646
'regexp_patch.dart',
47+
'resource_patch.dart',
4748
'stacktrace.cc',
4849
'stacktrace.dart',
4950
'stopwatch.cc',

runtime/lib/internal_patch.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class VMLibraryHooks {
1313
static var timerFactory;
1414
// Example: "dart:io _EventHandler._sendData"
1515
static var eventHandlerSendData;
16+
// Implementation of Resource.readAsBytes.
17+
static var resourceReadAsBytes;
1618
}
1719

1820
patch class CodeUnits {

0 commit comments

Comments
 (0)