Skip to content

Commit ec49bf8

Browse files
committed
Lazy load @parcel/watcher and fallback to chokidar
1 parent 7129352 commit ec49bf8

File tree

8 files changed

+98
-81
lines changed

8 files changed

+98
-81
lines changed

lib/src/io/js.dart

Lines changed: 58 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -254,60 +254,68 @@ Future<Stream<WatchEvent>> watchDir(String path, {bool poll = false}) async {
254254
throw UnsupportedError("watchDir() is only supported on Node.js");
255255
}
256256

257+
if (poll || parcelWatcher == null) {
258+
return _chokidarWatchDir(path, poll: poll);
259+
} else {
260+
return _parcelWatcherWatchDir(path);
261+
}
262+
}
263+
264+
Future<Stream<WatchEvent>> _chokidarWatchDir(String path, {bool poll = false}) {
257265
// Don't assign the controller until after the ready event fires. Otherwise,
258266
// Chokidar will give us a bunch of add events for files that already exist.
259267
StreamController<WatchEvent>? controller;
260-
if (poll) {
261-
var watcher = chokidar.watch(path, ChokidarOptions(usePolling: true));
262-
watcher
263-
..on(
264-
'add',
265-
allowInterop((String path, [void _]) =>
266-
controller?.add(WatchEvent(ChangeType.ADD, path))))
267-
..on(
268-
'change',
269-
allowInterop((String path, [void _]) =>
270-
controller?.add(WatchEvent(ChangeType.MODIFY, path))))
271-
..on(
272-
'unlink',
273-
allowInterop((String path) =>
274-
controller?.add(WatchEvent(ChangeType.REMOVE, path))))
275-
..on(
276-
'error', allowInterop((Object error) => controller?.addError(error)));
277-
278-
var completer = Completer<Stream<WatchEvent>>();
279-
watcher.on('ready', allowInterop(() {
280-
// dart-lang/sdk#45348
281-
var stream = (controller = StreamController<WatchEvent>(onCancel: () {
282-
watcher.close();
283-
}))
284-
.stream;
285-
completer.complete(stream);
286-
}));
287-
288-
return completer.future;
289-
} else {
290-
var subscription = await ParcelWatcher.subscribeFuture(path,
291-
(Object? error, List<ParcelWatcherEvent> events) {
292-
if (error != null) {
293-
controller?.addError(error);
294-
} else {
295-
for (var event in events) {
296-
switch (event.type) {
297-
case 'create':
298-
controller?.add(WatchEvent(ChangeType.ADD, event.path));
299-
case 'update':
300-
controller?.add(WatchEvent(ChangeType.MODIFY, event.path));
301-
case 'delete':
302-
controller?.add(WatchEvent(ChangeType.REMOVE, event.path));
303-
}
268+
var watcher = chokidar.watch(path, ChokidarOptions(usePolling: poll));
269+
watcher
270+
..on(
271+
'add',
272+
allowInterop((String path, [void _]) =>
273+
controller?.add(WatchEvent(ChangeType.ADD, path))))
274+
..on(
275+
'change',
276+
allowInterop((String path, [void _]) =>
277+
controller?.add(WatchEvent(ChangeType.MODIFY, path))))
278+
..on(
279+
'unlink',
280+
allowInterop((String path) =>
281+
controller?.add(WatchEvent(ChangeType.REMOVE, path))))
282+
..on('error', allowInterop((Object error) => controller?.addError(error)));
283+
284+
var completer = Completer<Stream<WatchEvent>>();
285+
watcher.on('ready', allowInterop(() {
286+
// dart-lang/sdk#45348
287+
var stream = (controller = StreamController<WatchEvent>(onCancel: () {
288+
watcher.close();
289+
}))
290+
.stream;
291+
completer.complete(stream);
292+
}));
293+
294+
return completer.future;
295+
}
296+
297+
Future<Stream<WatchEvent>> _parcelWatcherWatchDir(String path) async {
298+
StreamController<WatchEvent>? controller;
299+
var subscription = await parcelWatcher!.subscribe(path,
300+
(Object? error, List<ParcelWatcherEvent> events) {
301+
if (error != null) {
302+
controller?.addError(error);
303+
} else {
304+
for (var event in events) {
305+
switch (event.type) {
306+
case 'create':
307+
controller?.add(WatchEvent(ChangeType.ADD, event.path));
308+
case 'update':
309+
controller?.add(WatchEvent(ChangeType.MODIFY, event.path));
310+
case 'delete':
311+
controller?.add(WatchEvent(ChangeType.REMOVE, event.path));
304312
}
305313
}
306-
});
314+
}
315+
});
307316

308-
return (controller = StreamController<WatchEvent>(onCancel: () {
309-
subscription.unsubscribe();
310-
}))
311-
.stream;
312-
}
317+
return (controller = StreamController<WatchEvent>(onCancel: () {
318+
subscription.unsubscribe();
319+
}))
320+
.stream;
313321
}

lib/src/js/parcel_watcher.dart

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,48 @@
22
// MIT-style license that can be found in the LICENSE file or at
33
// https://opensource.org/licenses/MIT.
44

5-
import 'package:js/js.dart';
6-
import 'package:node_interop/js.dart';
7-
import 'package:node_interop/util.dart';
5+
import 'dart:js_interop';
86

97
@JS()
10-
class ParcelWatcherSubscription {
8+
extension type ParcelWatcherSubscription(JSObject _) implements JSObject {
119
external void unsubscribe();
1210
}
1311

1412
@JS()
15-
class ParcelWatcherEvent {
13+
extension type ParcelWatcherEvent(JSObject _) implements JSObject {
1614
external String get type;
1715
external String get path;
1816
}
1917

2018
/// The @parcel/watcher module.
2119
///
2220
/// See [the docs on npm](https://www.npmjs.com/package/@parcel/watcher).
23-
@JS('parcel_watcher')
24-
class ParcelWatcher {
25-
external static Promise subscribe(String path, Function callback);
26-
static Future<ParcelWatcherSubscription> subscribeFuture(String path,
21+
@JS()
22+
extension type ParcelWatcher(JSObject _) implements JSObject {
23+
@JS('subscribe')
24+
external JSPromise<ParcelWatcherSubscription> _subscribe(
25+
String path, JSFunction callback);
26+
Future<ParcelWatcherSubscription> subscribe(String path,
2727
void Function(Object? error, List<ParcelWatcherEvent>) callback) =>
28-
promiseToFuture(
29-
subscribe(path, allowInterop((Object? error, List<dynamic> events) {
30-
callback(error, events.cast<ParcelWatcherEvent>());
31-
})));
28+
_subscribe(
29+
path,
30+
(JSObject? error, JSArray<ParcelWatcherEvent> events) {
31+
callback(error, events.toDart);
32+
}.toJS)
33+
.toDart;
3234

33-
external static Promise getEventsSince(String path, String snapshotPath);
34-
static Future<List<ParcelWatcherEvent>> getEventsSinceFuture(
35-
String path, String snapshotPath) async {
36-
List<dynamic> events =
37-
await promiseToFuture(getEventsSince(path, snapshotPath));
38-
return events.cast<ParcelWatcherEvent>();
39-
}
35+
@JS('getEventsSince')
36+
external JSPromise<JSArray<ParcelWatcherEvent>> _getEventsSince(
37+
String path, String snapshotPath);
38+
Future<List<ParcelWatcherEvent>> getEventsSince(
39+
String path, String snapshotPath) async =>
40+
(await _getEventsSince(path, snapshotPath).toDart).toDart;
4041

41-
external static Promise writeSnapshot(String path, String snapshotPath);
42-
static Future<void> writeSnapshotFuture(String path, String snapshotPath) =>
43-
promiseToFuture(writeSnapshot(path, snapshotPath));
42+
@JS('writeSnapshot')
43+
external JSPromise<JSAny> _writeSnapshot(String path, String snapshotPath);
44+
Future<void> writeSnapshot(String path, String snapshotPath) =>
45+
_writeSnapshot(path, snapshotPath).toDart;
4446
}
47+
48+
@JS('parcel_watcher')
49+
external ParcelWatcher? get parcelWatcher;

lib/src/parse/parser.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ class Parser {
651651
var span = scanner.spanFrom(state);
652652
return _interpolationMap == null
653653
? span
654-
: LazyFileSpan(() => _interpolationMap!.mapSpan(span));
654+
: LazyFileSpan(() => _interpolationMap.mapSpan(span));
655655
}
656656

657657
/// Throws an error associated with [span].

lib/src/visitor/async_evaluate.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1812,7 +1812,7 @@ final class _EvaluateVisitor
18121812
if (result != null) {
18131813
isDependency = _inDependency;
18141814
} else {
1815-
result = await _nodeImporter!.loadAsync(originalUrl, previous, forImport);
1815+
result = await _nodeImporter.loadAsync(originalUrl, previous, forImport);
18161816
if (result == null) return null;
18171817
isDependency = true;
18181818
}

lib/src/visitor/evaluate.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// DO NOT EDIT. This file was generated from async_evaluate.dart.
66
// See tool/grind/synchronize.dart for details.
77
//
8-
// Checksum: 396c8f169d95c601598b8c3be1f4b948ca22effa
8+
// Checksum: 3986f5db33dd220dcd971a39e8587ca4e52d9a3f
99
//
1010
// ignore_for_file: unused_import
1111

@@ -1808,7 +1808,7 @@ final class _EvaluateVisitor
18081808
if (result != null) {
18091809
isDependency = _inDependency;
18101810
} else {
1811-
result = _nodeImporter!.load(originalUrl, previous, forImport);
1811+
result = _nodeImporter.load(originalUrl, previous, forImport);
18121812
if (result == null) return null;
18131813
isDependency = true;
18141814
}

pkg/sass_api/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ description: Additional APIs for Dart Sass.
77
homepage: https://github.com/sass/dart-sass
88

99
environment:
10-
sdk: ">=3.0.0 <4.0.0"
10+
sdk: ">=3.3.0 <4.0.0"
1111

1212
dependencies:
1313
sass: 1.80.5

pubspec.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@ executables:
88
sass: sass
99

1010
environment:
11-
sdk: ">=3.0.0 <4.0.0"
11+
sdk: ">=3.3.0 <4.0.0"
1212

1313
dependencies:
1414
args: ^2.0.0
1515
async: ^2.5.0
1616
charcode: ^1.2.0
17-
cli_pkg: ^2.8.0
17+
cli_pkg:
18+
git:
19+
url: https://github.com/google/dart_cli_pkg.git
20+
ref: refs/pull/169/head
1821
cli_repl: ^0.2.1
1922
collection: ^1.16.0
2023
http: ^1.1.0

tool/grind.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ void main(List<String> args) {
3535
pkg.homebrewFormula.value = "Formula/sass.rb";
3636
pkg.homebrewEditFormula.value = _updateHomebrewLanguageRevision;
3737
pkg.jsRequires.value = [
38-
pkg.JSRequire("@parcel/watcher", target: pkg.JSRequireTarget.cli),
38+
pkg.JSRequire("@parcel/watcher",
39+
target: pkg.JSRequireTarget.cli, lazy: true, optional: true),
3940
pkg.JSRequire("immutable", target: pkg.JSRequireTarget.all),
4041
pkg.JSRequire("chokidar", target: pkg.JSRequireTarget.cli),
4142
pkg.JSRequire("readline", target: pkg.JSRequireTarget.cli),

0 commit comments

Comments
 (0)