lrhn / dep-configured-imports Goto Github PK
View Code? Open in Web Editor NEWDart Enhancement Proposal for Configurable Imports.
Dart Enhancement Proposal for Configurable Imports.
In the Syntax section, we say "default uri.dart"
and that's not clear if the word default
is a special word, we actually meant default_uri.dart
Can we remove the spaces in the uri examples or is the space intentional?
Thanks!
@bwilkerson wrote dart-archive/dart_enhancement_proposals#6 (comment):
The proposal states:
An analysis tool, like the Dart Analyzer, can see all possible import strings, and either resolve to a single URI for a given platform/configuration, or examine all the combinations.
This is not true (or at the very least is misleading). The analyzer does not require the values of "environment" variables to be specified. Therefore, it will not, in general, be able to determine which import will be selected, and will be forced to analyze every such library against all possible combinations of imports. This will significantly increase the amount of analysis that needs to be performed, which could have serious performance implications. (Three imports with two options each will result in analyzing the library 8 times. Any library that directly or indirectly imports the library containing the imports will (in the worst case scenario) likewise need to be analyzed 8 times.)
AFAIK feature detection is generally preferable to platform sniffing ("user agent sniffing" in the web world). So why do we need the latter?
The ||
and :
seem strange and arbitrary to me. I don't think a random Dart user could easily intuit what they do, especially since their meaning is different from how those operators are understood in other contexts.
However, there is already a language feature that:
How about we leverage that?
import case dart.platform == "browser": "some_uri.dart"
case dart.platform == "standalone": "other_uri.dart"
default: "default_uri.dart"
deferred as foo show x hide y;
What do you think?
// Directives import/export
// Here allowed conditional directives
// Declarations
// Here not allowed conditional directives
library name
#if env_constant expression
// Directives import/export
#elif other_env_constant expression
// Directives import/export
#else
// Directives import/export
#endif
library name
#if dart_platform == "server" || dart_platform == "browser"
import "common.dart";
#else
#error Unsupported platform
#endif
#if dart_platform == "server"
import "server.dart";
#elif dart_platform == "browser"
import "browser.dart";
#else
#error Unsupported platform
#endif
Currently it is dart.feature.dom
... wouldn't it be better to match?
This is a question of behavior. Don't we currently use the build tools to pull in the correct libraries?
Or, am I misunderstanding the wording or context in your usage.
Is this proposal adding language that would be better defined in the implementation behavior?
Instead of explicitly telling the tools what to do in each case, can't we describe behaviors that accomplish the same tasks?
In this case, instead of adding all of this verbosity, can we add a convention for naming libraries
work.s.dart
work.w.dart
work.*.dart
to deal with these cases? I realize a lot of thought went into this, so I am curios if you thought along this approach. By naming the files with the same starting name and this hint, a very dartian thing to do, and importing specific libraries, the vm and packaging should have enough info to handle a large number of use cases.
Or we could add an environment specifier such as
env server;
or
env browser;
to serve the same purpose, if we need to be more explicit.
We've been thinking about a problem for which configured imports could be an important piece of the solution. However, to be useful we would need a more expressive expression language to choose which import to load.
The problem I'd like to address it to reduce cascading effects that occur when versioning package dependencies. Here is an example: Say package A and C have a dependency on package B and a new version with breaking changes comes along for B. Developers of A and C today must pick to stay in the old version of B or move to the new version. If A and C developers pick differently, users will have trouble using A and C together in their apps.
One way to address this problem is to let developers use either version of B. We could do so with configured imports if, say, there is a user defined configuration with the version of the packages it uses:
import analyzer.package.version == "0.22.0" : "some uri.dart"
|| "default uri.dart"
deferred as foo show x hide y;
(let's put aside how to determine what the current version is to set analyzer.package.version
, since that is less relevant to the discussion of configured imports here).
The challenge for configured imports though, is that the expression language for tests is not expressive enough to write more complex version constraint tests. For example, it's important to be able to select a version range, like:
import analyzer.version in ">= 0.22.0 <0.23.0" : "uri.dart"
|| "default uri.dart"
deferred as foo show x hide y;
I think that adding general support for boolean expressions might be too expressive for this (even if they are limited to const objects defined in non-configured libraries).
An option is to add special support for version constraints. They are a key part of the Dart ecosystem and definitions for constraints could be exposed either in the import syntax or as const definitions in a dart:
library. This example treats it as part of the language:
import analyzer.version in ">= 0.22.0 <0.23.0" : "uri.dart"
alternatively we could do:
import 'dart:constraints';
import const VersionRange(">= 0.22.0 <0.23.0").contains(analyzer.version) : "uri.dart"
or
import analyzer.version.inRange(">= 0.22.0 <0.23.0") : "uri.dart"
This proposal doesn't support a use-case I think is important: implementing an interface from a platform-specific library in a way that works across platforms. In particular, if A
is in dart:io
, there's no way for my package to write B implements A
in a way that is visible to code that runs in the browser.
Here's a more concrete example. Suppose I'm writing an HTML-sanitizing API and I want to take a user-supplied Element
. Other than the Element
itself, my API is perfectly platform-independent, and I want to make my package easy to use on the server as well as the browser.
String sanitizeHtml(??? element);
Meanwhile, unbeknownst to me, John has been hard at work on html5lib and has produced a full-featured server-side implementation of Element
; for clarity, let's call this CrossPlatformElement
. There's nothing I can write for the ???
above that will let me take both a native Element
object on the browser and a CrossPlatformElement
object on the server; even if John wants to have CrossPlatformElement
implement Element
, there's no way for to do so that's visible on the server.
As part of this, I think it would be helpful if we could configure imports based on Platform (isWindows, isLinux, isMacOS) and Architecture (32bit or 64bit). The particular use case in this scenario would be Dart VM Native Extension shared library files.
In this situation, a package can ship with pre-compiled binaries and the correct shared library can be imported based on the platform.
For example, a package layout could be like:
package/
lib/
sample_extension.dart
darwin-x64/
libsample_extension.dylib
linux-ia32/
libsample_extension.so
linux-x64/
libsample_extension.so
win-ia32/
sample_extension.dll
win-x64/
sample_extension.dll
Based on the platform and architecture, you could adjust the import URI to the correct subfolder and the shared library for the platform would be loaded.
A solution like this would eliminate the need for end-users to need compile tools in order to use a Dart VM Native extension. Simply pub get
and start using.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.