Skip to content

Commit

Permalink
NodeJS run_ API method should return native JavaScript Promise
Browse files Browse the repository at this point in the history
Currently the `run_` method, exposed through the `dart.sass.js` file,
returns a `Future`. The `Future` object is not accessible due to the
Dart compilation process and `Future` not being a thing in the
JavaScript/NodeJS platform.

In order to provide a better interface to the Sass API for
JavaScript/NodeJS consumers, a native `Promise` is now returned.

Fixes bazelbuild/rules_sass#96.
  • Loading branch information
devversion committed Jan 15, 2020
1 parent ca63b1b commit 7699029
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 2 deletions.
6 changes: 4 additions & 2 deletions lib/src/node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'dart:async';
import 'dart:convert';
import 'dart:js';
import 'dart:js_util';
import 'dart:typed_data';

Expand All @@ -21,6 +22,7 @@ import 'importer/node.dart';
import 'node/error.dart';
import 'node/exports.dart';
import 'node/function.dart';
import 'node/promise.dart';
import 'node/render_context.dart';
import 'node/render_context_options.dart';
import 'node/render_options.dart';
Expand All @@ -39,8 +41,8 @@ import 'visitor/serialize.dart';
/// export that runs the normal `main()`, which is called from `package/sass.js`
/// to run the executable when installed from npm.
void main() {
exports.run_ = allowInterop(
(Object args) => executable.main(List.from(args as List<Object>)));
exports.run_ = allowInterop((Object args) =>
futureToPromise(executable.main(List.from(args as List<Object>))));
exports.render = allowInterop(_render);
exports.renderSync = allowInterop(_renderSync);
exports.info =
Expand Down
19 changes: 19 additions & 0 deletions lib/src/node/promise.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2019 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:js';

import 'package:js/js.dart';

/// Describes the native JavaScript `Promise` global.
@JS()
class Promise<T> {
external Promise(void executor(void resolve(T result), Function reject));
}

/// Converts a Future to a JavaScript Promise.
Promise<T> futureToPromise<T>(Future<T> future) {
return Promise<T>(allowInterop((resolve, reject) =>
future.then(resolve, onError: reject)));
}
2 changes: 2 additions & 0 deletions test/node_api/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export 'package:sass/src/node/render_context.dart';
export 'package:sass/src/node/render_options.dart';
export 'package:sass/src/node/render_result.dart';
import 'package:sass/src/node/fiber.dart';
import 'package:sass/src/node/promise.dart';
import 'package:sass/src/node/render_options.dart';
import 'package:sass/src/node/render_result.dart';

Expand Down Expand Up @@ -50,6 +51,7 @@ external FiberClass _requireFiber(String path);

@JS()
class Sass {
external Promise<void> run_(Object args);
external RenderResult renderSync(RenderOptions args);
external void render(RenderOptions args,
void callback(RenderError error, RenderResult result));
Expand Down
37 changes: 37 additions & 0 deletions test/node_api/exports_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2018 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.

@TestOn('node')
@Tags(['node'])

import 'package:js/js.dart';
import 'package:js/js_util.dart';
import 'package:sass/src/node/promise.dart';
import 'package:test/test.dart';

import '../ensure_npm_package.dart';
import 'api.dart';
import 'utils.dart';

/// Describes a JavaScript object.
///
/// Object's always have a `constructor` property in JavaScript.
@JS()
class ObjectWithConstructor {
Object constructor;
}

void main() {
setUpAll(ensureNpmPackage);
useSandbox();

group('run_ method', () {
test('returns a JavaScript native Promise', () async {
var result = sass.run_([]) as ObjectWithConstructor;
expect(result, isA<Promise<void>>());
expect(result.constructor.toString(), contains('[native code]'));
await promiseToFuture(result);
});
});
}

0 comments on commit 7699029

Please sign in to comment.