├── AUTHORS ├── pubspec.yaml ├── .gitignore ├── lib └── js.dart ├── PATENTS ├── LICENSE └── README.md /AUTHORS: -------------------------------------------------------------------------------- 1 | # Below is a list of people and organizations that have contributed 2 | # to the Dart project. Names should be added to the list like so: 3 | # 4 | # Name/Organization 5 | 6 | Google Inc. 7 | 8 | Alexandre Ardhuin 9 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: js 2 | version: 0.5.0-dev.1 3 | authors: 4 | - Dart Team 5 | - Alexandre Ardhuin 6 | description: Access JavaScript from Dart. 7 | homepage: https://github.com/dart-lang/js-interop 8 | environment: 9 | sdk: '>=1.0.0 <2.0.0' 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Don’t commit the following directories created by pub. 2 | .buildlog 3 | .pub/ 4 | build/ 5 | packages 6 | 7 | # Or the files created by dart2js. 8 | *.dart.js 9 | *.dart.precompiled.js 10 | *.js_ 11 | *.js.deps 12 | *.js.map 13 | 14 | # Include when developing application packages. 15 | pubspec.lock 16 | 17 | .DS_Store 18 | .project 19 | -------------------------------------------------------------------------------- /lib/js.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | /** 6 | * The js library allows Dart library authors to export their APIs to JavaScript 7 | * and to define Dart interfaces for JavaScript objects. 8 | */ 9 | library js; 10 | 11 | /// A metadata annotation that marks an enum as a set of values. 12 | const jsEnum = const _JsEnum(); 13 | class _JsEnum { 14 | const _JsEnum(); 15 | } 16 | 17 | /// A metadata annotation that allows to customize the name used for method call 18 | /// or attribute access on the javascript side. 19 | /// 20 | /// You can use it on libraries, classes, members. 21 | class JsName { 22 | final String name; 23 | const JsName([this.name]); 24 | } 25 | 26 | /// A metadata annotation used to indicate that the Js object is a anonymous js 27 | /// object. That is it is created with `new Object()`. 28 | const anonymous = const _Anonymous(); 29 | class _Anonymous { 30 | const _Anonymous(); 31 | } 32 | -------------------------------------------------------------------------------- /PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Dart Project. 5 | 6 | Google hereby grants to you a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this 8 | section) patent license to make, have made, use, offer to sell, sell, 9 | import, transfer, and otherwise run, modify and propagate the contents 10 | of this implementation of Dart, where such license applies only to 11 | those patent claims, both currently owned by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by 13 | this implementation of Dart. This grant does not include claims that 14 | would be infringed only as a consequence of further modification of 15 | this implementation. If you or your agent or exclusive licensee 16 | institute or order or agree to the institution of patent litigation 17 | against any entity (including a cross-claim or counterclaim in a 18 | lawsuit) alleging that this implementation of Dart or any code 19 | incorporated within this implementation of Dart constitutes direct or 20 | contributory patent infringement, or inducement of patent 21 | infringement, then any patent rights granted to you under this License 22 | for this implementation of Dart shall terminate as of the date such 23 | litigation is filed. 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2012, the Dart project authors. All rights reserved. 2 | Redistribution and use in source and binary forms, with or without 3 | modification, are permitted provided that the following conditions are 4 | met: 5 | * Redistributions of source code must retain the above copyright 6 | notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above 8 | copyright notice, this list of conditions and the following 9 | disclaimer in the documentation and/or other materials provided 10 | with the distribution. 11 | * Neither the name of Google Inc. nor the names of its 12 | contributors may be used to endorse or promote products derived 13 | from this software without specific prior written permission. 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Dart-JavaScript Interop (paused) 2 | ======================= 3 | 4 | **Note:** Development on this package has paused. We encourage every developer 5 | to use `dart:js` for Dart-JavaScript interop. Further work on a 6 | higher-level interop with JavaScript will be explored along with 7 | new experimental approaches to compiling to JavaScript. 8 | 9 | package:js provides high-level, typed interopability between Dart and 10 | JavaScript. It allows developers to export Dart APIs to JavaScript and define 11 | well-typed interfaces for JavaScript objects. 12 | 13 | Status 14 | ------ 15 | 16 | **Paused** 17 | 18 | Version 0.4.0 is a complete rewrite of package:js as described in the 19 | package:js 1.0 [design document][design]. 20 | 21 | [design]: https://docs.google.com/a/google.com/document/d/1X0M7iQ1PraH50353OnjKidgrd0EK6NpLNXVI27jitFY/edit#] 22 | 23 | Usage 24 | ----- 25 | 26 | **Warning: The API is still changing rapidly. Not for the faint of heart** 27 | 28 | 29 | ### Defining Typed JavaScript Proxies 30 | 31 | Typed JavaScript Proxies are classes that represent a JavaScript object and have a well-defined Dart API, complete with type annotations, constructors, even optional and named parameters. They are defined in two parts: 32 | 33 | 1. An abstract class that defines the interface 34 | 2. A concrete class that implements the interface (automatically, either via mirrors or the `js` transformer) 35 | 36 | The abstract class is defined as follows: 37 | 38 | 1. It must extend `JsInterface` 39 | 2. It must have a constructor with the signature `C.created(JsObject o)`. 40 | 3. Any abstract methods or accessors on the class are automatically implemented for you to call into JavaScript. Becuase only abstract class members are proxied to JavaScript, fields must be represented as abstract getter/setter pairs. 41 | 4. Ideally, all parameters and returns should have type annotations. The generator adds casts based on the type annotations which help dart2js produce smaller, faster output. 42 | 5. Add a factory constructor if you want to create new instances from Dart. The constructor must redirect to a factory constructor on the implementation class. 43 | 6. Maps and Lists need to be copied to be usable in JavaScript. Add a `@jsify` annotation to any parameter that takes a Map or List. Note that modification from JS won't be visible in Dart, unless you send the copied collection back later. 44 | 45 | The concrete implementation class is defined as follows: 46 | 47 | 1. It must extend the interface class. 48 | 2. It must have a `created` constructor. 49 | 3. It must have a `@JsProxy` annotation. This tells `package:js` that the class is a proxy, and which JavaScript prototype it should proxy. 50 | 4. It should have a `noSuchMethod` that forwards to the super class to suppress warnings. 51 | 52 | #### Example - Proxying JavaScript to Dart 53 | 54 | ##### JavaScript 55 | 56 | ```javascript 57 | function Foo(name) { 58 | this.name = name; 59 | } 60 | 61 | Foo.prototype.sayHello = function() { 62 | return "Hello " + name; 63 | } 64 | ``` 65 | 66 | ##### Dart 67 | 68 | ```dart 69 | import 'package:js/js.dart'; 70 | 71 | abstract class Foo extends JsInterface { 72 | Foo.created(JsObject o) : super.created(o); 73 | 74 | factory Foo(String name) => new FooImpl(name); 75 | 76 | String get name; 77 | void set name(String n); 78 | 79 | String sayHello(); 80 | } 81 | 82 | @JsProxy(constructor: 'Foo') 83 | class FooImpl extends Foo { 84 | FooImpl.created(JsObject o) : super.created(o); 85 | 86 | factory FooImpl(String name) => new JsInterface(FooImpl, [name]); 87 | 88 | noSuchMethod(i) => super.noSuchMethod(i); 89 | } 90 | ``` 91 | 92 | This may seem a bit verbose, and it is, but it's because of a few constraints we have: 93 | 94 | * The proxy methods should be abstract. 95 | * Abstract members cause warnings on non-abstract classes, which can't be silenced by adding a `noSuchMethod()`, so the proxy class must be abstract. 96 | * Abstract classes can't be instantiated, so we need a separate implementation class. 97 | * The abstract methods are implemented via `noSuchMethod()` in `JsInterface`, which doesn't silence the warnings cause be "unimplemented" methods, so we must add a `noSuchMethod()` to the implementation class. 98 | * The only way to express an "abstract field" is with a getter/setter pair. 99 | * `JsInterface` needs a reference to the raw `JsObject`, so must have a generative constructor. 100 | * We want to create new instances with expressions like `new Foo()`, not `new FooImpl()`, so we need a factory constructor on the interface class. 101 | 102 | We will try to see what changes we can make in the future to this package or the language to alleviate the boilerplate. The good news is that once the boilerplate for the class is set up, the interesting parts - the methods and fields - are quite simple to write and maintain. We will also look into generators for proxies from various sources like TypeScript, Closure, JSHint annotations, Polymer, etc. 103 | 104 | ### Exporting Dart APIs to JavaScript 105 | 106 | You can export classes, functions, variables, and even whole libraries to JavaScript by using the `@Export` annotation. 107 | 108 | #### Example 109 | 110 | ##### a.dart: 111 | 112 | ```dart 113 | library a; 114 | 115 | import 'package:js/js.dart'; 116 | 117 | @Export() 118 | class A { 119 | String name; 120 | 121 | A(); 122 | 123 | A.withName(this.name); 124 | } 125 | ``` 126 | 127 | ##### JavaScript 128 | 129 | ```javascript 130 | var a1 = new dart.a.A(); 131 | a1 instanceof dart.a.A; // true 132 | a1.name; // null 133 | a1.name = 'red'; // sets the value in Dart 134 | 135 | // Named constructors are supported 136 | var a2 = new dart.a.A.withName('blue'); 137 | a2 instanceof dart.a.A; 138 | a2.name; // 'blue' 139 | ``` 140 | 141 | All of the types referenced by exported functions and methods must either be "primitives" as defined by dart:js 142 | (`bool`, `num`, `String`, `DateTime`), JsInterfaces, or other exported classes. 143 | 144 | As with parameters for JsInterfaces, the return values of exported methods are Dart objects being passed to JavaScript. If these are Maps or Lists, they too must be copied to work in JavaScript, so add `@jsify` to the method, field or getter. 145 | 146 | Configuration and Initialization 147 | -------------------------------- 148 | 149 | ### Adding the dependency 150 | 151 | Version 0.4.0 is not published to pub.dartlang.org yet, so you must use a Git 152 | dependency to install it. 153 | 154 | Add the following to your `pubspec.yaml`: 155 | 156 | ```yaml 157 | dependencies: 158 | js: 159 | git: 160 | url: git://github.com/dart-lang/js-interop.git 161 | ``` 162 | 163 | ### Configuring the transformers 164 | 165 | `package:js` requires two transformers to be installed, a transformer that works on packages that directly use `package:js` to generate implementations of JavaScript proxy classes, and another transformer that works on entry-points that generates the necessary setup code. 166 | 167 | If your packages uses `package:js` to export APIs or define JavaScript proxies, add this to your `pubspec.yaml`: 168 | 169 | transformers: 170 | - js 171 | 172 | If your packages defines an entry-point in `web/`, add this to your `pubspec.yaml`: 173 | 174 | transformers: 175 | - js/intializer 176 | 177 | If your package both defines proxies or exports, and has an HTML entry-point in `web/`, then add both transformers: 178 | 179 | transformers: 180 | - js 181 | - js/intializer 182 | 183 | ### Loading the generated JavaScript 184 | 185 | The JavaScript prototypes for exported APIs must be loaded in a page for them to be available to other JavaScript code. This code is loaded by including `packages/js/interop.js` in your HTML. When your application is built that script is replaced by the generated JavaScript. The interop script must be loaded before your main Dart script. 186 | 187 | ##### main.html 188 | 189 | ```html 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | ``` 199 | ### Initializing Interop 200 | 201 | Your `main()` method must call `initializeJavaScript()` in order to export Dart classes and register proxies. This call should be made as early as possible, ideally first. 202 | 203 | ##### main.dart 204 | 205 | ```dart 206 | library main; 207 | 208 | import 'package:js/js.dart'; 209 | 210 | main() { 211 | initializeJavaScript(); 212 | } 213 | ``` 214 | 215 | Contributing and Filing Bugs 216 | ---------------------------- 217 | 218 | Please file bugs and features requests on the Github issue tracker: https://github.com/dart-lang/js-interop/issues 219 | 220 | We also love and accept community contributions, from API suggestions to pull requests. Please file an issue before beginning work so we can discuss the design and implementation. We are trying to create issues for all current and future work, so if something there intrigues you (or you need it!) join in on the discussion. 221 | 222 | All we require is that you sign the Google Individual Contributor License Agreement https://developers.google.com/open-source/cla/individual?csw=1 223 | --------------------------------------------------------------------------------