js_wrapping 0.5.0

  • README.md
  • CHANGELOG.md
  • Installing
  • Versions
  • 67

Dart Js Wrapping

This package allows developers to define well-typed interfaces for JavaScript objects. Typed JavaScript Interfaces are classes that describes a JavaScript object and have a well-defined Dart API, complete with type annotations, constructors, even optional and named parameters.

Writing Js wrapper

Here's a quick example to show the package in action.

Given a JS class like :

LatLng = function(lat, lng) {
  this.lat = lat;
  this.lng = lng;
}
LatLng.prototype.equals = function(other) {
  return this.lat === other.lat && this.lng === other.lng;
}

You can create a wrapper like :

// you define a private abstract class implementing/extending JsInterface
abstract class _LatLng implements JsInterface {

  // factories to create js objects
  factory _LatLng(num lat, num lng) => null;

  // uninitialized fields to bind to properties
  num lat, lng;

  // abstract methods to call Js methods
  bool equals(LatLng other);
}

Once the generator executed you will be able to use a LatLng that wraps a js LatLng.

Configuration and Initialization

Adding the dependency

Add the following to your pubspec.yaml:

dependencies:
  js_wrapping: ^0.5.0
dev_dependencies:
  js_wrapping_generator: ^0.5.0

Running the generator

See the Running generators section of the source_gen package.

Usage

Warning: The API is still changing rapidly. Not for the faint of heart

Defining Typed JavaScript Interfaces

To create a Typed JavaScript Interface you will start by creating a private class that extends or implements JsInterface. It will be the template used to create a really class that wrap the underlying JsObject.

import 'package:js_wrapping/js_wrapping.dart';

part 'mylib.g.dart'; // assuming the current file is 'mylib.dart'

abstract class _Foo implements JsInterface {
}

The generator will provide the part mylib.g.dart containing :

// **************************************************************************
// Generator: Instance of 'JsInterfaceGenerator'
// Target: abstract class _Foo
// **************************************************************************

class Foo extends JsInterface implements _Foo {
  Foo.created(JsObject o) : super.created(o);
}

The contructor created allows to wrap existing JsObject.

Constructors to create js object

If Foo is a js object/function you can create a new instance in js with new Foo(). To make it possible to create such js instance from the Dart-side you have to define a factory constructor:

abstract class _Foo implements JsInterface {
  factory _Foo() => null;
}

This will provide:

class Foo extends JsInterface implements _Foo {
  Foo.created(JsObject o) : super.created(o);
  Foo() : this.created(new JsObject(context['Foo']));
}

It's now possible to instantiate js object from Dart with new Foo().

NB: You can also use named constructors.

Properties and accessors

Properties or abstract getters/setters can be added to the private class and will generate getters and setters to access to the properties of the underlying js object.

abstract class _Person implements JsInterface {
  String firstname, lastname;
  int get age;
  void set email(String email);
}

This will provide:

class Person extends JsInterface implements _Person {
  Person.created(JsObject o) : super.created(o);

  void set lastname(String _lastname) {
    asJsObject(this)['lastname'] = _lastname;
  }
  String get lastname => asJsObject(this)['lastname'];
  void set firstname(String _firstname) {
    asJsObject(this)['firstname'] = _firstname;
  }
  String get firstname => asJsObject(this)['firstname'];
  int get age => asJsObject(this)['age'];
  void set email(String email) {
    asJsObject(this)['email'] = email;
  }
}

NB: asJsObject(this) is used to get the underlying JsObject and perform operations on it.

Methods

The abstract methods will be implemented the same way :

abstract class _Person implements JsInterface {
  String sayHelloTo(String other);
  void fall();
}

This will provide:

class Person extends JsInterface implements _Person {
  Person.created(JsObject o) : super.created(o);

  String sayHelloTo(String other) =>
      asJsObject(this).callMethod('sayHelloTo', [other]);
  void fall() {
    asJsObject(this).callMethod('fall');
  }
}

Parameters types and return types

The generation relies on the type annotations provided. If you use a JsInterface as return type the generator will automatically wrap the underlying js object in the indicated type. You are also allowed to use JsInterface as parameters.

For instance:

abstract class _Person implements JsInterface {
  String sayHelloTo(Person other);
  Person get father;
}

This will provide:

class Person extends JsInterface implements _Person {
  Person.created(JsObject o) : super.created(o);

  String sayHelloTo(Person other) =>
      asJsObject(this).callMethod('sayHelloTo', [__codec2.encode(other)]);
  Person get father => __codec2.decode(asJsObject(this)['father']);
}
/// codec for Person
final __codec2 = new JsInterfaceCodec<Person>((o) => new Person.created(o));

Note that in sayHelloTo other is unwrapped with toJs automatically. In get father a new Person object is created.

NB: returning Lists and using them as parameters are also supported.

Names used

constructors

By default the names used for object instantiation are the name minus the prepended _. Thus a class _Foo will use the js function/class Foo. You can override this name by providing a JsName('MyClassName') on the class.

@JsName('People')
abstract class _Person implements JsInterface {
  String sayHelloTo(Person other);
  Person get father;
}

members

By default the name used for the call is the member's name if public or the name minus the prepended _ if private. Thus the methods m1() and _m1() will use the same js function m1. You can override this name by providing a JsName('myMemberName') on the member.

abstract class _Person implements JsInterface {
  @JsName('daddy') Person get father;
}

Tips & Tricks

anonymous objects

It's common to instantiate anonymous Js object. If your private classe maps an anonymous object you can add @anonymous on it.

@anonymous
abstract class _Foo implements JsInterface {
  factory _Foo() => null;
}

This generates:

@anonymous
class Foo extends JsInterface implements _Foo {
  Foo.created(JsObject o) : super.created(o);
  Foo() : this.created(new JsObject(context['Object']));
}

Note the context['Object'] used on creation.

create getter from method

If a js object as a getXxx() function you would like to map on the dart side with a get xxx you can do something like that:

abstract class _Person implements JsInterface {
  String get firstname => _getFirstname();
  String _getFirstname();
}

This can be applied to any redirection you'd like to do.

avoid to repeat a namespace on every classes

You can add a JsName('my.namespace') on your library. Thus every constructor will prepend the name of the class with this name.

@JsName('my.namespace')
library familly;
abstract class _Person implements JsInterface {
  factory _Person() => null;
}

This generates:

class Person extends JsInterface implements _Person {
  Person.created(JsObject o) : super.created(o);
  Person() : this.created(new JsObject(context['my']['namespace']['Person']));
}

v0.5.0 (2018-07-27)

  • migration to Dart 2.

v0.4.9 (2018-07-06)

  • Bump dependencies.

v0.4.8 (2018-06-26)

  • Fix issue in JsList and JsMap without codec.

v0.4.7 (2018-04-13)

  • Revert changes introduce in 0.4.6.

v0.4.6 (2018-04-13)

  • Fix IdentityConverter for dart2.

v0.4.5 (2018-04-07)

  • Remove unused codec in generated code.

v0.4.4 (2018-04-06)

  • Migrate to new build_runner system.

v0.4.3 (2018-03-14)

  • Fix runtime cast failure in JsObjectAsMap.keys for dart2.

v0.4.2 (2017-06-30)

  • Fix issue with js function unwrapping.

v0.4.1 (2017-08-28)

  • upgrade dependencies

v0.4.0 (2017-06-20)

  • Fix issue with dart-lang/sdk#28371.

    Breaking change: use factory _MyClass() => null; instead of external factory _MyClass() for your construtor templates.

  • remove comment generics syntax

v0.2.0+1 (2015-06-01)

Fix issue with callback returning void.

v0.2.0 (2015-05-28)

Total rewrite on top of the source_gen package.

Semantic Version Conventions

http://semver.org/

  • Stable: All even numbered minor versions are considered API stable: i.e.: v1.0.x, v1.2.x, and so on.
  • Development: All odd numbered minor versions are considered API unstable: i.e.: v0.9.x, v1.1.x, and so on.

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  js_wrapping: ^0.5.0

2. Install it

You can install packages from the command line:

with pub:


$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:js_wrapping/js_wrapping.dart';
  
Version Uploaded Documentation Archive
0.5.0 Jul 27, 2018 Go to the documentation of js_wrapping 0.5.0 Download js_wrapping 0.5.0 archive
0.4.9 Jul 6, 2018 Go to the documentation of js_wrapping 0.4.9 Download js_wrapping 0.4.9 archive
0.4.8 Jun 26, 2018 Go to the documentation of js_wrapping 0.4.8 Download js_wrapping 0.4.8 archive
0.4.7 Apr 13, 2018 Go to the documentation of js_wrapping 0.4.7 Download js_wrapping 0.4.7 archive
0.4.6 Apr 13, 2018 Go to the documentation of js_wrapping 0.4.6 Download js_wrapping 0.4.6 archive
0.4.5 Apr 7, 2018 Go to the documentation of js_wrapping 0.4.5 Download js_wrapping 0.4.5 archive
0.4.4 Apr 6, 2018 Go to the documentation of js_wrapping 0.4.4 Download js_wrapping 0.4.4 archive
0.4.3 Mar 14, 2018 Go to the documentation of js_wrapping 0.4.3 Download js_wrapping 0.4.3 archive
0.4.2 Aug 30, 2017 Go to the documentation of js_wrapping 0.4.2 Download js_wrapping 0.4.2 archive
0.4.1 Aug 28, 2017 Go to the documentation of js_wrapping 0.4.1 Download js_wrapping 0.4.1 archive

All 21 versions...

Popularity:
Describes how popular the package is relative to other packages. [more]
37
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
90
Overall:
Weighted score of the above. [more]
67
Learn more about scoring.

We analyzed this package on Dec 5, 2018, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.1.0
  • pana: 0.12.7

Platforms

Detected platforms: web, other

Primary library: package:js_wrapping/js_wrapping.dart with components: js.

Maintenance suggestions

Maintain an example. (-10 points)

Create a short demo in the example/ directory to show how to use this package. Common file name patterns include: main.dart, example.dart or you could also use js_wrapping.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0-dev.67.0 <3.0.0