4
4
5
5
library builtin;
6
6
// NOTE: Do not import 'dart:io' in builtin.
7
+ import 'dart:async' ;
7
8
import 'dart:collection' ;
9
+ import 'dart:_internal' ;
8
10
import 'dart:isolate' ;
9
11
import 'dart:typed_data' ;
10
12
13
+
14
+ // Before handling an embedder entrypoint we finalize the setup of the
15
+ // dart:_builtin library.
16
+ bool _setupCompleted = false ;
17
+
18
+
11
19
// The root library (aka the script) is imported into this library. The
12
20
// standalone embedder uses this to lookup the main entrypoint in the
13
21
// root library's namespace.
@@ -49,10 +57,11 @@ _getUriBaseClosure() => _uriBase;
49
57
// The embedder forwards most loading requests to this library.
50
58
51
59
// 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 ;
56
65
57
66
// Embedder sets this to true if the --trace-loading flag was passed on the
58
67
// command line.
@@ -119,16 +128,16 @@ class _LoadRequest {
119
128
final int _id;
120
129
final int _tag;
121
130
final String _uri;
122
- final String _libraryUri;
123
131
final Uri _resourceUri;
132
+ final _context;
124
133
125
134
_LoadRequest (this ._id,
126
135
this ._tag,
127
136
this ._uri,
128
- this ._libraryUri ,
129
- this ._resourceUri );
137
+ this ._resourceUri ,
138
+ this ._context );
130
139
131
- toString () => "LoadRequest($_id , $_tag , $_uri , $_libraryUri , $_resourceUri )" ;
140
+ toString () => "LoadRequest($_id , $_tag , $_uri , $_resourceUri , $_context )" ;
132
141
}
133
142
134
143
@@ -195,6 +204,9 @@ _enforceTrailingSlash(uri) {
195
204
// Embedder Entrypoint:
196
205
// The embedder calls this method with the current working directory.
197
206
void _setWorkingDirectory (cwd) {
207
+ if (! _setupCompleted) {
208
+ _setupHooks ();
209
+ }
198
210
if (_traceLoading) {
199
211
_log ('Setting working directory: $cwd ' );
200
212
}
@@ -208,6 +220,9 @@ void _setWorkingDirectory(cwd) {
208
220
// Embedder Entrypoint:
209
221
// The embedder calls this method with a custom package root.
210
222
_setPackageRoot (String packageRoot) {
223
+ if (! _setupCompleted) {
224
+ _setupHooks ();
225
+ }
211
226
if (_traceLoading) {
212
227
_log ('Setting package root: $packageRoot ' );
213
228
}
@@ -323,26 +338,33 @@ void _handleLoaderReply(msg) {
323
338
var req = _reqMap[id];
324
339
try {
325
340
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);
327
352
} else {
328
353
assert (dataOrError is String );
329
354
var error = new _LoadError (req._uri, dataOrError.toString ());
330
- _asyncLoadError (req, error);
355
+ _asyncLoadError (req, error, null );
331
356
}
332
357
} catch (e, s) {
333
358
// Wrap inside a _LoadError unless we are already propagating a
334
359
// previous _LoadError.
335
360
var error = (e is _LoadError ) ? e : new _LoadError (req._uri, e.toString ());
336
361
assert (req != null );
337
- _asyncLoadError (req, error);
362
+ _asyncLoadError (req, error, s );
338
363
}
339
364
}
340
365
341
366
342
- void _startLoadRequest (int tag,
343
- String uri,
344
- String libraryUri,
345
- Uri resourceUri) {
367
+ void _startLoadRequest (int tag, String uri, Uri resourceUri, context) {
346
368
if (_receivePort == null ) {
347
369
if (_traceLoading) {
348
370
_log ("Initializing load port." );
@@ -356,7 +378,7 @@ void _startLoadRequest(int tag,
356
378
var curId = _reqId++ ;
357
379
358
380
assert (_reqMap[curId] == null );
359
- _reqMap[curId] = new _LoadRequest (curId, tag, uri, libraryUri, resourceUri );
381
+ _reqMap[curId] = new _LoadRequest (curId, tag, uri, resourceUri, context );
360
382
361
383
assert (_receivePort != null );
362
384
assert (_sendPort != null );
@@ -369,8 +391,9 @@ void _startLoadRequest(int tag,
369
391
_loadPort.send (msg);
370
392
371
393
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." );
374
397
}
375
398
}
376
399
@@ -408,13 +431,17 @@ void _handlePackagesReply(msg) {
408
431
}
409
432
410
433
// 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 () ;
413
436
if (req != null ) {
414
437
if (_traceLoading) {
415
438
_log ("Handling deferred load request: $req " );
416
439
}
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
+ }
418
445
}
419
446
}
420
447
// Reset the pending package loads to empty. So that we eventually can
@@ -446,6 +473,9 @@ void _requestPackagesMap() {
446
473
// Embedder Entrypoint:
447
474
// Request the load of a particular packages map.
448
475
void _loadPackagesMap (String packagesParam) {
476
+ if (! _setupCompleted) {
477
+ _setupHooks ();
478
+ }
449
479
// First convert the packages parameter from the command line to a URI which
450
480
// can be handled by the loader code.
451
481
// TODO(iposva): Consider refactoring the common code below which is almost
@@ -490,60 +520,53 @@ void _loadPackagesMap(String packagesParam) {
490
520
}
491
521
492
522
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) {
503
524
if (_traceLoading) {
504
- _log ("_asyncLoadError(${req ._uri }), error: $error " );
525
+ _log ("_asyncLoadError(${req ._uri }), error: $error \n stack: $ stack " );
505
526
}
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);
511
538
}
512
- _asyncLoadErrorCallback (req._uri, libraryUri, error);
513
539
_finishLoadRequest (req);
514
540
}
515
541
516
542
517
- _loadDataFromLoadPort (int tag,
518
- String uri,
519
- String libraryUri,
520
- Uri resourceUri) {
543
+ _loadDataFromLoadPort (int tag, String uri, Uri resourceUri, context) {
521
544
try {
522
- _startLoadRequest (tag, uri, libraryUri, resourceUri );
523
- } catch (e) {
545
+ _startLoadRequest (tag, uri, resourceUri, context );
546
+ } catch (e, s ) {
524
547
if (_traceLoading) {
525
548
_log ("Exception when communicating with service isolate: $e " );
526
549
}
527
550
// Wrap inside a _LoadError unless we are already propagating a previously
528
551
// seen _LoadError.
529
552
var error = (e is _LoadError ) ? e : new _LoadError (e.toString ());
530
- _asyncLoadError (tag, uri, libraryUri , error);
553
+ _asyncLoadError (tag, uri, context , error, s );
531
554
}
532
555
}
533
556
534
557
535
558
// Loading a package URI needs to first map the package name to a loadable
536
559
// URI.
537
- _loadPackage (int tag, String uri, String libraryUri, Uri resourceUri) {
560
+ _loadPackage (int tag, String uri, Uri resourceUri, context ) {
538
561
if (_packagesReady ()) {
539
- _loadData (tag, uri, libraryUri, _resolvePackageUri (resourceUri));
562
+ _loadData (tag, uri, _resolvePackageUri (resourceUri), context );
540
563
} else {
541
564
if (_pendingPackageLoads.isEmpty) {
542
565
// Package resolution has not been setup yet, and this is the first
543
566
// request for package resolution & loading.
544
567
_requestPackagesMap ();
545
568
}
546
- var req = new _LoadRequest (- 1 , tag, uri, libraryUri, resourceUri );
569
+ var req = new _LoadRequest (- 1 , tag, uri, resourceUri, context );
547
570
_pendingPackageLoads.add (req);
548
571
if (_traceLoading) {
549
572
_log ("Pending package load of '$uri ': "
@@ -554,36 +577,42 @@ _loadPackage(int tag, String uri, String libraryUri, Uri resourceUri) {
554
577
555
578
556
579
// 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 ) {
558
581
if (resourceUri.scheme == 'package' ) {
559
582
// package based uris need to be resolved to the correct loadable location.
560
583
// The logic of which is handled seperately, and then _loadData is called
561
584
// recursively.
562
- _loadPackage (tag, uri, libraryUri, resourceUri );
585
+ _loadPackage (tag, uri, resourceUri, context );
563
586
} else {
564
- _loadDataFromLoadPort (tag, uri, libraryUri, resourceUri );
587
+ _loadDataFromLoadPort (tag, uri, resourceUri, context );
565
588
}
566
589
}
567
590
568
591
569
592
// Embedder Entrypoint:
570
593
// Asynchronously loads script data through a http[s] or file uri.
571
594
_loadDataAsync (int tag, String uri, String libraryUri) {
595
+ if (! _setupCompleted) {
596
+ _setupHooks ();
597
+ }
572
598
var resourceUri;
573
- if (tag == Dart_kScriptTag ) {
599
+ if (tag == _Dart_kScriptTag ) {
574
600
resourceUri = _resolveScriptUri (uri);
575
601
uri = resourceUri.toString ();
576
602
} else {
577
603
resourceUri = Uri .parse (uri);
578
604
}
579
- _loadData (tag, uri, libraryUri, resourceUri );
605
+ _loadData (tag, uri, resourceUri, libraryUri );
580
606
}
581
607
582
608
583
609
// Embedder Entrypoint:
584
610
// Function called by standalone embedder to resolve uris when the VM requests
585
611
// Dart_kCanonicalizeUrl from the tag handler.
586
612
String _resolveUri (String base , String userString) {
613
+ if (! _setupCompleted) {
614
+ _setupHooks ();
615
+ }
587
616
if (_traceLoading) {
588
617
_log ('Resolving: $userString from $base ' );
589
618
}
@@ -602,9 +631,23 @@ String _resolveUri(String base, String userString) {
602
631
}
603
632
604
633
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
+
605
645
// Embedder Entrypoint (gen_snapshot):
606
646
// Resolve relative paths relative to working directory.
607
647
String _resolveInWorkingDirectory (String fileName) {
648
+ if (! _setupCompleted) {
649
+ _setupHooks ();
650
+ }
608
651
if (_workingDirectory == null ) {
609
652
throw 'No current working directory set.' ;
610
653
}
@@ -679,6 +722,9 @@ String _filePathFromUri(String userUri) {
679
722
// The filename part is the extension name, with the platform-dependent
680
723
// prefixes and extensions added.
681
724
_extensionPathFromUri (String userUri) {
725
+ if (! _setupCompleted) {
726
+ _setupHooks ();
727
+ }
682
728
if (! userUri.startsWith (_DART_EXT )) {
683
729
throw 'Unexpected internal error: Extension URI $userUri missing dart-ext:' ;
684
730
}
@@ -706,3 +752,10 @@ _extensionPathFromUri(String userUri) {
706
752
707
753
return [path, filename, name];
708
754
}
755
+
756
+
757
+ // Register callbacks and hooks with the rest of the core libraries.
758
+ _setupHooks () {
759
+ _setupCompleted = true ;
760
+ VMLibraryHooks .resourceReadAsBytes = _resourceReadAsBytes;
761
+ }
0 commit comments