mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:39:49 +00:00
17f80f0d1f
This tests static analysis on the ddc patch, but not the dart2js one yet. It also fixes js/null_test.dart to ensure it passes. Note, that test was broken independent of NNBD. Change-Id: I5a6bfdfaac845eaba6f154d30f2c1e30199574d0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/131300 Commit-Queue: Vijay Menon <vsm@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
234 lines
8.8 KiB
Dart
234 lines
8.8 KiB
Dart
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
/// Low-level support for interoperating with JavaScript.
|
|
///
|
|
/// You should usually use `package:js` instead of this library. For more
|
|
/// information, see the [JS interop page](https://dart.dev/web/js-interop).
|
|
///
|
|
/// This library provides access to JavaScript objects from Dart, allowing
|
|
/// Dart code to get and set properties, and call methods of JavaScript objects
|
|
/// and invoke JavaScript functions. The library takes care of converting
|
|
/// between Dart and JavaScript objects where possible, or providing proxies if
|
|
/// conversion isn't possible.
|
|
///
|
|
/// This library does not make Dart objects usable from JavaScript, their
|
|
/// methods and properties are not accessible, though it does allow Dart
|
|
/// functions to be passed into and called from JavaScript.
|
|
///
|
|
/// [JsObject] is the core type and represents a proxy of a JavaScript object.
|
|
/// JsObject gives access to the underlying JavaScript objects properties and
|
|
/// methods. `JsObject`s can be acquired by calls to JavaScript, or they can be
|
|
/// created from proxies to JavaScript constructors.
|
|
///
|
|
/// The top-level getter [context] provides a [JsObject] that represents the
|
|
/// global object in JavaScript, usually `window`.
|
|
///
|
|
/// The following example shows an alert dialog via a JavaScript call to the
|
|
/// global function `alert()`:
|
|
///
|
|
/// import 'dart:js';
|
|
///
|
|
/// main() => context.callMethod('alert', ['Hello from Dart!']);
|
|
///
|
|
/// This example shows how to create a [JsObject] from a JavaScript constructor
|
|
/// and access its properties:
|
|
///
|
|
/// import 'dart:js';
|
|
///
|
|
/// main() {
|
|
/// var object = JsObject(context['Object']);
|
|
/// object['greeting'] = 'Hello';
|
|
/// object['greet'] = (name) => "${object['greeting']} $name";
|
|
/// var message = object.callMethod('greet', ['JavaScript']);
|
|
/// context['console'].callMethod('log', [message]);
|
|
/// }
|
|
///
|
|
/// ## Proxying and automatic conversion
|
|
///
|
|
/// When setting properties on a JsObject or passing arguments to a Javascript
|
|
/// method or function, Dart objects are automatically converted or proxied to
|
|
/// JavaScript objects. When accessing JavaScript properties, or when a Dart
|
|
/// closure is invoked from JavaScript, the JavaScript objects are also
|
|
/// converted to Dart.
|
|
///
|
|
/// Functions and closures are proxied in such a way that they are callable. A
|
|
/// Dart closure assigned to a JavaScript property is proxied by a function in
|
|
/// JavaScript. A JavaScript function accessed from Dart is proxied by a
|
|
/// [JsFunction], which has a [JsFunction.apply] method to invoke it.
|
|
///
|
|
/// The following types are transferred directly and not proxied:
|
|
///
|
|
/// * Basic types: `null`, `bool`, `num`, `String`, `DateTime`
|
|
/// * `TypedData`, including its subclasses like `Int32List`, but _not_
|
|
/// `ByteBuffer`
|
|
/// * When compiling for the web, also: `Blob`, `Event`, `ImageData`,
|
|
/// `KeyRange`, `Node`, and `Window`.
|
|
///
|
|
/// ## Converting collections with JsObject.jsify()
|
|
///
|
|
/// To create a JavaScript collection from a Dart collection use the
|
|
/// [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s
|
|
/// into JavaScript Objects and Arrays.
|
|
///
|
|
/// The following expression creates a new JavaScript object with the properties
|
|
/// `a` and `b` defined:
|
|
///
|
|
/// var jsMap = JsObject.jsify({'a': 1, 'b': 2});
|
|
///
|
|
/// This expression creates a JavaScript array:
|
|
///
|
|
/// var jsArray = JsObject.jsify([1, 2, 3]);
|
|
///
|
|
/// {@category Web}
|
|
library dart.js;
|
|
|
|
import 'dart:collection' show ListMixin;
|
|
|
|
/// The JavaScript global object, usually `window`.
|
|
external JsObject get context;
|
|
|
|
/// A proxy on a JavaScript object.
|
|
///
|
|
/// The properties of the JavaScript object are accessible via the `[]` and
|
|
/// `[]=` operators. Methods are callable via [callMethod].
|
|
class JsObject {
|
|
/// Constructs a JavaScript object from its native [constructor] and returns
|
|
/// a proxy to it.
|
|
external factory JsObject(JsFunction constructor, [List? arguments]);
|
|
|
|
/// Constructs a [JsObject] that proxies a native Dart object; _for expert use
|
|
/// only_.
|
|
///
|
|
/// Use this constructor only if you wish to get access to JavaScript
|
|
/// properties attached to a browser host object, such as a Node or Blob, that
|
|
/// is normally automatically converted into a native Dart object.
|
|
///
|
|
/// An exception will be thrown if [object] has the type
|
|
/// `bool`, `num`, or `String`.
|
|
external factory JsObject.fromBrowserObject(Object object);
|
|
|
|
/// Recursively converts a JSON-like collection of Dart objects to a
|
|
/// collection of JavaScript objects and returns a [JsObject] proxy to it.
|
|
///
|
|
/// [object] must be a [Map] or [Iterable], the contents of which are also
|
|
/// converted. Maps and Iterables are copied to a new JavaScript object.
|
|
/// Primitives and other transferable values are directly converted to their
|
|
/// JavaScript type, and all other objects are proxied.
|
|
external factory JsObject.jsify(Object object);
|
|
|
|
/// Returns the value associated with [property] from the proxied JavaScript
|
|
/// object.
|
|
///
|
|
/// The type of [property] must be either [String] or [num].
|
|
external dynamic operator [](Object property);
|
|
|
|
// Sets the value associated with [property] on the proxied JavaScript
|
|
// object.
|
|
//
|
|
// The type of [property] must be either [String] or [num].
|
|
external void operator []=(Object property, Object? value);
|
|
|
|
int get hashCode => 0;
|
|
|
|
external bool operator ==(Object other);
|
|
|
|
/// Returns `true` if the JavaScript object contains the specified property
|
|
/// either directly or though its prototype chain.
|
|
///
|
|
/// This is the equivalent of the `in` operator in JavaScript.
|
|
external bool hasProperty(Object property);
|
|
|
|
/// Removes [property] from the JavaScript object.
|
|
///
|
|
/// This is the equivalent of the `delete` operator in JavaScript.
|
|
external void deleteProperty(Object property);
|
|
|
|
/// Returns `true` if the JavaScript object has [type] in its prototype chain.
|
|
///
|
|
/// This is the equivalent of the `instanceof` operator in JavaScript.
|
|
external bool instanceof(JsFunction type);
|
|
|
|
/// Returns the result of the JavaScript objects `toString` method.
|
|
external String toString();
|
|
|
|
/// Calls [method] on the JavaScript object with the arguments [args] and
|
|
/// returns the result.
|
|
///
|
|
/// The type of [method] must be either [String] or [num].
|
|
external dynamic callMethod(Object method, [List? args]);
|
|
}
|
|
|
|
/// A proxy on a JavaScript Function object.
|
|
class JsFunction extends JsObject {
|
|
/// Returns a [JsFunction] that captures its 'this' binding and calls [f]
|
|
/// with the value of JavaScript `this` passed as the first argument.
|
|
external factory JsFunction.withThis(Function f);
|
|
|
|
/// Invokes the JavaScript function with arguments [args]. If [thisArg] is
|
|
/// supplied it is the value of `this` for the invocation.
|
|
external dynamic apply(List args, {thisArg});
|
|
}
|
|
|
|
/// A [List] that proxies a JavaScript array.
|
|
class JsArray<E> extends JsObject with ListMixin<E> {
|
|
/// Creates an empty JavaScript array.
|
|
external factory JsArray();
|
|
|
|
/// Creates a new JavaScript array and initializes it to the contents of
|
|
/// [other].
|
|
external factory JsArray.from(Iterable<E> other);
|
|
|
|
// Methods required by ListMixin
|
|
|
|
external E operator [](Object index);
|
|
|
|
external void operator []=(Object index, E value);
|
|
|
|
external int get length;
|
|
|
|
external void set length(int length);
|
|
|
|
// Methods overridden for better performance
|
|
|
|
external void add(E value);
|
|
|
|
external void addAll(Iterable<E> iterable);
|
|
|
|
external void insert(int index, E element);
|
|
|
|
external E removeAt(int index);
|
|
|
|
external E removeLast();
|
|
|
|
external void removeRange(int start, int end);
|
|
|
|
external void setRange(int start, int end, Iterable<E> iterable,
|
|
[int skipCount = 0]);
|
|
|
|
external void sort([int compare(E a, E b)?]);
|
|
}
|
|
|
|
/// Returns a wrapper around function [f] that can be called from JavaScript
|
|
/// using `package:js` JavaScript interop.
|
|
///
|
|
/// The calling conventions in Dart2Js differ from JavaScript and so, by
|
|
/// default, it is not possible to call a Dart function directly. Wrapping with
|
|
/// `allowInterop` creates a function that can be called from JavaScript or
|
|
/// Dart. The semantics of the wrapped function are still more strict than
|
|
/// JavaScript, and the function will throw if called with too many or too few
|
|
/// arguments.
|
|
///
|
|
/// Calling this method repeatedly on a function will return the same result.
|
|
external F allowInterop<F extends Function>(F f);
|
|
|
|
/// Returns a wrapper around function [f] that can be called from JavaScript
|
|
/// using `package:js` JavaScript interop, passing JavaScript `this` as the first
|
|
/// argument.
|
|
///
|
|
/// See [allowInterop].
|
|
///
|
|
/// When called from Dart, [null] will be passed as the first argument.
|
|
external Function allowInteropCaptureThis(Function f);
|