js_wrapping 0.5.0

  • Readme
  • Changelog
  • Installing
  • 76

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

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter 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';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
92
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
0
Overall:
Weighted score of the above. [more]
76
Learn more about scoring.

We analyzed this package on Jul 2, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.9+1

Analysis suggestions

Package not compatible with runtime flutter-native of android

Because of the import of dart:js via the import chain package:js_wrapping/js_wrapping.dart->package:js_wrapping/adapter/js_map.dart->dart:js

Package not compatible with runtime flutter-native of ios

Because of the import of dart:js via the import chain package:js_wrapping/js_wrapping.dart->package:js_wrapping/adapter/js_map.dart->dart:js

Package not compatible with runtime flutter-native of linux

Because of the import of dart:js via the import chain package:js_wrapping/js_wrapping.dart->package:js_wrapping/adapter/js_map.dart->dart:js

Package not compatible with runtime flutter-native of macos

Because of the import of dart:js via the import chain package:js_wrapping/js_wrapping.dart->package:js_wrapping/adapter/js_map.dart->dart:js

Package not compatible with runtime flutter-native of windows

Because of the import of dart:js via the import chain package:js_wrapping/js_wrapping.dart->package:js_wrapping/adapter/js_map.dart->dart:js

Package not compatible with runtime native-aot

Because of the import of dart:js via the import chain package:js_wrapping/js_wrapping.dart->package:js_wrapping/adapter/js_map.dart->dart:js

Package not compatible with runtime native-jit

Because of the import of dart:js via the import chain package:js_wrapping/js_wrapping.dart->package:js_wrapping/adapter/js_map.dart->dart:js

Maintenance suggestions

Package is getting outdated. (-93.15 points)

The package was last published 100 weeks ago.

Maintain an example. (-10 points)

Create a short demo in the example/ directory to show how to use this package.

Common filename patterns include main.dart, example.dart, and js_wrapping.dart. Packages with multiple examples should provide example/README.md.

For more information see the pub package layout conventions.

Dependencies

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