Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Shared Resources] dart-sass implementation #2134

Merged
merged 13 commits into from
Jan 18, 2024
6 changes: 6 additions & 0 deletions lib/src/js.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'js/exception.dart';
import 'js/exports.dart';
import 'js/compile.dart';
import 'js/compiler.dart';
import 'js/legacy.dart';
import 'js/legacy/types.dart';
import 'js/legacy/value.dart';
Expand All @@ -24,6 +25,11 @@ void main() {
exports.compileAsync = allowInteropNamed('sass.compileAsync', compileAsync);
exports.compileStringAsync =
allowInteropNamed('sass.compileStringAsync', compileStringAsync);
exports.initCompiler = allowInteropNamed('sass.initCompiler', initCompiler);
exports.initAsyncCompiler =
allowInteropNamed('sass.initAsyncCompiler', initAsyncCompiler);
exports.Compiler = compilerClass;
exports.AsyncCompiler = asyncCompilerClass;
exports.Value = valueClass;
exports.SassBoolean = booleanClass;
exports.SassArgumentList = argumentListClass;
Expand Down
99 changes: 99 additions & 0 deletions lib/src/js/compiler.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import 'dart:js_util';

import 'package:async/async.dart';
import 'package:node_interop/js.dart';

import 'compile.dart';
import 'compile_options.dart';
import 'reflection.dart';
import 'utils.dart';

/// The Dart Compiler class.
class Compiler {
jamesnw marked this conversation as resolved.
Show resolved Hide resolved
jamesnw marked this conversation as resolved.
Show resolved Hide resolved
/// A flag signifying whether the instance has been disposed.
bool _disposed = false;

/// Checks if `dispose()` has been called on this instance, and throws an
/// error if it has. Used to verify that compilation methods are not called
/// after disposal.
void throwIfDisposed() {
if (_disposed) {
jsThrow(JsError('Compiler has already been disposed.'));
}
}
}

/// The Dart Async Compiler class.
class AsyncCompiler extends Compiler {
/// A set of all compilations, tracked to ensure all compilations settle
jamesnw marked this conversation as resolved.
Show resolved Hide resolved
/// before async disposal resolves.
final FutureGroup<dynamic> compilations = FutureGroup();
jamesnw marked this conversation as resolved.
Show resolved Hide resolved

/// Adds a compilation to the FutureGroup.
void addCompilation(Promise compilation) {
Future<dynamic> comp = promiseToFuture(compilation);
comp.catchError((err) {
return;
jamesnw marked this conversation as resolved.
Show resolved Hide resolved
});
compilations.add(comp);
}
}

/// The JavaScript `Compiler` class.
final JSClass compilerClass = () {
var jsClass = createJSClass('sass.Compiler', () => Compiler());
jamesnw marked this conversation as resolved.
Show resolved Hide resolved

jsClass.defineMethods({
'compile': (Compiler self, String path, [CompileOptions? options]) {
self.throwIfDisposed();
return compile(path, options);
},
'compileString': (Compiler self, String source,
[CompileStringOptions? options]) {
self.throwIfDisposed();
return compileString(source, options);
},
'dispose': (Compiler self) {
self._disposed = true;
},
});

getJSClass(Compiler()).injectSuperclass(jsClass);
return jsClass;
}();

Compiler initCompiler() => Compiler();

/// The JavaScript `AsyncCompiler` class.
final JSClass asyncCompilerClass = () {
var jsClass = createJSClass('sass.AsyncCompiler', () => AsyncCompiler());

jsClass.defineMethods({
'compileAsync': (AsyncCompiler self, String path,
[CompileOptions? options]) {
self.throwIfDisposed();
var compilation = compileAsync(path, options);
self.addCompilation(compilation);
return compilation;
},
'compileStringAsync': (AsyncCompiler self, String source,
[CompileStringOptions? options]) {
self.throwIfDisposed();
var compilation = compileStringAsync(source, options);
self.addCompilation(compilation);
return compilation;
},
'dispose': (AsyncCompiler self) {
self._disposed = true;
return futureToPromise((() async {
self.compilations.close();
await self.compilations.future;
})());
}
});

getJSClass(AsyncCompiler()).injectSuperclass(jsClass);
return jsClass;
}();

Promise initAsyncCompiler() => futureToPromise((() async => AsyncCompiler())());
4 changes: 4 additions & 0 deletions lib/src/js/exports.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ class Exports {
external set compileStringAsync(Function function);
external set compile(Function function);
external set compileAsync(Function function);
external set initCompiler(Function function);
external set initAsyncCompiler(Function function);
external set Compiler(JSClass function);
external set AsyncCompiler(JSClass function);
external set info(String info);
external set Exception(JSClass function);
external set Logger(LoggerNamespace namespace);
Expand Down
4 changes: 4 additions & 0 deletions tool/grind.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ void main(List<String> args) {
'compileAsync',
'compileString',
'compileStringAsync',
'initCompiler',
'initAsyncCompiler',
'Compiler',
'AsyncCompiler',
'Logger',
'SassArgumentList',
'SassBoolean',
Expand Down