-
Notifications
You must be signed in to change notification settings - Fork 347
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for the new importer API (#1522)
- Loading branch information
Showing
8 changed files
with
412 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// Copyright 2021 Google Inc. Use of this source code is governed by an | ||
// MIT-style license that can be found in the LICENSE file or at | ||
// https://opensource.org/licenses/MIT. | ||
|
||
import 'dart:async'; | ||
|
||
import 'package:node_interop/js.dart'; | ||
import 'package:node_interop/util.dart'; | ||
|
||
import '../../node/importer.dart'; | ||
import '../../node/url.dart'; | ||
import '../../node/utils.dart'; | ||
import '../../util/nullable.dart'; | ||
import '../async.dart'; | ||
import '../result.dart'; | ||
|
||
/// A wrapper for a potentially-asynchronous JS API importer that exposes it as | ||
/// a Dart [AsyncImporter]. | ||
class NodeToDartAsyncImporter extends AsyncImporter { | ||
/// The wrapped canonicalize function. | ||
final Object? Function(String, CanonicalizeOptions) _canonicalize; | ||
|
||
/// The wrapped load function. | ||
final Object? Function(JSUrl) _load; | ||
|
||
NodeToDartAsyncImporter(this._canonicalize, this._load); | ||
|
||
FutureOr<Uri?> canonicalize(Uri url) async { | ||
var result = _canonicalize( | ||
url.toString(), CanonicalizeOptions(fromImport: fromImport)); | ||
if (isPromise(result)) result = await promiseToFuture(result as Promise); | ||
if (result == null) return null; | ||
|
||
if (isJSUrl(result)) return jsToDartUrl(result as JSUrl); | ||
|
||
jsThrow(JsError("The canonicalize() method must return a URL.")); | ||
} | ||
|
||
FutureOr<ImporterResult?> load(Uri url) async { | ||
var result = _load(dartToJSUrl(url)); | ||
if (isPromise(result)) result = await promiseToFuture(result as Promise); | ||
if (result == null) return null; | ||
|
||
result as NodeImporterResult; | ||
var contents = result.contents; | ||
var syntax = result.syntax; | ||
if (contents == null || syntax == null) { | ||
jsThrow(JsError("The load() function must return an object with contents " | ||
"and syntax fields.")); | ||
} | ||
|
||
return ImporterResult(contents, | ||
syntax: parseSyntax(syntax), | ||
sourceMapUrl: result.sourceMapUrl.andThen(jsToDartUrl)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// Copyright 2021 Google Inc. Use of this source code is governed by an | ||
// MIT-style license that can be found in the LICENSE file or at | ||
// https://opensource.org/licenses/MIT. | ||
|
||
import 'dart:async'; | ||
|
||
import 'package:node_interop/js.dart'; | ||
import 'package:node_interop/util.dart'; | ||
import 'package:path/path.dart' as p; | ||
|
||
import '../../io.dart' as io; | ||
import '../../node/importer.dart'; | ||
import '../../node/utils.dart'; | ||
import '../../syntax.dart'; | ||
import '../async.dart'; | ||
import '../filesystem.dart'; | ||
import '../result.dart'; | ||
import '../utils.dart'; | ||
|
||
/// A filesystem importer to use for most implementation details of | ||
/// [NodeToDartAsyncFileImporter]. | ||
/// | ||
/// This allows us to avoid duplicating logic between the two importers. | ||
final _filesystemImporter = FilesystemImporter('.'); | ||
|
||
/// A wrapper for a potentially-asynchronous JS API file importer that exposes | ||
/// it as a Dart [AsyncImporter]. | ||
class NodeToDartAsyncFileImporter extends AsyncImporter { | ||
/// The wrapped `findFileUrl` function. | ||
final Object? Function(String, CanonicalizeOptions) _findFileUrl; | ||
|
||
/// A map from canonical URLs to the `sourceMapUrl`s associated with them. | ||
final _sourceMapUrls = <Uri, Uri>{}; | ||
|
||
NodeToDartAsyncFileImporter(this._findFileUrl); | ||
|
||
FutureOr<Uri?> canonicalize(Uri url) async { | ||
if (url.scheme != 'file' && url.scheme != '') return null; | ||
|
||
var result = _findFileUrl( | ||
url.toString(), CanonicalizeOptions(fromImport: fromImport)); | ||
if (isPromise(result)) result = await promiseToFuture(result as Promise); | ||
if (result == null) return null; | ||
|
||
result as NodeFileImporterResult; | ||
var dartUrl = result.url; | ||
var sourceMapUrl = result.sourceMapUrl; | ||
if (dartUrl == null) { | ||
jsThrow(JsError( | ||
"The findFileUrl() method must return an object a url field.")); | ||
} | ||
|
||
var resultUrl = jsToDartUrl(dartUrl); | ||
if (resultUrl.scheme != 'file') { | ||
jsThrow(JsError( | ||
'The findFileUrl() must return a URL with scheme file://, was ' | ||
'"$url".')); | ||
} | ||
|
||
var canonical = _filesystemImporter.canonicalize(resultUrl); | ||
if (canonical == null) return null; | ||
if (sourceMapUrl != null) { | ||
_sourceMapUrls[canonical] = jsToDartUrl(sourceMapUrl); | ||
} | ||
|
||
return canonical; | ||
} | ||
|
||
ImporterResult? load(Uri url) { | ||
var path = p.fromUri(url); | ||
return ImporterResult(io.readFile(path), | ||
sourceMapUrl: _sourceMapUrls[url] ?? url, syntax: Syntax.forPath(path)); | ||
} | ||
|
||
DateTime modificationTime(Uri url) => | ||
_filesystemImporter.modificationTime(url); | ||
|
||
bool couldCanonicalize(Uri url, Uri canonicalUrl) => | ||
_filesystemImporter.couldCanonicalize(url, canonicalUrl); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Copyright 2021 Google Inc. Use of this source code is governed by an | ||
// MIT-style license that can be found in the LICENSE file or at | ||
// https://opensource.org/licenses/MIT. | ||
|
||
import 'package:node_interop/js.dart'; | ||
import 'package:path/path.dart' as p; | ||
|
||
import '../../io.dart' as io; | ||
import '../../importer.dart'; | ||
import '../../node/importer.dart'; | ||
import '../../node/utils.dart'; | ||
import '../../syntax.dart'; | ||
import '../filesystem.dart'; | ||
import '../result.dart'; | ||
import '../utils.dart'; | ||
|
||
/// A filesystem importer to use for most implementation details of | ||
/// [NodeToDartAsyncFileImporter]. | ||
/// | ||
/// This allows us to avoid duplicating logic between the two importers. | ||
final _filesystemImporter = FilesystemImporter('.'); | ||
|
||
/// A wrapper for a potentially-asynchronous JS API file importer that exposes | ||
/// it as a Dart [AsyncImporter]. | ||
class NodeToDartFileImporter extends Importer { | ||
/// The wrapped `findFileUrl` function. | ||
final Object? Function(String, CanonicalizeOptions) _findFileUrl; | ||
|
||
/// A map from canonical URLs to the `sourceMapUrl`s associated with them. | ||
final _sourceMapUrls = <Uri, Uri>{}; | ||
|
||
NodeToDartFileImporter(this._findFileUrl); | ||
|
||
Uri? canonicalize(Uri url) { | ||
if (url.scheme != 'file' && url.scheme != '') return null; | ||
|
||
var result = _findFileUrl( | ||
url.toString(), CanonicalizeOptions(fromImport: fromImport)); | ||
if (result == null) return null; | ||
|
||
if (isPromise(result)) { | ||
jsThrow(JsError( | ||
"The canonicalize() function can't return a Promise for synchronous " | ||
"compile functions.")); | ||
} | ||
|
||
result as NodeFileImporterResult; | ||
var dartUrl = result.url; | ||
var sourceMapUrl = result.sourceMapUrl; | ||
if (dartUrl == null) { | ||
jsThrow(JsError( | ||
"The findFileUrl() method must return an object a url field.")); | ||
} | ||
|
||
var resultUrl = jsToDartUrl(dartUrl); | ||
if (resultUrl.scheme != 'file') { | ||
jsThrow(JsError( | ||
'The findFileUrl() must return a URL with scheme file://, was ' | ||
'"$url".')); | ||
} | ||
|
||
var canonical = _filesystemImporter.canonicalize(resultUrl); | ||
if (canonical == null) return null; | ||
if (sourceMapUrl != null) { | ||
_sourceMapUrls[canonical] = jsToDartUrl(sourceMapUrl); | ||
} | ||
|
||
return canonical; | ||
} | ||
|
||
ImporterResult? load(Uri url) { | ||
var path = p.fromUri(url); | ||
return ImporterResult(io.readFile(path), | ||
sourceMapUrl: _sourceMapUrls[url] ?? url, syntax: Syntax.forPath(path)); | ||
} | ||
|
||
DateTime modificationTime(Uri url) => | ||
_filesystemImporter.modificationTime(url); | ||
|
||
bool couldCanonicalize(Uri url, Uri canonicalUrl) => | ||
_filesystemImporter.couldCanonicalize(url, canonicalUrl); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright 2021 Google Inc. Use of this source code is governed by an | ||
// MIT-style license that can be found in the LICENSE file or at | ||
// https://opensource.org/licenses/MIT. | ||
|
||
import 'package:node_interop/js.dart'; | ||
|
||
import '../../importer.dart'; | ||
import '../../node/importer.dart'; | ||
import '../../node/url.dart'; | ||
import '../../node/utils.dart'; | ||
import '../../util/nullable.dart'; | ||
import '../result.dart'; | ||
|
||
/// A wrapper for a synchronous JS API importer that exposes it as a Dart | ||
/// [Importer]. | ||
class NodeToDartImporter extends Importer { | ||
/// The wrapped canonicalize function. | ||
final Object? Function(String, CanonicalizeOptions) _canonicalize; | ||
|
||
/// The wrapped load function. | ||
final Object? Function(JSUrl) _load; | ||
|
||
NodeToDartImporter(this._canonicalize, this._load); | ||
|
||
Uri? canonicalize(Uri url) { | ||
var result = _canonicalize( | ||
url.toString(), CanonicalizeOptions(fromImport: fromImport)); | ||
if (result == null) return null; | ||
if (isJSUrl(result)) return jsToDartUrl(result as JSUrl); | ||
|
||
if (isPromise(result)) { | ||
jsThrow(JsError( | ||
"The canonicalize() function can't return a Promise for synchronous " | ||
"compile functions.")); | ||
} else { | ||
jsThrow(JsError("The canonicalize() method must return a URL.")); | ||
} | ||
} | ||
|
||
ImporterResult? load(Uri url) { | ||
var result = _load(dartToJSUrl(url)); | ||
if (result == null) return null; | ||
|
||
if (isPromise(result)) { | ||
jsThrow(JsError( | ||
"The load() function can't return a Promise for synchronous compile " | ||
"functions.")); | ||
} | ||
|
||
result as NodeImporterResult; | ||
var contents = result.contents; | ||
var syntax = result.syntax; | ||
if (contents == null || syntax == null) { | ||
jsThrow(JsError("The load() function must return an object with contents " | ||
"and syntax fields.")); | ||
} | ||
|
||
return ImporterResult(contents, | ||
syntax: parseSyntax(syntax), | ||
sourceMapUrl: result.sourceMapUrl.andThen(jsToDartUrl)); | ||
} | ||
} |
Oops, something went wrong.