Skip to content

Commit d53fcc5

Browse files
committed
Implement sass --embedded in pure JS mode
1 parent 7129352 commit d53fcc5

File tree

13 files changed

+104
-25
lines changed

13 files changed

+104
-25
lines changed

bin/sass.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ import 'package:sass/src/io.dart';
1818
import 'package:sass/src/stylesheet_graph.dart';
1919
import 'package:sass/src/utils.dart';
2020
import 'package:sass/src/embedded/executable.dart'
21-
// Never load the embedded protocol when compiling to JS.
22-
if (dart.library.js) 'package:sass/src/embedded/unavailable.dart'
21+
if (dart.library.js) 'package:sass/src/embedded/js/executable.dart'
2322
as embedded;
2423

2524
Future<void> main(List<String> args) async {

lib/src/embedded/compilation_dispatcher.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44

55
import 'dart:convert';
66
import 'dart:io';
7-
import 'dart:isolate';
7+
import 'dart:isolate' if (dart.library.js) './js/isolate.dart';
88
import 'dart:typed_data';
99

10-
import 'package:native_synchronization/mailbox.dart';
10+
import 'package:native_synchronization/mailbox.dart'
11+
if (dart.library.js) './js/mailbox.dart';
1112
import 'package:path/path.dart' as p;
1213
import 'package:protobuf/protobuf.dart';
1314
import 'package:pub_semver/pub_semver.dart';
@@ -392,3 +393,6 @@ final class CompilationDispatcher {
392393
}
393394
}
394395
}
396+
397+
void spawnCompilationDispatcher(Mailbox mailbox, SendPort sendPort) =>
398+
CompilationDispatcher(mailbox, sendPort).listen();

lib/src/embedded/js/executable.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2024 Google Inc. Use of this source code is governed by an
2+
// MIT-style license that can be found in the LICENSE file or at
3+
// https://opensource.org/licenses/MIT.
4+
5+
import 'dart:js_interop';
6+
7+
import '../compilation_dispatcher.dart';
8+
9+
@JS('sass_embedded')
10+
extension type SassEmbedded._(JSObject o) implements JSObject {
11+
external static void main(JSExportedDartFunction createCompilationDispatcher);
12+
}
13+
14+
void main(List<String> args) {
15+
try {
16+
SassEmbedded.main(spawnCompilationDispatcher.toJS);
17+
} catch (error) {
18+
print(error);
19+
}
20+
}

lib/src/embedded/js/isolate.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2024 Google Inc. Use of this source code is governed by an
2+
// MIT-style license that can be found in the LICENSE file or at
3+
// https://opensource.org/licenses/MIT.
4+
5+
import 'dart:js_interop';
6+
import 'dart:typed_data';
7+
8+
/// MessagePort from JS wrapped as SendPort in Dart
9+
@JS()
10+
extension type SendPort._(JSObject o) implements JSObject {
11+
@JS('postMessage')
12+
external void _postMessage(JSAny message);
13+
void send(Uint8List message) => _postMessage(message.toJS);
14+
}
15+
16+
@JS()
17+
extension type Isolate._(JSObject o) implements JSObject {
18+
static Never exit([SendPort? finalMessagePort, Uint8List? message]) {
19+
if (message != null) {
20+
finalMessagePort?.send(message);
21+
}
22+
throw Error();
23+
}
24+
}

lib/src/embedded/js/mailbox.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2024 Google Inc. Use of this source code is governed by an
2+
// MIT-style license that can be found in the LICENSE file or at
3+
// https://opensource.org/licenses/MIT.
4+
5+
import 'dart:js_interop';
6+
import 'dart:typed_data';
7+
8+
/// SyncMessagePort from JS wrapped as Mailbox in Dart
9+
@JS()
10+
extension type Mailbox._(JSObject o) implements JSObject {
11+
@JS('receiveMessage')
12+
external JSAny _receiveMessage();
13+
Uint8List take() => (_receiveMessage() as JSUint8Array).toDart;
14+
}

lib/src/embedded/unavailable.dart

Lines changed: 0 additions & 10 deletions
This file was deleted.

lib/src/embedded/utils.dart

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

5-
import 'dart:io';
65
import 'dart:typed_data';
76

87
import 'package:protobuf/protobuf.dart';
98
import 'package:source_span/source_span.dart';
109
import 'package:stack_trace/stack_trace.dart';
1110
import 'package:term_glyph/term_glyph.dart' as term_glyph;
1211

12+
import '../io.dart';
1313
import '../syntax.dart';
1414
import 'embedded_sass.pb.dart' as proto;
1515
import 'embedded_sass.pb.dart' hide SourceSpan, Syntax;
@@ -136,15 +136,17 @@ ProtocolError handleError(Object error, StackTrace stackTrace,
136136
{int? messageId}) {
137137
if (error is ProtocolError) {
138138
error.id = messageId ?? errorId;
139-
stderr.write("Host caused ${error.type.name.toLowerCase()} error");
140-
if (error.id != errorId) stderr.write(" with request ${error.id}");
141-
stderr.writeln(": ${error.message}");
139+
var buffer = StringBuffer();
140+
buffer.write("Host caused ${error.type.name.toLowerCase()} error");
141+
if (error.id != errorId) buffer.write(" with request ${error.id}");
142+
buffer.write(": ${error.message}");
143+
printError(buffer.toString());
142144
// PROTOCOL error from https://bit.ly/2poTt90
143145
exitCode = 76; // EX_PROTOCOL
144146
return error;
145147
} else {
146148
var errorMessage = "$error\n${Chain.forTrace(stackTrace)}";
147-
stderr.write("Internal compiler error: $errorMessage");
149+
printError("Internal compiler error: $errorMessage");
148150
exitCode = 70; // EX_SOFTWARE
149151
return ProtocolError()
150152
..type = ProtocolErrorType.INTERNAL

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
}

0 commit comments

Comments
 (0)