-
Notifications
You must be signed in to change notification settings - Fork 353
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
Support package: URLs in Dart #53
Conversation
8fbcb0c
to
6b30c9c
Compare
I like this change, but I think we should take a |
Using |
We use configuration-specific imports to support VM-only APIs as well as JS. You can add a conditional import that imports a stubbed |
ok, I'll try to make the changes. I'll let you know |
b8509ca
to
a32d759
Compare
Changes has been made. Please review them @nex3 |
lib/sass.dart
Outdated
@@ -15,12 +16,12 @@ import 'src/visitor/serialize.dart'; | |||
/// If [color] is `true`, this will use terminal colors in warnings. | |||
/// | |||
/// Throws a [SassException] if conversion fails. | |||
String render(String path, {bool color: false}) { | |||
Future<String> render(String path, {bool color: false}) async { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function should take the SyncPackageResolver
, not _PerformVisitor
. Rendering needs to be synchronous in order to be compatible with the node-sass API.
Also, there should be a command-line --packages
flag that allows the user to manually specify a package spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what do you mean with package spec
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A .packages
file.
lib/src/parse/stylesheet.dart
Outdated
@@ -1403,6 +1403,12 @@ abstract class StylesheetParser extends Parser { | |||
break; | |||
|
|||
case $0: | |||
if (scanner.peekChar(1) == $backslash && scanner.peekChar(2) == $0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's this all about?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these lines are for parsing code like next:
@media screen and (min-width:0\0) {
...
}
specifically are for parsing 0\0
inside a media query.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please leave fixes for other issues outside of this PR. One thing at a time makes it easier to review.
/// [PackageInfo] is usually preferable when the current Isolate's package | ||
/// resolution logic may be used. | ||
/// | ||
/// This class should not be implemented by user code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to copy over the documentation here or in the stub implementation.
/// Returns `null` when using a [packageRoot] for resolution, or when no | ||
/// package resolution is being used. | ||
Map<String, Uri> get packageConfigMap => | ||
throw new Exception('not implemented for node'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These methods should throw UnsupportedException
s, which should include the name of the class and method (for example, "SyncPackageResolver.packageConfigMap isn't supported on Node.js.").
lib/src/visitor/perform.dart
Outdated
@@ -509,11 +519,17 @@ class _PerformVisitor | |||
}); | |||
} | |||
|
|||
Uri _resolvePackageUri(Uri packageUri) { | |||
return packageUri.scheme == 'package' && packageResolver != null | |||
? packageResolver.resolveUri(packageUri) ?? new Uri() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think new Uri()
is right here. A blank URL doesn't help anyone. We should throw a useful error message saying "Can't resolve "$packageUri"" if it fails to resolve, or if there's no resolver available.
@@ -0,0 +1 @@ | |||
$color: blue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this node_sample
directory for?
test/import_package_uri_test.dart
Outdated
main() { | ||
group('import "package:" uri', () { | ||
test('found', () async { | ||
var result = await render('test/styles/import-package.scss'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than using assets on the filesystem, Dart Sass tests use scheduled_test
's descriptor
library to create assets in the test itself. This helps keep the test self-contained, and makes diffs a lot easier to read. See test/cli_shared.dart
for examples.
pubspec.yaml
Outdated
@@ -29,3 +30,4 @@ dev_dependencies: | |||
node_preamble: "^1.0.0" | |||
test: "^0.12.0" | |||
yaml: "^2.0.0" | |||
bootstrap_sass: ^4.0.0-alpah.3+4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like making assertions about other packages' assets in tests. I'd rather create a folder in the test body, then create a .packages
file that points to it.
tool/grind.dart
Outdated
@@ -16,15 +15,15 @@ import 'package:yaml/yaml.dart'; | |||
|
|||
/// The version of Dart Sass. | |||
final String _version = | |||
loadYaml(new File('pubspec.yaml').readAsStringSync())['version']; | |||
loadYaml(new File('pubspec.yaml').readAsStringSync())['version'] as String; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'll be quicker for me to review this PR if you keep the changes focused on package:
URLs.
a32d759
to
270551c
Compare
7935021
to
93a5d83
Compare
@luisvt Is this ready for another round of review? |
Not yet sorry |
93a5d83
to
b6095cc
Compare
We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for the commit author(s). If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google. |
b6095cc
to
7dcb1c8
Compare
CLAs look good, thanks! |
7dcb1c8
to
40c7950
Compare
now I think is ready, please review it. |
lib/sass.dart
Outdated
/// If [color] is `true`, this will use terminal colors in warnings. | ||
/// | ||
/// Throws a [SassException] if conversion fails. | ||
Future<String> renderAsync(String path, {bool color: false}) async => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I want to add this. I don't think having a default for packageResolver
is worth an extra top-level function.
lib/src/node.dart
Outdated
void _render( | ||
NodeOptions options, void callback(NodeError error, NodeResult result)) { | ||
Future _render(NodeOptions options, | ||
void callback(NodeError error, NodeResult result)) async { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you changing the types here? Node doesn't understand what a "Future" is, so this will definitely break it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I forgot to revert it.
@@ -0,0 +1,3 @@ | |||
export 'interface.dart' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To match the way we stub out IO, this file (sync_package_resolver/index.dart
) should be sync_package_resolver.dart
instead.
import 'dart:async'; | ||
|
||
abstract class SyncPackageResolver { | ||
Map<String, Uri> get packageConfigMap; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only include the members that Dart Sass actually uses in practice.
lib/src/visitor/perform.dart
Outdated
@@ -123,8 +128,13 @@ class _PerformVisitor | |||
/// invocations, and imports surrounding the current context. | |||
final _stack = <Frame>[]; | |||
|
|||
final SyncPackageResolver packageResolver; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this private.
lib/sass.dart
Outdated
@@ -15,12 +17,24 @@ import 'src/visitor/serialize.dart'; | |||
/// If [color] is `true`, this will use terminal colors in warnings. | |||
/// | |||
/// Throws a [SassException] if conversion fails. | |||
String render(String path, {bool color: false}) { | |||
String render(String path, | |||
{bool color: false, SyncPackageResolver packageResolver}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Document the packageResolver
parameter.
lib/src/visitor/perform.dart
Outdated
Uri _resolvePackageUri(DynamicImport import) { | ||
var packageUri = import.url; | ||
if (packageUri.scheme == 'package') { | ||
if (packageResolver == null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: include {}
even for single-statement if
s (see the style guide).
pubspec.yaml
Outdated
@@ -19,6 +19,7 @@ dependencies: | |||
string_scanner: ">=0.1.5 <2.0.0" | |||
stack_trace: ">=0.9.0 <2.0.0" | |||
tuple: "^1.0.0" | |||
package_resolver: ^1.0.2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Always declare the lowest version that has all the APIs you need. In this case, that's 1.0.0.
test/dart_cli_test.dart
Outdated
|
||
group("supports package imports", () { | ||
test("is found", () { | ||
d.file("test.scss", "a {b: 1 + 2}").create('lib'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't create files outside of the sandbox during tests. To properly test this, you'll probably need to add that --packages
flag.
lib/src/executable.dart
Outdated
@@ -47,7 +47,7 @@ main(List<String> args) async { | |||
|
|||
var color = (options['color'] as bool) ?? hasTerminal; | |||
try { | |||
var css = render(options.rest.first, color: color); | |||
var css = await renderAsync(options.rest.first, color: color); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Defaulting to the current isolate's package resolver only makes sense here if Sass is being used as a library or a direct dependency of a package. If it's being run as a global or standalone executable—which is better supported anyway—that logic won't work.
Probably the best thing to do here is to follow Dart's behavior for auto-detecting package resolution from the Sass file's location, and allow users to override it with a --packages
flag. For now, just remove the default behavior and implement the flag; we can do the auto-detection in a separate CL.
0d6e758
to
1168754
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking really good! Just a few small changes left.
lib/src/visitor/perform.dart
Outdated
|
||
var resolvedPackageUri = _packageResolver.resolveUri(packageUri); | ||
if (resolvedPackageUri == null || | ||
!dirExists(p.dirname(p.fromUri(resolvedPackageUri)))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand the point of this check. If the package URI is resolvable, we'll already get an error when we try to load the file, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is for when the package URI is not resolvable. What should I do instead this check?
If I remove this check resolvedPackageUri
will be null, which in turn will throw:
NoSuchMethodError: The getter 'scheme' was called on null.
Second option would be return an empty uri, which was what I have at the beginning and you told me to better add a check and throw a better error. Please see the comment you added on #53 (diff)
Third option would be return the original packageUri
, but that lets to previous problem on having an error message not showing good information.
Finally the line 585 in #53 (diff) was added because previous version of sdk returned an URI even when there was no existing file.
test/dart_cli_test.dart
Outdated
// ])); | ||
// sass.shouldExit(0); | ||
// }); | ||
// }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this commented-out code.
test/dart_script_test.dart
Outdated
"@import \"package:fake_package/test_aux\";\n" | ||
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" | ||
" $sandbox/test.scss 1:9 root stylesheet"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's generally better to use the throwsA()
matcher than to manually write a try/catch block. Then you can verify the exception's message with the predicate()
matcher.
changes: * remove commented out code in `dart_cli_test.dart` * use `throwsA` instead doing a `try-catch` in `dart_script_test.dart`
We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for the commit author(s). If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google. |
e33a390
to
87934d3
Compare
CLAs look good, thanks! |
We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for the commit author(s). If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google. |
changes: * remove `dirExist` check for `packageUri`
2eaddcd
to
880de11
Compare
CLAs look good, thanks! |
1102235
to
08e0788
Compare
Exporting a stub produced errors when passing a real instance.
Thanks for the patch! |
Co-authored-by: Natalie Weizenbaum <nweiz@google.com>
fixes #19