[dart:html] Modify scripts to always use NNBD

Since the sdk has been unforked, scripts should be updated to
generate files by always using NNBD. As such, nnbd_src has been
moved to src and the old src has been deleted. This does not address
the nnbd tokens e.g. $NULLABLE. That will be done in a future CL.

Change-Id: I00bead16a9d19569b07ad0601f581fc14400fdce
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151864
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Srujan Gaddam <srujzs@google.com>
This commit is contained in:
Srujan Gaddam
2020-06-23 23:17:35 +00:00
committed by commit-bot@chromium.org
parent 4993179a62
commit b5470ae013
60 changed files with 278 additions and 7336 deletions
-299
View File
@@ -1,299 +0,0 @@
// Copyright (c) 2012, 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.
part of html;
abstract class _AttributeMap extends MapBase<String, String> {
final Element _element;
_AttributeMap(this._element);
void addAll(Map<String, String> other) {
other.forEach((k, v) {
this[k] = v;
});
}
Map<K, V> cast<K, V>() => Map.castFrom<String, String, K, V>(this);
bool containsValue(Object? value) {
for (var v in this.values) {
if (value == v) {
return true;
}
}
return false;
}
String putIfAbsent(String key, String ifAbsent()) {
if (!containsKey(key)) {
this[key] = ifAbsent();
}
return this[key] as String;
}
void clear() {
for (var key in keys) {
remove(key);
}
}
void forEach(void f(String key, String value)) {
for (var key in keys) {
var value = this[key];
f(key, value as String);
}
}
Iterable<String> get keys {
// TODO: generate a lazy collection instead.
var attributes = _element._attributes;
var keys = <String>[];
for (int i = 0, len = attributes.length; i < len; i++) {
_Attr attr = attributes[i] as _Attr;
if (_matches(attr)) {
keys.add(attr.name);
}
}
return keys;
}
Iterable<String> get values {
// TODO: generate a lazy collection instead.
var attributes = _element._attributes;
var values = <String>[];
for (int i = 0, len = attributes.length; i < len; i++) {
_Attr attr = attributes[i] as _Attr;
if (_matches(attr)) {
values.add(attr.value);
}
}
return values;
}
/**
* Returns true if there is no {key, value} pair in the map.
*/
bool get isEmpty {
return length == 0;
}
/**
* Returns true if there is at least one {key, value} pair in the map.
*/
bool get isNotEmpty => !isEmpty;
/**
* Checks to see if the node should be included in this map.
*/
bool _matches(_Attr node);
}
/**
* Wrapper to expose [Element.attributes] as a typed map.
*/
class _ElementAttributeMap extends _AttributeMap {
_ElementAttributeMap(Element element) : super(element);
bool containsKey(Object? key) {
return key is String && _element._hasAttribute(key);
}
String? operator [](Object? key) {
return _element.getAttribute(key as String);
}
void operator []=(String key, String value) {
_element.setAttribute(key, value);
}
@pragma('dart2js:tryInline')
String? remove(Object? key) => key is String ? _remove(_element, key) : null;
/**
* The number of {key, value} pairs in the map.
*/
int get length {
return keys.length;
}
bool _matches(_Attr node) => node._namespaceUri == null;
// Inline this because almost all call sites of [remove] do not use [value],
// and the annotations on the `getAttribute` call allow it to be removed.
@pragma('dart2js:tryInline')
static String? _remove(Element element, String key) {
String? value = JS(
// throws:null(1) is not accurate since [key] could be malformed, but
// [key] is checked again by `removeAttributeNS`.
'returns:String|Null;depends:all;effects:none;throws:null(1)',
'#.getAttribute(#)',
element,
key);
JS('', '#.removeAttribute(#)', element, key);
return value;
}
}
/**
* Wrapper to expose namespaced attributes as a typed map.
*/
class _NamespacedAttributeMap extends _AttributeMap {
final String? _namespace;
_NamespacedAttributeMap(Element element, this._namespace) : super(element);
bool containsKey(Object? key) {
return key is String && _element._hasAttributeNS(_namespace, key);
}
String? operator [](Object? key) {
return _element.getAttributeNS(_namespace, key as String);
}
void operator []=(String key, String value) {
_element.setAttributeNS(_namespace, key, value);
}
@pragma('dart2js:tryInline')
String? remove(Object? key) =>
key is String ? _remove(_namespace, _element, key) : null;
/**
* The number of {key, value} pairs in the map.
*/
int get length {
return keys.length;
}
bool _matches(_Attr node) => node._namespaceUri == _namespace;
// Inline this because almost all call sites of [remove] do not use the
// returned [value], and the annotations on the `getAttributeNS` call allow it
// to be removed.
@pragma('dart2js:tryInline')
static String? _remove(String? namespace, Element element, String key) {
String? value = JS(
// throws:null(1) is not accurate since [key] could be malformed, but
// [key] is checked again by `removeAttributeNS`.
'returns:String|Null;depends:all;effects:none;throws:null(1)',
'#.getAttributeNS(#, #)',
element,
namespace,
key);
JS('', '#.removeAttributeNS(#, #)', element, namespace, key);
return value;
}
}
/**
* Provides a Map abstraction on top of data-* attributes, similar to the
* dataSet in the old DOM.
*/
class _DataAttributeMap extends MapBase<String, String> {
final Map<String, String> _attributes;
_DataAttributeMap(this._attributes);
// interface Map
void addAll(Map<String, String> other) {
other.forEach((k, v) {
this[k] = v;
});
}
Map<K, V> cast<K, V>() => Map.castFrom<String, String, K, V>(this);
// TODO: Use lazy iterator when it is available on Map.
bool containsValue(Object? value) => values.any((v) => v == value);
bool containsKey(Object? key) =>
_attributes.containsKey(_attr(key as String));
String? operator [](Object? key) => _attributes[_attr(key as String)];
void operator []=(String key, String value) {
_attributes[_attr(key)] = value;
}
String putIfAbsent(String key, String ifAbsent()) =>
_attributes.putIfAbsent(_attr(key), ifAbsent);
String? remove(Object? key) => _attributes.remove(_attr(key as String));
void clear() {
// Needs to operate on a snapshot since we are mutating the collection.
for (String key in keys) {
remove(key);
}
}
void forEach(void f(String key, String value)) {
_attributes.forEach((String key, String value) {
if (_matches(key)) {
f(_strip(key), value);
}
});
}
Iterable<String> get keys {
final keys = <String>[];
_attributes.forEach((String key, String value) {
if (_matches(key)) {
keys.add(_strip(key));
}
});
return keys;
}
Iterable<String> get values {
final values = <String>[];
_attributes.forEach((String key, String value) {
if (_matches(key)) {
values.add(value);
}
});
return values;
}
int get length => keys.length;
// TODO: Use lazy iterator when it is available on Map.
bool get isEmpty => length == 0;
bool get isNotEmpty => !isEmpty;
// Helpers.
String _attr(String key) => 'data-${_toHyphenedName(key)}';
bool _matches(String key) => key.startsWith('data-');
String _strip(String key) => _toCamelCase(key.substring(5));
/**
* Converts a string name with hyphens into an identifier, by removing hyphens
* and capitalizing the following letter. Optionally [startUppercase] to
* capitalize the first letter.
*/
String _toCamelCase(String hyphenedName, {bool startUppercase: false}) {
var segments = hyphenedName.split('-');
int start = startUppercase ? 0 : 1;
for (int i = start; i < segments.length; i++) {
var segment = segments[i];
if (segment.length > 0) {
// Character between 'a'..'z' mapped to 'A'..'Z'
segments[i] = '${segment[0].toUpperCase()}${segment.substring(1)}';
}
}
return segments.join('');
}
/** Reverse of [toCamelCase]. */
String _toHyphenedName(String word) {
var sb = new StringBuffer();
for (int i = 0; i < word.length; i++) {
var lower = word[i].toLowerCase();
if (word[i] != lower && i > 0) sb.write('-');
sb.write(lower);
}
return sb.toString();
}
}
-42
View File
@@ -1,42 +0,0 @@
// Copyright (c) 2012, 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.
part of html;
/**
* An object that can be drawn to a 2D canvas rendering context.
*
* The image drawn to the canvas depends on the type of this object:
*
* * If this object is an [ImageElement], then this element's image is
* drawn to the canvas. If this element is an animated image, then this
* element's poster frame is drawn. If this element has no poster frame, then
* the first frame of animation is drawn.
*
* * If this object is a [VideoElement], then the frame at this element's current
* playback position is drawn to the canvas.
*
* * If this object is a [CanvasElement], then this element's bitmap is drawn to
* the canvas.
*
* **Note:** Currently all versions of Internet Explorer do not support
* drawing a video element to a canvas. You may also encounter problems drawing
* a video to a canvas in Firefox if the source of the video is a data URL.
*
* ## See also
*
* * [CanvasRenderingContext2D.drawImage]
* * [CanvasRenderingContext2D.drawImageToRect]
* * [CanvasRenderingContext2D.drawImageScaled]
* * [CanvasRenderingContext2D.drawImageScaledFromSource]
*
* ## Other resources
*
* * [Image sources for 2D rendering
* contexts](https://html.spec.whatwg.org/multipage/scripting.html#image-sources-for-2d-rendering-contexts)
* from WHATWG.
* * [Drawing images](https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-drawimage)
* from WHATWG.
*/
abstract class CanvasImageSource {}
-156
View File
@@ -1,156 +0,0 @@
// Copyright (c) 2012, 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.
part of html;
/**
* Top-level container for a browser tab or window.
*
* In a web browser, a [WindowBase] object represents any browser window. This
* object contains the window's state and its relation to other
* windows, such as which window opened this window.
*
* **Note:** This class represents any window, while [Window] is
* used to access the properties and content of the current window or tab.
*
* ## See also
*
* * [Window]
*
* ## Other resources
*
* * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.
* * [Window](http://www.w3.org/TR/Window/) from the W3C.
*/
abstract class WindowBase implements EventTarget {
// Fields.
/**
* The current location of this window.
*
* Location currentLocation = window.location;
* print(currentLocation.href); // 'http://www.example.com:80/'
*/
LocationBase get location;
/**
* The current session history for this window.
*
* ## Other resources
*
* * [Session history and navigation
* specification](https://html.spec.whatwg.org/multipage/browsers.html#history)
* from WHATWG.
*/
HistoryBase get history;
/**
* Indicates whether this window has been closed.
*
* print(window.closed); // 'false'
* window.close();
* print(window.closed); // 'true'
*/
bool get closed;
/**
* A reference to the window that opened this one.
*
* Window thisWindow = window;
* WindowBase otherWindow = thisWindow.open('http://www.example.com/', 'foo');
* print(otherWindow.opener == thisWindow); // 'true'
*/
WindowBase? get opener;
/**
* A reference to the parent of this window.
*
* If this [WindowBase] has no parent, [parent] will return a reference to
* the [WindowBase] itself.
*
* IFrameElement myIFrame = new IFrameElement();
* window.document.body.elements.add(myIFrame);
* print(myIframe.contentWindow.parent == window) // 'true'
*
* print(window.parent == window) // 'true'
*/
WindowBase? get parent;
/**
* A reference to the topmost window in the window hierarchy.
*
* If this [WindowBase] is the topmost [WindowBase], [top] will return a
* reference to the [WindowBase] itself.
*
* // Add an IFrame to the current window.
* IFrameElement myIFrame = new IFrameElement();
* window.document.body.elements.add(myIFrame);
*
* // Add an IFrame inside of the other IFrame.
* IFrameElement innerIFrame = new IFrameElement();
* myIFrame.elements.add(innerIFrame);
*
* print(myIframe.contentWindow.top == window) // 'true'
* print(innerIFrame.contentWindow.top == window) // 'true'
*
* print(window.top == window) // 'true'
*/
WindowBase? get top;
// Methods.
/**
* Closes the window.
*
* This method should only succeed if the [WindowBase] object is
* **script-closeable** and the window calling [close] is allowed to navigate
* the window.
*
* A window is script-closeable if it is either a window
* that was opened by another window, or if it is a window with only one
* document in its history.
*
* A window might not be allowed to navigate, and therefore close, another
* window due to browser security features.
*
* var other = window.open('http://www.example.com', 'foo');
* // Closes other window, as it is script-closeable.
* other.close();
* print(other.closed); // 'true'
*
* var newLocation = window.location
* ..href = 'http://www.mysite.com';
* window.location = newLocation;
* // Does not close this window, as the history has changed.
* window.close();
* print(window.closed); // 'false'
*
* See also:
*
* * [Window close discussion](http://www.w3.org/TR/html5/browsers.html#dom-window-close) from the W3C
*/
void close();
/**
* Sends a cross-origin message.
*
* ## Other resources
*
* * [window.postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage)
* from MDN.
* * [Cross-document messaging](https://html.spec.whatwg.org/multipage/comms.html#web-messaging)
* from WHATWG.
*/
void postMessage(var message, String targetOrigin,
[List<MessagePort>? messagePorts]);
}
abstract class LocationBase {
void set href(String val);
}
abstract class HistoryBase {
void back();
void forward();
void go(int distance);
}
-113
View File
@@ -1,113 +0,0 @@
// Copyright (c) 2012, 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.
part of html;
/** A Set that stores the CSS class names for an element. */
abstract class CssClassSet implements Set<String> {
/**
* Adds the class [value] to the element if it is not on it, removes it if it
* is.
*
* If [shouldAdd] is true, then we always add that [value] to the element. If
* [shouldAdd] is false then we always remove [value] from the element.
*
* If this corresponds to one element, returns `true` if [value] is present
* after the operation, and returns `false` if [value] is absent after the
* operation.
*
* If this CssClassSet corresponds to many elements, `false` is always
* returned.
*
* [value] must be a valid 'token' representing a single class, i.e. a
* non-empty string containing no whitespace. To toggle multiple classes, use
* [toggleAll].
*/
bool toggle(String value, [bool? shouldAdd]);
/**
* Returns [:true:] if classes cannot be added or removed from this
* [:CssClassSet:].
*/
bool get frozen;
/**
* Determine if this element contains the class [value].
*
* This is the Dart equivalent of jQuery's
* [hasClass](http://api.jquery.com/hasClass/).
*
* [value] must be a valid 'token' representing a single class, i.e. a
* non-empty string containing no whitespace.
*/
bool contains(Object? value);
/**
* Add the class [value] to element.
*
* [add] and [addAll] are the Dart equivalent of jQuery's
* [addClass](http://api.jquery.com/addClass/).
*
* If this CssClassSet corresponds to one element. Returns true if [value] was
* added to the set, otherwise false.
*
* If this CssClassSet corresponds to many elements, `false` is always
* returned.
*
* [value] must be a valid 'token' representing a single class, i.e. a
* non-empty string containing no whitespace. To add multiple classes use
* [addAll].
*/
bool add(String value);
/**
* Remove the class [value] from element, and return true on successful
* removal.
*
* [remove] and [removeAll] are the Dart equivalent of jQuery's
* [removeClass](http://api.jquery.com/removeClass/).
*
* [value] must be a valid 'token' representing a single class, i.e. a
* non-empty string containing no whitespace. To remove multiple classes, use
* [removeAll].
*/
bool remove(Object? value);
/**
* Add all classes specified in [iterable] to element.
*
* [add] and [addAll] are the Dart equivalent of jQuery's
* [addClass](http://api.jquery.com/addClass/).
*
* Each element of [iterable] must be a valid 'token' representing a single
* class, i.e. a non-empty string containing no whitespace.
*/
void addAll(Iterable<String> iterable);
/**
* Remove all classes specified in [iterable] from element.
*
* [remove] and [removeAll] are the Dart equivalent of jQuery's
* [removeClass](http://api.jquery.com/removeClass/).
*
* Each element of [iterable] must be a valid 'token' representing a single
* class, i.e. a non-empty string containing no whitespace.
*/
void removeAll(Iterable<Object?> iterable);
/**
* Toggles all classes specified in [iterable] on element.
*
* Iterate through [iterable]'s items, and add it if it is not on it, or
* remove it if it is. This is the Dart equivalent of jQuery's
* [toggleClass](http://api.jquery.com/toggleClass/).
* If [shouldAdd] is true, then we always add all the classes in [iterable]
* element. If [shouldAdd] is false then we always remove all the classes in
* [iterable] from the element.
*
* Each element of [iterable] must be a valid 'token' representing a single
* class, i.e. a non-empty string containing no whitespace.
*/
void toggleAll(Iterable<String> iterable, [bool? shouldAdd]);
}
-372
View File
@@ -1,372 +0,0 @@
// 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.
part of html;
/**
* A rectangle representing all the content of the element in the
* [box model](http://www.w3.org/TR/CSS2/box.html).
*/
class _ContentCssRect extends CssRect {
_ContentCssRect(Element element) : super(element);
num get height =>
_element.offsetHeight + _addOrSubtractToBoxModel(_HEIGHT, _CONTENT);
num get width =>
_element.offsetWidth + _addOrSubtractToBoxModel(_WIDTH, _CONTENT);
/**
* Set the height to `newHeight`.
*
* newHeight can be either a [num] representing the height in pixels or a
* [Dimension] object. Values of newHeight that are less than zero are
* converted to effectively setting the height to 0. This is equivalent to the
* `height` function in jQuery and the calculated `height` CSS value,
* converted to a num in pixels.
*/
set height(dynamic newHeight) {
if (newHeight is Dimension) {
Dimension newHeightAsDimension = newHeight;
if (newHeightAsDimension.value < 0) newHeight = new Dimension.px(0);
_element.style.height = newHeight.toString();
} else if (newHeight is num) {
if (newHeight < 0) newHeight = 0;
_element.style.height = '${newHeight}px';
} else {
throw new ArgumentError("newHeight is not a Dimension or num");
}
}
/**
* Set the current computed width in pixels of this element.
*
* newWidth can be either a [num] representing the width in pixels or a
* [Dimension] object. This is equivalent to the `width` function in jQuery
* and the calculated
* `width` CSS value, converted to a dimensionless num in pixels.
*/
set width(dynamic newWidth) {
if (newWidth is Dimension) {
Dimension newWidthAsDimension = newWidth;
if (newWidthAsDimension.value < 0) newWidth = new Dimension.px(0);
_element.style.width = newWidth.toString();
} else if (newWidth is num) {
if (newWidth < 0) newWidth = 0;
_element.style.width = '${newWidth}px';
} else {
throw new ArgumentError("newWidth is not a Dimension or num");
}
}
num get left =>
_element.getBoundingClientRect().left -
_addOrSubtractToBoxModel(['left'], _CONTENT);
num get top =>
_element.getBoundingClientRect().top -
_addOrSubtractToBoxModel(['top'], _CONTENT);
}
/**
* A list of element content rectangles in the
* [box model](http://www.w3.org/TR/CSS2/box.html).
*/
class _ContentCssListRect extends _ContentCssRect {
List<Element> _elementList;
_ContentCssListRect(List<Element> elementList)
: _elementList = elementList,
super(elementList.first);
/**
* Set the height to `newHeight`.
*
* Values of newHeight that are less than zero are converted to effectively
* setting the height to 0. This is equivalent to the `height`
* function in jQuery and the calculated `height` CSS value, converted to a
* num in pixels.
*/
set height(newHeight) {
_elementList.forEach((e) => e.contentEdge.height = newHeight);
}
/**
* Set the current computed width in pixels of this element.
*
* This is equivalent to the `width` function in jQuery and the calculated
* `width` CSS value, converted to a dimensionless num in pixels.
*/
set width(newWidth) {
_elementList.forEach((e) => e.contentEdge.width = newWidth);
}
}
/**
* A rectangle representing the dimensions of the space occupied by the
* element's content + padding in the
* [box model](http://www.w3.org/TR/CSS2/box.html).
*/
class _PaddingCssRect extends CssRect {
_PaddingCssRect(element) : super(element);
num get height =>
_element.offsetHeight + _addOrSubtractToBoxModel(_HEIGHT, _PADDING);
num get width =>
_element.offsetWidth + _addOrSubtractToBoxModel(_WIDTH, _PADDING);
num get left =>
_element.getBoundingClientRect().left -
_addOrSubtractToBoxModel(['left'], _PADDING);
num get top =>
_element.getBoundingClientRect().top -
_addOrSubtractToBoxModel(['top'], _PADDING);
}
/**
* A rectangle representing the dimensions of the space occupied by the
* element's content + padding + border in the
* [box model](http://www.w3.org/TR/CSS2/box.html).
*/
class _BorderCssRect extends CssRect {
_BorderCssRect(element) : super(element);
num get height => _element.offsetHeight;
num get width => _element.offsetWidth;
num get left => _element.getBoundingClientRect().left;
num get top => _element.getBoundingClientRect().top;
}
/**
* A rectangle representing the dimensions of the space occupied by the
* element's content + padding + border + margin in the
* [box model](http://www.w3.org/TR/CSS2/box.html).
*/
class _MarginCssRect extends CssRect {
_MarginCssRect(element) : super(element);
num get height =>
_element.offsetHeight + _addOrSubtractToBoxModel(_HEIGHT, _MARGIN);
num get width =>
_element.offsetWidth + _addOrSubtractToBoxModel(_WIDTH, _MARGIN);
num get left =>
_element.getBoundingClientRect().left -
_addOrSubtractToBoxModel(['left'], _MARGIN);
num get top =>
_element.getBoundingClientRect().top -
_addOrSubtractToBoxModel(['top'], _MARGIN);
}
/**
* A class for representing CSS dimensions.
*
* In contrast to the more general purpose [Rectangle] class, this class's
* values are mutable, so one can change the height of an element
* programmatically.
*
* _Important_ _note_: use of these methods will perform CSS calculations that
* can trigger a browser reflow. Therefore, use of these properties _during_ an
* animation frame is discouraged. See also:
* [Browser Reflow](https://developers.google.com/speed/articles/reflow)
*/
abstract class CssRect implements Rectangle<num> {
Element _element;
CssRect(this._element);
num get left;
num get top;
/**
* The height of this rectangle.
*
* This is equivalent to the `height` function in jQuery and the calculated
* `height` CSS value, converted to a dimensionless num in pixels. Unlike
* [getBoundingClientRect], `height` will return the same numerical width if
* the element is hidden or not.
*/
num get height;
/**
* The width of this rectangle.
*
* This is equivalent to the `width` function in jQuery and the calculated
* `width` CSS value, converted to a dimensionless num in pixels. Unlike
* [getBoundingClientRect], `width` will return the same numerical width if
* the element is hidden or not.
*/
num get width;
/**
* Set the height to `newHeight`.
*
* newHeight can be either a [num] representing the height in pixels or a
* [Dimension] object. Values of newHeight that are less than zero are
* converted to effectively setting the height to 0. This is equivalent to the
* `height` function in jQuery and the calculated `height` CSS value,
* converted to a num in pixels.
*
* Note that only the content height can actually be set via this method.
*/
set height(dynamic newHeight) {
throw new UnsupportedError("Can only set height for content rect.");
}
/**
* Set the current computed width in pixels of this element.
*
* newWidth can be either a [num] representing the width in pixels or a
* [Dimension] object. This is equivalent to the `width` function in jQuery
* and the calculated
* `width` CSS value, converted to a dimensionless num in pixels.
*
* Note that only the content width can be set via this method.
*/
set width(dynamic newWidth) {
throw new UnsupportedError("Can only set width for content rect.");
}
/**
* Return a value that is used to modify the initial height or width
* measurement of an element. Depending on the value (ideally an enum) passed
* to augmentingMeasurement, we may need to add or subtract margin, padding,
* or border values, depending on the measurement we're trying to obtain.
*/
num _addOrSubtractToBoxModel(
List<String> dimensions, String augmentingMeasurement) {
// getComputedStyle always returns pixel values (hence, computed), so we're
// always dealing with pixels in this method.
var styles = _element.getComputedStyle();
num val = 0;
for (String measurement in dimensions) {
// The border-box and default box model both exclude margin in the regular
// height/width calculation, so add it if we want it for this measurement.
if (augmentingMeasurement == _MARGIN) {
val += new Dimension.css(
styles.getPropertyValue('$augmentingMeasurement-$measurement'))
.value;
}
// The border-box includes padding and border, so remove it if we want
// just the content itself.
if (augmentingMeasurement == _CONTENT) {
val -= new Dimension.css(
styles.getPropertyValue('${_PADDING}-$measurement'))
.value;
}
// At this point, we don't wan't to augment with border or margin,
// so remove border.
if (augmentingMeasurement != _MARGIN) {
val -= new Dimension.css(
styles.getPropertyValue('border-${measurement}-width'))
.value;
}
}
return val;
}
// TODO(jacobr): these methods are duplicated from _RectangleBase in dart:math
// Ideally we would provide a RectangleMixin class that provides this
// implementation. In an ideal world we would exp
/** The x-coordinate of the right edge. */
num get right => left + width;
/** The y-coordinate of the bottom edge. */
num get bottom => top + height;
String toString() {
return 'Rectangle ($left, $top) $width x $height';
}
bool operator ==(other) =>
other is Rectangle &&
left == other.left &&
top == other.top &&
right == other.right &&
bottom == other.bottom;
int get hashCode => _JenkinsSmiHash.hash4(
left.hashCode, top.hashCode, right.hashCode, bottom.hashCode);
/**
* Computes the intersection of `this` and [other].
*
* The intersection of two axis-aligned rectangles, if any, is always another
* axis-aligned rectangle.
*
* Returns the intersection of this and `other`, or `null` if they don't
* intersect.
*/
Rectangle<num>? intersection(Rectangle<num> other) {
var x0 = max(left, other.left);
var x1 = min(left + width, other.left + other.width);
if (x0 <= x1) {
var y0 = max(top, other.top);
var y1 = min(top + height, other.top + other.height);
if (y0 <= y1) {
return new Rectangle<num>(x0, y0, x1 - x0, y1 - y0);
}
}
return null;
}
/**
* Returns true if `this` intersects [other].
*/
bool intersects(Rectangle<num> other) {
return (left <= other.left + other.width &&
other.left <= left + width &&
top <= other.top + other.height &&
other.top <= top + height);
}
/**
* Returns a new rectangle which completely contains `this` and [other].
*/
Rectangle<num> boundingBox(Rectangle<num> other) {
var right = max(this.left + this.width, other.left + other.width);
var bottom = max(this.top + this.height, other.top + other.height);
var left = min(this.left, other.left);
var top = min(this.top, other.top);
return new Rectangle<num>(left, top, right - left, bottom - top);
}
/**
* Tests whether `this` entirely contains [another].
*/
bool containsRectangle(Rectangle<num> another) {
return left <= another.left &&
left + width >= another.left + another.width &&
top <= another.top &&
top + height >= another.top + another.height;
}
/**
* Tests whether [another] is inside or along the edges of `this`.
*/
bool containsPoint(Point<num> another) {
return another.x >= left &&
another.x <= left + width &&
another.y >= top &&
another.y <= top + height;
}
Point<num> get topLeft => new Point<num>(this.left, this.top);
Point<num> get topRight => new Point<num>(this.left + this.width, this.top);
Point<num> get bottomRight =>
new Point<num>(this.left + this.width, this.top + this.height);
Point<num> get bottomLeft =>
new Point<num>(this.left, this.top + this.height);
}
final _HEIGHT = ['top', 'bottom'];
final _WIDTH = ['right', 'left'];
final _CONTENT = 'content';
final _PADDING = 'padding';
final _MARGIN = 'margin';
-84
View File
@@ -1,84 +0,0 @@
part of html;
/**
* Class representing a
* [length measurement](https://developer.mozilla.org/en-US/docs/Web/CSS/length)
* in CSS.
*/
class Dimension {
num _value;
String _unit;
/** Set this CSS Dimension to a percentage `value`. */
Dimension.percent(this._value) : _unit = '%';
/** Set this CSS Dimension to a pixel `value`. */
Dimension.px(this._value) : _unit = 'px';
/** Set this CSS Dimension to a pica `value`. */
Dimension.pc(this._value) : _unit = 'pc';
/** Set this CSS Dimension to a point `value`. */
Dimension.pt(this._value) : _unit = 'pt';
/** Set this CSS Dimension to an inch `value`. */
Dimension.inch(this._value) : _unit = 'in';
/** Set this CSS Dimension to a centimeter `value`. */
Dimension.cm(this._value) : _unit = 'cm';
/** Set this CSS Dimension to a millimeter `value`. */
Dimension.mm(this._value) : _unit = 'mm';
/**
* Set this CSS Dimension to the specified number of ems.
*
* 1em is equal to the current font size. (So 2ems is equal to double the font
* size). This is useful for producing website layouts that scale nicely with
* the user's desired font size.
*/
Dimension.em(this._value) : _unit = 'em';
/**
* Set this CSS Dimension to the specified number of x-heights.
*
* One ex is equal to the x-height of a font's baseline to its mean line,
* generally the height of the letter "x" in the font, which is usually about
* half the font-size.
*/
Dimension.ex(this._value) : _unit = 'ex';
/**
* Construct a Dimension object from the valid, simple CSS string `cssValue`
* that represents a distance measurement.
*
* This constructor is intended as a convenience method for working with
* simplistic CSS length measurements. Non-numeric values such as `auto` or
* `inherit` or invalid CSS will cause this constructor to throw a
* FormatError.
*/
Dimension.css(String cssValue)
: _unit = '',
_value = 0 {
if (cssValue == '') cssValue = '0px';
if (cssValue.endsWith('%')) {
_unit = '%';
} else {
_unit = cssValue.substring(cssValue.length - 2);
}
if (cssValue.contains('.')) {
_value =
double.parse(cssValue.substring(0, cssValue.length - _unit.length));
} else {
_value = int.parse(cssValue.substring(0, cssValue.length - _unit.length));
}
}
/** Print out the CSS String representation of this value. */
String toString() {
return '${_value}${_unit}';
}
/** Return a unitless, numerical value of this CSS value. */
num get value => this._value;
}
-7
View File
@@ -1,7 +0,0 @@
// Copyright (c) 2011, 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.
part of html;
typedef EventListener(Event event);
-461
View File
@@ -1,461 +0,0 @@
// 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.
part of html;
/**
* A factory to expose DOM events as Streams.
*/
class EventStreamProvider<T extends Event> {
final String _eventType;
const EventStreamProvider(this._eventType);
/**
* Gets a [Stream] for this event type, on the specified target.
*
* This will always return a broadcast stream so multiple listeners can be
* used simultaneously.
*
* This may be used to capture DOM events:
*
* Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
*
* // Alternate method:
* Element.keyDownEvent.forTarget(element).capture(...);
*
* Or for listening to an event which will bubble through the DOM tree:
*
* MediaElement.pauseEvent.forTarget(document.body).listen(...);
*
* See also:
*
* * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
* from MDN.
*/
Stream<T> forTarget(EventTarget? e, {bool useCapture: false}) =>
new _EventStream<T>(e, _eventType, useCapture);
/**
* Gets an [ElementEventStream] for this event type, on the specified element.
*
* This will always return a broadcast stream so multiple listeners can be
* used simultaneously.
*
* This may be used to capture DOM events:
*
* Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
*
* // Alternate method:
* Element.keyDownEvent.forElement(element).capture(...);
*
* Or for listening to an event which will bubble through the DOM tree:
*
* MediaElement.pauseEvent.forElement(document.body).listen(...);
*
* See also:
*
* * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
* from MDN.
*/
ElementStream<T> forElement(Element e, {bool useCapture: false}) {
return new _ElementEventStreamImpl<T>(e, _eventType, useCapture);
}
/**
* Gets an [ElementEventStream] for this event type, on the list of elements.
*
* This will always return a broadcast stream so multiple listeners can be
* used simultaneously.
*
* This may be used to capture DOM events:
*
* Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
*
* See also:
*
* * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
* from MDN.
*/
ElementStream<T> _forElementList(ElementList<Element> e,
{bool useCapture: false}) {
return new _ElementListEventStreamImpl<T>(e, _eventType, useCapture);
}
/**
* Gets the type of the event which this would listen for on the specified
* event target.
*
* The target is necessary because some browsers may use different event names
* for the same purpose and the target allows differentiating browser support.
*/
String getEventType(EventTarget target) {
return _eventType;
}
}
/** A specialized Stream available to [Element]s to enable event delegation. */
abstract class ElementStream<T extends Event> implements Stream<T> {
/**
* Return a stream that only fires when the particular event fires for
* elements matching the specified CSS selector.
*
* This is the Dart equivalent to jQuery's
* [delegate](http://api.jquery.com/delegate/).
*/
Stream<T> matches(String selector);
/**
* Adds a capturing subscription to this stream.
*
* If the target of the event is a descendant of the element from which this
* stream derives then [onData] is called before the event propagates down to
* the target. This is the opposite of bubbling behavior, where the event
* is first processed for the event target and then bubbles upward.
*
* ## Other resources
*
* * [Event Capture](http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture)
* from the W3C DOM Events specification.
*/
StreamSubscription<T> capture(void onData(T event));
}
/**
* Adapter for exposing DOM events as Dart streams.
*/
class _EventStream<T extends Event> extends Stream<T> {
final EventTarget? _target;
final String _eventType;
final bool _useCapture;
_EventStream(this._target, this._eventType, this._useCapture);
// DOM events are inherently multi-subscribers.
Stream<T> asBroadcastStream(
{void onListen(StreamSubscription<T> subscription)?,
void onCancel(StreamSubscription<T> subscription)?}) =>
this;
bool get isBroadcast => true;
// TODO(9757): Inlining should be smart and inline only when inlining would
// enable scalar replacement of an immediately allocated receiver.
@pragma('dart2js:tryInline')
StreamSubscription<T> listen(void onData(T event)?,
{Function? onError, void onDone()?, bool? cancelOnError}) {
return new _EventStreamSubscription<T>(
this._target, this._eventType, onData, this._useCapture);
}
}
bool _matchesWithAncestors(Event event, String selector) {
var target = event.target;
return target is Element ? target.matchesWithAncestors(selector) : false;
}
/**
* Adapter for exposing DOM Element events as streams, while also allowing
* event delegation.
*/
class _ElementEventStreamImpl<T extends Event> extends _EventStream<T>
implements ElementStream<T> {
_ElementEventStreamImpl(target, eventType, useCapture)
: super(target, eventType, useCapture);
Stream<T> matches(String selector) =>
this.where((event) => _matchesWithAncestors(event, selector)).map((e) {
e._selector = selector;
return e;
});
StreamSubscription<T> capture(void onData(T event)) =>
new _EventStreamSubscription<T>(
this._target, this._eventType, onData, true);
}
/**
* Adapter for exposing events on a collection of DOM Elements as streams,
* while also allowing event delegation.
*/
class _ElementListEventStreamImpl<T extends Event> extends Stream<T>
implements ElementStream<T> {
final Iterable<Element> _targetList;
final bool _useCapture;
final String _eventType;
_ElementListEventStreamImpl(
this._targetList, this._eventType, this._useCapture);
Stream<T> matches(String selector) =>
this.where((event) => _matchesWithAncestors(event, selector)).map((e) {
e._selector = selector;
return e;
});
// Delegate all regular Stream behavior to a wrapped Stream.
StreamSubscription<T> listen(void onData(T event)?,
{Function? onError, void onDone()?, bool? cancelOnError}) {
var pool = new _StreamPool<T>.broadcast();
for (var target in _targetList) {
pool.add(new _EventStream<T>(target, _eventType, _useCapture));
}
return pool.stream.listen(onData,
onError: onError, onDone: onDone, cancelOnError: cancelOnError);
}
StreamSubscription<T> capture(void onData(T event)) {
var pool = new _StreamPool<T>.broadcast();
for (var target in _targetList) {
pool.add(new _EventStream<T>(target, _eventType, true));
}
return pool.stream.listen(onData);
}
Stream<T> asBroadcastStream(
{void onListen(StreamSubscription<T> subscription)?,
void onCancel(StreamSubscription<T> subscription)?}) =>
this;
bool get isBroadcast => true;
}
// We would like this to just be EventListener<T> but that typdef cannot
// use generics until dartbug/26276 is fixed.
typedef _EventListener<T extends Event>(T event);
class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
int _pauseCount = 0;
EventTarget? _target;
final String _eventType;
EventListener? _onData;
final bool _useCapture;
// TODO(leafp): It would be better to write this as
// _onData = onData == null ? null :
// onData is void Function(Event)
// ? _wrapZone<Event>(onData)
// : _wrapZone<Event>((e) => onData(e as T))
// In order to support existing tests which pass the wrong type of events but
// use a more general listener, without causing as much slowdown for things
// which are typed correctly. But this currently runs afoul of restrictions
// on is checks for compatibility with the VM.
_EventStreamSubscription(
this._target, this._eventType, void onData(T event)?, this._useCapture)
: _onData = onData == null
? null
: _wrapZone<Event>((e) => (onData as dynamic)(e)) {
_tryResume();
}
Future cancel() {
// Check for strong mode. This function can no longer return null in strong
// mode, so only return null in weak mode to preserve synchronous timing.
// See issue 41653 for more details.
dynamic emptyFuture =
typeAcceptsNull<Event>() ? null : Future<void>.value();
if (_canceled) return emptyFuture as Future;
_unlisten();
// Clear out the target to indicate this is complete.
_target = null;
_onData = null;
return emptyFuture as Future;
}
bool get _canceled => _target == null;
void onData(void handleData(T event)?) {
if (_canceled) {
throw new StateError("Subscription has been canceled.");
}
// Remove current event listener.
_unlisten();
_onData = handleData == null
? null
: _wrapZone<Event>((e) => (handleData as dynamic)(e));
_tryResume();
}
/// Has no effect.
void onError(Function? handleError) {}
/// Has no effect.
void onDone(void handleDone()?) {}
void pause([Future? resumeSignal]) {
if (_canceled) return;
++_pauseCount;
_unlisten();
if (resumeSignal != null) {
resumeSignal.whenComplete(resume);
}
}
bool get isPaused => _pauseCount > 0;
void resume() {
if (_canceled || !isPaused) return;
--_pauseCount;
_tryResume();
}
void _tryResume() {
if (_onData != null && !isPaused) {
_target!.addEventListener(_eventType, _onData, _useCapture);
}
}
void _unlisten() {
if (_onData != null) {
_target!.removeEventListener(_eventType, _onData, _useCapture);
}
}
Future<E> asFuture<E>([E? futureValue]) {
// We just need a future that will never succeed or fail.
var completer = new Completer<E>();
return completer.future;
}
}
/**
* A stream of custom events, which enables the user to "fire" (add) their own
* custom events to a stream.
*/
abstract class CustomStream<T extends Event> implements Stream<T> {
/**
* Add the following custom event to the stream for dispatching to interested
* listeners.
*/
void add(T event);
}
class _CustomEventStreamImpl<T extends Event> extends Stream<T>
implements CustomStream<T> {
StreamController<T> _streamController;
/** The type of event this stream is providing (e.g. "keydown"). */
String _type;
_CustomEventStreamImpl(String type)
: _type = type,
_streamController = new StreamController.broadcast(sync: true);
// Delegate all regular Stream behavior to our wrapped Stream.
StreamSubscription<T> listen(void onData(T event)?,
{Function? onError, void onDone()?, bool? cancelOnError}) {
return _streamController.stream.listen(onData,
onError: onError, onDone: onDone, cancelOnError: cancelOnError);
}
Stream<T> asBroadcastStream(
{void onListen(StreamSubscription<T> subscription)?,
void onCancel(StreamSubscription<T> subscription)?}) =>
_streamController.stream;
bool get isBroadcast => true;
void add(T event) {
if (event.type == _type) _streamController.add(event);
}
}
class _CustomKeyEventStreamImpl extends _CustomEventStreamImpl<KeyEvent>
implements CustomStream<KeyEvent> {
_CustomKeyEventStreamImpl(String type) : super(type);
void add(KeyEvent event) {
if (event.type == _type) {
event.currentTarget!.dispatchEvent(event._parent);
_streamController.add(event);
}
}
}
/**
* A pool of streams whose events are unified and emitted through a central
* stream.
*/
// TODO (efortuna): Remove this when Issue 12218 is addressed.
class _StreamPool<T> {
StreamController<T>? _controller;
/// Subscriptions to the streams that make up the pool.
var _subscriptions = new Map<Stream<T>, StreamSubscription<T>>();
/**
* Creates a new stream pool where [stream] can be listened to more than
* once.
*
* Any events from buffered streams in the pool will be emitted immediately,
* regardless of whether [stream] has any subscribers.
*/
_StreamPool.broadcast() {
_controller =
new StreamController<T>.broadcast(sync: true, onCancel: close);
}
/**
* The stream through which all events from streams in the pool are emitted.
*/
Stream<T> get stream => _controller!.stream;
/**
* Adds [stream] as a member of this pool.
*
* Any events from [stream] will be emitted through [this.stream]. If
* [stream] is sync, they'll be emitted synchronously; if [stream] is async,
* they'll be emitted asynchronously.
*/
void add(Stream<T> stream) {
if (_subscriptions.containsKey(stream)) return;
_subscriptions[stream] = stream.listen(_controller!.add,
onError: _controller!.addError, onDone: () => remove(stream));
}
/** Removes [stream] as a member of this pool. */
void remove(Stream<T> stream) {
var subscription = _subscriptions.remove(stream);
if (subscription != null) subscription.cancel();
}
/** Removes all streams from this pool and closes [stream]. */
void close() {
for (var subscription in _subscriptions.values) {
subscription.cancel();
}
_subscriptions.clear();
_controller!.close();
}
}
/**
* A factory to expose DOM events as streams, where the DOM event name has to
* be determined on the fly (for example, mouse wheel events).
*/
class _CustomEventStreamProvider<T extends Event>
implements EventStreamProvider<T> {
final _eventTypeGetter;
const _CustomEventStreamProvider(this._eventTypeGetter);
Stream<T> forTarget(EventTarget? e, {bool useCapture: false}) {
return new _EventStream<T>(e, _eventTypeGetter(e), useCapture);
}
ElementStream<T> forElement(Element e, {bool useCapture: false}) {
return new _ElementEventStreamImpl<T>(e, _eventTypeGetter(e), useCapture);
}
ElementStream<T> _forElementList(ElementList<Element> e,
{bool useCapture: false}) {
return new _ElementListEventStreamImpl<T>(
e, _eventTypeGetter(e), useCapture);
}
String getEventType(EventTarget target) {
return _eventTypeGetter(target);
}
String get _eventType =>
throw new UnsupportedError('Access type through getEventType method.');
}
-449
View File
@@ -1,449 +0,0 @@
// DO NOT EDIT- this file is generated from running tool/generator.sh.
// 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.
part of dart.dom.html;
/**
* A Dart DOM validator generated from Caja whitelists.
*
* This contains a whitelist of known HTML tagNames and attributes and will only
* accept known good values.
*
* See also:
*
* * <https://code.google.com/p/google-caja/wiki/CajaWhitelists>
*/
class _Html5NodeValidator implements NodeValidator {
static final Set<String> _allowedElements = new Set.from([
'A',
'ABBR',
'ACRONYM',
'ADDRESS',
'AREA',
'ARTICLE',
'ASIDE',
'AUDIO',
'B',
'BDI',
'BDO',
'BIG',
'BLOCKQUOTE',
'BR',
'BUTTON',
'CANVAS',
'CAPTION',
'CENTER',
'CITE',
'CODE',
'COL',
'COLGROUP',
'COMMAND',
'DATA',
'DATALIST',
'DD',
'DEL',
'DETAILS',
'DFN',
'DIR',
'DIV',
'DL',
'DT',
'EM',
'FIELDSET',
'FIGCAPTION',
'FIGURE',
'FONT',
'FOOTER',
'FORM',
'H1',
'H2',
'H3',
'H4',
'H5',
'H6',
'HEADER',
'HGROUP',
'HR',
'I',
'IFRAME',
'IMG',
'INPUT',
'INS',
'KBD',
'LABEL',
'LEGEND',
'LI',
'MAP',
'MARK',
'MENU',
'METER',
'NAV',
'NOBR',
'OL',
'OPTGROUP',
'OPTION',
'OUTPUT',
'P',
'PRE',
'PROGRESS',
'Q',
'S',
'SAMP',
'SECTION',
'SELECT',
'SMALL',
'SOURCE',
'SPAN',
'STRIKE',
'STRONG',
'SUB',
'SUMMARY',
'SUP',
'TABLE',
'TBODY',
'TD',
'TEXTAREA',
'TFOOT',
'TH',
'THEAD',
'TIME',
'TR',
'TRACK',
'TT',
'U',
'UL',
'VAR',
'VIDEO',
'WBR',
]);
static const _standardAttributes = const <String>[
'*::class',
'*::dir',
'*::draggable',
'*::hidden',
'*::id',
'*::inert',
'*::itemprop',
'*::itemref',
'*::itemscope',
'*::lang',
'*::spellcheck',
'*::title',
'*::translate',
'A::accesskey',
'A::coords',
'A::hreflang',
'A::name',
'A::shape',
'A::tabindex',
'A::target',
'A::type',
'AREA::accesskey',
'AREA::alt',
'AREA::coords',
'AREA::nohref',
'AREA::shape',
'AREA::tabindex',
'AREA::target',
'AUDIO::controls',
'AUDIO::loop',
'AUDIO::mediagroup',
'AUDIO::muted',
'AUDIO::preload',
'BDO::dir',
'BODY::alink',
'BODY::bgcolor',
'BODY::link',
'BODY::text',
'BODY::vlink',
'BR::clear',
'BUTTON::accesskey',
'BUTTON::disabled',
'BUTTON::name',
'BUTTON::tabindex',
'BUTTON::type',
'BUTTON::value',
'CANVAS::height',
'CANVAS::width',
'CAPTION::align',
'COL::align',
'COL::char',
'COL::charoff',
'COL::span',
'COL::valign',
'COL::width',
'COLGROUP::align',
'COLGROUP::char',
'COLGROUP::charoff',
'COLGROUP::span',
'COLGROUP::valign',
'COLGROUP::width',
'COMMAND::checked',
'COMMAND::command',
'COMMAND::disabled',
'COMMAND::label',
'COMMAND::radiogroup',
'COMMAND::type',
'DATA::value',
'DEL::datetime',
'DETAILS::open',
'DIR::compact',
'DIV::align',
'DL::compact',
'FIELDSET::disabled',
'FONT::color',
'FONT::face',
'FONT::size',
'FORM::accept',
'FORM::autocomplete',
'FORM::enctype',
'FORM::method',
'FORM::name',
'FORM::novalidate',
'FORM::target',
'FRAME::name',
'H1::align',
'H2::align',
'H3::align',
'H4::align',
'H5::align',
'H6::align',
'HR::align',
'HR::noshade',
'HR::size',
'HR::width',
'HTML::version',
'IFRAME::align',
'IFRAME::frameborder',
'IFRAME::height',
'IFRAME::marginheight',
'IFRAME::marginwidth',
'IFRAME::width',
'IMG::align',
'IMG::alt',
'IMG::border',
'IMG::height',
'IMG::hspace',
'IMG::ismap',
'IMG::name',
'IMG::usemap',
'IMG::vspace',
'IMG::width',
'INPUT::accept',
'INPUT::accesskey',
'INPUT::align',
'INPUT::alt',
'INPUT::autocomplete',
'INPUT::autofocus',
'INPUT::checked',
'INPUT::disabled',
'INPUT::inputmode',
'INPUT::ismap',
'INPUT::list',
'INPUT::max',
'INPUT::maxlength',
'INPUT::min',
'INPUT::multiple',
'INPUT::name',
'INPUT::placeholder',
'INPUT::readonly',
'INPUT::required',
'INPUT::size',
'INPUT::step',
'INPUT::tabindex',
'INPUT::type',
'INPUT::usemap',
'INPUT::value',
'INS::datetime',
'KEYGEN::disabled',
'KEYGEN::keytype',
'KEYGEN::name',
'LABEL::accesskey',
'LABEL::for',
'LEGEND::accesskey',
'LEGEND::align',
'LI::type',
'LI::value',
'LINK::sizes',
'MAP::name',
'MENU::compact',
'MENU::label',
'MENU::type',
'METER::high',
'METER::low',
'METER::max',
'METER::min',
'METER::value',
'OBJECT::typemustmatch',
'OL::compact',
'OL::reversed',
'OL::start',
'OL::type',
'OPTGROUP::disabled',
'OPTGROUP::label',
'OPTION::disabled',
'OPTION::label',
'OPTION::selected',
'OPTION::value',
'OUTPUT::for',
'OUTPUT::name',
'P::align',
'PRE::width',
'PROGRESS::max',
'PROGRESS::min',
'PROGRESS::value',
'SELECT::autocomplete',
'SELECT::disabled',
'SELECT::multiple',
'SELECT::name',
'SELECT::required',
'SELECT::size',
'SELECT::tabindex',
'SOURCE::type',
'TABLE::align',
'TABLE::bgcolor',
'TABLE::border',
'TABLE::cellpadding',
'TABLE::cellspacing',
'TABLE::frame',
'TABLE::rules',
'TABLE::summary',
'TABLE::width',
'TBODY::align',
'TBODY::char',
'TBODY::charoff',
'TBODY::valign',
'TD::abbr',
'TD::align',
'TD::axis',
'TD::bgcolor',
'TD::char',
'TD::charoff',
'TD::colspan',
'TD::headers',
'TD::height',
'TD::nowrap',
'TD::rowspan',
'TD::scope',
'TD::valign',
'TD::width',
'TEXTAREA::accesskey',
'TEXTAREA::autocomplete',
'TEXTAREA::cols',
'TEXTAREA::disabled',
'TEXTAREA::inputmode',
'TEXTAREA::name',
'TEXTAREA::placeholder',
'TEXTAREA::readonly',
'TEXTAREA::required',
'TEXTAREA::rows',
'TEXTAREA::tabindex',
'TEXTAREA::wrap',
'TFOOT::align',
'TFOOT::char',
'TFOOT::charoff',
'TFOOT::valign',
'TH::abbr',
'TH::align',
'TH::axis',
'TH::bgcolor',
'TH::char',
'TH::charoff',
'TH::colspan',
'TH::headers',
'TH::height',
'TH::nowrap',
'TH::rowspan',
'TH::scope',
'TH::valign',
'TH::width',
'THEAD::align',
'THEAD::char',
'THEAD::charoff',
'THEAD::valign',
'TR::align',
'TR::bgcolor',
'TR::char',
'TR::charoff',
'TR::valign',
'TRACK::default',
'TRACK::kind',
'TRACK::label',
'TRACK::srclang',
'UL::compact',
'UL::type',
'VIDEO::controls',
'VIDEO::height',
'VIDEO::loop',
'VIDEO::mediagroup',
'VIDEO::muted',
'VIDEO::preload',
'VIDEO::width',
];
static const _uriAttributes = const <String>[
'A::href',
'AREA::href',
'BLOCKQUOTE::cite',
'BODY::background',
'COMMAND::icon',
'DEL::cite',
'FORM::action',
'IMG::src',
'INPUT::src',
'INS::cite',
'Q::cite',
'VIDEO::poster',
];
final UriPolicy uriPolicy;
static final Map<String, Function> _attributeValidators = {};
/**
* All known URI attributes will be validated against the UriPolicy, if
* [uriPolicy] is null then a default UriPolicy will be used.
*/
_Html5NodeValidator({UriPolicy? uriPolicy})
: uriPolicy = uriPolicy ?? UriPolicy() {
if (_attributeValidators.isEmpty) {
for (var attr in _standardAttributes) {
_attributeValidators[attr] = _standardAttributeValidator;
}
for (var attr in _uriAttributes) {
_attributeValidators[attr] = _uriAttributeValidator;
}
}
}
bool allowsElement(Element element) {
return _allowedElements.contains(Element._safeTagName(element));
}
bool allowsAttribute(Element element, String attributeName, String value) {
var tagName = Element._safeTagName(element);
var validator = _attributeValidators['$tagName::$attributeName'];
if (validator == null) {
validator = _attributeValidators['*::$attributeName'];
}
if (validator == null) {
return false;
}
return validator(element, attributeName, value, this);
}
static bool _standardAttributeValidator(Element element, String attributeName,
String value, _Html5NodeValidator context) {
return true;
}
static bool _uriAttributeValidator(Element element, String attributeName,
String value, _Html5NodeValidator context) {
return context.uriPolicy.allowsUri(value);
}
}
@@ -1,80 +0,0 @@
// Copyright (c) 2012, 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.
part of dart.dom.html;
abstract class ImmutableListMixin<E> implements List<E> {
// From Iterable<$E>:
Iterator<E> get iterator {
// Note: NodeLists are not fixed size. And most probably length shouldn't
// be cached in both iterator _and_ forEach method. For now caching it
// for consistency.
return new FixedSizeListIterator<E>(this);
}
// From List<E>:
void add(E value) {
throw new UnsupportedError("Cannot add to immutable List.");
}
void addAll(Iterable<E> iterable) {
throw new UnsupportedError("Cannot add to immutable List.");
}
void sort([int compare(E a, E b)?]) {
throw new UnsupportedError("Cannot sort immutable List.");
}
void shuffle([Random? random]) {
throw new UnsupportedError("Cannot shuffle immutable List.");
}
void insert(int index, E element) {
throw new UnsupportedError("Cannot add to immutable List.");
}
void insertAll(int index, Iterable<E> iterable) {
throw new UnsupportedError("Cannot add to immutable List.");
}
void setAll(int index, Iterable<E> iterable) {
throw new UnsupportedError("Cannot modify an immutable List.");
}
E removeAt(int pos) {
throw new UnsupportedError("Cannot remove from immutable List.");
}
E removeLast() {
throw new UnsupportedError("Cannot remove from immutable List.");
}
bool remove(Object? object) {
throw new UnsupportedError("Cannot remove from immutable List.");
}
void removeWhere(bool test(E element)) {
throw new UnsupportedError("Cannot remove from immutable List.");
}
void retainWhere(bool test(E element)) {
throw new UnsupportedError("Cannot remove from immutable List.");
}
void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
throw new UnsupportedError("Cannot setRange on immutable List.");
}
void removeRange(int start, int end) {
throw new UnsupportedError("Cannot removeRange on immutable List.");
}
void replaceRange(int start, int end, Iterable<E> iterable) {
throw new UnsupportedError("Cannot modify an immutable List.");
}
void fillRange(int start, int end, [E? fillValue]) {
throw new UnsupportedError("Cannot modify an immutable List.");
}
}
-331
View File
@@ -1,331 +0,0 @@
// Copyright (c) 2012, 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.
part of html;
/**
* Defines the keycode values for keys that are returned by
* KeyboardEvent.keyCode.
*
* Important note: There is substantial divergence in how different browsers
* handle keycodes and their variants in different locales/keyboard layouts. We
* provide these constants to help make code processing keys more readable.
*/
abstract class KeyCode {
// These constant names were borrowed from Closure's Keycode enumeration
// class.
// https://github.com/google/closure-library/blob/master/closure/goog/events/keycodes.js
static const int WIN_KEY_FF_LINUX = 0;
static const int MAC_ENTER = 3;
static const int BACKSPACE = 8;
static const int TAB = 9;
/** NUM_CENTER is also NUMLOCK for FF and Safari on Mac. */
static const int NUM_CENTER = 12;
static const int ENTER = 13;
static const int SHIFT = 16;
static const int CTRL = 17;
static const int ALT = 18;
static const int PAUSE = 19;
static const int CAPS_LOCK = 20;
static const int ESC = 27;
static const int SPACE = 32;
static const int PAGE_UP = 33;
static const int PAGE_DOWN = 34;
static const int END = 35;
static const int HOME = 36;
static const int LEFT = 37;
static const int UP = 38;
static const int RIGHT = 39;
static const int DOWN = 40;
static const int NUM_NORTH_EAST = 33;
static const int NUM_SOUTH_EAST = 34;
static const int NUM_SOUTH_WEST = 35;
static const int NUM_NORTH_WEST = 36;
static const int NUM_WEST = 37;
static const int NUM_NORTH = 38;
static const int NUM_EAST = 39;
static const int NUM_SOUTH = 40;
static const int PRINT_SCREEN = 44;
static const int INSERT = 45;
static const int NUM_INSERT = 45;
static const int DELETE = 46;
static const int NUM_DELETE = 46;
static const int ZERO = 48;
static const int ONE = 49;
static const int TWO = 50;
static const int THREE = 51;
static const int FOUR = 52;
static const int FIVE = 53;
static const int SIX = 54;
static const int SEVEN = 55;
static const int EIGHT = 56;
static const int NINE = 57;
static const int FF_SEMICOLON = 59;
static const int FF_EQUALS = 61;
/**
* CAUTION: The question mark is for US-keyboard layouts. It varies
* for other locales and keyboard layouts.
*/
static const int QUESTION_MARK = 63;
static const int A = 65;
static const int B = 66;
static const int C = 67;
static const int D = 68;
static const int E = 69;
static const int F = 70;
static const int G = 71;
static const int H = 72;
static const int I = 73;
static const int J = 74;
static const int K = 75;
static const int L = 76;
static const int M = 77;
static const int N = 78;
static const int O = 79;
static const int P = 80;
static const int Q = 81;
static const int R = 82;
static const int S = 83;
static const int T = 84;
static const int U = 85;
static const int V = 86;
static const int W = 87;
static const int X = 88;
static const int Y = 89;
static const int Z = 90;
static const int META = 91;
static const int WIN_KEY_LEFT = 91;
static const int WIN_KEY_RIGHT = 92;
static const int CONTEXT_MENU = 93;
static const int NUM_ZERO = 96;
static const int NUM_ONE = 97;
static const int NUM_TWO = 98;
static const int NUM_THREE = 99;
static const int NUM_FOUR = 100;
static const int NUM_FIVE = 101;
static const int NUM_SIX = 102;
static const int NUM_SEVEN = 103;
static const int NUM_EIGHT = 104;
static const int NUM_NINE = 105;
static const int NUM_MULTIPLY = 106;
static const int NUM_PLUS = 107;
static const int NUM_MINUS = 109;
static const int NUM_PERIOD = 110;
static const int NUM_DIVISION = 111;
static const int F1 = 112;
static const int F2 = 113;
static const int F3 = 114;
static const int F4 = 115;
static const int F5 = 116;
static const int F6 = 117;
static const int F7 = 118;
static const int F8 = 119;
static const int F9 = 120;
static const int F10 = 121;
static const int F11 = 122;
static const int F12 = 123;
static const int NUMLOCK = 144;
static const int SCROLL_LOCK = 145;
// OS-specific media keys like volume controls and browser controls.
static const int FIRST_MEDIA_KEY = 166;
static const int LAST_MEDIA_KEY = 183;
/**
* CAUTION: This constant requires localization for other locales and keyboard
* layouts.
*/
static const int SEMICOLON = 186;
/**
* CAUTION: This constant requires localization for other locales and keyboard
* layouts.
*/
static const int DASH = 189;
/**
* CAUTION: This constant requires localization for other locales and keyboard
* layouts.
*/
static const int EQUALS = 187;
/**
* CAUTION: This constant requires localization for other locales and keyboard
* layouts.
*/
static const int COMMA = 188;
/**
* CAUTION: This constant requires localization for other locales and keyboard
* layouts.
*/
static const int PERIOD = 190;
/**
* CAUTION: This constant requires localization for other locales and keyboard
* layouts.
*/
static const int SLASH = 191;
/**
* CAUTION: This constant requires localization for other locales and keyboard
* layouts.
*/
static const int APOSTROPHE = 192;
/**
* CAUTION: This constant requires localization for other locales and keyboard
* layouts.
*/
static const int TILDE = 192;
/**
* CAUTION: This constant requires localization for other locales and keyboard
* layouts.
*/
static const int SINGLE_QUOTE = 222;
/**
* CAUTION: This constant requires localization for other locales and keyboard
* layouts.
*/
static const int OPEN_SQUARE_BRACKET = 219;
/**
* CAUTION: This constant requires localization for other locales and keyboard
* layouts.
*/
static const int BACKSLASH = 220;
/**
* CAUTION: This constant requires localization for other locales and keyboard
* layouts.
*/
static const int CLOSE_SQUARE_BRACKET = 221;
static const int WIN_KEY = 224;
static const int MAC_FF_META = 224;
static const int WIN_IME = 229;
/** A sentinel value if the keycode could not be determined. */
static const int UNKNOWN = -1;
/**
* Returns true if the keyCode produces a (US keyboard) character.
* Note: This does not (yet) cover characters on non-US keyboards (Russian,
* Hebrew, etc.).
*/
static bool isCharacterKey(int keyCode) {
if ((keyCode >= ZERO && keyCode <= NINE) ||
(keyCode >= NUM_ZERO && keyCode <= NUM_MULTIPLY) ||
(keyCode >= A && keyCode <= Z)) {
return true;
}
// Safari sends zero key code for non-latin characters.
if (Device.isWebKit && keyCode == 0) {
return true;
}
return (keyCode == SPACE ||
keyCode == QUESTION_MARK ||
keyCode == NUM_PLUS ||
keyCode == NUM_MINUS ||
keyCode == NUM_PERIOD ||
keyCode == NUM_DIVISION ||
keyCode == SEMICOLON ||
keyCode == FF_SEMICOLON ||
keyCode == DASH ||
keyCode == EQUALS ||
keyCode == FF_EQUALS ||
keyCode == COMMA ||
keyCode == PERIOD ||
keyCode == SLASH ||
keyCode == APOSTROPHE ||
keyCode == SINGLE_QUOTE ||
keyCode == OPEN_SQUARE_BRACKET ||
keyCode == BACKSLASH ||
keyCode == CLOSE_SQUARE_BRACKET);
}
/**
* Experimental helper function for converting keyCodes to keyNames for the
* keyIdentifier attribute still used in browsers not updated with current
* spec. This is an imperfect conversion! It will need to be refined, but
* hopefully it can just completely go away once all the browsers update to
* follow the DOM3 spec.
*/
static String _convertKeyCodeToKeyName(int keyCode) {
switch (keyCode) {
case KeyCode.ALT:
return _KeyName.ALT;
case KeyCode.BACKSPACE:
return _KeyName.BACKSPACE;
case KeyCode.CAPS_LOCK:
return _KeyName.CAPS_LOCK;
case KeyCode.CTRL:
return _KeyName.CONTROL;
case KeyCode.DELETE:
return _KeyName.DEL;
case KeyCode.DOWN:
return _KeyName.DOWN;
case KeyCode.END:
return _KeyName.END;
case KeyCode.ENTER:
return _KeyName.ENTER;
case KeyCode.ESC:
return _KeyName.ESC;
case KeyCode.F1:
return _KeyName.F1;
case KeyCode.F2:
return _KeyName.F2;
case KeyCode.F3:
return _KeyName.F3;
case KeyCode.F4:
return _KeyName.F4;
case KeyCode.F5:
return _KeyName.F5;
case KeyCode.F6:
return _KeyName.F6;
case KeyCode.F7:
return _KeyName.F7;
case KeyCode.F8:
return _KeyName.F8;
case KeyCode.F9:
return _KeyName.F9;
case KeyCode.F10:
return _KeyName.F10;
case KeyCode.F11:
return _KeyName.F11;
case KeyCode.F12:
return _KeyName.F12;
case KeyCode.HOME:
return _KeyName.HOME;
case KeyCode.INSERT:
return _KeyName.INSERT;
case KeyCode.LEFT:
return _KeyName.LEFT;
case KeyCode.META:
return _KeyName.META;
case KeyCode.NUMLOCK:
return _KeyName.NUM_LOCK;
case KeyCode.PAGE_DOWN:
return _KeyName.PAGE_DOWN;
case KeyCode.PAGE_UP:
return _KeyName.PAGE_UP;
case KeyCode.PAUSE:
return _KeyName.PAUSE;
case KeyCode.PRINT_SCREEN:
return _KeyName.PRINT_SCREEN;
case KeyCode.RIGHT:
return _KeyName.RIGHT;
case KeyCode.SCROLL_LOCK:
return _KeyName.SCROLL;
case KeyCode.SHIFT:
return _KeyName.SHIFT;
case KeyCode.SPACE:
return _KeyName.SPACEBAR;
case KeyCode.TAB:
return _KeyName.TAB;
case KeyCode.UP:
return _KeyName.UP;
case KeyCode.WIN_IME:
case KeyCode.WIN_KEY:
case KeyCode.WIN_KEY_LEFT:
case KeyCode.WIN_KEY_RIGHT:
return _KeyName.WIN;
default:
return _KeyName.UNIDENTIFIED;
}
return _KeyName.UNIDENTIFIED;
}
}
-46
View File
@@ -1,46 +0,0 @@
// Copyright (c) 2011, 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.
part of html;
/**
* Defines the standard key locations returned by
* KeyboardEvent.getKeyLocation.
*/
abstract class KeyLocation {
/**
* The event key is not distinguished as the left or right version
* of the key, and did not originate from the numeric keypad (or did not
* originate with a virtual key corresponding to the numeric keypad).
*/
static const int STANDARD = 0;
/**
* The event key is in the left key location.
*/
static const int LEFT = 1;
/**
* The event key is in the right key location.
*/
static const int RIGHT = 2;
/**
* The event key originated on the numeric keypad or with a virtual key
* corresponding to the numeric keypad.
*/
static const int NUMPAD = 3;
/**
* The event key originated on a mobile device, either on a physical
* keypad or a virtual keyboard.
*/
static const int MOBILE = 4;
/**
* The event key originated on a game controller or a joystick on a mobile
* device.
*/
static const int JOYSTICK = 5;
}
-494
View File
@@ -1,494 +0,0 @@
// Copyright (c) 2012, 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.
part of html;
/**
* Defines the standard keyboard identifier names for keys that are returned
* by KeyboardEvent.getKeyboardIdentifier when the key does not have a direct
* unicode mapping.
*/
abstract class _KeyName {
/** The Accept (Commit, OK) key */
static const String ACCEPT = "Accept";
/** The Add key */
static const String ADD = "Add";
/** The Again key */
static const String AGAIN = "Again";
/** The All Candidates key */
static const String ALL_CANDIDATES = "AllCandidates";
/** The Alphanumeric key */
static const String ALPHANUMERIC = "Alphanumeric";
/** The Alt (Menu) key */
static const String ALT = "Alt";
/** The Alt-Graph key */
static const String ALT_GRAPH = "AltGraph";
/** The Application key */
static const String APPS = "Apps";
/** The ATTN key */
static const String ATTN = "Attn";
/** The Browser Back key */
static const String BROWSER_BACK = "BrowserBack";
/** The Browser Favorites key */
static const String BROWSER_FAVORTIES = "BrowserFavorites";
/** The Browser Forward key */
static const String BROWSER_FORWARD = "BrowserForward";
/** The Browser Home key */
static const String BROWSER_NAME = "BrowserHome";
/** The Browser Refresh key */
static const String BROWSER_REFRESH = "BrowserRefresh";
/** The Browser Search key */
static const String BROWSER_SEARCH = "BrowserSearch";
/** The Browser Stop key */
static const String BROWSER_STOP = "BrowserStop";
/** The Camera key */
static const String CAMERA = "Camera";
/** The Caps Lock (Capital) key */
static const String CAPS_LOCK = "CapsLock";
/** The Clear key */
static const String CLEAR = "Clear";
/** The Code Input key */
static const String CODE_INPUT = "CodeInput";
/** The Compose key */
static const String COMPOSE = "Compose";
/** The Control (Ctrl) key */
static const String CONTROL = "Control";
/** The Crsel key */
static const String CRSEL = "Crsel";
/** The Convert key */
static const String CONVERT = "Convert";
/** The Copy key */
static const String COPY = "Copy";
/** The Cut key */
static const String CUT = "Cut";
/** The Decimal key */
static const String DECIMAL = "Decimal";
/** The Divide key */
static const String DIVIDE = "Divide";
/** The Down Arrow key */
static const String DOWN = "Down";
/** The diagonal Down-Left Arrow key */
static const String DOWN_LEFT = "DownLeft";
/** The diagonal Down-Right Arrow key */
static const String DOWN_RIGHT = "DownRight";
/** The Eject key */
static const String EJECT = "Eject";
/** The End key */
static const String END = "End";
/**
* The Enter key. Note: This key value must also be used for the Return
* (Macintosh numpad) key
*/
static const String ENTER = "Enter";
/** The Erase EOF key */
static const String ERASE_EOF = "EraseEof";
/** The Execute key */
static const String EXECUTE = "Execute";
/** The Exsel key */
static const String EXSEL = "Exsel";
/** The Function switch key */
static const String FN = "Fn";
/** The F1 key */
static const String F1 = "F1";
/** The F2 key */
static const String F2 = "F2";
/** The F3 key */
static const String F3 = "F3";
/** The F4 key */
static const String F4 = "F4";
/** The F5 key */
static const String F5 = "F5";
/** The F6 key */
static const String F6 = "F6";
/** The F7 key */
static const String F7 = "F7";
/** The F8 key */
static const String F8 = "F8";
/** The F9 key */
static const String F9 = "F9";
/** The F10 key */
static const String F10 = "F10";
/** The F11 key */
static const String F11 = "F11";
/** The F12 key */
static const String F12 = "F12";
/** The F13 key */
static const String F13 = "F13";
/** The F14 key */
static const String F14 = "F14";
/** The F15 key */
static const String F15 = "F15";
/** The F16 key */
static const String F16 = "F16";
/** The F17 key */
static const String F17 = "F17";
/** The F18 key */
static const String F18 = "F18";
/** The F19 key */
static const String F19 = "F19";
/** The F20 key */
static const String F20 = "F20";
/** The F21 key */
static const String F21 = "F21";
/** The F22 key */
static const String F22 = "F22";
/** The F23 key */
static const String F23 = "F23";
/** The F24 key */
static const String F24 = "F24";
/** The Final Mode (Final) key used on some asian keyboards */
static const String FINAL_MODE = "FinalMode";
/** The Find key */
static const String FIND = "Find";
/** The Full-Width Characters key */
static const String FULL_WIDTH = "FullWidth";
/** The Half-Width Characters key */
static const String HALF_WIDTH = "HalfWidth";
/** The Hangul (Korean characters) Mode key */
static const String HANGUL_MODE = "HangulMode";
/** The Hanja (Korean characters) Mode key */
static const String HANJA_MODE = "HanjaMode";
/** The Help key */
static const String HELP = "Help";
/** The Hiragana (Japanese Kana characters) key */
static const String HIRAGANA = "Hiragana";
/** The Home key */
static const String HOME = "Home";
/** The Insert (Ins) key */
static const String INSERT = "Insert";
/** The Japanese-Hiragana key */
static const String JAPANESE_HIRAGANA = "JapaneseHiragana";
/** The Japanese-Katakana key */
static const String JAPANESE_KATAKANA = "JapaneseKatakana";
/** The Japanese-Romaji key */
static const String JAPANESE_ROMAJI = "JapaneseRomaji";
/** The Junja Mode key */
static const String JUNJA_MODE = "JunjaMode";
/** The Kana Mode (Kana Lock) key */
static const String KANA_MODE = "KanaMode";
/**
* The Kanji (Japanese name for ideographic characters of Chinese origin)
* Mode key
*/
static const String KANJI_MODE = "KanjiMode";
/** The Katakana (Japanese Kana characters) key */
static const String KATAKANA = "Katakana";
/** The Start Application One key */
static const String LAUNCH_APPLICATION_1 = "LaunchApplication1";
/** The Start Application Two key */
static const String LAUNCH_APPLICATION_2 = "LaunchApplication2";
/** The Start Mail key */
static const String LAUNCH_MAIL = "LaunchMail";
/** The Left Arrow key */
static const String LEFT = "Left";
/** The Menu key */
static const String MENU = "Menu";
/**
* The Meta key. Note: This key value shall be also used for the Apple
* Command key
*/
static const String META = "Meta";
/** The Media Next Track key */
static const String MEDIA_NEXT_TRACK = "MediaNextTrack";
/** The Media Play Pause key */
static const String MEDIA_PAUSE_PLAY = "MediaPlayPause";
/** The Media Previous Track key */
static const String MEDIA_PREVIOUS_TRACK = "MediaPreviousTrack";
/** The Media Stop key */
static const String MEDIA_STOP = "MediaStop";
/** The Mode Change key */
static const String MODE_CHANGE = "ModeChange";
/** The Next Candidate function key */
static const String NEXT_CANDIDATE = "NextCandidate";
/** The Nonconvert (Don't Convert) key */
static const String NON_CONVERT = "Nonconvert";
/** The Number Lock key */
static const String NUM_LOCK = "NumLock";
/** The Page Down (Next) key */
static const String PAGE_DOWN = "PageDown";
/** The Page Up key */
static const String PAGE_UP = "PageUp";
/** The Paste key */
static const String PASTE = "Paste";
/** The Pause key */
static const String PAUSE = "Pause";
/** The Play key */
static const String PLAY = "Play";
/**
* The Power key. Note: Some devices may not expose this key to the
* operating environment
*/
static const String POWER = "Power";
/** The Previous Candidate function key */
static const String PREVIOUS_CANDIDATE = "PreviousCandidate";
/** The Print Screen (PrintScrn, SnapShot) key */
static const String PRINT_SCREEN = "PrintScreen";
/** The Process key */
static const String PROCESS = "Process";
/** The Props key */
static const String PROPS = "Props";
/** The Right Arrow key */
static const String RIGHT = "Right";
/** The Roman Characters function key */
static const String ROMAN_CHARACTERS = "RomanCharacters";
/** The Scroll Lock key */
static const String SCROLL = "Scroll";
/** The Select key */
static const String SELECT = "Select";
/** The Select Media key */
static const String SELECT_MEDIA = "SelectMedia";
/** The Separator key */
static const String SEPARATOR = "Separator";
/** The Shift key */
static const String SHIFT = "Shift";
/** The Soft1 key */
static const String SOFT_1 = "Soft1";
/** The Soft2 key */
static const String SOFT_2 = "Soft2";
/** The Soft3 key */
static const String SOFT_3 = "Soft3";
/** The Soft4 key */
static const String SOFT_4 = "Soft4";
/** The Stop key */
static const String STOP = "Stop";
/** The Subtract key */
static const String SUBTRACT = "Subtract";
/** The Symbol Lock key */
static const String SYMBOL_LOCK = "SymbolLock";
/** The Up Arrow key */
static const String UP = "Up";
/** The diagonal Up-Left Arrow key */
static const String UP_LEFT = "UpLeft";
/** The diagonal Up-Right Arrow key */
static const String UP_RIGHT = "UpRight";
/** The Undo key */
static const String UNDO = "Undo";
/** The Volume Down key */
static const String VOLUME_DOWN = "VolumeDown";
/** The Volume Mute key */
static const String VOLUMN_MUTE = "VolumeMute";
/** The Volume Up key */
static const String VOLUMN_UP = "VolumeUp";
/** The Windows Logo key */
static const String WIN = "Win";
/** The Zoom key */
static const String ZOOM = "Zoom";
/**
* The Backspace (Back) key. Note: This key value shall be also used for the
* key labeled 'delete' MacOS keyboards when not modified by the 'Fn' key
*/
static const String BACKSPACE = "Backspace";
/** The Horizontal Tabulation (Tab) key */
static const String TAB = "Tab";
/** The Cancel key */
static const String CANCEL = "Cancel";
/** The Escape (Esc) key */
static const String ESC = "Esc";
/** The Space (Spacebar) key: */
static const String SPACEBAR = "Spacebar";
/**
* The Delete (Del) Key. Note: This key value shall be also used for the key
* labeled 'delete' MacOS keyboards when modified by the 'Fn' key
*/
static const String DEL = "Del";
/** The Combining Grave Accent (Greek Varia, Dead Grave) key */
static const String DEAD_GRAVE = "DeadGrave";
/**
* The Combining Acute Accent (Stress Mark, Greek Oxia, Tonos, Dead Eacute)
* key
*/
static const String DEAD_EACUTE = "DeadEacute";
/** The Combining Circumflex Accent (Hat, Dead Circumflex) key */
static const String DEAD_CIRCUMFLEX = "DeadCircumflex";
/** The Combining Tilde (Dead Tilde) key */
static const String DEAD_TILDE = "DeadTilde";
/** The Combining Macron (Long, Dead Macron) key */
static const String DEAD_MACRON = "DeadMacron";
/** The Combining Breve (Short, Dead Breve) key */
static const String DEAD_BREVE = "DeadBreve";
/** The Combining Dot Above (Derivative, Dead Above Dot) key */
static const String DEAD_ABOVE_DOT = "DeadAboveDot";
/**
* The Combining Diaeresis (Double Dot Abode, Umlaut, Greek Dialytika,
* Double Derivative, Dead Diaeresis) key
*/
static const String DEAD_UMLAUT = "DeadUmlaut";
/** The Combining Ring Above (Dead Above Ring) key */
static const String DEAD_ABOVE_RING = "DeadAboveRing";
/** The Combining Double Acute Accent (Dead Doubleacute) key */
static const String DEAD_DOUBLEACUTE = "DeadDoubleacute";
/** The Combining Caron (Hacek, V Above, Dead Caron) key */
static const String DEAD_CARON = "DeadCaron";
/** The Combining Cedilla (Dead Cedilla) key */
static const String DEAD_CEDILLA = "DeadCedilla";
/** The Combining Ogonek (Nasal Hook, Dead Ogonek) key */
static const String DEAD_OGONEK = "DeadOgonek";
/**
* The Combining Greek Ypogegrammeni (Greek Non-Spacing Iota Below, Iota
* Subscript, Dead Iota) key
*/
static const String DEAD_IOTA = "DeadIota";
/**
* The Combining Katakana-Hiragana Voiced Sound Mark (Dead Voiced Sound) key
*/
static const String DEAD_VOICED_SOUND = "DeadVoicedSound";
/**
* The Combining Katakana-Hiragana Semi-Voiced Sound Mark (Dead Semivoiced
* Sound) key
*/
static const String DEC_SEMIVOICED_SOUND = "DeadSemivoicedSound";
/**
* Key value used when an implementation is unable to identify another key
* value, due to either hardware, platform, or software constraints
*/
static const String UNIDENTIFIED = "Unidentified";
}
-394
View File
@@ -1,394 +0,0 @@
// Copyright (c) 2012, 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.
part of html;
/**
* Internal class that does the actual calculations to determine keyCode and
* charCode for keydown, keypress, and keyup events for all browsers.
*/
class _KeyboardEventHandler extends EventStreamProvider<KeyEvent> {
// This code inspired by Closure's KeyHandling library.
// https://github.com/google/closure-library/blob/master/closure/goog/events/keyhandler.js
/**
* The set of keys that have been pressed down without seeing their
* corresponding keyup event.
*/
final List<KeyEvent> _keyDownList = <KeyEvent>[];
/** The type of KeyEvent we are tracking (keyup, keydown, keypress). */
final String _type;
/** The element we are watching for events to happen on. */
final EventTarget? _target;
// The distance to shift from upper case alphabet Roman letters to lower case.
static final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
/** Custom Stream (Controller) to produce KeyEvents for the stream. */
_CustomKeyEventStreamImpl _stream;
static const _EVENT_TYPE = 'KeyEvent';
/**
* An enumeration of key identifiers currently part of the W3C draft for DOM3
* and their mappings to keyCodes.
* https://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/keyset.html#KeySet-Set
*/
static const Map<String, int> _keyIdentifier = const {
'Up': KeyCode.UP,
'Down': KeyCode.DOWN,
'Left': KeyCode.LEFT,
'Right': KeyCode.RIGHT,
'Enter': KeyCode.ENTER,
'F1': KeyCode.F1,
'F2': KeyCode.F2,
'F3': KeyCode.F3,
'F4': KeyCode.F4,
'F5': KeyCode.F5,
'F6': KeyCode.F6,
'F7': KeyCode.F7,
'F8': KeyCode.F8,
'F9': KeyCode.F9,
'F10': KeyCode.F10,
'F11': KeyCode.F11,
'F12': KeyCode.F12,
'U+007F': KeyCode.DELETE,
'Home': KeyCode.HOME,
'End': KeyCode.END,
'PageUp': KeyCode.PAGE_UP,
'PageDown': KeyCode.PAGE_DOWN,
'Insert': KeyCode.INSERT
};
/** Return a stream for KeyEvents for the specified target. */
// Note: this actually functions like a factory constructor.
CustomStream<KeyEvent> forTarget(EventTarget? e, {bool useCapture: false}) {
var handler =
new _KeyboardEventHandler.initializeAllEventListeners(_type, e);
return handler._stream;
}
/**
* General constructor, performs basic initialization for our improved
* KeyboardEvent controller.
*/
_KeyboardEventHandler(this._type)
: _stream = new _CustomKeyEventStreamImpl('event'),
_target = null,
super(_EVENT_TYPE);
/**
* Hook up all event listeners under the covers so we can estimate keycodes
* and charcodes when they are not provided.
*/
_KeyboardEventHandler.initializeAllEventListeners(this._type, this._target)
: _stream = new _CustomKeyEventStreamImpl(_type),
super(_EVENT_TYPE) {
Element.keyDownEvent
.forTarget(_target, useCapture: true)
.listen(processKeyDown);
Element.keyPressEvent
.forTarget(_target, useCapture: true)
.listen(processKeyPress);
Element.keyUpEvent
.forTarget(_target, useCapture: true)
.listen(processKeyUp);
}
/** Determine if caps lock is one of the currently depressed keys. */
bool get _capsLockOn =>
_keyDownList.any((var element) => element.keyCode == KeyCode.CAPS_LOCK);
/**
* Given the previously recorded keydown key codes, see if we can determine
* the keycode of this keypress [event]. (Generally browsers only provide
* charCode information for keypress events, but with a little
* reverse-engineering, we can also determine the keyCode.) Returns
* KeyCode.UNKNOWN if the keycode could not be determined.
*/
int _determineKeyCodeForKeypress(KeyboardEvent event) {
// Note: This function is a work in progress. We'll expand this function
// once we get more information about other keyboards.
for (var prevEvent in _keyDownList) {
if (prevEvent._shadowCharCode == event.charCode) {
return prevEvent.keyCode;
}
if ((event.shiftKey || _capsLockOn) &&
event.charCode >= "A".codeUnits[0] &&
event.charCode <= "Z".codeUnits[0] &&
event.charCode + _ROMAN_ALPHABET_OFFSET ==
prevEvent._shadowCharCode) {
return prevEvent.keyCode;
}
}
return KeyCode.UNKNOWN;
}
/**
* Given the character code returned from a keyDown [event], try to ascertain
* and return the corresponding charCode for the character that was pressed.
* This information is not shown to the user, but used to help polyfill
* keypress events.
*/
int _findCharCodeKeyDown(KeyboardEvent event) {
if (event.location == 3) {
// Numpad keys.
switch (event.keyCode) {
case KeyCode.NUM_ZERO:
// Even though this function returns _charCodes_, for some cases the
// KeyCode == the charCode we want, in which case we use the keycode
// constant for readability.
return KeyCode.ZERO;
case KeyCode.NUM_ONE:
return KeyCode.ONE;
case KeyCode.NUM_TWO:
return KeyCode.TWO;
case KeyCode.NUM_THREE:
return KeyCode.THREE;
case KeyCode.NUM_FOUR:
return KeyCode.FOUR;
case KeyCode.NUM_FIVE:
return KeyCode.FIVE;
case KeyCode.NUM_SIX:
return KeyCode.SIX;
case KeyCode.NUM_SEVEN:
return KeyCode.SEVEN;
case KeyCode.NUM_EIGHT:
return KeyCode.EIGHT;
case KeyCode.NUM_NINE:
return KeyCode.NINE;
case KeyCode.NUM_MULTIPLY:
return 42; // Char code for *
case KeyCode.NUM_PLUS:
return 43; // +
case KeyCode.NUM_MINUS:
return 45; // -
case KeyCode.NUM_PERIOD:
return 46; // .
case KeyCode.NUM_DIVISION:
return 47; // /
}
} else if (event.keyCode >= 65 && event.keyCode <= 90) {
// Set the "char code" for key down as the lower case letter. Again, this
// will not show up for the user, but will be helpful in estimating
// keyCode locations and other information during the keyPress event.
return event.keyCode + _ROMAN_ALPHABET_OFFSET;
}
switch (event.keyCode) {
case KeyCode.SEMICOLON:
return KeyCode.FF_SEMICOLON;
case KeyCode.EQUALS:
return KeyCode.FF_EQUALS;
case KeyCode.COMMA:
return 44; // Ascii value for ,
case KeyCode.DASH:
return 45; // -
case KeyCode.PERIOD:
return 46; // .
case KeyCode.SLASH:
return 47; // /
case KeyCode.APOSTROPHE:
return 96; // `
case KeyCode.OPEN_SQUARE_BRACKET:
return 91; // [
case KeyCode.BACKSLASH:
return 92; // \
case KeyCode.CLOSE_SQUARE_BRACKET:
return 93; // ]
case KeyCode.SINGLE_QUOTE:
return 39; // '
}
return event.keyCode;
}
/**
* Returns true if the key fires a keypress event in the current browser.
*/
bool _firesKeyPressEvent(KeyEvent event) {
if (!Device.isIE && !Device.isWebKit) {
return true;
}
if (Device.userAgent.contains('Mac') && event.altKey) {
return KeyCode.isCharacterKey(event.keyCode);
}
// Alt but not AltGr which is represented as Alt+Ctrl.
if (event.altKey && !event.ctrlKey) {
return false;
}
// Saves Ctrl or Alt + key for IE and WebKit, which won't fire keypress.
if (!event.shiftKey &&
(_keyDownList.last.keyCode == KeyCode.CTRL ||
_keyDownList.last.keyCode == KeyCode.ALT ||
Device.userAgent.contains('Mac') &&
_keyDownList.last.keyCode == KeyCode.META)) {
return false;
}
// Some keys with Ctrl/Shift do not issue keypress in WebKit.
if (Device.isWebKit &&
event.ctrlKey &&
event.shiftKey &&
(event.keyCode == KeyCode.BACKSLASH ||
event.keyCode == KeyCode.OPEN_SQUARE_BRACKET ||
event.keyCode == KeyCode.CLOSE_SQUARE_BRACKET ||
event.keyCode == KeyCode.TILDE ||
event.keyCode == KeyCode.SEMICOLON ||
event.keyCode == KeyCode.DASH ||
event.keyCode == KeyCode.EQUALS ||
event.keyCode == KeyCode.COMMA ||
event.keyCode == KeyCode.PERIOD ||
event.keyCode == KeyCode.SLASH ||
event.keyCode == KeyCode.APOSTROPHE ||
event.keyCode == KeyCode.SINGLE_QUOTE)) {
return false;
}
switch (event.keyCode) {
case KeyCode.ENTER:
// IE9 does not fire keypress on ENTER.
return !Device.isIE;
case KeyCode.ESC:
return !Device.isWebKit;
}
return KeyCode.isCharacterKey(event.keyCode);
}
/**
* Normalize the keycodes to the IE KeyCodes (this is what Chrome, IE, and
* Opera all use).
*/
int _normalizeKeyCodes(KeyboardEvent event) {
// Note: This may change once we get input about non-US keyboards.
if (Device.isFirefox) {
switch (event.keyCode) {
case KeyCode.FF_EQUALS:
return KeyCode.EQUALS;
case KeyCode.FF_SEMICOLON:
return KeyCode.SEMICOLON;
case KeyCode.MAC_FF_META:
return KeyCode.META;
case KeyCode.WIN_KEY_FF_LINUX:
return KeyCode.WIN_KEY;
}
}
return event.keyCode;
}
/** Handle keydown events. */
void processKeyDown(KeyboardEvent e) {
// Ctrl-Tab and Alt-Tab can cause the focus to be moved to another window
// before we've caught a key-up event. If the last-key was one of these
// we reset the state.
if (_keyDownList.length > 0 &&
(_keyDownList.last.keyCode == KeyCode.CTRL && !e.ctrlKey ||
_keyDownList.last.keyCode == KeyCode.ALT && !e.altKey ||
Device.userAgent.contains('Mac') &&
_keyDownList.last.keyCode == KeyCode.META &&
!e.metaKey)) {
_keyDownList.clear();
}
var event = new KeyEvent.wrap(e);
event._shadowKeyCode = _normalizeKeyCodes(event);
// Technically a "keydown" event doesn't have a charCode. This is
// calculated nonetheless to provide us with more information in giving
// as much information as possible on keypress about keycode and also
// charCode.
event._shadowCharCode = _findCharCodeKeyDown(event);
if (_keyDownList.length > 0 &&
event.keyCode != _keyDownList.last.keyCode &&
!_firesKeyPressEvent(event)) {
// Some browsers have quirks not firing keypress events where all other
// browsers do. This makes them more consistent.
processKeyPress(e);
}
_keyDownList.add(event);
_stream.add(event);
}
/** Handle keypress events. */
void processKeyPress(KeyboardEvent event) {
var e = new KeyEvent.wrap(event);
// IE reports the character code in the keyCode field for keypress events.
// There are two exceptions however, Enter and Escape.
if (Device.isIE) {
if (e.keyCode == KeyCode.ENTER || e.keyCode == KeyCode.ESC) {
e._shadowCharCode = 0;
} else {
e._shadowCharCode = e.keyCode;
}
} else if (Device.isOpera) {
// Opera reports the character code in the keyCode field.
e._shadowCharCode = KeyCode.isCharacterKey(e.keyCode) ? e.keyCode : 0;
}
// Now we guesstimate about what the keycode is that was actually
// pressed, given previous keydown information.
e._shadowKeyCode = _determineKeyCodeForKeypress(e);
// Correct the key value for certain browser-specific quirks.
if (e._shadowKeyIdentifier != null &&
_keyIdentifier.containsKey(e._shadowKeyIdentifier)) {
// This is needed for Safari Windows because it currently doesn't give a
// keyCode/which for non printable keys.
e._shadowKeyCode = _keyIdentifier[e._shadowKeyIdentifier]!;
}
e._shadowAltKey = _keyDownList.any((var element) => element.altKey);
_stream.add(e);
}
/** Handle keyup events. */
void processKeyUp(KeyboardEvent event) {
var e = new KeyEvent.wrap(event);
KeyboardEvent? toRemove = null;
for (var key in _keyDownList) {
if (key.keyCode == e.keyCode) {
toRemove = key;
}
}
if (toRemove != null) {
_keyDownList.removeWhere((element) => element == toRemove);
} else if (_keyDownList.length > 0) {
// This happens when we've reached some international keyboard case we
// haven't accounted for or we haven't correctly eliminated all browser
// inconsistencies. Filing bugs on when this is reached is welcome!
_keyDownList.removeLast();
}
_stream.add(e);
}
}
/**
* Records KeyboardEvents that occur on a particular element, and provides a
* stream of outgoing KeyEvents with cross-browser consistent keyCode and
* charCode values despite the fact that a multitude of browsers that have
* varying keyboard default behavior.
*
* Example usage:
*
* KeyboardEventStream.onKeyDown(document.body).listen(
* keydownHandlerTest);
*
* This class is very much a work in progress, and we'd love to get information
* on how we can make this class work with as many international keyboards as
* possible. Bugs welcome!
*/
class KeyboardEventStream {
/** Named constructor to produce a stream for onKeyPress events. */
static CustomStream<KeyEvent> onKeyPress(EventTarget target) =>
new _KeyboardEventHandler('keypress').forTarget(target);
/** Named constructor to produce a stream for onKeyUp events. */
static CustomStream<KeyEvent> onKeyUp(EventTarget target) =>
new _KeyboardEventHandler('keyup').forTarget(target);
/** Named constructor to produce a stream for onKeyDown events. */
static CustomStream<KeyEvent> onKeyDown(EventTarget target) =>
new _KeyboardEventHandler('keydown').forTarget(target);
}
@@ -1,454 +0,0 @@
// 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.
part of dart.dom.html;
/**
* Class which helps construct standard node validation policies.
*
* By default this will not accept anything, but the 'allow*' functions can be
* used to expand what types of elements or attributes are allowed.
*
* All allow functions are additive- elements will be accepted if they are
* accepted by any specific rule.
*
* It is important to remember that sanitization is not just intended to prevent
* cross-site scripting attacks, but also to prevent information from being
* displayed in unexpected ways. For example something displaying basic
* formatted text may not expect `<video>` tags to appear. In this case an
* empty NodeValidatorBuilder with just [allowTextElements] might be
* appropriate.
*/
class NodeValidatorBuilder implements NodeValidator {
final List<NodeValidator> _validators = <NodeValidator>[];
NodeValidatorBuilder() {}
/**
* Creates a new NodeValidatorBuilder which accepts common constructs.
*
* By default this will accept HTML5 elements and attributes with the default
* [UriPolicy] and templating elements.
*
* Notable syntax which is filtered:
*
* * Only known-good HTML5 elements and attributes are allowed.
* * All URLs must be same-origin, use [allowNavigation] and [allowImages] to
* specify additional URI policies.
* * Inline-styles are not allowed.
* * Custom element tags are disallowed, use [allowCustomElement].
* * Custom tags extensions are disallowed, use [allowTagExtension].
* * SVG Elements are not allowed, use [allowSvg].
*
* For scenarios where the HTML should only contain formatted text
* [allowTextElements] is more appropriate.
*
* Use [allowSvg] to allow SVG elements.
*/
NodeValidatorBuilder.common() {
allowHtml5();
allowTemplating();
}
/**
* Allows navigation elements- Form and Anchor tags, along with common
* attributes.
*
* The UriPolicy can be used to restrict the locations the navigation elements
* are allowed to direct to. By default this will use the default [UriPolicy].
*/
void allowNavigation([UriPolicy? uriPolicy]) {
if (uriPolicy == null) {
uriPolicy = new UriPolicy();
}
add(new _SimpleNodeValidator.allowNavigation(uriPolicy));
}
/**
* Allows image elements.
*
* The UriPolicy can be used to restrict the locations the images may be
* loaded from. By default this will use the default [UriPolicy].
*/
void allowImages([UriPolicy? uriPolicy]) {
if (uriPolicy == null) {
uriPolicy = new UriPolicy();
}
add(new _SimpleNodeValidator.allowImages(uriPolicy));
}
/**
* Allow basic text elements.
*
* This allows a subset of HTML5 elements, specifically just these tags and
* no attributes.
*
* * B
* * BLOCKQUOTE
* * BR
* * EM
* * H1
* * H2
* * H3
* * H4
* * H5
* * H6
* * HR
* * I
* * LI
* * OL
* * P
* * SPAN
* * UL
*/
void allowTextElements() {
add(new _SimpleNodeValidator.allowTextElements());
}
/**
* Allow inline styles on elements.
*
* If [tagName] is not specified then this allows inline styles on all
* elements. Otherwise tagName limits the styles to the specified elements.
*/
void allowInlineStyles({String? tagName}) {
if (tagName == null) {
tagName = '*';
} else {
tagName = tagName.toUpperCase();
}
add(new _SimpleNodeValidator(null, allowedAttributes: ['$tagName::style']));
}
/**
* Allow common safe HTML5 elements and attributes.
*
* This list is based off of the Caja whitelists at:
* https://code.google.com/p/google-caja/wiki/CajaWhitelists.
*
* Common things which are not allowed are script elements, style attributes
* and any script handlers.
*/
void allowHtml5({UriPolicy? uriPolicy}) {
add(new _Html5NodeValidator(uriPolicy: uriPolicy));
}
/**
* Allow SVG elements and attributes except for known bad ones.
*/
void allowSvg() {
add(new _SvgNodeValidator());
}
/**
* Allow custom elements with the specified tag name and specified attributes.
*
* This will allow the elements as custom tags (such as <x-foo></x-foo>),
* but will not allow tag extensions. Use [allowTagExtension] to allow
* tag extensions.
*/
void allowCustomElement(String tagName,
{UriPolicy? uriPolicy,
Iterable<String>? attributes,
Iterable<String>? uriAttributes}) {
var tagNameUpper = tagName.toUpperCase();
var attrs = attributes
?.map<String>((name) => '$tagNameUpper::${name.toLowerCase()}');
var uriAttrs = uriAttributes
?.map<String>((name) => '$tagNameUpper::${name.toLowerCase()}');
if (uriPolicy == null) {
uriPolicy = new UriPolicy();
}
add(new _CustomElementNodeValidator(
uriPolicy, [tagNameUpper], attrs, uriAttrs, false, true));
}
/**
* Allow custom tag extensions with the specified type name and specified
* attributes.
*
* This will allow tag extensions (such as <div is="x-foo"></div>),
* but will not allow custom tags. Use [allowCustomElement] to allow
* custom tags.
*/
void allowTagExtension(String tagName, String baseName,
{UriPolicy? uriPolicy,
Iterable<String>? attributes,
Iterable<String>? uriAttributes}) {
var baseNameUpper = baseName.toUpperCase();
var tagNameUpper = tagName.toUpperCase();
var attrs = attributes
?.map<String>((name) => '$baseNameUpper::${name.toLowerCase()}');
var uriAttrs = uriAttributes
?.map<String>((name) => '$baseNameUpper::${name.toLowerCase()}');
if (uriPolicy == null) {
uriPolicy = new UriPolicy();
}
add(new _CustomElementNodeValidator(uriPolicy,
[tagNameUpper, baseNameUpper], attrs, uriAttrs, true, false));
}
void allowElement(String tagName,
{UriPolicy? uriPolicy,
Iterable<String>? attributes,
Iterable<String>? uriAttributes}) {
allowCustomElement(tagName,
uriPolicy: uriPolicy,
attributes: attributes,
uriAttributes: uriAttributes);
}
/**
* Allow templating elements (such as <template> and template-related
* attributes.
*
* This still requires other validators to allow regular attributes to be
* bound (such as [allowHtml5]).
*/
void allowTemplating() {
add(new _TemplatingNodeValidator());
}
/**
* Add an additional validator to the current list of validators.
*
* Elements and attributes will be accepted if they are accepted by any
* validators.
*/
void add(NodeValidator validator) {
_validators.add(validator);
}
bool allowsElement(Element element) {
return _validators.any((v) => v.allowsElement(element));
}
bool allowsAttribute(Element element, String attributeName, String value) {
return _validators
.any((v) => v.allowsAttribute(element, attributeName, value));
}
}
class _SimpleNodeValidator implements NodeValidator {
final Set<String> allowedElements = new Set<String>();
final Set<String> allowedAttributes = new Set<String>();
final Set<String> allowedUriAttributes = new Set<String>();
final UriPolicy? uriPolicy;
factory _SimpleNodeValidator.allowNavigation(UriPolicy uriPolicy) {
return new _SimpleNodeValidator(uriPolicy, allowedElements: const [
'A',
'FORM'
], allowedAttributes: const [
'A::accesskey',
'A::coords',
'A::hreflang',
'A::name',
'A::shape',
'A::tabindex',
'A::target',
'A::type',
'FORM::accept',
'FORM::autocomplete',
'FORM::enctype',
'FORM::method',
'FORM::name',
'FORM::novalidate',
'FORM::target',
], allowedUriAttributes: const [
'A::href',
'FORM::action',
]);
}
factory _SimpleNodeValidator.allowImages(UriPolicy uriPolicy) {
return new _SimpleNodeValidator(uriPolicy, allowedElements: const [
'IMG'
], allowedAttributes: const [
'IMG::align',
'IMG::alt',
'IMG::border',
'IMG::height',
'IMG::hspace',
'IMG::ismap',
'IMG::name',
'IMG::usemap',
'IMG::vspace',
'IMG::width',
], allowedUriAttributes: const [
'IMG::src',
]);
}
factory _SimpleNodeValidator.allowTextElements() {
return new _SimpleNodeValidator(null, allowedElements: const [
'B',
'BLOCKQUOTE',
'BR',
'EM',
'H1',
'H2',
'H3',
'H4',
'H5',
'H6',
'HR',
'I',
'LI',
'OL',
'P',
'SPAN',
'UL',
]);
}
/**
* Elements must be uppercased tag names. For example `'IMG'`.
* Attributes must be uppercased tag name followed by :: followed by
* lowercase attribute name. For example `'IMG:src'`.
*/
_SimpleNodeValidator(this.uriPolicy,
{Iterable<String>? allowedElements,
Iterable<String>? allowedAttributes,
Iterable<String>? allowedUriAttributes}) {
this.allowedElements.addAll(allowedElements ?? const []);
allowedAttributes = allowedAttributes ?? const [];
allowedUriAttributes = allowedUriAttributes ?? const [];
var legalAttributes = allowedAttributes
.where((x) => !_Html5NodeValidator._uriAttributes.contains(x));
var extraUriAttributes = allowedAttributes
.where((x) => _Html5NodeValidator._uriAttributes.contains(x));
this.allowedAttributes.addAll(legalAttributes);
this.allowedUriAttributes.addAll(allowedUriAttributes);
this.allowedUriAttributes.addAll(extraUriAttributes);
}
bool allowsElement(Element element) {
return allowedElements.contains(Element._safeTagName(element));
}
bool allowsAttribute(Element element, String attributeName, String value) {
var tagName = Element._safeTagName(element);
if (allowedUriAttributes.contains('$tagName::$attributeName')) {
return uriPolicy!.allowsUri(value);
} else if (allowedUriAttributes.contains('*::$attributeName')) {
return uriPolicy!.allowsUri(value);
} else if (allowedAttributes.contains('$tagName::$attributeName')) {
return true;
} else if (allowedAttributes.contains('*::$attributeName')) {
return true;
} else if (allowedAttributes.contains('$tagName::*')) {
return true;
} else if (allowedAttributes.contains('*::*')) {
return true;
}
return false;
}
}
class _CustomElementNodeValidator extends _SimpleNodeValidator {
final bool allowTypeExtension;
final bool allowCustomTag;
_CustomElementNodeValidator(
UriPolicy uriPolicy,
Iterable<String> allowedElements,
Iterable<String>? allowedAttributes,
Iterable<String>? allowedUriAttributes,
bool allowTypeExtension,
bool allowCustomTag)
: this.allowTypeExtension = allowTypeExtension == true,
this.allowCustomTag = allowCustomTag == true,
super(uriPolicy,
allowedElements: allowedElements,
allowedAttributes: allowedAttributes,
allowedUriAttributes: allowedUriAttributes);
bool allowsElement(Element element) {
if (allowTypeExtension) {
var isAttr = element.attributes['is'];
if (isAttr != null) {
return allowedElements.contains(isAttr.toUpperCase()) &&
allowedElements.contains(Element._safeTagName(element));
}
}
return allowCustomTag &&
allowedElements.contains(Element._safeTagName(element));
}
bool allowsAttribute(Element element, String attributeName, String value) {
if (allowsElement(element)) {
if (allowTypeExtension &&
attributeName == 'is' &&
allowedElements.contains(value.toUpperCase())) {
return true;
}
return super.allowsAttribute(element, attributeName, value);
}
return false;
}
}
class _TemplatingNodeValidator extends _SimpleNodeValidator {
static const _TEMPLATE_ATTRS = const <String>[
'bind',
'if',
'ref',
'repeat',
'syntax'
];
final Set<String> _templateAttrs;
_TemplatingNodeValidator()
: _templateAttrs = new Set<String>.from(_TEMPLATE_ATTRS),
super(null,
allowedElements: ['TEMPLATE'],
allowedAttributes:
_TEMPLATE_ATTRS.map((attr) => 'TEMPLATE::$attr')) {}
bool allowsAttribute(Element element, String attributeName, String value) {
if (super.allowsAttribute(element, attributeName, value)) {
return true;
}
if (attributeName == 'template' && value == "") {
return true;
}
if (element.attributes['template'] == "") {
return _templateAttrs.contains(attributeName);
}
return false;
}
}
class _SvgNodeValidator implements NodeValidator {
bool allowsElement(Element element) {
if (element is svg.ScriptElement) {
return false;
}
// Firefox 37 has issues with creating foreign elements inside a
// foreignobject tag as SvgElement. We don't want foreignobject contents
// anyway, so just remove the whole tree outright. And we can't rely
// on IE recognizing the SvgForeignObject type, so go by tagName. Bug 23144
if (element is svg.SvgElement &&
Element._safeTagName(element) == 'foreignObject') {
return false;
}
if (element is svg.SvgElement) {
return true;
}
return false;
}
bool allowsAttribute(Element element, String attributeName, String value) {
if (attributeName == 'is' || attributeName.startsWith('on')) {
return false;
}
return allowsElement(element);
}
}
-26
View File
@@ -1,26 +0,0 @@
// Copyright (c) 2011, 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.
part of html;
/**
* Contains the set of standard values returned by HTMLDocument.getReadyState.
*/
abstract class ReadyState {
/**
* Indicates the document is still loading and parsing.
*/
static const String LOADING = "loading";
/**
* Indicates the document is finished parsing but is still loading
* subresources.
*/
static const String INTERACTIVE = "interactive";
/**
* Indicates the document and all subresources have been loaded.
*/
static const String COMPLETE = "complete";
}
-321
View File
@@ -1,321 +0,0 @@
// 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.
part of dart.dom.html;
/**
* Interface used to validate that only accepted elements and attributes are
* allowed while parsing HTML strings into DOM nodes.
*
* In general, customization of validation behavior should be done via the
* [NodeValidatorBuilder] class to mitigate the chances of incorrectly
* implementing validation rules.
*/
abstract class NodeValidator {
/**
* Construct a default NodeValidator which only accepts whitelisted HTML5
* elements and attributes.
*
* If a uriPolicy is not specified then the default uriPolicy will be used.
*/
factory NodeValidator({UriPolicy? uriPolicy}) =>
new _Html5NodeValidator(uriPolicy: uriPolicy);
factory NodeValidator.throws(NodeValidator base) =>
new _ThrowsNodeValidator(base);
/**
* Returns true if the tagName is an accepted type.
*/
bool allowsElement(Element element);
/**
* Returns true if the attribute is allowed.
*
* The attributeName parameter will always be in lowercase.
*
* See [allowsElement] for format of tagName.
*/
bool allowsAttribute(Element element, String attributeName, String value);
}
/**
* Performs sanitization of a node tree after construction to ensure that it
* does not contain any disallowed elements or attributes.
*
* In general custom implementations of this class should not be necessary and
* all validation customization should be done in custom NodeValidators, but
* custom implementations of this class can be created to perform more complex
* tree sanitization.
*/
abstract class NodeTreeSanitizer {
/**
* Constructs a default tree sanitizer which will remove all elements and
* attributes which are not allowed by the provided validator.
*/
factory NodeTreeSanitizer(NodeValidator validator) =>
new _ValidatingTreeSanitizer(validator);
/**
* Called with the root of the tree which is to be sanitized.
*
* This method needs to walk the entire tree and either remove elements and
* attributes which are not recognized as safe or throw an exception which
* will mark the entire tree as unsafe.
*/
void sanitizeTree(Node node);
/**
* A sanitizer for trees that we trust. It does no validation and allows
* any elements. It is also more efficient, since it can pass the text
* directly through to the underlying APIs without creating a document
* fragment to be sanitized.
*/
static const trusted = const _TrustedHtmlTreeSanitizer();
}
/**
* A sanitizer for trees that we trust. It does no validation and allows
* any elements.
*/
class _TrustedHtmlTreeSanitizer implements NodeTreeSanitizer {
const _TrustedHtmlTreeSanitizer();
sanitizeTree(Node node) {}
}
/**
* Defines the policy for what types of uris are allowed for particular
* attribute values.
*
* This can be used to provide custom rules such as allowing all http:// URIs
* for image attributes but only same-origin URIs for anchor tags.
*/
abstract class UriPolicy {
/**
* Constructs the default UriPolicy which is to only allow Uris to the same
* origin as the application was launched from.
*
* This will block all ftp: mailto: URIs. It will also block accessing
* https://example.com if the app is running from http://example.com.
*/
factory UriPolicy() => new _SameOriginUriPolicy();
/**
* Checks if the uri is allowed on the specified attribute.
*
* The uri provided may or may not be a relative path.
*/
bool allowsUri(String uri);
}
/**
* Allows URIs to the same origin as the current application was loaded from
* (such as https://example.com:80).
*/
class _SameOriginUriPolicy implements UriPolicy {
final AnchorElement _hiddenAnchor = new AnchorElement();
final Location _loc = window.location;
bool allowsUri(String uri) {
_hiddenAnchor.href = uri;
// IE leaves an empty hostname for same-origin URIs.
return (_hiddenAnchor.hostname == _loc.hostname &&
_hiddenAnchor.port == _loc.port &&
_hiddenAnchor.protocol == _loc.protocol) ||
(_hiddenAnchor.hostname == '' &&
_hiddenAnchor.port == '' &&
(_hiddenAnchor.protocol == ':' || _hiddenAnchor.protocol == ''));
}
}
class _ThrowsNodeValidator implements NodeValidator {
final NodeValidator validator;
_ThrowsNodeValidator(this.validator) {}
bool allowsElement(Element element) {
if (!validator.allowsElement(element)) {
throw new ArgumentError(Element._safeTagName(element));
}
return true;
}
bool allowsAttribute(Element element, String attributeName, String value) {
if (!validator.allowsAttribute(element, attributeName, value)) {
throw new ArgumentError(
'${Element._safeTagName(element)}[$attributeName="$value"]');
}
return true;
}
}
/**
* Standard tree sanitizer which validates a node tree against the provided
* validator and removes any nodes or attributes which are not allowed.
*/
class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
NodeValidator validator;
/// Did we modify the tree by removing anything.
bool modifiedTree = false;
_ValidatingTreeSanitizer(this.validator) {}
void sanitizeTree(Node node) {
void walk(Node node, Node? parent) {
sanitizeNode(node, parent);
var child = node.lastChild;
while (null != child) {
Node? nextChild;
try {
// Child may be removed during the walk, and we may not even be able
// to get its previousNode. But it's also possible that previousNode
// (i.e. previousSibling) is being spoofed, so double-check it.
nextChild = child.previousNode;
if (nextChild != null && nextChild.nextNode != child) {
throw StateError("Corrupt HTML");
}
} catch (e) {
// Child appears bad, remove it. We want to check the rest of the
// children of node and, but we have no way of getting to the next
// child, so start again from the last child.
_removeNode(child, node);
child = null;
nextChild = node.lastChild;
}
if (child != null) walk(child, node);
child = nextChild;
}
}
modifiedTree = false;
walk(node, null);
while (modifiedTree) {
modifiedTree = false;
walk(node, null);
}
}
/// Aggressively try to remove node.
void _removeNode(Node node, Node? parent) {
// If we have the parent, it's presumably already passed more sanitization
// or is the fragment, so ask it to remove the child. And if that fails
// try to set the outer html.
modifiedTree = true;
if (parent == null || parent != node.parentNode) {
node.remove();
} else {
parent._removeChild(node);
}
}
/// Sanitize the element, assuming we can't trust anything about it.
void _sanitizeUntrustedElement(/* Element */ element, Node? parent) {
// If the _hasCorruptedAttributes does not successfully return false,
// then we consider it corrupted and remove.
// TODO(alanknight): This is a workaround because on Firefox
// embed/object
// tags typeof is "function", not "object". We don't recognize them, and
// can't call methods. This does mean that you can't explicitly allow an
// embed tag. The only thing that will let it through is a null
// sanitizer that doesn't traverse the tree at all. But sanitizing while
// allowing embeds seems quite unlikely. This is also the reason that we
// can't declare the type of element, as an embed won't pass any type
// check in dart2js.
var corrupted = true;
var attrs;
var isAttr;
try {
// If getting/indexing attributes throws, count that as corrupt.
attrs = element.attributes;
isAttr = attrs['is'];
var corruptedTest1 = Element._hasCorruptedAttributes(element);
// On IE, erratically, the hasCorruptedAttributes test can return false,
// even though it clearly is corrupted. A separate copy of the test
// inlining just the basic check seems to help.
corrupted = corruptedTest1
? true
: Element._hasCorruptedAttributesAdditionalCheck(element);
} catch (e) {}
var elementText = 'element unprintable';
try {
elementText = element.toString();
} catch (e) {}
try {
var elementTagName = Element._safeTagName(element);
_sanitizeElement(element, parent, corrupted, elementText, elementTagName,
attrs, isAttr);
} on ArgumentError {
// Thrown by _ThrowsNodeValidator
rethrow;
} catch (e) {
// Unexpected exception sanitizing -> remove
_removeNode(element, parent);
window.console.warn('Removing corrupted element $elementText');
}
}
/// Having done basic sanity checking on the element, and computed the
/// important attributes we want to check, remove it if it's not valid
/// or not allowed, either as a whole or particular attributes.
void _sanitizeElement(Element element, Node? parent, bool corrupted,
String text, String tag, Map attrs, String? isAttr) {
if (false != corrupted) {
_removeNode(element, parent);
window.console
.warn('Removing element due to corrupted attributes on <$text>');
return;
}
if (!validator.allowsElement(element)) {
_removeNode(element, parent);
window.console.warn('Removing disallowed element <$tag> from $parent');
return;
}
if (isAttr != null) {
if (!validator.allowsAttribute(element, 'is', isAttr)) {
_removeNode(element, parent);
window.console.warn('Removing disallowed type extension '
'<$tag is="$isAttr">');
return;
}
}
// TODO(blois): Need to be able to get all attributes, irrespective of
// XMLNS.
var keys = attrs.keys.toList();
for (var i = attrs.length - 1; i >= 0; --i) {
var name = keys[i];
if (!validator.allowsAttribute(
element, name.toLowerCase(), attrs[name])) {
window.console.warn('Removing disallowed attribute '
'<$tag $name="${attrs[name]}">');
attrs.remove(name);
}
}
if (element is TemplateElement) {
TemplateElement template = element;
sanitizeTree(template.content);
}
}
/// Sanitize the node and its children recursively.
void sanitizeNode(Node node, Node? parent) {
switch (node.nodeType) {
case Node.ELEMENT_NODE:
_sanitizeUntrustedElement(node, parent);
break;
case Node.COMMENT_NODE:
case Node.DOCUMENT_FRAGMENT_NODE:
case Node.TEXT_NODE:
case Node.CDATA_SECTION_NODE:
break;
default:
_removeNode(node, parent);
}
}
}
-97
View File
@@ -1,97 +0,0 @@
// 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.
part of dart.dom.html;
/**
* A list which just wraps another list, for either intercepting list calls or
* retyping the list (for example, from List<A> to List<B> where B extends A).
*/
class _WrappedList<E extends Node> extends ListBase<E>
implements NodeListWrapper {
final List<Node> _list;
_WrappedList(this._list);
// Iterable APIs
Iterator<E> get iterator => new _WrappedIterator<E>(_list.iterator);
int get length => _list.length;
// Collection APIs
void add(E element) {
_list.add(element);
}
bool remove(Object? element) => _list.remove(element);
void clear() {
_list.clear();
}
// List APIs
E operator [](int index) => _list[index] as E;
void operator []=(int index, E value) {
_list[index] = value;
}
set length(int newLength) {
_list.length = newLength;
}
void sort([int compare(E a, E b)?]) {
if (compare == null) {
_list.sort();
} else {
_list.sort((Node a, Node b) => compare(a as E, b as E));
}
}
int indexOf(Object? element, [int start = 0]) =>
_list.indexOf(element as Node, start);
int lastIndexOf(Object? element, [int? start]) =>
_list.lastIndexOf(element as Node, start);
void insert(int index, E element) => _list.insert(index, element);
E removeAt(int index) => _list.removeAt(index) as E;
void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
_list.setRange(start, end, iterable, skipCount);
}
void removeRange(int start, int end) {
_list.removeRange(start, end);
}
void replaceRange(int start, int end, Iterable<E> iterable) {
_list.replaceRange(start, end, iterable);
}
void fillRange(int start, int end, [E? fillValue]) {
_list.fillRange(start, end, fillValue);
}
List<Node> get rawList => _list;
}
/**
* Iterator wrapper for _WrappedList.
*/
class _WrappedIterator<E extends Node> implements Iterator<E> {
Iterator<Node> _iterator;
_WrappedIterator(this._iterator);
bool moveNext() {
return _iterator.moveNext();
}
E get current => _iterator.current as E;
}
-26
View File
@@ -1,26 +0,0 @@
// Copyright (c) 2012, 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.
part of html;
class _HttpRequestUtils {
// Helper for factory HttpRequest.get
static HttpRequest get(
String url, onComplete(HttpRequest request), bool withCredentials) {
final request = new HttpRequest();
request.open('GET', url, async: true);
request.withCredentials = withCredentials;
request.onReadyStateChange.listen((e) {
if (request.readyState == HttpRequest.DONE) {
onComplete(request);
}
});
request.send();
return request;
}
}
-57
View File
@@ -1,57 +0,0 @@
// Copyright (c) 2011, 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.
part of html;
// Iterator for arrays with fixed size.
class FixedSizeListIterator<T> implements Iterator<T> {
final List<T> _array;
final int _length; // Cache array length for faster access.
int _position;
T? _current;
FixedSizeListIterator(List<T> array)
: _array = array,
_position = -1,
_length = array.length;
bool moveNext() {
int nextPosition = _position + 1;
if (nextPosition < _length) {
_current = _array[nextPosition];
_position = nextPosition;
return true;
}
_current = null;
_position = _length;
return false;
}
T get current => _current as T;
}
// Iterator for arrays with variable size.
class _VariableSizeListIterator<T> implements Iterator<T> {
final List<T> _array;
int _position;
T? _current;
_VariableSizeListIterator(List<T> array)
: _array = array,
_position = -1;
bool moveNext() {
int nextPosition = _position + 1;
if (nextPosition < _array.length) {
_current = _array[nextPosition];
_position = nextPosition;
return true;
}
_current = null;
_position = _array.length;
return false;
}
T get current => _current as T;
}
-82
View File
@@ -1,82 +0,0 @@
// Copyright (c) 2017, 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.
part of html;
class Console {
const Console._safe();
static const Console _safeConsole = const Console._safe();
bool get _isConsoleDefined => JS('bool', 'typeof console != "undefined"');
MemoryInfo? get memory =>
_isConsoleDefined ? JS('MemoryInfo', 'window.console.memory') : null;
void assertCondition(bool condition, Object arg) => _isConsoleDefined
? JS('void', 'window.console.assertCondition(#, #)', condition, arg)
: null;
void clear(Object arg) =>
_isConsoleDefined ? JS('void', 'window.console.clear(#)', arg) : null;
void count(Object arg) =>
_isConsoleDefined ? JS('void', 'window.console.count(#)', arg) : null;
void debug(Object arg) =>
_isConsoleDefined ? JS('void', 'window.console.debug(#)', arg) : null;
void dir(Object arg) =>
_isConsoleDefined ? JS('void', 'window.console.dir(#)', arg) : null;
void dirxml(Object arg) =>
_isConsoleDefined ? JS('void', 'window.console.dirxml(#)', arg) : null;
void error(Object arg) =>
_isConsoleDefined ? JS('void', 'window.console.error(#)', arg) : null;
void group(Object arg) =>
_isConsoleDefined ? JS('void', 'window.console.group(#)', arg) : null;
void groupCollapsed(Object arg) => _isConsoleDefined
? JS('void', 'window.console.groupCollapsed(#)', arg)
: null;
void groupEnd() =>
_isConsoleDefined ? JS('void', 'window.console.groupEnd()') : null;
void info(Object arg) =>
_isConsoleDefined ? JS('void', 'window.console.info(#)', arg) : null;
void log(Object arg) =>
_isConsoleDefined ? JS('void', 'window.console.log(#)', arg) : null;
void markTimeline(Object arg) => _isConsoleDefined
? JS('void', 'window.console.markTimeline(#)', arg)
: null;
void profile(String title) =>
_isConsoleDefined ? JS('void', 'window.console.profile(#)', title) : null;
void profileEnd(String title) => _isConsoleDefined
? JS('void', 'window.console.profileEnd(#)', title)
: null;
void table(Object arg) =>
_isConsoleDefined ? JS('void', 'window.console.table(#)', arg) : null;
void time(String title) =>
_isConsoleDefined ? JS('void', 'window.console.time(#)', title) : null;
void timeEnd(String title) =>
_isConsoleDefined ? JS('void', 'window.console.timeEnd(#)', title) : null;
void timeStamp(Object arg) =>
_isConsoleDefined ? JS('void', 'window.console.timeStamp(#)', arg) : null;
void trace(Object arg) =>
_isConsoleDefined ? JS('void', 'window.console.trace(#)', arg) : null;
void warn(Object arg) =>
_isConsoleDefined ? JS('void', 'window.console.warn(#)', arg) : null;
}
@@ -1,49 +0,0 @@
// Copyright (c) 2012, 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.
// Conversions for Window. These check if the window is the local
// window, and if it's not, wraps or unwraps it with a secure wrapper.
// We need to test for EventTarget here as well as it's a base type.
// We omit an unwrapper for Window as no methods take a non-local
// window as a parameter.
part of html;
WindowBase? _convertNativeToDart_Window(win) {
if (win == null) return null;
return _DOMWindowCrossFrame._createSafe(win);
}
EventTarget? _convertNativeToDart_EventTarget(e) {
if (e == null) {
return null;
}
// Assume it's a Window if it contains the postMessage property. It may be
// from a different frame - without a patched prototype - so we cannot
// rely on Dart type checking.
if (JS('bool', r'"postMessage" in #', e)) {
var window = _DOMWindowCrossFrame._createSafe(e);
// If it's a native window.
if (window is EventTarget) {
return window;
}
return null;
} else
return e;
}
EventTarget? _convertDartToNative_EventTarget(e) {
if (e is _DOMWindowCrossFrame) {
return e._window;
} else {
return e;
}
}
_convertNativeToDart_XHR_Response(o) {
if (o is Document) {
return o;
}
return convertNativeToDart_SerializedScriptValue(o);
}
-260
View File
@@ -1,260 +0,0 @@
// Copyright (c) 2015, 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.
part of html;
/**
* A set (union) of the CSS classes that are present in a set of elements.
* Implemented separately from _ElementCssClassSet for performance.
*/
class _MultiElementCssClassSet extends CssClassSetImpl {
final Iterable<Element> _elementIterable;
// TODO(sra): Perhaps we should store the DomTokenList instead.
final List<CssClassSetImpl> _sets;
factory _MultiElementCssClassSet(Iterable<Element> elements) {
return new _MultiElementCssClassSet._(elements,
new List<CssClassSetImpl>.from(elements.map((Element e) => e.classes)));
}
_MultiElementCssClassSet._(this._elementIterable, this._sets);
Set<String> readClasses() {
var s = new LinkedHashSet<String>();
_sets.forEach((CssClassSetImpl e) => s.addAll(e.readClasses()));
return s;
}
void writeClasses(Set<String> s) {
var classes = s.join(' ');
for (Element e in _elementIterable) {
e.className = classes;
}
}
/**
* Helper method used to modify the set of css classes on this element.
*
* f - callback with:
* s - a Set of all the css class name currently on this element.
*
* After f returns, the modified set is written to the
* className property of this element.
*/
modify(f(Set<String> s)) {
_sets.forEach((CssClassSetImpl e) => e.modify(f));
}
/**
* Adds the class [value] to the element if it is not on it, removes it if it
* is.
*
* TODO(sra): It seems wrong to collect a 'changed' flag like this when the
* underlying toggle returns an 'is set' flag.
*/
bool toggle(String value, [bool? shouldAdd]) => _sets.fold(
false,
(bool changed, CssClassSetImpl e) =>
e.toggle(value, shouldAdd) || changed);
/**
* Remove the class [value] from element, and return true on successful
* removal.
*
* This is the Dart equivalent of jQuery's
* [removeClass](http://api.jquery.com/removeClass/).
*/
bool remove(Object? value) => _sets.fold(
false, (bool changed, CssClassSetImpl e) => e.remove(value) || changed);
}
class _ElementCssClassSet extends CssClassSetImpl {
final Element _element;
_ElementCssClassSet(this._element);
Set<String> readClasses() {
var s = new LinkedHashSet<String>();
var classname = _element.className;
for (String name in classname.split(' ')) {
String trimmed = name.trim();
if (!trimmed.isEmpty) {
s.add(trimmed);
}
}
return s;
}
void writeClasses(Set<String> s) {
_element.className = s.join(' ');
}
int get length => _classListLength(_classListOf(_element));
bool get isEmpty => length == 0;
bool get isNotEmpty => length != 0;
void clear() {
_element.className = '';
}
bool contains(Object? value) {
return _contains(_element, value);
}
bool add(String value) {
return _add(_element, value);
}
bool remove(Object? value) {
return value is String && _remove(_element, value);
}
bool toggle(String value, [bool? shouldAdd]) {
return _toggle(_element, value, shouldAdd);
}
void addAll(Iterable<String> iterable) {
_addAll(_element, iterable);
}
void removeAll(Iterable<Object?> iterable) {
_removeAll(_element, iterable);
}
void retainAll(Iterable<Object?> iterable) {
_removeWhere(_element, iterable.toSet().contains, false);
}
void removeWhere(bool test(String name)) {
_removeWhere(_element, test, true);
}
void retainWhere(bool test(String name)) {
_removeWhere(_element, test, false);
}
static bool _contains(Element _element, Object? value) {
return value is String && _classListContains(_classListOf(_element), value);
}
@pragma('dart2js:tryInline')
static bool _add(Element _element, String value) {
DomTokenList list = _classListOf(_element);
// Compute returned result independently of action upon the set.
bool added = !_classListContainsBeforeAddOrRemove(list, value);
_classListAdd(list, value);
return added;
}
@pragma('dart2js:tryInline')
static bool _remove(Element _element, String value) {
DomTokenList list = _classListOf(_element);
bool removed = _classListContainsBeforeAddOrRemove(list, value);
_classListRemove(list, value);
return removed;
}
static bool _toggle(Element _element, String value, bool? shouldAdd) {
// There is no value that can be passed as the second argument of
// DomTokenList.toggle that behaves the same as passing one argument.
// `null` is seen as false, meaning 'remove'.
return shouldAdd == null
? _toggleDefault(_element, value)
: _toggleOnOff(_element, value, shouldAdd);
}
static bool _toggleDefault(Element _element, String value) {
DomTokenList list = _classListOf(_element);
return _classListToggle1(list, value);
}
static bool _toggleOnOff(Element _element, String value, bool? shouldAdd) {
DomTokenList list = _classListOf(_element);
// IE's toggle does not take a second parameter. We would prefer:
//
// return _classListToggle2(list, value, shouldAdd);
//
if (shouldAdd ?? false) {
_classListAdd(list, value);
return true;
} else {
_classListRemove(list, value);
return false;
}
}
static void _addAll(Element _element, Iterable<String> iterable) {
DomTokenList list = _classListOf(_element);
for (String value in iterable) {
_classListAdd(list, value);
}
}
static void _removeAll(Element _element, Iterable<Object?> iterable) {
DomTokenList list = _classListOf(_element);
for (Object? value in iterable) {
_classListRemove(list, value as String);
}
}
static void _removeWhere(
Element _element, bool test(String name), bool doRemove) {
DomTokenList list = _classListOf(_element);
int i = 0;
while (i < _classListLength(list)) {
String item = list.item(i)!;
if (doRemove == test(item)) {
_classListRemove(list, item);
} else {
++i;
}
}
}
// A collection of static methods for DomTokenList. These methods are a
// work-around for the lack of annotations to express the full behaviour of
// the DomTokenList methods.
static DomTokenList _classListOf(Element e) => JS(
'returns:DomTokenList;creates:DomTokenList;effects:none;depends:all;',
'#.classList',
e);
static int _classListLength(DomTokenList list) =>
JS('returns:JSUInt31;effects:none;depends:all;', '#.length', list);
static bool _classListContains(DomTokenList list, String value) =>
JS('returns:bool;effects:none;depends:all', '#.contains(#)', list, value);
static bool _classListContainsBeforeAddOrRemove(
DomTokenList list, String value) =>
// 'throws:never' is a lie, since 'contains' will throw on an illegal
// token. However, we always call this function immediately prior to
// add/remove/toggle with the same token. Often the result of 'contains'
// is unused and the lie makes it possible for the 'contains' instruction
// to be removed.
JS('returns:bool;effects:none;depends:all;throws:null(1)',
'#.contains(#)', list, value);
static void _classListAdd(DomTokenList list, String value) {
// list.add(value);
JS('', '#.add(#)', list, value);
}
static void _classListRemove(DomTokenList list, String value) {
// list.remove(value);
JS('', '#.remove(#)', list, value);
}
static bool _classListToggle1(DomTokenList list, String value) {
return JS('bool', '#.toggle(#)', list, value);
}
static bool _classListToggle2(
DomTokenList list, String value, bool? shouldAdd) {
return JS('bool', '#.toggle(#, #)', list, value, shouldAdd);
}
}
@@ -1,214 +0,0 @@
// 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.
part of dart.dom.html;
_callConstructor(constructor, interceptor) {
return (receiver) {
setNativeSubclassDispatchRecord(receiver, interceptor);
// Mirrors uses the constructor property to cache lookups, so we need it to
// be set correctly, including on IE where it is not automatically picked
// up from the __proto__.
JS('', '#.constructor = #.__proto__.constructor', receiver, receiver);
return JS('', '#(#)', constructor, receiver);
};
}
_callAttached(receiver) {
return receiver.attached();
}
_callDetached(receiver) {
return receiver.detached();
}
_callAttributeChanged(receiver, name, oldValue, newValue) {
return receiver.attributeChanged(name, oldValue, newValue);
}
_makeCallbackMethod(callback) {
return JS(
'',
'''((function(invokeCallback) {
return function() {
return invokeCallback(this);
};
})(#))''',
convertDartClosureToJS(callback, 1));
}
_makeCallbackMethod3(callback) {
return JS(
'',
'''((function(invokeCallback) {
return function(arg1, arg2, arg3) {
return invokeCallback(this, arg1, arg2, arg3);
};
})(#))''',
convertDartClosureToJS(callback, 4));
}
/// Checks whether the given [element] correctly extends from the native class
/// with the given [baseClassName]. This method will throw if the base class
/// doesn't match, except when the element extends from `template` and it's base
/// class is `HTMLUnknownElement`. This exclusion is needed to support extension
/// of template elements (used heavily in Polymer 1.0) on IE11 when using the
/// webcomponents-lite.js polyfill.
void _checkExtendsNativeClassOrTemplate(
Element element, String extendsTag, String baseClassName) {
if (!JS('bool', '(# instanceof window[#])', element, baseClassName) &&
!((extendsTag == 'template' &&
JS('bool', '(# instanceof window["HTMLUnknownElement"])',
element)))) {
throw new UnsupportedError('extendsTag does not match base native class');
}
}
Function _registerCustomElement(context, document, String tag, [Map? options]) {
// Function follows the same pattern as the following JavaScript code for
// registering a custom element.
//
// var proto = Object.create(HTMLElement.prototype, {
// createdCallback: {
// value: function() {
// window.console.log('here');
// }
// }
// });
// document.registerElement('x-foo', { prototype: proto });
// ...
// var e = document.createElement('x-foo');
var extendsTagName = '';
Type? type;
if (options != null) {
extendsTagName = options['extends'];
type = options['prototype'];
}
var interceptorClass = findInterceptorConstructorForType(type);
if (interceptorClass == null) {
throw new ArgumentError(type);
}
var interceptor = JS('=Object', '#.prototype', interceptorClass);
var constructor = findConstructorForNativeSubclassType(type, 'created');
if (constructor == null) {
throw new ArgumentError("$type has no constructor called 'created'");
}
// Workaround for 13190- use an article element to ensure that HTMLElement's
// interceptor is resolved correctly.
getNativeInterceptor(new Element.tag('article'));
String baseClassName = findDispatchTagForInterceptorClass(interceptorClass);
if (baseClassName == null) {
throw new ArgumentError(type);
}
if (extendsTagName == null) {
if (baseClassName != 'HTMLElement') {
throw new UnsupportedError('Class must provide extendsTag if base '
'native class is not HtmlElement');
}
} else {
var element = document.createElement(extendsTagName);
_checkExtendsNativeClassOrTemplate(element, extendsTagName, baseClassName);
}
var baseConstructor = JS('=Object', '#[#]', context, baseClassName);
var properties = JS('=Object', '{}');
JS(
'void',
'#.createdCallback = #',
properties,
JS('=Object', '{value: #}',
_makeCallbackMethod(_callConstructor(constructor, interceptor))));
JS('void', '#.attachedCallback = #', properties,
JS('=Object', '{value: #}', _makeCallbackMethod(_callAttached)));
JS('void', '#.detachedCallback = #', properties,
JS('=Object', '{value: #}', _makeCallbackMethod(_callDetached)));
JS('void', '#.attributeChangedCallback = #', properties,
JS('=Object', '{value: #}', _makeCallbackMethod3(_callAttributeChanged)));
var baseProto = JS('=Object', '#.prototype', baseConstructor);
var proto = JS('=Object', 'Object.create(#, #)', baseProto, properties);
setNativeSubclassDispatchRecord(proto, interceptor);
var opts = JS('=Object', '{prototype: #}', proto);
if (extendsTagName != null) {
JS('=Object', '#.extends = #', opts, extendsTagName);
}
return JS(
'JavaScriptFunction', '#.registerElement(#, #)', document, tag, opts);
}
//// Called by Element.created to do validation & initialization.
void _initializeCustomElement(Element e) {
// TODO(blois): Add validation that this is only in response to an upgrade.
}
/// Dart2JS implementation of ElementUpgrader
class _JSElementUpgrader implements ElementUpgrader {
var _interceptor;
var _constructor;
var _nativeType;
_JSElementUpgrader(Document document, Type type, String? extendsTag) {
var interceptorClass = findInterceptorConstructorForType(type);
if (interceptorClass == null) {
throw new ArgumentError(type);
}
_constructor = findConstructorForNativeSubclassType(type, 'created');
if (_constructor == null) {
throw new ArgumentError("$type has no constructor called 'created'");
}
// Workaround for 13190- use an article element to ensure that HTMLElement's
// interceptor is resolved correctly.
getNativeInterceptor(new Element.tag('article'));
var baseClassName = findDispatchTagForInterceptorClass(interceptorClass);
if (baseClassName == null) {
throw new ArgumentError(type);
}
if (extendsTag == null) {
if (baseClassName != 'HTMLElement') {
throw new UnsupportedError('Class must provide extendsTag if base '
'native class is not HtmlElement');
}
_nativeType = HtmlElement;
} else {
var element = document.createElement(extendsTag);
_checkExtendsNativeClassOrTemplate(element, extendsTag, baseClassName);
_nativeType = element.runtimeType;
}
_interceptor = JS('=Object', '#.prototype', interceptorClass);
}
Element upgrade(Element element) {
// Only exact type matches are supported- cannot be a subclass.
if (element.runtimeType != _nativeType) {
// Some browsers may represent non-upgraded elements <x-foo> as
// UnknownElement and not a plain HtmlElement.
if (_nativeType != HtmlElement || element.runtimeType != UnknownElement) {
throw new ArgumentError('element is not subclass of $_nativeType');
}
}
setNativeSubclassDispatchRecord(element, _interceptor);
JS('', '#(#)', _constructor, element);
return element;
}
}
@@ -1,136 +0,0 @@
// Copyright (c) 2012, 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.
part of html;
// TODO(vsm): Unify with Dartium version.
class _DOMWindowCrossFrame implements WindowBase {
// Private window. Note, this is a window in another frame, so it
// cannot be typed as "Window" as its prototype is not patched
// properly. Its fields and methods can only be accessed via JavaScript.
final _window;
// Fields.
HistoryBase get history =>
_HistoryCrossFrame._createSafe(JS('HistoryBase', '#.history', _window));
LocationBase get location => _LocationCrossFrame._createSafe(
JS('LocationBase', '#.location', _window));
// TODO(vsm): Add frames to navigate subframes. See 2312.
bool get closed => JS('bool', '#.closed', _window);
WindowBase get opener => _createSafe(JS('WindowBase', '#.opener', _window));
WindowBase get parent => _createSafe(JS('WindowBase', '#.parent', _window));
WindowBase get top => _createSafe(JS('WindowBase', '#.top', _window));
// Methods.
void close() => JS('void', '#.close()', _window);
void postMessage(var message, String targetOrigin, [List? messagePorts]) {
if (messagePorts == null) {
JS('void', '#.postMessage(#,#)', _window,
convertDartToNative_SerializedScriptValue(message), targetOrigin);
} else {
JS(
'void',
'#.postMessage(#,#,#)',
_window,
convertDartToNative_SerializedScriptValue(message),
targetOrigin,
messagePorts);
}
}
// Implementation support.
_DOMWindowCrossFrame(this._window);
static WindowBase _createSafe(w) {
if (identical(w, window)) {
return w;
} else {
// TODO(vsm): Cache or implement equality.
registerGlobalObject(w);
return new _DOMWindowCrossFrame(w);
}
}
// TODO(efortuna): Remove this method. dartbug.com/16814
Events get on => throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
void _addEventListener(String? type, EventListener? listener,
[bool? useCapture]) =>
throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
void addEventListener(String type, EventListener? listener,
[bool? useCapture]) =>
throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
bool dispatchEvent(Event event) => throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
void _removeEventListener(String? type, EventListener? listener,
[bool? useCapture]) =>
throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
void removeEventListener(String type, EventListener? listener,
[bool? useCapture]) =>
throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
}
class _LocationCrossFrame implements LocationBase {
// Private location. Note, this is a location object in another frame, so it
// cannot be typed as "Location" as its prototype is not patched
// properly. Its fields and methods can only be accessed via JavaScript.
var _location;
set href(String val) => _setHref(_location, val);
static void _setHref(location, val) {
JS('void', '#.href = #', location, val);
}
// Implementation support.
_LocationCrossFrame(this._location);
static LocationBase _createSafe(location) {
if (identical(location, window.location)) {
return location;
} else {
// TODO(vsm): Cache or implement equality.
return new _LocationCrossFrame(location);
}
}
}
class _HistoryCrossFrame implements HistoryBase {
// Private history. Note, this is a history object in another frame, so it
// cannot be typed as "History" as its prototype is not patched
// properly. Its fields and methods can only be accessed via JavaScript.
var _history;
void back() => JS('void', '#.back()', _history);
void forward() => JS('void', '#.forward()', _history);
void go(int distance) => JS('void', '#.go(#)', _history, distance);
// Implementation support.
_HistoryCrossFrame(this._history);
static HistoryBase _createSafe(h) {
if (identical(h, window.history)) {
return h;
} else {
// TODO(vsm): Cache or implement equality.
return new _HistoryCrossFrame(h);
}
}
}
-243
View File
@@ -1,243 +0,0 @@
/**
* A custom KeyboardEvent that attempts to eliminate cross-browser
* inconsistencies, and also provide both keyCode and charCode information
* for all key events (when such information can be determined).
*
* KeyEvent tries to provide a higher level, more polished keyboard event
* information on top of the "raw" [KeyboardEvent].
*
* The mechanics of using KeyEvents is a little different from the underlying
* [KeyboardEvent]. To use KeyEvents, you need to create a stream and then add
* KeyEvents to the stream, rather than using the [EventTarget.dispatchEvent].
* Here's an example usage:
*
* // Initialize a stream for the KeyEvents:
* var stream = KeyEvent.keyPressEvent.forTarget(document.body);
* // Start listening to the stream of KeyEvents.
* stream.listen((keyEvent) =>
* window.console.log('KeyPress event detected ${keyEvent.charCode}'));
* ...
* // Add a new KeyEvent of someone pressing the 'A' key to the stream so
* // listeners can know a KeyEvent happened.
* stream.add(new KeyEvent('keypress', keyCode: 65, charCode: 97));
*
* This class is very much a work in progress, and we'd love to get information
* on how we can make this class work with as many international keyboards as
* possible. Bugs welcome!
*/
class KeyEvent extends _WrappedEvent implements KeyboardEvent {
/** The parent KeyboardEvent that this KeyEvent is wrapping and "fixing". */
KeyboardEvent _parent;
/** The "fixed" value of whether the alt key is being pressed. */
bool _shadowAltKey;
/** Calculated value of what the estimated charCode is for this event. */
int _shadowCharCode;
/** Calculated value of what the estimated keyCode is for this event. */
int _shadowKeyCode;
/** Calculated value of what the estimated keyCode is for this event. */
int get keyCode => _shadowKeyCode;
/** Calculated value of what the estimated charCode is for this event. */
int get charCode => this.type == 'keypress' ? _shadowCharCode : 0;
/** Calculated value of whether the alt key is pressed is for this event. */
bool get altKey => _shadowAltKey;
/** Calculated value of what the estimated keyCode is for this event. */
int get which => keyCode;
/** Accessor to the underlying keyCode value is the parent event. */
int get _realKeyCode => JS('int', '#.keyCode', _parent);
/** Accessor to the underlying charCode value is the parent event. */
int get _realCharCode => JS('int', '#.charCode', _parent);
/** Accessor to the underlying altKey value is the parent event. */
bool get _realAltKey => JS('bool', '#.altKey', _parent);
/** Shadows on top of the parent's currentTarget. */
EventTarget? _currentTarget;
InputDeviceCapabilities? get sourceCapabilities =>
JS('InputDeviceCapabilities', '#.sourceCapabilities', this);
/**
* The value we want to use for this object's dispatch. Created here so it is
* only invoked once.
*/
static final _keyboardEventDispatchRecord = _makeRecord();
/** Helper to statically create the dispatch record. */
static _makeRecord() {
var interceptor = JS_INTERCEPTOR_CONSTANT(KeyboardEvent);
return makeLeafDispatchRecord(interceptor);
}
/** Construct a KeyEvent with [parent] as the event we're emulating. */
KeyEvent.wrap(KeyboardEvent parent)
: _parent = parent,
_shadowAltKey = false,
_shadowCharCode = 0,
_shadowKeyCode = 0,
super(parent) {
_parent = parent;
_shadowAltKey = _realAltKey;
_shadowCharCode = _realCharCode;
_shadowKeyCode = _realKeyCode;
_currentTarget = _parent.currentTarget;
}
/** Programmatically create a new KeyEvent (and KeyboardEvent). */
factory KeyEvent(String type,
{Window? view,
bool canBubble: true,
bool cancelable: true,
int keyCode: 0,
int charCode: 0,
int location: 1,
bool ctrlKey: false,
bool altKey: false,
bool shiftKey: false,
bool metaKey: false,
EventTarget? currentTarget}) {
if (view == null) {
view = window;
}
dynamic eventObj;
// Currently this works on everything but Safari. Safari throws an
// "Attempting to change access mechanism for an unconfigurable property"
// TypeError when trying to do the Object.defineProperty hack, so we avoid
// this branch if possible.
// Also, if we want this branch to work in FF, we also need to modify
// _initKeyboardEvent to also take charCode and keyCode values to
// initialize initKeyEvent.
eventObj = new Event.eventType('KeyboardEvent', type,
canBubble: canBubble, cancelable: cancelable);
// Chromium Hack
JS(
'void',
"Object.defineProperty(#, 'keyCode', {"
" get : function() { return this.keyCodeVal; } })",
eventObj);
JS(
'void',
"Object.defineProperty(#, 'which', {"
" get : function() { return this.keyCodeVal; } })",
eventObj);
JS(
'void',
"Object.defineProperty(#, 'charCode', {"
" get : function() { return this.charCodeVal; } })",
eventObj);
var keyIdentifier = _convertToHexString(charCode, keyCode);
eventObj._initKeyboardEvent(type, canBubble, cancelable, view,
keyIdentifier, location, ctrlKey, altKey, shiftKey, metaKey);
JS('void', '#.keyCodeVal = #', eventObj, keyCode);
JS('void', '#.charCodeVal = #', eventObj, charCode);
// Tell dart2js that it smells like a KeyboardEvent!
setDispatchProperty(eventObj, _keyboardEventDispatchRecord);
var keyEvent = new KeyEvent.wrap(eventObj);
if (keyEvent._currentTarget == null) {
keyEvent._currentTarget = currentTarget == null ? window : currentTarget;
}
return keyEvent;
}
// Currently known to work on all browsers but IE.
static bool get canUseDispatchEvent => JS(
'bool',
'(typeof document.body.dispatchEvent == "function")'
'&& document.body.dispatchEvent.length > 0');
/** The currently registered target for this event. */
EventTarget? get currentTarget => _currentTarget;
// This is an experimental method to be sure.
static String _convertToHexString(int charCode, int keyCode) {
if (charCode != -1) {
var hex = charCode.toRadixString(16); // Convert to hexadecimal.
StringBuffer sb = new StringBuffer('U+');
for (int i = 0; i < 4 - hex.length; i++) sb.write('0');
sb.write(hex);
return sb.toString();
} else {
return KeyCode._convertKeyCodeToKeyName(keyCode);
}
}
// TODO(efortuna): If KeyEvent is sufficiently successful that we want to make
// it the default keyboard event handling, move these methods over to Element.
/** Accessor to provide a stream of KeyEvents on the desired target. */
static EventStreamProvider<KeyEvent> keyDownEvent =
new _KeyboardEventHandler('keydown');
/** Accessor to provide a stream of KeyEvents on the desired target. */
static EventStreamProvider<KeyEvent> keyUpEvent =
new _KeyboardEventHandler('keyup');
/** Accessor to provide a stream of KeyEvents on the desired target. */
static EventStreamProvider<KeyEvent> keyPressEvent =
new _KeyboardEventHandler('keypress');
String get code => _parent.code;
/** True if the ctrl key is pressed during this event. */
bool get ctrlKey => _parent.ctrlKey;
int get detail => _parent.detail;
bool get isComposing => _parent.isComposing;
String get key => _parent.key;
/**
* Accessor to the part of the keyboard that the key was pressed from (one of
* KeyLocation.STANDARD, KeyLocation.RIGHT, KeyLocation.LEFT,
* KeyLocation.NUMPAD, KeyLocation.MOBILE, KeyLocation.JOYSTICK).
*/
int get location => _parent.location;
/** True if the Meta (or Mac command) key is pressed during this event. */
bool get metaKey => _parent.metaKey;
/** True if the shift key was pressed during this event. */
bool get shiftKey => _parent.shiftKey;
WindowBase? get view => _parent.view;
void _initUIEvent(
String type, bool canBubble, bool cancelable, Window? view, int detail) {
throw new UnsupportedError("Cannot initialize a UI Event from a KeyEvent.");
}
String get _shadowKeyIdentifier => JS('String', '#.keyIdentifier', _parent);
int get _charCode => charCode;
int get _keyCode => keyCode;
int get _which => which;
String get _keyIdentifier {
throw new UnsupportedError("keyIdentifier is unsupported.");
}
void _initKeyboardEvent(
String type,
bool canBubble,
bool cancelable,
Window? view,
String keyIdentifier,
int? location,
bool ctrlKey,
bool altKey,
bool shiftKey,
bool metaKey) {
throw new UnsupportedError(
"Cannot initialize a KeyboardEvent from a KeyEvent.");
}
bool getModifierState(String keyArgument) => throw new UnimplementedError();
bool get repeat => throw new UnimplementedError();
bool get isComposed => throw new UnimplementedError();
dynamic get _get_view => throw new UnimplementedError();
}
-21
View File
@@ -1,21 +0,0 @@
// 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.
part of html;
class Platform {
/**
* Returns true if dart:typed_data types are supported on this
* browser. If false, using these types will generate a runtime
* error.
*/
static final bool supportsTypedData = JS('bool', '!!(window.ArrayBuffer)');
/**
* Returns true if SIMD types in dart:typed_data types are supported
* on this browser. If false, using these types will generate a runtime
* error.
*/
static final supportsSimd = false;
}
@@ -1,154 +0,0 @@
// Copyright (c) 2012, 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.
part of html;
class _TypedArrayFactoryProvider {
static ByteData createByteData(int length) => _B8(length);
static ByteData createByteData_fromBuffer(ByteBuffer buffer,
[int byteOffset = 0, int length]) {
if (length == null) return _B8_2(buffer, byteOffset);
return _B8_3(buffer, byteOffset, length);
}
static Float32List createFloat32List(int length) => _F32(length);
static Float32List createFloat32List_fromList(List<num> list) =>
_F32(ensureNative(list));
static Float32List createFloat32List_fromBuffer(ByteBuffer buffer,
[int byteOffset = 0, int length]) {
if (length == null) return _F32_2(buffer, byteOffset);
return _F32_3(buffer, byteOffset, length);
}
static Float64List createFloat64List(int length) => _F64(length);
static Float64List createFloat64List_fromList(List<num> list) =>
_F64(ensureNative(list));
static Float64List createFloat64List_fromBuffer(ByteBuffer buffer,
[int byteOffset = 0, int length]) {
if (length == null) return _F64_2(buffer, byteOffset);
return _F64_3(buffer, byteOffset, length);
}
static Int8List createInt8List(int length) => _I8(length);
static Int8List createInt8List_fromList(List<num> list) =>
_I8(ensureNative(list));
static Int8List createInt8List_fromBuffer(ByteBuffer buffer,
[int byteOffset = 0, int length]) {
if (length == null) return _I8_2(buffer, byteOffset);
return _I8_3(buffer, byteOffset, length);
}
static Int16List createInt16List(int length) => _I16(length);
static Int16List createInt16List_fromList(List<num> list) =>
_I16(ensureNative(list));
static Int16List createInt16List_fromBuffer(ByteBuffer buffer,
[int byteOffset = 0, int length]) {
if (length == null) return _I16_2(buffer, byteOffset);
return _I16_3(buffer, byteOffset, length);
}
static Int32List createInt32List(int length) => _I32(length);
static Int32List createInt32List_fromList(List<num> list) =>
_I32(ensureNative(list));
static Int32List createInt32List_fromBuffer(ByteBuffer buffer,
[int byteOffset = 0, int length]) {
if (length == null) return _I32_2(buffer, byteOffset);
return _I32_3(buffer, byteOffset, length);
}
static Uint8List createUint8List(int length) => _U8(length);
static Uint8List createUint8List_fromList(List<num> list) =>
_U8(ensureNative(list));
static Uint8List createUint8List_fromBuffer(ByteBuffer buffer,
[int byteOffset = 0, int length]) {
if (length == null) return _U8_2(buffer, byteOffset);
return _U8_3(buffer, byteOffset, length);
}
static Uint16List createUint16List(int length) => _U16(length);
static Uint16List createUint16List_fromList(List<num> list) =>
_U16(ensureNative(list));
static Uint16List createUint16List_fromBuffer(ByteBuffer buffer,
[int byteOffset = 0, int length]) {
if (length == null) return _U16_2(buffer, byteOffset);
return _U16_3(buffer, byteOffset, length);
}
static Uint32List createUint32List(int length) => _U32(length);
static Uint32List createUint32List_fromList(List<num> list) =>
_U32(ensureNative(list));
static Uint32List createUint32List_fromBuffer(ByteBuffer buffer,
[int byteOffset = 0, int length]) {
if (length == null) return _U32_2(buffer, byteOffset);
return _U32_3(buffer, byteOffset, length);
}
static Uint8ClampedList createUint8ClampedList(int length) => _U8C(length);
static Uint8ClampedList createUint8ClampedList_fromList(List<num> list) =>
_U8C(ensureNative(list));
static Uint8ClampedList createUint8ClampedList_fromBuffer(ByteBuffer buffer,
[int byteOffset = 0, int length]) {
if (length == null) return _U8C_2(buffer, byteOffset);
return _U8C_3(buffer, byteOffset, length);
}
static ByteData _B8(arg) =>
JS('ByteData', 'new DataView(new ArrayBuffer(#))', arg);
static Float32List _F32(arg) => JS('Float32List', 'new Float32Array(#)', arg);
static Float64List _F64(arg) => JS('Float64List', 'new Float64Array(#)', arg);
static Int8List _I8(arg) => JS('Int8List', 'new Int8Array(#)', arg);
static Int16List _I16(arg) => JS('Int16List', 'new Int16Array(#)', arg);
static Int32List _I32(arg) => JS('Int32List', 'new Int32Array(#)', arg);
static Uint8List _U8(arg) => JS('Uint8List', 'new Uint8Array(#)', arg);
static Uint16List _U16(arg) => JS('Uint16List', 'new Uint16Array(#)', arg);
static Uint32List _U32(arg) => JS('Uint32List', 'new Uint32Array(#)', arg);
static Uint8ClampedList _U8C(arg) =>
JS('Uint8ClampedList', 'new Uint8ClampedArray(#)', arg);
static ByteData _B8_2(arg1, arg2) =>
JS('ByteData', 'new DataView(#, #)', arg1, arg2);
static Float32List _F32_2(arg1, arg2) =>
JS('Float32List', 'new Float32Array(#, #)', arg1, arg2);
static Float64List _F64_2(arg1, arg2) =>
JS('Float64List', 'new Float64Array(#, #)', arg1, arg2);
static Int8List _I8_2(arg1, arg2) =>
JS('Int8List', 'new Int8Array(#, #)', arg1, arg2);
static Int16List _I16_2(arg1, arg2) =>
JS('Int16List', 'new Int16Array(#, #)', arg1, arg2);
static Int32List _I32_2(arg1, arg2) =>
JS('Int32List', 'new Int32Array(#, #)', arg1, arg2);
static Uint8List _U8_2(arg1, arg2) =>
JS('Uint8List', 'new Uint8Array(#, #)', arg1, arg2);
static Uint16List _U16_2(arg1, arg2) =>
JS('Uint16List', 'new Uint16Array(#, #)', arg1, arg2);
static Uint32List _U32_2(arg1, arg2) =>
JS('Uint32List', 'new Uint32Array(#, #)', arg1, arg2);
static Uint8ClampedList _U8C_2(arg1, arg2) =>
JS('Uint8ClampedList', 'new Uint8ClampedArray(#, #)', arg1, arg2);
static ByteData _B8_3(arg1, arg2, arg3) =>
JS('ByteData', 'new DataView(#, #, #)', arg1, arg2, arg3);
static Float32List _F32_3(arg1, arg2, arg3) =>
JS('Float32List', 'new Float32Array(#, #, #)', arg1, arg2, arg3);
static Float64List _F64_3(arg1, arg2, arg3) =>
JS('Float64List', 'new Float64Array(#, #, #)', arg1, arg2, arg3);
static Int8List _I8_3(arg1, arg2, arg3) =>
JS('Int8List', 'new Int8Array(#, #, #)', arg1, arg2, arg3);
static Int16List _I16_3(arg1, arg2, arg3) =>
JS('Int16List', 'new Int16Array(#, #, #)', arg1, arg2, arg3);
static Int32List _I32_3(arg1, arg2, arg3) =>
JS('Int32List', 'new Int32Array(#, #, #)', arg1, arg2, arg3);
static Uint8List _U8_3(arg1, arg2, arg3) =>
JS('Uint8List', 'new Uint8Array(#, #, #)', arg1, arg2, arg3);
static Uint16List _U16_3(arg1, arg2, arg3) =>
JS('Uint16List', 'new Uint16Array(#, #, #)', arg1, arg2, arg3);
static Uint32List _U32_3(arg1, arg2, arg3) =>
JS('Uint32List', 'new Uint32Array(#, #, #)', arg1, arg2, arg3);
static Uint8ClampedList _U8C_3(arg1, arg2, arg3) => JS(
'Uint8ClampedList', 'new Uint8ClampedArray(#, #, #)', arg1, arg2, arg3);
// Ensures that [list] is a JavaScript Array or a typed array. If necessary,
// copies the list.
static ensureNative(List list) => list; // TODO: make sure.
}
@@ -1,90 +0,0 @@
// 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.
part of dart.html;
/**
* Helper class to implement custom events which wrap DOM events.
*/
class _WrappedEvent implements Event {
final Event wrapped;
/** The CSS selector involved with event delegation. */
String? _selector;
_WrappedEvent(this.wrapped);
bool get bubbles => wrapped.bubbles;
bool get cancelable => wrapped.cancelable;
bool get composed => wrapped.composed;
EventTarget? get currentTarget => wrapped.currentTarget;
bool get defaultPrevented => wrapped.defaultPrevented;
int get eventPhase => wrapped.eventPhase;
bool get isTrusted => wrapped.isTrusted;
EventTarget? get target => wrapped.target;
double get timeStamp => wrapped.timeStamp as double;
String get type => wrapped.type;
void _initEvent(String type, [bool? bubbles, bool? cancelable]) {
throw new UnsupportedError('Cannot initialize this Event.');
}
void preventDefault() {
wrapped.preventDefault();
}
void stopImmediatePropagation() {
wrapped.stopImmediatePropagation();
}
void stopPropagation() {
wrapped.stopPropagation();
}
List<EventTarget> composedPath() => wrapped.composedPath();
/**
* A pointer to the element whose CSS selector matched within which an event
* was fired. If this Event was not associated with any Event delegation,
* accessing this value will throw an [UnsupportedError].
*/
Element get matchingTarget {
if (_selector == null) {
throw new UnsupportedError('Cannot call matchingTarget if this Event did'
' not arise as a result of event delegation.');
}
Element? currentTarget = this.currentTarget as Element?;
Element? target = this.target as Element?;
do {
if (target!.matches(_selector!)) return target;
target = target.parent;
} while (target != null && target != currentTarget!.parent);
throw new StateError('No selector matched for populating matchedTarget.');
}
/**
* This event's path, taking into account shadow DOM.
*
* ## Other resources
*
* * [Shadow DOM extensions to
* Event](http://w3c.github.io/webcomponents/spec/shadow/#extensions-to-event)
* from W3C.
*/
// https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#extensions-to-event
List<Node> get path => wrapped.path as List<Node>;
dynamic get _get_currentTarget => wrapped._get_currentTarget;
dynamic get _get_target => wrapped._get_target;
}
File diff suppressed because it is too large Load Diff
@@ -1,13 +0,0 @@
// Copyright (c) 2012, 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.
part of dart.dom.svg;
class _SvgElementFactoryProvider {
static SvgElement createSvgElement_tag(String tag) {
final Element temp =
document.createElementNS("http://www.w3.org/2000/svg", tag);
return temp as SvgElement;
}
}
-67
View File
@@ -1,67 +0,0 @@
// 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.
part of dart.dom.html;
void Function(T)? _wrapZone<T>(void Function(T)? callback) {
// For performance reasons avoid wrapping if we are in the root zone.
if (Zone.current == Zone.root) return callback;
if (callback == null) return null;
return Zone.current.bindUnaryCallbackGuarded(callback);
}
void Function(T1, T2)? _wrapBinaryZone<T1, T2>(
void Function(T1, T2)? callback) {
// For performance reasons avoid wrapping if we are in the root zone.
if (Zone.current == Zone.root) return callback;
if (callback == null) return null;
return Zone.current.bindBinaryCallbackGuarded(callback);
}
/**
* Finds the first descendant element of this document that matches the
* specified group of selectors.
*
* Unless your webpage contains multiple documents, the top-level
* [querySelector]
* method behaves the same as this method, so you should use it instead to
* save typing a few characters.
*
* [selectors] should be a string using CSS selector syntax.
*
* var element1 = document.querySelector('.className');
* var element2 = document.querySelector('#id');
*
* For details about CSS selector syntax, see the
* [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
*/
Element? querySelector(String selectors) => document.querySelector(selectors);
/**
* Finds all descendant elements of this document that match the specified
* group of selectors.
*
* Unless your webpage contains multiple documents, the top-level
* [querySelectorAll]
* method behaves the same as this method, so you should use it instead to
* save typing a few characters.
*
* [selectors] should be a string using CSS selector syntax.
*
* var items = document.querySelectorAll('.itemClassName');
*
* For details about CSS selector syntax, see the
* [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
*/
ElementList<T> querySelectorAll<T extends Element>(String selectors) =>
document.querySelectorAll(selectors);
/// A utility for changing the Dart wrapper type for elements.
abstract class ElementUpgrader {
/// Upgrade the specified element to be of the Dart type this was created for.
///
/// After upgrading the element passed in is invalid and the returned value
/// should be used instead.
Element upgrade(Element element);
}
+7 -18
View File
@@ -73,14 +73,13 @@ _logger = logging.getLogger('dartdomgenerator')
class GeneratorOptions(object):
def __init__(self, templates, database, type_registry, renamer, metadata,
dart_js_interop, nnbd):
dart_js_interop):
self.templates = templates
self.database = database
self.type_registry = type_registry
self.renamer = renamer
self.metadata = metadata
self.dart_js_interop = dart_js_interop
self.nnbd = nnbd
def LoadDatabase(database_dir, use_database_cache):
@@ -96,18 +95,14 @@ def GenerateFromDatabase(common_database,
dart2js_output_dir,
update_dom_metadata=False,
logging_level=logging.WARNING,
dart_js_interop=False,
nnbd=False):
dart_js_interop=False):
print '\n ----- Accessing DOM using %s -----\n' % (
'dart:js' if dart_js_interop else 'C++')
start_time = time.time()
current_dir = os.path.dirname(__file__)
if nnbd:
auxiliary_dir = os.path.join(current_dir, '..', 'nnbd_src')
else:
auxiliary_dir = os.path.join(current_dir, '..', 'src')
auxiliary_dir = os.path.join(current_dir, '..', 'src')
template_dir = os.path.join(current_dir, '..', 'templates')
_logger.setLevel(logging_level)
@@ -142,7 +137,7 @@ def GenerateFromDatabase(common_database,
backend_factory, dart_js_interop):
options = GeneratorOptions(template_loader, webkit_database,
type_registry, renamer, metadata,
dart_js_interop, nnbd)
dart_js_interop)
dart_library_emitter = DartLibraryEmitter(emitters, dart_output_dir,
dart_libraries)
event_generator = HtmlEventGenerator(webkit_database, renamer, metadata,
@@ -167,11 +162,11 @@ def GenerateFromDatabase(common_database,
'DARTIUM': False,
'DART2JS': True,
'JSINTEROP': False,
'NNBD': nnbd
'NNBD': True,
})
backend_options = GeneratorOptions(template_loader, webkit_database,
type_registry, renamer, metadata,
dart_js_interop, nnbd)
dart_js_interop)
backend_factory = lambda interface:\
Dart2JSBackend(interface, backend_options, logging_level)
@@ -267,12 +262,6 @@ def main():
type='string',
default=None,
help='Directory to put the generated files')
parser.add_option(
'--nnbd',
dest='nnbd',
action='store_true',
default=False,
help='Generate code with non-nullability annotations')
parser.add_option(
'--use-database-cache',
dest='use_database_cache',
@@ -348,7 +337,7 @@ def main():
GenerateFromDatabase(database, dart2js_output_dir,
options.update_dom_metadata, logging_level,
options.dart_js_interop, options.nnbd)
options.dart_js_interop)
file_generation_start_time = time.time()
+2 -10
View File
@@ -13,13 +13,6 @@ import re
from htmlrenamer import custom_html_constructors, html_interface_renames, \
typed_array_renames
# TODO(srujzs): Pass options flag through to emitter functions.
class GlobalOptionsHack(object):
nnbd = False
global_options_hack = GlobalOptionsHack()
_pure_interfaces = monitored.Set('generator._pure_interfaces', [
'AbstractWorker',
'CanvasPath',
@@ -688,7 +681,7 @@ def TypeOrNothing(dart_type, comment=None, nullable=False):
where a type may be omitted.
The string is empty or has a trailing space.
"""
nullability_operator = '?' if global_options_hack.nnbd and nullable else ''
nullability_operator = '?' if nullable else ''
if dart_type == 'dynamic':
if comment:
return '/*%s*/ ' % comment # Just a comment foo(/*T*/ x)
@@ -1274,8 +1267,7 @@ class InterfaceIDLTypeInfo(IDLTypeInfo):
if self._data.dart_type:
return self._data.dart_type
if self.list_item_type() and not self.has_generated_interface():
item_nullable = '?' if self._data.item_type_nullable and \
global_options_hack.nnbd else ''
item_nullable = '?' if self._data.item_type_nullable else ''
return 'List<%s%s>' % (self._type_registry.TypeInfo(
self._data.item_type).dart_type(), item_nullable)
return self._dart_interface_name
+8 -13
View File
@@ -114,7 +114,6 @@ class HtmlDartGenerator(object):
for id in sorted(operationsByName.keys()):
operations = operationsByName[id]
info = AnalyzeOperation(interface, operations)
info.nnbd = self._nnbd
self.AddOperation(info, declare_only, dart_js_interop)
if ('%s.%s' % (interface.id,
info.declared_name) in convert_to_future_members):
@@ -519,8 +518,7 @@ class HtmlDartGenerator(object):
if self._interface_type_info.list_item_type():
item_type = self._type_registry.TypeInfo(
self._interface_type_info.list_item_type()).dart_type()
if self._nnbd and \
self._interface_type_info.list_item_type_nullable():
if self._interface_type_info.list_item_type_nullable():
item_type += '?'
implements.append('List<%s>' % item_type)
return implements
@@ -530,8 +528,7 @@ class HtmlDartGenerator(object):
if self._interface_type_info.list_item_type():
item_type = self._type_registry.TypeInfo(
self._interface_type_info.list_item_type()).dart_type()
if self._nnbd and \
self._interface_type_info.list_item_type_nullable():
if self._interface_type_info.list_item_type_nullable():
item_type += '?'
mixins.append('ListMixin<%s>' % item_type)
mixins.append('ImmutableListMixin<%s>' % item_type)
@@ -907,8 +904,7 @@ class HtmlDartGenerator(object):
})
if nullable:
element_js = element_name + "|Null"
if self._nnbd:
element_name += '?'
element_name += '?'
else:
element_js = element_name
self._members_emitter.Emit(
@@ -938,11 +934,10 @@ class HtmlDartGenerator(object):
assert (dart_name != 'HistoryBase' and dart_name != 'LocationBase')
if dart_name == 'Window':
dart_name = _secure_base_types[dart_name]
if self._nnbd:
if type_name == 'any':
dart_name = 'Object'
if nullable and dart_name != 'dynamic':
dart_name = dart_name + '?'
if type_name == 'any':
dart_name = 'Object'
if nullable and dart_name != 'dynamic':
dart_name = dart_name + '?'
return dart_name
def SecureBaseName(self, type_name):
@@ -1006,7 +1001,7 @@ class HtmlDartGenerator(object):
NAME=temp_name,
CONVERT=conversion.function_name,
ARG=info.param_infos[position].name,
NULLASSERT='!' if null_assert_needed and self._nnbd else '',
NULLASSERT='!' if null_assert_needed else '',
ARITY=callBackInfo)
converted_arguments.append(temp_name)
param_type = temp_type
+35 -48
View File
@@ -591,11 +591,6 @@ class HtmlDartInterfaceGenerator(object):
self._template_loader = options.templates
self._type_registry = options.type_registry
self._options = options
# TODO(srujzs): This sets the nnbd option globally inside generator.py
# since there is no options object there. This should should be cleaned
# up and passed as an option instead.
global_options_hack.nnbd = options.nnbd
self._nnbd = options.nnbd
self._library_emitter = library_emitter
self._event_generator = event_generator
self._interface = interface
@@ -808,9 +803,9 @@ class HtmlDartInterfaceGenerator(object):
NATIVESPEC=native_spec,
KEYTYPE=maplikeKeyType,
VALUETYPE=maplikeValueType,
NULLABLE='?' if self._options.nnbd else '',
NULLSAFECAST=True if self._options.nnbd else False,
NULLASSERT='!' if self._options.nnbd else '')
NULLABLE='?',
NULLSAFECAST=True,
NULLASSERT='!')
stream_getter_signatures_emitter = None
element_stream_getters_emitter = None
if type(implementation_members_emitter) == tuple:
@@ -1159,7 +1154,6 @@ class Dart2JSBackend(HtmlDartGenerator):
self._type_registry = options.type_registry
self._renamer = options.renamer
self._metadata = options.metadata
self._nnbd = options.nnbd
self._interface_type_info = self._type_registry.TypeInfo(
self._interface.id)
self._current_secondary_parent = None
@@ -1181,8 +1175,7 @@ class Dart2JSBackend(HtmlDartGenerator):
):
item_type = self._type_registry.TypeInfo(
self._interface_type_info.list_item_type()).dart_type()
if self._nnbd and \
self._interface_type_info.list_item_type_nullable():
if self._interface_type_info.list_item_type_nullable():
item_type += '?'
implements.append('JavaScriptIndexingBehavior<%s>' % item_type)
return implements
@@ -1241,19 +1234,17 @@ class Dart2JSBackend(HtmlDartGenerator):
"JS$CAST("
"'returns:$INTERFACE_NAME;creates:$INTERFACE_NAME;new:true',"
" '#.$METHOD(#)', $FACTORY, $ARGUMENTS)",
CAST='<' + self._interface_type_info.interface_name() +
'>' if self._nnbd else '',
CAST='<' + self._interface_type_info.interface_name() + '>',
INTERFACE_NAME=self._interface_type_info.interface_name(),
FACTORY=factory,
METHOD=method,
ARGUMENTS=arguments)
return emitter.Format(
'$FACTORY.$METHOD($ARGUMENTS)$CAST',
FACTORY=factory,
METHOD=method,
ARGUMENTS=arguments,
CAST=' as ' + self._interface_type_info.interface_name() \
if self._nnbd else '')
return emitter.Format('$FACTORY.$METHOD($ARGUMENTS)$CAST',
FACTORY=factory,
METHOD=method,
ARGUMENTS=arguments,
CAST=' as ' +
self._interface_type_info.interface_name())
def _HasUnreliableFactoryConstructor(self):
return self._interface.doc_js_name in _js_unreliable_element_factories
@@ -1361,8 +1352,8 @@ class Dart2JSBackend(HtmlDartGenerator):
nullable=nullable),
# If the type of the operation is not nullable but the getter
# is, we must assert non-null.
NULLASSERT='!' if self._nnbd and not nullable and \
indexed_getter_nullable else '')
NULLASSERT='!' if not nullable and indexed_getter_nullable \
else '')
if 'CustomIndexedSetter' in self._interface.ext_attrs:
self._members_emitter.Emit(
@@ -1370,7 +1361,7 @@ class Dart2JSBackend(HtmlDartGenerator):
' void operator[]=(int index, $TYPE$NULLABLE value) {'
' JS("void", "#[#] = #", this, index, value); }',
TYPE=self._NarrowInputType(element_type),
NULLABLE='?' if self._nnbd and nullable else '')
NULLABLE='?' if nullable else '')
else:
theType = self._NarrowInputType(element_type)
if theType == 'DomRectList':
@@ -1382,7 +1373,7 @@ class Dart2JSBackend(HtmlDartGenerator):
' throw new UnsupportedError("Cannot assign element of immutable List.");\n'
' }\n',
TYPE=theType,
NULLABLE='?' if self._nnbd and nullable else '')
NULLABLE='?' if nullable else '')
self.EmitListMixin(self._DartType(element_type), nullable)
@@ -1460,7 +1451,7 @@ class Dart2JSBackend(HtmlDartGenerator):
return
input_type = self._NarrowInputType(attribute.type.id)
if self._nnbd and attribute.type.nullable:
if attribute.type.nullable:
input_type += '?'
if not read_only:
if attribute.type.id == 'Promise':
@@ -1483,8 +1474,8 @@ class Dart2JSBackend(HtmlDartGenerator):
promiseCall = 'promiseToFutureAsMap'
output_conversion = self._OutputConversion("Dictionary",
None)
nullability = '?' if self._nnbd and \
output_conversion.nullable_output else ''
nullability = '?' if output_conversion.nullable_output \
else ''
promiseType = 'Future<Map<String, dynamic>' + \
nullability + '>'
else:
@@ -1492,7 +1483,7 @@ class Dart2JSBackend(HtmlDartGenerator):
promiseCall = 'promiseToFuture<%s>' % paramType
promiseType = 'Future<%s>' % paramType
if self._nnbd and attribute.type.nullable:
if attribute.type.nullable:
promiseType += '?'
template = '\n $RENAME$(ANNOTATIONS)$TYPE get $NAME => $PROMISE_CALL(JS("", "#.$NAME", this));\n'
@@ -1592,11 +1583,11 @@ class Dart2JSBackend(HtmlDartGenerator):
HTML_NAME=html_name,
NAME=attr.id,
RETURN_TYPE=conversion.output_type,
NULLABLE_OUT='?' if nullable_out and self._nnbd else '',
NULLABLE_OUT='?' if nullable_out else '',
NATIVE_TYPE=conversion.input_type,
NULLABLE_IN='?' if nullable_in and self._nnbd else '',
NULLABLE_IN='?' if nullable_in else '',
NULLASSERT='!' if nullable_in and \
not conversion.nullable_input and self._nnbd else '')
not conversion.nullable_input else '')
def _AddConvertingSetter(self, attr, html_name, conversion):
# If the attribute is nullable, the setter should be nullable.
@@ -1617,11 +1608,11 @@ class Dart2JSBackend(HtmlDartGenerator):
HTML_NAME=html_name,
NAME=attr.id,
INPUT_TYPE=conversion.input_type,
NULLABLE_IN='?' if nullable_in and self._nnbd else '',
NULLABLE_IN='?' if nullable_in else '',
NATIVE_TYPE=conversion.output_type,
NULLABLE_OUT='?' if nullable_out and self._nnbd else '',
NULLABLE_OUT='?' if nullable_out else '',
NULLASSERT='!' if nullable_in and \
not conversion.nullable_input and self._nnbd else '')
not conversion.nullable_input else '')
def AmendIndexer(self, element_type):
pass
@@ -1765,8 +1756,8 @@ class Dart2JSBackend(HtmlDartGenerator):
promiseCall = 'promiseToFutureAsMap'
output_conversion = self._OutputConversion("Dictionary",
None)
nullability = '?' if self._nnbd and \
output_conversion.nullable_output else ''
nullability = '?' if output_conversion.nullable_output \
else ''
promiseType = 'Future<Map<String, dynamic>' + \
nullability + '>'
else:
@@ -1777,7 +1768,7 @@ class Dart2JSBackend(HtmlDartGenerator):
dictionary_argument = info.dictionaryArgumentName()
codeTemplate = self._promiseToFutureCode(argsNames,
dictionary_argument)
if self._nnbd and info.type_nullable:
if info.type_nullable:
promiseType += '?'
self._members_emitter.Emit(
codeTemplate,
@@ -1852,8 +1843,7 @@ class Dart2JSBackend(HtmlDartGenerator):
if output_conversion:
call = '%s(%s)' % (output_conversion.function_name, call)
if self._nnbd and output_conversion.nullable_output and \
not info.type_nullable:
if output_conversion.nullable_output and not info.type_nullable:
# Return type of operation is not nullable while conversion
# is, so we need to assert non-null.
call += '!'
@@ -1904,7 +1894,7 @@ class Dart2JSBackend(HtmlDartGenerator):
html_name.startswith('_')) else True
nullsafe_return_type = return_type;
if self._nnbd and info.type_nullable:
if info.type_nullable:
nullsafe_return_type += '?'
declaration = '%s%s%s %s(%s)' % (
@@ -1970,18 +1960,15 @@ class Dart2JSBackend(HtmlDartGenerator):
return_type = self.SecureOutputType(idl_type)
native_type = self._NarrowToImplementationType(idl_type)
null_union = '' if self._nnbd and not nullable else '|Null'
null_union = '' if not nullable else '|Null'
if native_type != return_type:
anns = anns + [
"@Returns('%s%s')" % (native_type, null_union),
"@Creates('%s')" % native_type,
]
if dart_type == 'dynamic' or \
(not self._nnbd and dart_type == 'Object') or \
(self._nnbd and dart_type == 'Object?'):
# If we're generating nnbd code, we emit non-nullable Object
# annotations but exclude nullable Object annotations since that's
# the default.
if dart_type == 'dynamic' or dart_type == 'Object?':
# We emit non-nullable Object annotations but exclude nullable
# Object annotations since that's the default.
def js_type_annotation(ann):
return re.search('^@.*Returns', ann) or re.search(
@@ -2097,7 +2084,7 @@ class DartLibrary():
emitters = library_emitter.Emit(
self._template,
AUXILIARY_DIR=massage_path(auxiliary_dir),
NULLABLE='?' if global_options_hack.nnbd else '')
NULLABLE='?')
if isinstance(emitters, tuple):
imports_emitter, map_emitter = emitters
else:
+25 -24
View File
@@ -16,7 +16,7 @@ abstract class _AttributeMap extends MapBase<String, String> {
}
Map<K, V> cast<K, V>() => Map.castFrom<String, String, K, V>(this);
bool containsValue(Object value) {
bool containsValue(Object? value) {
for (var v in this.values) {
if (value == v) {
return true;
@@ -29,7 +29,7 @@ abstract class _AttributeMap extends MapBase<String, String> {
if (!containsKey(key)) {
this[key] = ifAbsent();
}
return this[key];
return this[key] as String;
}
void clear() {
@@ -41,7 +41,7 @@ abstract class _AttributeMap extends MapBase<String, String> {
void forEach(void f(String key, String value)) {
for (var key in keys) {
var value = this[key];
f(key, value);
f(key, value as String);
}
}
@@ -50,7 +50,7 @@ abstract class _AttributeMap extends MapBase<String, String> {
var attributes = _element._attributes;
var keys = <String>[];
for (int i = 0, len = attributes.length; i < len; i++) {
_Attr attr = attributes[i];
_Attr attr = attributes[i] as _Attr;
if (_matches(attr)) {
keys.add(attr.name);
}
@@ -63,7 +63,7 @@ abstract class _AttributeMap extends MapBase<String, String> {
var attributes = _element._attributes;
var values = <String>[];
for (int i = 0, len = attributes.length; i < len; i++) {
_Attr attr = attributes[i];
_Attr attr = attributes[i] as _Attr;
if (_matches(attr)) {
values.add(attr.value);
}
@@ -95,12 +95,12 @@ abstract class _AttributeMap extends MapBase<String, String> {
class _ElementAttributeMap extends _AttributeMap {
_ElementAttributeMap(Element element) : super(element);
bool containsKey(Object key) {
return _element._hasAttribute(key);
bool containsKey(Object? key) {
return key is String && _element._hasAttribute(key);
}
String operator [](Object key) {
return _element.getAttribute(key);
String? operator [](Object? key) {
return _element.getAttribute(key as String);
}
void operator []=(String key, String value) {
@@ -108,7 +108,7 @@ class _ElementAttributeMap extends _AttributeMap {
}
@pragma('dart2js:tryInline')
String remove(Object key) => key is String ? _remove(_element, key) : null;
String? remove(Object? key) => key is String ? _remove(_element, key) : null;
/**
* The number of {key, value} pairs in the map.
@@ -122,8 +122,8 @@ class _ElementAttributeMap extends _AttributeMap {
// Inline this because almost all call sites of [remove] do not use [value],
// and the annotations on the `getAttribute` call allow it to be removed.
@pragma('dart2js:tryInline')
static String _remove(Element element, String key) {
String value = JS(
static String? _remove(Element element, String key) {
String? value = JS(
// throws:null(1) is not accurate since [key] could be malformed, but
// [key] is checked again by `removeAttributeNS`.
'returns:String|Null;depends:all;effects:none;throws:null(1)',
@@ -139,16 +139,16 @@ class _ElementAttributeMap extends _AttributeMap {
* Wrapper to expose namespaced attributes as a typed map.
*/
class _NamespacedAttributeMap extends _AttributeMap {
final String _namespace;
final String? _namespace;
_NamespacedAttributeMap(Element element, this._namespace) : super(element);
bool containsKey(Object key) {
return _element._hasAttributeNS(_namespace, key);
bool containsKey(Object? key) {
return key is String && _element._hasAttributeNS(_namespace, key);
}
String operator [](Object key) {
return _element.getAttributeNS(_namespace, key);
String? operator [](Object? key) {
return _element.getAttributeNS(_namespace, key as String);
}
void operator []=(String key, String value) {
@@ -156,7 +156,7 @@ class _NamespacedAttributeMap extends _AttributeMap {
}
@pragma('dart2js:tryInline')
String remove(Object key) =>
String? remove(Object? key) =>
key is String ? _remove(_namespace, _element, key) : null;
/**
@@ -172,8 +172,8 @@ class _NamespacedAttributeMap extends _AttributeMap {
// returned [value], and the annotations on the `getAttributeNS` call allow it
// to be removed.
@pragma('dart2js:tryInline')
static String _remove(String namespace, Element element, String key) {
String value = JS(
static String? _remove(String? namespace, Element element, String key) {
String? value = JS(
// throws:null(1) is not accurate since [key] could be malformed, but
// [key] is checked again by `removeAttributeNS`.
'returns:String|Null;depends:all;effects:none;throws:null(1)',
@@ -205,11 +205,12 @@ class _DataAttributeMap extends MapBase<String, String> {
Map<K, V> cast<K, V>() => Map.castFrom<String, String, K, V>(this);
// TODO: Use lazy iterator when it is available on Map.
bool containsValue(Object value) => values.any((v) => v == value);
bool containsValue(Object? value) => values.any((v) => v == value);
bool containsKey(Object key) => _attributes.containsKey(_attr(key));
bool containsKey(Object? key) =>
_attributes.containsKey(_attr(key as String));
String operator [](Object key) => _attributes[_attr(key)];
String? operator [](Object? key) => _attributes[_attr(key as String)];
void operator []=(String key, String value) {
_attributes[_attr(key)] = value;
@@ -218,7 +219,7 @@ class _DataAttributeMap extends MapBase<String, String> {
String putIfAbsent(String key, String ifAbsent()) =>
_attributes.putIfAbsent(_attr(key), ifAbsent);
String remove(Object key) => _attributes.remove(_attr(key));
String? remove(Object? key) => _attributes.remove(_attr(key as String));
void clear() {
// Needs to operate on a snapshot since we are mutating the collection.
+4 -4
View File
@@ -61,7 +61,7 @@ abstract class WindowBase implements EventTarget {
* WindowBase otherWindow = thisWindow.open('http://www.example.com/', 'foo');
* print(otherWindow.opener == thisWindow); // 'true'
*/
WindowBase get opener;
WindowBase? get opener;
/**
* A reference to the parent of this window.
@@ -75,7 +75,7 @@ abstract class WindowBase implements EventTarget {
*
* print(window.parent == window) // 'true'
*/
WindowBase get parent;
WindowBase? get parent;
/**
* A reference to the topmost window in the window hierarchy.
@@ -96,7 +96,7 @@ abstract class WindowBase implements EventTarget {
*
* print(window.top == window) // 'true'
*/
WindowBase get top;
WindowBase? get top;
// Methods.
/**
@@ -142,7 +142,7 @@ abstract class WindowBase implements EventTarget {
* from WHATWG.
*/
void postMessage(var message, String targetOrigin,
[List<MessagePort> messagePorts]);
[List<MessagePort>? messagePorts]);
}
abstract class LocationBase {
+5 -5
View File
@@ -24,7 +24,7 @@ abstract class CssClassSet implements Set<String> {
* non-empty string containing no whitespace. To toggle multiple classes, use
* [toggleAll].
*/
bool toggle(String value, [bool shouldAdd]);
bool toggle(String value, [bool? shouldAdd]);
/**
* Returns [:true:] if classes cannot be added or removed from this
@@ -41,7 +41,7 @@ abstract class CssClassSet implements Set<String> {
* [value] must be a valid 'token' representing a single class, i.e. a
* non-empty string containing no whitespace.
*/
bool contains(Object value);
bool contains(Object? value);
/**
* Add the class [value] to element.
@@ -72,7 +72,7 @@ abstract class CssClassSet implements Set<String> {
* non-empty string containing no whitespace. To remove multiple classes, use
* [removeAll].
*/
bool remove(Object value);
bool remove(Object? value);
/**
* Add all classes specified in [iterable] to element.
@@ -94,7 +94,7 @@ abstract class CssClassSet implements Set<String> {
* Each element of [iterable] must be a valid 'token' representing a single
* class, i.e. a non-empty string containing no whitespace.
*/
void removeAll(Iterable<Object> iterable);
void removeAll(Iterable<Object?> iterable);
/**
* Toggles all classes specified in [iterable] on element.
@@ -109,5 +109,5 @@ abstract class CssClassSet implements Set<String> {
* Each element of [iterable] must be a valid 'token' representing a single
* class, i.e. a non-empty string containing no whitespace.
*/
void toggleAll(Iterable<String> iterable, [bool shouldAdd]);
void toggleAll(Iterable<String> iterable, [bool? shouldAdd]);
}
+4 -4
View File
@@ -75,9 +75,9 @@ class _ContentCssRect extends CssRect {
class _ContentCssListRect extends _ContentCssRect {
List<Element> _elementList;
_ContentCssListRect(List<Element> elementList) : super(elementList.first) {
_elementList = elementList;
}
_ContentCssListRect(List<Element> elementList)
: _elementList = elementList,
super(elementList.first);
/**
* Set the height to `newHeight`.
@@ -299,7 +299,7 @@ abstract class CssRect implements Rectangle<num> {
* Returns the intersection of this and `other`, or `null` if they don't
* intersect.
*/
Rectangle<num> intersection(Rectangle<num> other) {
Rectangle<num>? intersection(Rectangle<num> other) {
var x0 = max(left, other.left);
var x1 = min(left + width, other.left + other.width);
+3 -1
View File
@@ -57,7 +57,9 @@ class Dimension {
* `inherit` or invalid CSS will cause this constructor to throw a
* FormatError.
*/
Dimension.css(String cssValue) {
Dimension.css(String cssValue)
: _unit = '',
_value = 0 {
if (cssValue == '') cssValue = '0px';
if (cssValue.endsWith('%')) {
_unit = '%';
+41 -37
View File
@@ -34,7 +34,7 @@ class EventStreamProvider<T extends Event> {
* * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
* from MDN.
*/
Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
Stream<T> forTarget(EventTarget? e, {bool useCapture: false}) =>
new _EventStream<T>(e, _eventType, useCapture);
/**
@@ -126,7 +126,7 @@ abstract class ElementStream<T extends Event> implements Stream<T> {
* Adapter for exposing DOM events as Dart streams.
*/
class _EventStream<T extends Event> extends Stream<T> {
final EventTarget _target;
final EventTarget? _target;
final String _eventType;
final bool _useCapture;
@@ -134,16 +134,16 @@ class _EventStream<T extends Event> extends Stream<T> {
// DOM events are inherently multi-subscribers.
Stream<T> asBroadcastStream(
{void onListen(StreamSubscription<T> subscription),
void onCancel(StreamSubscription<T> subscription)}) =>
{void onListen(StreamSubscription<T> subscription)?,
void onCancel(StreamSubscription<T> subscription)?}) =>
this;
bool get isBroadcast => true;
// TODO(9757): Inlining should be smart and inline only when inlining would
// enable scalar replacement of an immediately allocated receiver.
@pragma('dart2js:tryInline')
StreamSubscription<T> listen(void onData(T event),
{Function onError, void onDone(), bool cancelOnError}) {
StreamSubscription<T> listen(void onData(T event)?,
{Function? onError, void onDone()?, bool? cancelOnError}) {
return new _EventStreamSubscription<T>(
this._target, this._eventType, onData, this._useCapture);
}
@@ -194,8 +194,8 @@ class _ElementListEventStreamImpl<T extends Event> extends Stream<T>
});
// Delegate all regular Stream behavior to a wrapped Stream.
StreamSubscription<T> listen(void onData(T event),
{Function onError, void onDone(), bool cancelOnError}) {
StreamSubscription<T> listen(void onData(T event)?,
{Function? onError, void onDone()?, bool? cancelOnError}) {
var pool = new _StreamPool<T>.broadcast();
for (var target in _targetList) {
pool.add(new _EventStream<T>(target, _eventType, _useCapture));
@@ -213,8 +213,8 @@ class _ElementListEventStreamImpl<T extends Event> extends Stream<T>
}
Stream<T> asBroadcastStream(
{void onListen(StreamSubscription<T> subscription),
void onCancel(StreamSubscription<T> subscription)}) =>
{void onListen(StreamSubscription<T> subscription)?,
void onCancel(StreamSubscription<T> subscription)?}) =>
this;
bool get isBroadcast => true;
}
@@ -225,9 +225,9 @@ typedef _EventListener<T extends Event>(T event);
class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
int _pauseCount = 0;
EventTarget _target;
EventTarget? _target;
final String _eventType;
EventListener _onData;
EventListener? _onData;
final bool _useCapture;
// TODO(leafp): It would be better to write this as
@@ -240,7 +240,7 @@ class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
// which are typed correctly. But this currently runs afoul of restrictions
// on is checks for compatibility with the VM.
_EventStreamSubscription(
this._target, this._eventType, void onData(T event), this._useCapture)
this._target, this._eventType, void onData(T event)?, this._useCapture)
: _onData = onData == null
? null
: _wrapZone<Event>((e) => (onData as dynamic)(e)) {
@@ -248,18 +248,23 @@ class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
}
Future cancel() {
if (_canceled) return null;
// Check for strong mode. This function can no longer return null in strong
// mode, so only return null in weak mode to preserve synchronous timing.
// See issue 41653 for more details.
dynamic emptyFuture =
typeAcceptsNull<Event>() ? null : Future<void>.value();
if (_canceled) return emptyFuture as Future;
_unlisten();
// Clear out the target to indicate this is complete.
_target = null;
_onData = null;
return null;
return emptyFuture as Future;
}
bool get _canceled => _target == null;
void onData(void handleData(T event)) {
void onData(void handleData(T event)?) {
if (_canceled) {
throw new StateError("Subscription has been canceled.");
}
@@ -272,12 +277,12 @@ class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
}
/// Has no effect.
void onError(Function handleError) {}
void onError(Function? handleError) {}
/// Has no effect.
void onDone(void handleDone()) {}
void onDone(void handleDone()?) {}
void pause([Future resumeSignal]) {
void pause([Future? resumeSignal]) {
if (_canceled) return;
++_pauseCount;
_unlisten();
@@ -297,17 +302,17 @@ class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
void _tryResume() {
if (_onData != null && !isPaused) {
_target.addEventListener(_eventType, _onData, _useCapture);
_target!.addEventListener(_eventType, _onData, _useCapture);
}
}
void _unlisten() {
if (_onData != null) {
_target.removeEventListener(_eventType, _onData, _useCapture);
_target!.removeEventListener(_eventType, _onData, _useCapture);
}
}
Future<E> asFuture<E>([E futureValue]) {
Future<E> asFuture<E>([E? futureValue]) {
// We just need a future that will never succeed or fail.
var completer = new Completer<E>();
return completer.future;
@@ -332,21 +337,20 @@ class _CustomEventStreamImpl<T extends Event> extends Stream<T>
/** The type of event this stream is providing (e.g. "keydown"). */
String _type;
_CustomEventStreamImpl(String type) {
_type = type;
_streamController = new StreamController.broadcast(sync: true);
}
_CustomEventStreamImpl(String type)
: _type = type,
_streamController = new StreamController.broadcast(sync: true);
// Delegate all regular Stream behavior to our wrapped Stream.
StreamSubscription<T> listen(void onData(T event),
{Function onError, void onDone(), bool cancelOnError}) {
StreamSubscription<T> listen(void onData(T event)?,
{Function? onError, void onDone()?, bool? cancelOnError}) {
return _streamController.stream.listen(onData,
onError: onError, onDone: onDone, cancelOnError: cancelOnError);
}
Stream<T> asBroadcastStream(
{void onListen(StreamSubscription<T> subscription),
void onCancel(StreamSubscription<T> subscription)}) =>
{void onListen(StreamSubscription<T> subscription)?,
void onCancel(StreamSubscription<T> subscription)?}) =>
_streamController.stream;
bool get isBroadcast => true;
@@ -362,7 +366,7 @@ class _CustomKeyEventStreamImpl extends _CustomEventStreamImpl<KeyEvent>
void add(KeyEvent event) {
if (event.type == _type) {
event.currentTarget.dispatchEvent(event._parent);
event.currentTarget!.dispatchEvent(event._parent);
_streamController.add(event);
}
}
@@ -374,7 +378,7 @@ class _CustomKeyEventStreamImpl extends _CustomEventStreamImpl<KeyEvent>
*/
// TODO (efortuna): Remove this when Issue 12218 is addressed.
class _StreamPool<T> {
StreamController<T> _controller;
StreamController<T>? _controller;
/// Subscriptions to the streams that make up the pool.
var _subscriptions = new Map<Stream<T>, StreamSubscription<T>>();
@@ -394,7 +398,7 @@ class _StreamPool<T> {
/**
* The stream through which all events from streams in the pool are emitted.
*/
Stream<T> get stream => _controller.stream;
Stream<T> get stream => _controller!.stream;
/**
* Adds [stream] as a member of this pool.
@@ -405,8 +409,8 @@ class _StreamPool<T> {
*/
void add(Stream<T> stream) {
if (_subscriptions.containsKey(stream)) return;
_subscriptions[stream] = stream.listen(_controller.add,
onError: _controller.addError, onDone: () => remove(stream));
_subscriptions[stream] = stream.listen(_controller!.add,
onError: _controller!.addError, onDone: () => remove(stream));
}
/** Removes [stream] as a member of this pool. */
@@ -421,7 +425,7 @@ class _StreamPool<T> {
subscription.cancel();
}
_subscriptions.clear();
_controller.close();
_controller!.close();
}
}
@@ -434,7 +438,7 @@ class _CustomEventStreamProvider<T extends Event>
final _eventTypeGetter;
const _CustomEventStreamProvider(this._eventTypeGetter);
Stream<T> forTarget(EventTarget e, {bool useCapture: false}) {
Stream<T> forTarget(EventTarget? e, {bool useCapture: false}) {
return new _EventStream<T>(e, _eventTypeGetter(e), useCapture);
}
+2 -2
View File
@@ -408,8 +408,8 @@ class _Html5NodeValidator implements NodeValidator {
* All known URI attributes will be validated against the UriPolicy, if
* [uriPolicy] is null then a default UriPolicy will be used.
*/
_Html5NodeValidator({UriPolicy uriPolicy})
: uriPolicy = uriPolicy != null ? uriPolicy : new UriPolicy() {
_Html5NodeValidator({UriPolicy? uriPolicy})
: uriPolicy = uriPolicy ?? UriPolicy() {
if (_attributeValidators.isEmpty) {
for (var attr in _standardAttributes) {
_attributeValidators[attr] = _standardAttributeValidator;
+4 -4
View File
@@ -22,11 +22,11 @@ abstract class ImmutableListMixin<E> implements List<E> {
throw new UnsupportedError("Cannot add to immutable List.");
}
void sort([int compare(E a, E b)]) {
void sort([int compare(E a, E b)?]) {
throw new UnsupportedError("Cannot sort immutable List.");
}
void shuffle([Random random]) {
void shuffle([Random? random]) {
throw new UnsupportedError("Cannot shuffle immutable List.");
}
@@ -50,7 +50,7 @@ abstract class ImmutableListMixin<E> implements List<E> {
throw new UnsupportedError("Cannot remove from immutable List.");
}
bool remove(Object object) {
bool remove(Object? object) {
throw new UnsupportedError("Cannot remove from immutable List.");
}
@@ -74,7 +74,7 @@ abstract class ImmutableListMixin<E> implements List<E> {
throw new UnsupportedError("Cannot modify an immutable List.");
}
void fillRange(int start, int end, [E fillValue]) {
void fillRange(int start, int end, [E? fillValue]) {
throw new UnsupportedError("Cannot modify an immutable List.");
}
}
+6 -6
View File
@@ -22,7 +22,7 @@ class _KeyboardEventHandler extends EventStreamProvider<KeyEvent> {
final String _type;
/** The element we are watching for events to happen on. */
final EventTarget _target;
final EventTarget? _target;
// The distance to shift from upper case alphabet Roman letters to lower case.
static final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
@@ -65,7 +65,7 @@ class _KeyboardEventHandler extends EventStreamProvider<KeyEvent> {
/** Return a stream for KeyEvents for the specified target. */
// Note: this actually functions like a factory constructor.
CustomStream<KeyEvent> forTarget(EventTarget e, {bool useCapture: false}) {
CustomStream<KeyEvent> forTarget(EventTarget? e, {bool useCapture: false}) {
var handler =
new _KeyboardEventHandler.initializeAllEventListeners(_type, e);
return handler._stream;
@@ -85,7 +85,8 @@ class _KeyboardEventHandler extends EventStreamProvider<KeyEvent> {
* and charcodes when they are not provided.
*/
_KeyboardEventHandler.initializeAllEventListeners(this._type, this._target)
: super(_EVENT_TYPE) {
: _stream = new _CustomKeyEventStreamImpl(_type),
super(_EVENT_TYPE) {
Element.keyDownEvent
.forTarget(_target, useCapture: true)
.listen(processKeyDown);
@@ -95,7 +96,6 @@ class _KeyboardEventHandler extends EventStreamProvider<KeyEvent> {
Element.keyUpEvent
.forTarget(_target, useCapture: true)
.listen(processKeyUp);
_stream = new _CustomKeyEventStreamImpl(_type);
}
/** Determine if caps lock is one of the currently depressed keys. */
@@ -337,7 +337,7 @@ class _KeyboardEventHandler extends EventStreamProvider<KeyEvent> {
_keyIdentifier.containsKey(e._shadowKeyIdentifier)) {
// This is needed for Safari Windows because it currently doesn't give a
// keyCode/which for non printable keys.
e._shadowKeyCode = _keyIdentifier[e._shadowKeyIdentifier];
e._shadowKeyCode = _keyIdentifier[e._shadowKeyIdentifier]!;
}
e._shadowAltKey = _keyDownList.any((var element) => element.altKey);
_stream.add(e);
@@ -346,7 +346,7 @@ class _KeyboardEventHandler extends EventStreamProvider<KeyEvent> {
/** Handle keyup events. */
void processKeyUp(KeyboardEvent event) {
var e = new KeyEvent.wrap(event);
KeyboardEvent toRemove = null;
KeyboardEvent? toRemove = null;
for (var key in _keyDownList) {
if (key.keyCode == e.keyCode) {
toRemove = key;
+21 -21
View File
@@ -58,7 +58,7 @@ class NodeValidatorBuilder implements NodeValidator {
* The UriPolicy can be used to restrict the locations the navigation elements
* are allowed to direct to. By default this will use the default [UriPolicy].
*/
void allowNavigation([UriPolicy uriPolicy]) {
void allowNavigation([UriPolicy? uriPolicy]) {
if (uriPolicy == null) {
uriPolicy = new UriPolicy();
}
@@ -71,7 +71,7 @@ class NodeValidatorBuilder implements NodeValidator {
* The UriPolicy can be used to restrict the locations the images may be
* loaded from. By default this will use the default [UriPolicy].
*/
void allowImages([UriPolicy uriPolicy]) {
void allowImages([UriPolicy? uriPolicy]) {
if (uriPolicy == null) {
uriPolicy = new UriPolicy();
}
@@ -112,7 +112,7 @@ class NodeValidatorBuilder implements NodeValidator {
* If [tagName] is not specified then this allows inline styles on all
* elements. Otherwise tagName limits the styles to the specified elements.
*/
void allowInlineStyles({String tagName}) {
void allowInlineStyles({String? tagName}) {
if (tagName == null) {
tagName = '*';
} else {
@@ -130,7 +130,7 @@ class NodeValidatorBuilder implements NodeValidator {
* Common things which are not allowed are script elements, style attributes
* and any script handlers.
*/
void allowHtml5({UriPolicy uriPolicy}) {
void allowHtml5({UriPolicy? uriPolicy}) {
add(new _Html5NodeValidator(uriPolicy: uriPolicy));
}
@@ -149,9 +149,9 @@ class NodeValidatorBuilder implements NodeValidator {
* tag extensions.
*/
void allowCustomElement(String tagName,
{UriPolicy uriPolicy,
Iterable<String> attributes,
Iterable<String> uriAttributes}) {
{UriPolicy? uriPolicy,
Iterable<String>? attributes,
Iterable<String>? uriAttributes}) {
var tagNameUpper = tagName.toUpperCase();
var attrs = attributes
?.map<String>((name) => '$tagNameUpper::${name.toLowerCase()}');
@@ -174,9 +174,9 @@ class NodeValidatorBuilder implements NodeValidator {
* custom tags.
*/
void allowTagExtension(String tagName, String baseName,
{UriPolicy uriPolicy,
Iterable<String> attributes,
Iterable<String> uriAttributes}) {
{UriPolicy? uriPolicy,
Iterable<String>? attributes,
Iterable<String>? uriAttributes}) {
var baseNameUpper = baseName.toUpperCase();
var tagNameUpper = tagName.toUpperCase();
var attrs = attributes
@@ -192,9 +192,9 @@ class NodeValidatorBuilder implements NodeValidator {
}
void allowElement(String tagName,
{UriPolicy uriPolicy,
Iterable<String> attributes,
Iterable<String> uriAttributes}) {
{UriPolicy? uriPolicy,
Iterable<String>? attributes,
Iterable<String>? uriAttributes}) {
allowCustomElement(tagName,
uriPolicy: uriPolicy,
attributes: attributes,
@@ -236,7 +236,7 @@ class _SimpleNodeValidator implements NodeValidator {
final Set<String> allowedElements = new Set<String>();
final Set<String> allowedAttributes = new Set<String>();
final Set<String> allowedUriAttributes = new Set<String>();
final UriPolicy uriPolicy;
final UriPolicy? uriPolicy;
factory _SimpleNodeValidator.allowNavigation(UriPolicy uriPolicy) {
return new _SimpleNodeValidator(uriPolicy, allowedElements: const [
@@ -311,9 +311,9 @@ class _SimpleNodeValidator implements NodeValidator {
* lowercase attribute name. For example `'IMG:src'`.
*/
_SimpleNodeValidator(this.uriPolicy,
{Iterable<String> allowedElements,
Iterable<String> allowedAttributes,
Iterable<String> allowedUriAttributes}) {
{Iterable<String>? allowedElements,
Iterable<String>? allowedAttributes,
Iterable<String>? allowedUriAttributes}) {
this.allowedElements.addAll(allowedElements ?? const []);
allowedAttributes = allowedAttributes ?? const [];
allowedUriAttributes = allowedUriAttributes ?? const [];
@@ -333,9 +333,9 @@ class _SimpleNodeValidator implements NodeValidator {
bool allowsAttribute(Element element, String attributeName, String value) {
var tagName = Element._safeTagName(element);
if (allowedUriAttributes.contains('$tagName::$attributeName')) {
return uriPolicy.allowsUri(value);
return uriPolicy!.allowsUri(value);
} else if (allowedUriAttributes.contains('*::$attributeName')) {
return uriPolicy.allowsUri(value);
return uriPolicy!.allowsUri(value);
} else if (allowedAttributes.contains('$tagName::$attributeName')) {
return true;
} else if (allowedAttributes.contains('*::$attributeName')) {
@@ -356,8 +356,8 @@ class _CustomElementNodeValidator extends _SimpleNodeValidator {
_CustomElementNodeValidator(
UriPolicy uriPolicy,
Iterable<String> allowedElements,
Iterable<String> allowedAttributes,
Iterable<String> allowedUriAttributes,
Iterable<String>? allowedAttributes,
Iterable<String>? allowedUriAttributes,
bool allowTypeExtension,
bool allowCustomTag)
: this.allowTypeExtension = allowTypeExtension == true,
+8 -8
View File
@@ -19,7 +19,7 @@ abstract class NodeValidator {
*
* If a uriPolicy is not specified then the default uriPolicy will be used.
*/
factory NodeValidator({UriPolicy uriPolicy}) =>
factory NodeValidator({UriPolicy? uriPolicy}) =>
new _Html5NodeValidator(uriPolicy: uriPolicy);
factory NodeValidator.throws(NodeValidator base) =>
@@ -163,12 +163,12 @@ class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
_ValidatingTreeSanitizer(this.validator) {}
void sanitizeTree(Node node) {
void walk(Node node, Node parent) {
void walk(Node node, Node? parent) {
sanitizeNode(node, parent);
var child = node.lastChild;
while (null != child) {
Node nextChild;
Node? nextChild;
try {
// Child may be removed during the walk, and we may not even be able
// to get its previousNode. But it's also possible that previousNode
@@ -199,7 +199,7 @@ class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
}
/// Aggressively try to remove node.
void _removeNode(Node node, Node parent) {
void _removeNode(Node node, Node? parent) {
// If we have the parent, it's presumably already passed more sanitization
// or is the fragment, so ask it to remove the child. And if that fails
// try to set the outer html.
@@ -212,7 +212,7 @@ class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
}
/// Sanitize the element, assuming we can't trust anything about it.
void _sanitizeUntrustedElement(/* Element */ element, Node parent) {
void _sanitizeUntrustedElement(/* Element */ element, Node? parent) {
// If the _hasCorruptedAttributes does not successfully return false,
// then we consider it corrupted and remove.
// TODO(alanknight): This is a workaround because on Firefox
@@ -261,8 +261,8 @@ class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
/// Having done basic sanity checking on the element, and computed the
/// important attributes we want to check, remove it if it's not valid
/// or not allowed, either as a whole or particular attributes.
void _sanitizeElement(Element element, Node parent, bool corrupted,
String text, String tag, Map attrs, String isAttr) {
void _sanitizeElement(Element element, Node? parent, bool corrupted,
String text, String tag, Map attrs, String? isAttr) {
if (false != corrupted) {
_removeNode(element, parent);
window.console
@@ -304,7 +304,7 @@ class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
}
/// Sanitize the node and its children recursively.
void sanitizeNode(Node node, Node parent) {
void sanitizeNode(Node node, Node? parent) {
switch (node.nodeType) {
case Node.ELEMENT_NODE:
_sanitizeUntrustedElement(node, parent);
+15 -11
View File
@@ -26,7 +26,7 @@ class _WrappedList<E extends Node> extends ListBase<E>
_list.add(element);
}
bool remove(Object element) => _list.remove(element);
bool remove(Object? element) => _list.remove(element);
void clear() {
_list.clear();
@@ -34,7 +34,7 @@ class _WrappedList<E extends Node> extends ListBase<E>
// List APIs
E operator [](int index) => _list[index];
E operator [](int index) => _list[index] as E;
void operator []=(int index, E value) {
_list[index] = value;
@@ -44,19 +44,23 @@ class _WrappedList<E extends Node> extends ListBase<E>
_list.length = newLength;
}
void sort([int compare(E a, E b)]) {
// Implicit downcast on argument from Node to E-extends-Node.
_list.sort((Node a, Node b) => compare(a, b));
void sort([int compare(E a, E b)?]) {
if (compare == null) {
_list.sort();
} else {
_list.sort((Node a, Node b) => compare(a as E, b as E));
}
}
int indexOf(Object element, [int start = 0]) => _list.indexOf(element, start);
int indexOf(Object? element, [int start = 0]) =>
_list.indexOf(element as Node, start);
int lastIndexOf(Object element, [int start]) =>
_list.lastIndexOf(element, start);
int lastIndexOf(Object? element, [int? start]) =>
_list.lastIndexOf(element as Node, start);
void insert(int index, E element) => _list.insert(index, element);
E removeAt(int index) => _list.removeAt(index);
E removeAt(int index) => _list.removeAt(index) as E;
void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
_list.setRange(start, end, iterable, skipCount);
@@ -70,7 +74,7 @@ class _WrappedList<E extends Node> extends ListBase<E>
_list.replaceRange(start, end, iterable);
}
void fillRange(int start, int end, [E fillValue]) {
void fillRange(int start, int end, [E? fillValue]) {
_list.fillRange(start, end, fillValue);
}
@@ -89,5 +93,5 @@ class _WrappedIterator<E extends Node> implements Iterator<E> {
return _iterator.moveNext();
}
E get current => _iterator.current;
E get current => _iterator.current as E;
}
+4 -4
View File
@@ -9,7 +9,7 @@ class FixedSizeListIterator<T> implements Iterator<T> {
final List<T> _array;
final int _length; // Cache array length for faster access.
int _position;
T _current;
T? _current;
FixedSizeListIterator(List<T> array)
: _array = array,
@@ -28,14 +28,14 @@ class FixedSizeListIterator<T> implements Iterator<T> {
return false;
}
T get current => _current;
T get current => _current as T;
}
// Iterator for arrays with variable size.
class _VariableSizeListIterator<T> implements Iterator<T> {
final List<T> _array;
int _position;
T _current;
T? _current;
_VariableSizeListIterator(List<T> array)
: _array = array,
@@ -53,5 +53,5 @@ class _VariableSizeListIterator<T> implements Iterator<T> {
return false;
}
T get current => _current;
T get current => _current as T;
}
+1 -1
View File
@@ -10,7 +10,7 @@ class Console {
bool get _isConsoleDefined => JS('bool', 'typeof console != "undefined"');
MemoryInfo get memory =>
MemoryInfo? get memory =>
_isConsoleDefined ? JS('MemoryInfo', 'window.console.memory') : null;
void assertCondition(bool condition, Object arg) => _isConsoleDefined
+3 -3
View File
@@ -10,12 +10,12 @@
part of html;
WindowBase _convertNativeToDart_Window(win) {
WindowBase? _convertNativeToDart_Window(win) {
if (win == null) return null;
return _DOMWindowCrossFrame._createSafe(win);
}
EventTarget _convertNativeToDart_EventTarget(e) {
EventTarget? _convertNativeToDart_EventTarget(e) {
if (e == null) {
return null;
}
@@ -33,7 +33,7 @@ EventTarget _convertNativeToDart_EventTarget(e) {
return e;
}
EventTarget _convertDartToNative_EventTarget(e) {
EventTarget? _convertDartToNative_EventTarget(e) {
if (e is _DOMWindowCrossFrame) {
return e._window;
} else {
+16 -16
View File
@@ -54,7 +54,7 @@ class _MultiElementCssClassSet extends CssClassSetImpl {
* TODO(sra): It seems wrong to collect a 'changed' flag like this when the
* underlying toggle returns an 'is set' flag.
*/
bool toggle(String value, [bool shouldAdd]) => _sets.fold(
bool toggle(String value, [bool? shouldAdd]) => _sets.fold(
false,
(bool changed, CssClassSetImpl e) =>
e.toggle(value, shouldAdd) || changed);
@@ -66,7 +66,7 @@ class _MultiElementCssClassSet extends CssClassSetImpl {
* This is the Dart equivalent of jQuery's
* [removeClass](http://api.jquery.com/removeClass/).
*/
bool remove(Object value) => _sets.fold(
bool remove(Object? value) => _sets.fold(
false, (bool changed, CssClassSetImpl e) => e.remove(value) || changed);
}
@@ -100,7 +100,7 @@ class _ElementCssClassSet extends CssClassSetImpl {
_element.className = '';
}
bool contains(Object value) {
bool contains(Object? value) {
return _contains(_element, value);
}
@@ -108,11 +108,11 @@ class _ElementCssClassSet extends CssClassSetImpl {
return _add(_element, value);
}
bool remove(Object value) {
bool remove(Object? value) {
return value is String && _remove(_element, value);
}
bool toggle(String value, [bool shouldAdd]) {
bool toggle(String value, [bool? shouldAdd]) {
return _toggle(_element, value, shouldAdd);
}
@@ -120,11 +120,11 @@ class _ElementCssClassSet extends CssClassSetImpl {
_addAll(_element, iterable);
}
void removeAll(Iterable<Object> iterable) {
void removeAll(Iterable<Object?> iterable) {
_removeAll(_element, iterable);
}
void retainAll(Iterable<Object> iterable) {
void retainAll(Iterable<Object?> iterable) {
_removeWhere(_element, iterable.toSet().contains, false);
}
@@ -136,7 +136,7 @@ class _ElementCssClassSet extends CssClassSetImpl {
_removeWhere(_element, test, false);
}
static bool _contains(Element _element, Object value) {
static bool _contains(Element _element, Object? value) {
return value is String && _classListContains(_classListOf(_element), value);
}
@@ -157,7 +157,7 @@ class _ElementCssClassSet extends CssClassSetImpl {
return removed;
}
static bool _toggle(Element _element, String value, bool shouldAdd) {
static bool _toggle(Element _element, String value, bool? shouldAdd) {
// There is no value that can be passed as the second argument of
// DomTokenList.toggle that behaves the same as passing one argument.
// `null` is seen as false, meaning 'remove'.
@@ -171,13 +171,13 @@ class _ElementCssClassSet extends CssClassSetImpl {
return _classListToggle1(list, value);
}
static bool _toggleOnOff(Element _element, String value, bool shouldAdd) {
static bool _toggleOnOff(Element _element, String value, bool? shouldAdd) {
DomTokenList list = _classListOf(_element);
// IE's toggle does not take a second parameter. We would prefer:
//
// return _classListToggle2(list, value, shouldAdd);
//
if (shouldAdd) {
if (shouldAdd ?? false) {
_classListAdd(list, value);
return true;
} else {
@@ -193,10 +193,10 @@ class _ElementCssClassSet extends CssClassSetImpl {
}
}
static void _removeAll(Element _element, Iterable<Object> iterable) {
static void _removeAll(Element _element, Iterable<Object?> iterable) {
DomTokenList list = _classListOf(_element);
for (String value in iterable) {
_classListRemove(list, value);
for (Object? value in iterable) {
_classListRemove(list, value as String);
}
}
@@ -205,7 +205,7 @@ class _ElementCssClassSet extends CssClassSetImpl {
DomTokenList list = _classListOf(_element);
int i = 0;
while (i < _classListLength(list)) {
String item = list.item(i);
String item = list.item(i)!;
if (doRemove == test(item)) {
_classListRemove(list, item);
} else {
@@ -254,7 +254,7 @@ class _ElementCssClassSet extends CssClassSetImpl {
}
static bool _classListToggle2(
DomTokenList list, String value, bool shouldAdd) {
DomTokenList list, String value, bool? shouldAdd) {
return JS('bool', '#.toggle(#, #)', list, value, shouldAdd);
}
}
@@ -66,7 +66,7 @@ void _checkExtendsNativeClassOrTemplate(
}
}
Function _registerCustomElement(context, document, String tag, [Map options]) {
Function _registerCustomElement(context, document, String tag, [Map? options]) {
// Function follows the same pattern as the following JavaScript code for
// registering a custom element.
//
@@ -82,7 +82,7 @@ Function _registerCustomElement(context, document, String tag, [Map options]) {
// var e = document.createElement('x-foo');
var extendsTagName = '';
Type type;
Type? type;
if (options != null) {
extendsTagName = options['extends'];
type = options['prototype'];
@@ -162,7 +162,7 @@ class _JSElementUpgrader implements ElementUpgrader {
var _constructor;
var _nativeType;
_JSElementUpgrader(Document document, Type type, String extendsTag) {
_JSElementUpgrader(Document document, Type type, String? extendsTag) {
var interceptorClass = findInterceptorConstructorForType(type);
if (interceptorClass == null) {
throw new ArgumentError(type);
+11 -12
View File
@@ -14,8 +14,8 @@ class _DOMWindowCrossFrame implements WindowBase {
// Fields.
HistoryBase get history =>
_HistoryCrossFrame._createSafe(JS('HistoryBase', '#.history', _window));
LocationBase get location => _LocationCrossFrame
._createSafe(JS('LocationBase', '#.location', _window));
LocationBase get location => _LocationCrossFrame._createSafe(
JS('LocationBase', '#.location', _window));
// TODO(vsm): Add frames to navigate subframes. See 2312.
@@ -30,8 +30,7 @@ class _DOMWindowCrossFrame implements WindowBase {
// Methods.
void close() => JS('void', '#.close()', _window);
void postMessage(var message, String targetOrigin,
[List messagePorts = null]) {
void postMessage(var message, String targetOrigin, [List? messagePorts]) {
if (messagePorts == null) {
JS('void', '#.postMessage(#,#)', _window,
convertDartToNative_SerializedScriptValue(message), targetOrigin);
@@ -63,26 +62,26 @@ class _DOMWindowCrossFrame implements WindowBase {
Events get on => throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
void _addEventListener(String type, EventListener listener,
[bool useCapture]) =>
void _addEventListener(String? type, EventListener? listener,
[bool? useCapture]) =>
throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
void addEventListener(String type, EventListener listener,
[bool useCapture]) =>
void addEventListener(String type, EventListener? listener,
[bool? useCapture]) =>
throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
bool dispatchEvent(Event event) => throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
void _removeEventListener(String type, EventListener listener,
[bool useCapture]) =>
void _removeEventListener(String? type, EventListener? listener,
[bool? useCapture]) =>
throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
void removeEventListener(String type, EventListener listener,
[bool useCapture]) =>
void removeEventListener(String type, EventListener? listener,
[bool? useCapture]) =>
throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
}
+21 -15
View File
@@ -60,9 +60,10 @@ class KeyEvent extends _WrappedEvent implements KeyboardEvent {
bool get _realAltKey => JS('bool', '#.altKey', _parent);
/** Shadows on top of the parent's currentTarget. */
EventTarget _currentTarget;
EventTarget? _currentTarget;
final InputDeviceCapabilities sourceCapabilities;
InputDeviceCapabilities? get sourceCapabilities =>
JS('InputDeviceCapabilities', '#.sourceCapabilities', this);
/**
* The value we want to use for this object's dispatch. Created here so it is
@@ -77,7 +78,12 @@ class KeyEvent extends _WrappedEvent implements KeyboardEvent {
}
/** Construct a KeyEvent with [parent] as the event we're emulating. */
KeyEvent.wrap(KeyboardEvent parent) : super(parent) {
KeyEvent.wrap(KeyboardEvent parent)
: _parent = parent,
_shadowAltKey = false,
_shadowCharCode = 0,
_shadowKeyCode = 0,
super(parent) {
_parent = parent;
_shadowAltKey = _realAltKey;
_shadowCharCode = _realCharCode;
@@ -87,7 +93,7 @@ class KeyEvent extends _WrappedEvent implements KeyboardEvent {
/** Programmatically create a new KeyEvent (and KeyboardEvent). */
factory KeyEvent(String type,
{Window view,
{Window? view,
bool canBubble: true,
bool cancelable: true,
int keyCode: 0,
@@ -97,12 +103,12 @@ class KeyEvent extends _WrappedEvent implements KeyboardEvent {
bool altKey: false,
bool shiftKey: false,
bool metaKey: false,
EventTarget currentTarget}) {
EventTarget? currentTarget}) {
if (view == null) {
view = window;
}
var eventObj;
dynamic eventObj;
// Currently this works on everything but Safari. Safari throws an
// "Attempting to change access mechanism for an unconfigurable property"
@@ -119,17 +125,17 @@ class KeyEvent extends _WrappedEvent implements KeyboardEvent {
JS(
'void',
"Object.defineProperty(#, 'keyCode', {"
" get : function() { return this.keyCodeVal; } })",
" get : function() { return this.keyCodeVal; } })",
eventObj);
JS(
'void',
"Object.defineProperty(#, 'which', {"
" get : function() { return this.keyCodeVal; } })",
" get : function() { return this.keyCodeVal; } })",
eventObj);
JS(
'void',
"Object.defineProperty(#, 'charCode', {"
" get : function() { return this.charCodeVal; } })",
" get : function() { return this.charCodeVal; } })",
eventObj);
var keyIdentifier = _convertToHexString(charCode, keyCode);
@@ -152,10 +158,10 @@ class KeyEvent extends _WrappedEvent implements KeyboardEvent {
static bool get canUseDispatchEvent => JS(
'bool',
'(typeof document.body.dispatchEvent == "function")'
'&& document.body.dispatchEvent.length > 0');
'&& document.body.dispatchEvent.length > 0');
/** The currently registered target for this event. */
EventTarget get currentTarget => _currentTarget;
EventTarget? get currentTarget => _currentTarget;
// This is an experimental method to be sure.
static String _convertToHexString(int charCode, int keyCode) {
@@ -198,9 +204,9 @@ class KeyEvent extends _WrappedEvent implements KeyboardEvent {
bool get metaKey => _parent.metaKey;
/** True if the shift key was pressed during this event. */
bool get shiftKey => _parent.shiftKey;
Window get view => _parent.view;
WindowBase? get view => _parent.view;
void _initUIEvent(
String type, bool canBubble, bool cancelable, Window view, int detail) {
String type, bool canBubble, bool cancelable, Window? view, int detail) {
throw new UnsupportedError("Cannot initialize a UI Event from a KeyEvent.");
}
@@ -218,9 +224,9 @@ class KeyEvent extends _WrappedEvent implements KeyboardEvent {
String type,
bool canBubble,
bool cancelable,
Window view,
Window? view,
String keyIdentifier,
int location,
int? location,
bool ctrlKey,
bool altKey,
bool shiftKey,
+1 -1
View File
@@ -10,7 +10,7 @@ class Platform {
* browser. If false, using these types will generate a runtime
* error.
*/
static final supportsTypedData = JS('bool', '!!(window.ArrayBuffer)');
static final bool supportsTypedData = JS('bool', '!!(window.ArrayBuffer)');
/**
* Returns true if SIMD types in dart:typed_data types are supported
+10 -11
View File
@@ -11,7 +11,7 @@ class _WrappedEvent implements Event {
final Event wrapped;
/** The CSS selector involved with event delegation. */
String _selector;
String? _selector;
_WrappedEvent(this.wrapped);
@@ -21,7 +21,7 @@ class _WrappedEvent implements Event {
bool get composed => wrapped.composed;
EventTarget get currentTarget => wrapped.currentTarget;
EventTarget? get currentTarget => wrapped.currentTarget;
bool get defaultPrevented => wrapped.defaultPrevented;
@@ -29,13 +29,13 @@ class _WrappedEvent implements Event {
bool get isTrusted => wrapped.isTrusted;
EventTarget get target => wrapped.target;
EventTarget? get target => wrapped.target;
double get timeStamp => wrapped.timeStamp;
double get timeStamp => wrapped.timeStamp as double;
String get type => wrapped.type;
void _initEvent(String type, [bool bubbles, bool cancelable]) {
void _initEvent(String type, [bool? bubbles, bool? cancelable]) {
throw new UnsupportedError('Cannot initialize this Event.');
}
@@ -63,13 +63,12 @@ class _WrappedEvent implements Event {
throw new UnsupportedError('Cannot call matchingTarget if this Event did'
' not arise as a result of event delegation.');
}
Element currentTarget = this.currentTarget;
Element target = this.target;
var matchedTarget;
Element? currentTarget = this.currentTarget as Element?;
Element? target = this.target as Element?;
do {
if (target.matches(_selector)) return target;
if (target!.matches(_selector!)) return target;
target = target.parent;
} while (target != null && target != currentTarget.parent);
} while (target != null && target != currentTarget!.parent);
throw new StateError('No selector matched for populating matchedTarget.');
}
@@ -83,7 +82,7 @@ class _WrappedEvent implements Event {
* from W3C.
*/
// https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#extensions-to-event
List<Node> get path => wrapped.path;
List<Node> get path => wrapped.path as List<Node>;
dynamic get _get_currentTarget => wrapped._get_currentTarget;
+13 -13
View File
@@ -137,7 +137,7 @@ class _LibraryManager {
return matches.toList();
}
static setLibrary([String name]) {
static setLibrary([String? name]) {
// Bust cache in case library list has changed. Ideally we would listen for
// when libraries are loaded and invalidate based on that.
_validCache = false;
@@ -1084,16 +1084,16 @@ class _DOMWindowCrossFrame extends DartHtmlDomObject implements WindowBase {
var history = _blink.BlinkWindow.instance.history_Getter_(this);
return history is _HistoryCrossFrame
? history
: _blink.Blink_Utils
.setInstanceInterceptor(history, _HistoryCrossFrame);
: _blink.Blink_Utils.setInstanceInterceptor(
history, _HistoryCrossFrame);
}
LocationBase get location {
var location = _blink.BlinkWindow.instance.location_Getter_(this);
return location is _LocationCrossFrame
? location
: _blink.Blink_Utils
.setInstanceInterceptor(location, _LocationCrossFrame);
: _blink.Blink_Utils.setInstanceInterceptor(
location, _LocationCrossFrame);
}
bool get closed => _blink.BlinkWindow.instance.closed_Getter_(this);
@@ -1107,7 +1107,7 @@ class _DOMWindowCrossFrame extends DartHtmlDomObject implements WindowBase {
// Methods.
void close() => _blink.BlinkWindow.instance.close_Callback_0_(this);
void postMessage(Object message, String targetOrigin,
[List<MessagePort> transfer]) =>
[List<MessagePort>? transfer]) =>
_blink.BlinkWindow.instance.postMessage_Callback_3_(
this,
convertDartToNative_SerializedScriptValue(message),
@@ -1122,12 +1122,12 @@ class _DOMWindowCrossFrame extends DartHtmlDomObject implements WindowBase {
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
void _addEventListener(
[String type, EventListener listener, bool useCapture]) =>
[String? type, EventListener? listener, bool? useCapture]) =>
throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
void addEventListener(String type, EventListener listener,
[bool useCapture]) =>
void addEventListener(String type, EventListener? listener,
[bool? useCapture]) =>
throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
@@ -1135,12 +1135,12 @@ class _DOMWindowCrossFrame extends DartHtmlDomObject implements WindowBase {
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
void _removeEventListener(
[String type, EventListener listener, bool useCapture]) =>
[String? type, EventListener? listener, bool? useCapture]) =>
throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
// TODO(efortuna): Remove this method. dartbug.com/16814
void removeEventListener(String type, EventListener listener,
[bool useCapture]) =>
void removeEventListener(String type, EventListener? listener,
[bool? useCapture]) =>
throw new UnsupportedError(
'You can only attach EventListeners to your own window.');
}
@@ -1151,7 +1151,7 @@ class _HistoryCrossFrame extends DartHtmlDomObject implements HistoryBase {
// Methods.
void back() => _blink.BlinkHistory.instance.back_Callback_0_(this);
void forward() => _blink.BlinkHistory.instance.forward_Callback_0_(this);
void go([int delta]) {
void go([int? delta]) {
if (delta != null) {
_blink.BlinkHistory.instance.go_Callback_1_(this, delta);
return;
@@ -8,6 +8,6 @@ class _SvgElementFactoryProvider {
static SvgElement createSvgElement_tag(String tag) {
final Element temp =
document.createElementNS("http://www.w3.org/2000/svg", tag);
return temp;
return temp as SvgElement;
}
}
+4 -3
View File
@@ -4,14 +4,15 @@
part of dart.dom.html;
void Function(T) _wrapZone<T>(void Function(T) callback) {
void Function(T)? _wrapZone<T>(void Function(T)? callback) {
// For performance reasons avoid wrapping if we are in the root zone.
if (Zone.current == Zone.root) return callback;
if (callback == null) return null;
return Zone.current.bindUnaryCallbackGuarded(callback);
}
void Function(T1, T2) _wrapBinaryZone<T1, T2>(void Function(T1, T2) callback) {
void Function(T1, T2)? _wrapBinaryZone<T1, T2>(
void Function(T1, T2)? callback) {
// For performance reasons avoid wrapping if we are in the root zone.
if (Zone.current == Zone.root) return callback;
if (callback == null) return null;
@@ -35,7 +36,7 @@ void Function(T1, T2) _wrapBinaryZone<T1, T2>(void Function(T1, T2) callback) {
* For details about CSS selector syntax, see the
* [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
*/
Element querySelector(String selectors) => document.querySelector(selectors);
Element? querySelector(String selectors) => document.querySelector(selectors);
/**
* Finds all descendant elements of this document that match the specified