From 984164c0f9fcc129e9910fa100b9a67d9ce0c40e Mon Sep 17 00:00:00 2001 From: terrier989 Date: Fri, 26 Mar 2021 03:07:02 +0000 Subject: [PATCH] v2.0.7: Improves documentation, test suite, and enables construction of Window instances in browser. --- CHANGELOG.md | 4 + README.md | 2 +- .../window_behavior_impl_browser.dart | 730 +++++++++++++++++- lib/src/controller/window_controller.dart | 5 +- lib/src/html/_html_parser.dart | 66 +- lib/src/html/api/accessible_node.dart | 8 +- lib/src/html/api/blob.dart | 16 +- lib/src/html/api/canvas.dart | 8 +- lib/src/html/api/console.dart | 4 +- lib/src/html/api/crypto.dart | 8 +- lib/src/html/api/event_subclasses.dart | 40 +- lib/src/html/api/history.dart | 4 +- lib/src/html/api/navigator_misc.dart | 92 +-- lib/src/html/api/payment.dart | 44 +- lib/src/html/api/performance.dart | 4 +- lib/src/html/api/scroll.dart | 8 +- lib/src/html/api/speech_synthesis.dart | 40 +- lib/src/html/api/web_socket.dart | 20 +- lib/src/html/api/window.dart | 208 ++--- lib/src/html/api/window_misc.dart | 20 +- lib/src/html/dom/css.dart | 10 +- lib/src/html/dom/css_style_declaration.dart | 2 +- lib/src/html/dom/document.dart | 4 +- lib/src/html/dom/document_fragment.dart | 42 +- .../dom/element_subclasses_for_inputs.dart | 16 +- lib/src/html/dom/node.dart | 3 +- lib/src/parsing/parsing_impl_browser.dart | 3 +- pubspec.yaml | 4 +- test/main_test.dart | 54 +- test/reflection_test.dart | 15 + ...etworking_test_server.dart => server.dart} | 37 +- test/src/controller/window_controller.dart | 36 +- .../window_controller_networking.dart | 28 + test/src/html/dom/cloning.dart | 66 +- test/src/html/dom/css_style_declaration.dart | 17 +- test/src/html/dom/element_computed_style.dart | 12 +- test/src/html/dom/element_subclasses.dart | 122 +-- test/src/html/dom/helpers.dart | 46 +- test_in_flutter/dart_test.yaml | 1 + .../lib/main.dart | 21 +- test_in_flutter/pubspec.yaml | 4 +- test_in_flutter/test/main_test.dart | 14 + test_in_flutter/test/server.dart | 20 + test_in_flutter/web/favicon.png | Bin 0 -> 917 bytes test_in_flutter/web/icons/Icon-192.png | Bin 0 -> 5292 bytes test_in_flutter/web/icons/Icon-512.png | Bin 0 -> 8252 bytes test_in_flutter/web/index.html | 45 ++ test_in_flutter/web/manifest.json | 23 + tool/test.sh | 5 +- 49 files changed, 1422 insertions(+), 559 deletions(-) rename test/{networking_test_server.dart => server.dart} (99%) create mode 100644 test/src/controller/window_controller_networking.dart rename test/src/html/api/networking.dart => test_in_flutter/lib/main.dart (59%) create mode 100644 test_in_flutter/test/server.dart create mode 100644 test_in_flutter/web/favicon.png create mode 100644 test_in_flutter/web/icons/Icon-192.png create mode 100644 test_in_flutter/web/icons/Icon-512.png create mode 100644 test_in_flutter/web/index.html create mode 100644 test_in_flutter/web/manifest.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 32577ce..985e8ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.0.7 +* Fixes documentation issues and other small issues. +* WindowController can now load (fake) `Window` instances in browser just like in VM. + ## 2.0.6 * Fixes a dependency constraint. diff --git a/README.md b/README.md index cb92570..31f93f2 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ documented in the relevant files. In `pubspec.yaml`: ```yaml dependencies: - universal_html: ^2.0.6 + universal_html: ^2.0.7 ``` ## 2. Use diff --git a/lib/src/controller/window_behavior_impl_browser.dart b/lib/src/controller/window_behavior_impl_browser.dart index b75cce4..3d7d735 100644 --- a/lib/src/controller/window_behavior_impl_browser.dart +++ b/lib/src/controller/window_behavior_impl_browser.dart @@ -13,6 +13,10 @@ // limitations under the License. import 'dart:html'; +import 'dart:indexed_db'; +import 'dart:web_sql'; + +import 'package:universal_html/parsing.dart'; import 'window_controller.dart'; @@ -21,14 +25,14 @@ Document newDocument({ required String contentType, required bool filled, }) { - return DomParser().parseFromString('', 'text/html'); + return DomParser().parseFromString('', contentType); } HtmlDocument newHtmlDocument({ required Window window, required String? contentType, }) { - return DomParser().parseFromString('', 'text/html') + return DomParser().parseFromString('', contentType ?? 'text/html') as HtmlDocument; } @@ -36,11 +40,729 @@ Navigator newNavigator({ required Window window, }) { throw UnsupportedError( - 'Constructing new navigator is unsupported in browser'); + 'Constructing a new navigator is unsupported in browser', + ); } Window newWindow({ required WindowController windowController, }) { - throw UnsupportedError('Constructing new window is unsupported in browser'); + return _FakeWindow(); +} + +/// A fake window that only implements [document]. +class _FakeWindow implements Window { + @override + String? defaultStatus; + + @override + String? defaultstatus; + + @override + String? name; + + @override + WindowBase? opener; + + @override + String? status; + + @override + late final Document document = newHtmlDocument(window: this, contentType: 'text/html'); + + @override + // TODO: implement animationFrame + Future get animationFrame => throw UnimplementedError(); + + @override + // TODO: implement animationWorklet + Never get animationWorklet => throw UnimplementedError(); + + @override + // TODO: implement applicationCache + ApplicationCache? get applicationCache => throw UnimplementedError(); + + @override + // TODO: implement audioWorklet + Never get audioWorklet => throw UnimplementedError(); + + @override + // TODO: implement caches + CacheStorage? get caches => throw UnimplementedError(); + + @override + // TODO: implement closed + bool? get closed => throw UnimplementedError(); + + @override + // TODO: implement console + Console get console => throw UnimplementedError(); + + @override + // TODO: implement cookieStore + CookieStore? get cookieStore => throw UnimplementedError(); + + @override + // TODO: implement crypto + Crypto? get crypto => throw UnimplementedError(); + + @override + // TODO: implement customElements + CustomElementRegistry? get customElements => throw UnimplementedError(); + + @override + // TODO: implement devicePixelRatio + num get devicePixelRatio => throw UnimplementedError(); + + @override + // TODO: implement external + External? get external => throw UnimplementedError(); + + @override + // TODO: implement history + History get history => throw UnimplementedError(); + + @override + // TODO: implement indexedDB + IdbFactory? get indexedDB => throw UnimplementedError(); + + @override + // TODO: implement innerHeight + int? get innerHeight => throw UnimplementedError(); + + @override + // TODO: implement innerWidth + int? get innerWidth => throw UnimplementedError(); + + @override + // TODO: implement isSecureContext + bool? get isSecureContext => throw UnimplementedError(); + + @override + // TODO: implement localStorage + Storage get localStorage => throw UnimplementedError(); + + @override + Location get location { + throw UnimplementedError(); + } + + @override + set location(LocationBase location) { + throw UnimplementedError(); + } + + @override + // TODO: implement locationbar + // ignore: deprecated_member_use + BarProp? get locationbar => throw UnimplementedError(); + + @override + // TODO: implement menubar + // ignore: deprecated_member_use + BarProp? get menubar => throw UnimplementedError(); + + @override + // TODO: implement navigator + Navigator get navigator => throw UnimplementedError(); + + @override + // TODO: implement offscreenBuffering + bool? get offscreenBuffering => throw UnimplementedError(); + + @override + // TODO: implement on + Events get on => throw UnimplementedError(); + + @override + // TODO: implement onAbort + Stream get onAbort => throw UnimplementedError(); + + @override + // TODO: implement onAnimationEnd + Stream get onAnimationEnd => throw UnimplementedError(); + + @override + // TODO: implement onAnimationIteration + Stream get onAnimationIteration => throw UnimplementedError(); + + @override + // TODO: implement onAnimationStart + Stream get onAnimationStart => throw UnimplementedError(); + + @override + // TODO: implement onBeforeUnload + Stream get onBeforeUnload => throw UnimplementedError(); + + @override + // TODO: implement onBlur + Stream get onBlur => throw UnimplementedError(); + + @override + // TODO: implement onCanPlay + Stream get onCanPlay => throw UnimplementedError(); + + @override + // TODO: implement onCanPlayThrough + Stream get onCanPlayThrough => throw UnimplementedError(); + + @override + // TODO: implement onChange + Stream get onChange => throw UnimplementedError(); + + @override + // TODO: implement onClick + Stream get onClick => throw UnimplementedError(); + + @override + // TODO: implement onContentLoaded + Stream get onContentLoaded => throw UnimplementedError(); + + @override + // TODO: implement onContextMenu + Stream get onContextMenu => throw UnimplementedError(); + + @override + // TODO: implement onDeviceMotion + Stream get onDeviceMotion => throw UnimplementedError(); + + @override + // TODO: implement onDeviceOrientation + Stream get onDeviceOrientation => + throw UnimplementedError(); + + @override + // TODO: implement onDoubleClick + Stream get onDoubleClick => throw UnimplementedError(); + + @override + // TODO: implement onDrag + Stream get onDrag => throw UnimplementedError(); + + @override + // TODO: implement onDragEnd + Stream get onDragEnd => throw UnimplementedError(); + + @override + // TODO: implement onDragEnter + Stream get onDragEnter => throw UnimplementedError(); + + @override + // TODO: implement onDragLeave + Stream get onDragLeave => throw UnimplementedError(); + + @override + // TODO: implement onDragOver + Stream get onDragOver => throw UnimplementedError(); + + @override + // TODO: implement onDragStart + Stream get onDragStart => throw UnimplementedError(); + + @override + // TODO: implement onDrop + Stream get onDrop => throw UnimplementedError(); + + @override + // TODO: implement onDurationChange + Stream get onDurationChange => throw UnimplementedError(); + + @override + // TODO: implement onEmptied + Stream get onEmptied => throw UnimplementedError(); + + @override + // TODO: implement onEnded + Stream get onEnded => throw UnimplementedError(); + + @override + // TODO: implement onError + Stream get onError => throw UnimplementedError(); + + @override + // TODO: implement onFocus + Stream get onFocus => throw UnimplementedError(); + + @override + // TODO: implement onHashChange + Stream get onHashChange => throw UnimplementedError(); + + @override + // TODO: implement onInput + Stream get onInput => throw UnimplementedError(); + + @override + // TODO: implement onInvalid + Stream get onInvalid => throw UnimplementedError(); + + @override + // TODO: implement onKeyDown + Stream get onKeyDown => throw UnimplementedError(); + + @override + // TODO: implement onKeyPress + Stream get onKeyPress => throw UnimplementedError(); + + @override + // TODO: implement onKeyUp + Stream get onKeyUp => throw UnimplementedError(); + + @override + // TODO: implement onLoad + Stream get onLoad => throw UnimplementedError(); + + @override + // TODO: implement onLoadedData + Stream get onLoadedData => throw UnimplementedError(); + + @override + // TODO: implement onLoadedMetadata + Stream get onLoadedMetadata => throw UnimplementedError(); + + @override + // TODO: implement onLoadStart + Stream get onLoadStart => throw UnimplementedError(); + + @override + // TODO: implement onMessage + Stream get onMessage => throw UnimplementedError(); + + @override + // TODO: implement onMouseDown + Stream get onMouseDown => throw UnimplementedError(); + + @override + // TODO: implement onMouseEnter + Stream get onMouseEnter => throw UnimplementedError(); + + @override + // TODO: implement onMouseLeave + Stream get onMouseLeave => throw UnimplementedError(); + + @override + // TODO: implement onMouseMove + Stream get onMouseMove => throw UnimplementedError(); + + @override + // TODO: implement onMouseOut + Stream get onMouseOut => throw UnimplementedError(); + + @override + // TODO: implement onMouseOver + Stream get onMouseOver => throw UnimplementedError(); + + @override + // TODO: implement onMouseUp + Stream get onMouseUp => throw UnimplementedError(); + + @override + // TODO: implement onMouseWheel + Stream get onMouseWheel => throw UnimplementedError(); + + @override + // TODO: implement onOffline + Stream get onOffline => throw UnimplementedError(); + + @override + // TODO: implement onOnline + Stream get onOnline => throw UnimplementedError(); + + @override + // TODO: implement onPageHide + Stream get onPageHide => throw UnimplementedError(); + + @override + // TODO: implement onPageShow + Stream get onPageShow => throw UnimplementedError(); + + @override + // TODO: implement onPause + Stream get onPause => throw UnimplementedError(); + + @override + // TODO: implement onPlay + Stream get onPlay => throw UnimplementedError(); + + @override + // TODO: implement onPlaying + Stream get onPlaying => throw UnimplementedError(); + + @override + // TODO: implement onPopState + Stream get onPopState => throw UnimplementedError(); + + @override + // TODO: implement onProgress + Stream get onProgress => throw UnimplementedError(); + + @override + // TODO: implement onRateChange + Stream get onRateChange => throw UnimplementedError(); + + @override + // TODO: implement onReset + Stream get onReset => throw UnimplementedError(); + + @override + // TODO: implement onResize + Stream get onResize => throw UnimplementedError(); + + @override + // TODO: implement onScroll + Stream get onScroll => throw UnimplementedError(); + + @override + // TODO: implement onSearch + Stream get onSearch => throw UnimplementedError(); + + @override + // TODO: implement onSeeked + Stream get onSeeked => throw UnimplementedError(); + + @override + // TODO: implement onSeeking + Stream get onSeeking => throw UnimplementedError(); + + @override + // TODO: implement onSelect + Stream get onSelect => throw UnimplementedError(); + + @override + // TODO: implement onStalled + Stream get onStalled => throw UnimplementedError(); + + @override + // TODO: implement onStorage + Stream get onStorage => throw UnimplementedError(); + + @override + // TODO: implement onSubmit + Stream get onSubmit => throw UnimplementedError(); + + @override + // TODO: implement onSuspend + Stream get onSuspend => throw UnimplementedError(); + + @override + // TODO: implement onTimeUpdate + Stream get onTimeUpdate => throw UnimplementedError(); + + @override + // TODO: implement onTouchCancel + Stream get onTouchCancel => throw UnimplementedError(); + + @override + // TODO: implement onTouchEnd + Stream get onTouchEnd => throw UnimplementedError(); + + @override + // TODO: implement onTouchMove + Stream get onTouchMove => throw UnimplementedError(); + + @override + // TODO: implement onTouchStart + Stream get onTouchStart => throw UnimplementedError(); + + @override + // TODO: implement onTransitionEnd + Stream get onTransitionEnd => throw UnimplementedError(); + + @override + // TODO: implement onUnload + Stream get onUnload => throw UnimplementedError(); + + @override + // TODO: implement onVolumeChange + Stream get onVolumeChange => throw UnimplementedError(); + + @override + // TODO: implement onWaiting + Stream get onWaiting => throw UnimplementedError(); + + @override + // TODO: implement onWheel + Stream get onWheel => throw UnimplementedError(); + + @override + // TODO: implement orientation + int? get orientation => throw UnimplementedError(); + + @override + // TODO: implement origin + String? get origin => throw UnimplementedError(); + + @override + // TODO: implement outerHeight + int get outerHeight => throw UnimplementedError(); + + @override + // TODO: implement outerWidth + int get outerWidth => throw UnimplementedError(); + + @override + // TODO: implement pageXOffset + int get pageXOffset => throw UnimplementedError(); + + @override + // TODO: implement pageYOffset + int get pageYOffset => throw UnimplementedError(); + + @override + // TODO: implement parent + WindowBase? get parent => throw UnimplementedError(); + + @override + // TODO: implement performance + Performance get performance => throw UnimplementedError(); + + @override + // TODO: implement screen + Screen? get screen => throw UnimplementedError(); + + @override + // TODO: implement screenLeft + int? get screenLeft => throw UnimplementedError(); + + @override + // TODO: implement screenTop + int? get screenTop => throw UnimplementedError(); + + @override + // TODO: implement screenX + int? get screenX => throw UnimplementedError(); + + @override + // TODO: implement screenY + int? get screenY => throw UnimplementedError(); + + @override + // TODO: implement scrollbars + // ignore: deprecated_member_use + BarProp? get scrollbars => throw UnimplementedError(); + + @override + // TODO: implement scrollX + int get scrollX => throw UnimplementedError(); + + @override + // TODO: implement scrollY + int get scrollY => throw UnimplementedError(); + + @override + // TODO: implement self + WindowBase? get self => throw UnimplementedError(); + + @override + // TODO: implement sessionStorage + Storage get sessionStorage => throw UnimplementedError(); + + @override + // TODO: implement speechSynthesis + SpeechSynthesis? get speechSynthesis => throw UnimplementedError(); + + @override + // TODO: implement statusbar + // ignore: deprecated_member_use + BarProp? get statusbar => throw UnimplementedError(); + + @override + // TODO: implement styleMedia + StyleMedia? get styleMedia => throw UnimplementedError(); + + @override + // TODO: implement toolbar + // ignore: deprecated_member_use + BarProp? get toolbar => throw UnimplementedError(); + + @override + // TODO: implement top + WindowBase? get top => throw UnimplementedError(); + + @override + // TODO: implement visualViewport + VisualViewport? get visualViewport => throw UnimplementedError(); + + @override + // TODO: implement window + WindowBase? get window => throw UnimplementedError(); + + @override + void addEventListener(String type, listener, [bool? useCapture]) { + // TODO: implement addEventListener + } + + @override + void alert([String? message]) { + // TODO: implement alert + } + + @override + String atob(String atob) { + // TODO: implement atob + throw UnimplementedError(); + } + + @override + String btoa(String btoa) { + // TODO: implement btoa + throw UnimplementedError(); + } + + @override + void cancelAnimationFrame(int id) { + // TODO: implement cancelAnimationFrame + } + + @override + void cancelIdleCallback(int handle) { + // TODO: implement cancelIdleCallback + } + + @override + void close() { + // TODO: implement close + } + + @override + bool confirm([String? message]) { + // TODO: implement confirm + throw UnimplementedError(); + } + + @override + bool dispatchEvent(Event event) { + // TODO: implement dispatchEvent + throw UnimplementedError(); + } + + @override + Future fetch(input, [Map? init]) { + // TODO: implement fetch + throw UnimplementedError(); + } + + @override + bool find(String? string, bool? caseSensitive, bool? backwards, bool? wrap, + bool? wholeWord, bool? searchInFrames, bool? showDialog) { + // TODO: implement find + throw UnimplementedError(); + } + + @override + StylePropertyMapReadonly getComputedStyleMap( + Element element, String? pseudoElement) { + // TODO: implement getComputedStyleMap + throw UnimplementedError(); + } + + @override + List getMatchedCssRules(Element? element, String? pseudoElement) { + // TODO: implement getMatchedCssRules + throw UnimplementedError(); + } + + @override + Selection? getSelection() { + // TODO: implement getSelection + throw UnimplementedError(); + } + + @override + MediaQueryList matchMedia(String query) { + // TODO: implement matchMedia + throw UnimplementedError(); + } + + @override + void moveBy(int x, int y) { + // TODO: implement moveBy + } + + @override + void moveTo(Point p) { + // TODO: implement moveTo + } + + @override + WindowBase open(String url, String name, [String? options]) { + // TODO: implement open + throw UnimplementedError(); + } + + @override + SqlDatabase openDatabase( + String name, String version, String displayName, int estimatedSize, + [creationCallback]) { + // TODO: implement openDatabase + throw UnimplementedError(); + } + + @override + void postMessage(message, String targetOrigin, [List? transfer]) { + // TODO: implement postMessage + } + + @override + void print() { + // TODO: implement print + } + + @override + void removeEventListener(String type, listener, [bool? useCapture]) { + // TODO: implement removeEventListener + } + + @override + int requestAnimationFrame(callback) { + // TODO: implement requestAnimationFrame + throw UnimplementedError(); + } + + @override + Future requestFileSystem(int size, {bool persistent = false}) { + // TODO: implement requestFileSystem + throw UnimplementedError(); + } + + @override + int requestIdleCallback(callback, [Map? options]) { + // TODO: implement requestIdleCallback + throw UnimplementedError(); + } + + @override + void resizeBy(int x, int y) { + // TODO: implement resizeBy + } + + @override + void resizeTo(int x, int y) { + // TODO: implement resizeTo + } + + @override + Future resolveLocalFileSystemUrl(String url) { + // TODO: implement resolveLocalFileSystemUrl + throw UnimplementedError(); + } + + @override + void scroll([options_OR_x, y, Map? scrollOptions]) { + // TODO: implement scroll + } + + @override + void scrollBy([options_OR_x, y, Map? scrollOptions]) { + // TODO: implement scrollBy + } + + @override + void scrollTo([options_OR_x, y, Map? scrollOptions]) { + // TODO: implement scrollTo + } + + @override + void stop() { + // TODO: implement stop + } } diff --git a/lib/src/controller/window_controller.dart b/lib/src/controller/window_controller.dart index 41f13ae..b651e67 100644 --- a/lib/src/controller/window_controller.dart +++ b/lib/src/controller/window_controller.dart @@ -38,10 +38,12 @@ import 'package:universal_io/io.dart' as io; /// } /// ``` class WindowController { + /// Instance returned by top-level `window` variable. static final WindowController topLevel = WindowController(); late Window? _window = windowBehavior.newWindow(windowController: this); + /// Behavior of the window. final WindowBehavior windowBehavior = WindowBehavior(); /// Returns true if this controller for the top-level window inside a browser. @@ -125,7 +127,7 @@ class WindowController { return openContent(content); } - /// Opens the HTTP endpoint. + /// Loads content using HTTP client. /// /// # Example /// ``` @@ -164,6 +166,7 @@ class WindowController { return openContent(content); } + /// Loads content from "file", "http", or "https" URI. Future openUri(Uri uri) { if (!uri.isAbsolute) { uri = Uri.parse(window!.location.href).resolveUri(uri); diff --git a/lib/src/html/_html_parser.dart b/lib/src/html/_html_parser.dart index 3f0ca62..34b086c 100644 --- a/lib/src/html/_html_parser.dart +++ b/lib/src/html/_html_parser.dart @@ -93,6 +93,39 @@ class _HtmlParser { required this.mime, }); + DocumentFragment parseDocumentFragment({ + required int type, + required Document ownerDocument, + required String html, + NodeValidator? validator, + NodeTreeSanitizer? treeSanitizer, + String container = 'div', + }) { + if (treeSanitizer == null) { + if (validator == null) { + validator = _defaultValidator; + treeSanitizer = _defaultSanitizer; + } else { + treeSanitizer = NodeTreeSanitizer(validator); + } + } else if (validator != null) { + throw ArgumentError( + 'validator can only be passed if treeSanitizer is null', + ); + } + final node = _newNodeFrom( + ownerDocument, + html_parsing.parseFragment(html, container: container), + ); + final fragment = node as DocumentFragment; + var child = fragment.firstChild; + while (child != null) { + treeSanitizer.sanitizeTree(child); + child = child.nextNode; + } + return fragment; + } + Element _newElementWithoutChildrenFrom( Document ownerDocument, html_parsing.Element input, @@ -229,37 +262,4 @@ class _HtmlParser { throw UnimplementedError(); } } - - DocumentFragment parseDocumentFragment({ - required int type, - required Document ownerDocument, - required String html, - NodeValidator? validator, - NodeTreeSanitizer? treeSanitizer, - String container = 'div', - }) { - if (treeSanitizer == null) { - if (validator == null) { - validator = _defaultValidator; - treeSanitizer = _defaultSanitizer; - } else { - treeSanitizer = NodeTreeSanitizer(validator); - } - } else if (validator != null) { - throw ArgumentError( - 'validator can only be passed if treeSanitizer is null', - ); - } - final node = _newNodeFrom( - ownerDocument, - html_parsing.parseFragment(html, container: container), - ); - final fragment = node as DocumentFragment; - var child = fragment.firstChild; - while (child != null) { - treeSanitizer.sanitizeTree(child); - child = child.nextNode; - } - return fragment; - } } diff --git a/lib/src/html/api/accessible_node.dart b/lib/src/html/api/accessible_node.dart index b946967..2543517 100644 --- a/lib/src/html/api/accessible_node.dart +++ b/lib/src/html/api/accessible_node.dart @@ -64,8 +64,6 @@ class AccessibleNode extends EventTarget { static const EventStreamProvider accessibleScrollIntoViewEvent = EventStreamProvider('accessiblescrollintoview'); - AccessibleNode() : super.internal(); - AccessibleNode? activeDescendant; bool? atomic; @@ -160,6 +158,8 @@ class AccessibleNode extends EventTarget { String? valueText; + AccessibleNode() : super.internal(); + Stream get onAccessibleClick => accessibleClickEvent.forTarget(this); Stream get onAccessibleContextMenu => @@ -180,12 +180,12 @@ class AccessibleNode extends EventTarget { } abstract class AccessibleNodeList { - int get length; - factory AccessibleNodeList([List? nodes]) { throw UnimplementedError(); } + int get length; + void add(AccessibleNode node, AccessibleNode before) { throw UnimplementedError(); } diff --git a/lib/src/html/api/blob.dart b/lib/src/html/api/blob.dart index 40851ef..54ac720 100644 --- a/lib/src/html/api/blob.dart +++ b/lib/src/html/api/blob.dart @@ -95,22 +95,16 @@ abstract class Blob { String get type; - Blob slice([int start = 0, int? end, String? contentType]); - /// Internal method. __Not part of "dart:html".__ @protected Future> internalBytes(); + + Blob slice([int start = 0, int? end, String? contentType]); } class _Blob implements Blob { final List _data; - @override - Blob slice([int start = 0, int? end, String? contentType]) { - end ??= _data.length; - return _Blob(_data.sublist(start, end), type: contentType ?? type); - } - @override final String type; @@ -123,4 +117,10 @@ class _Blob implements Blob { Future> internalBytes() { return Future>.value(_data); } + + @override + Blob slice([int start = 0, int? end, String? contentType]) { + end ??= _data.length; + return _Blob(_data.sublist(start, end), type: contentType ?? type); + } } diff --git a/lib/src/html/api/canvas.dart b/lib/src/html/api/canvas.dart index 4f0e23c..5c1364d 100644 --- a/lib/src/html/api/canvas.dart +++ b/lib/src/html/api/canvas.dart @@ -241,6 +241,10 @@ abstract class Path2D { } abstract class TextMetrics { + factory TextMetrics._() { + throw UnimplementedError(); + } + num? get actualBoundingBoxAscent; num? get actualBoundingBoxDescent; @@ -264,10 +268,6 @@ abstract class TextMetrics { num? get ideographicBaseline; num? get width; - - factory TextMetrics._() { - throw UnimplementedError(); - } } abstract class _CanvasRenderingContext2DBase implements CanvasRenderingContext { diff --git a/lib/src/html/api/console.dart b/lib/src/html/api/console.dart index 9a234c5..d09ce7d 100644 --- a/lib/src/html/api/console.dart +++ b/lib/src/html/api/console.dart @@ -50,14 +50,14 @@ class Console { /// Internal constructor. __Not part of dart:html__. Console.internal(); + MemoryInfo? get memory => null; + void assertCondition(bool condition, Object arg) { if (!condition) { log(arg); } } - MemoryInfo? get memory => null; - void clear(Object arg) {} void count(Object arg) {} diff --git a/lib/src/html/api/crypto.dart b/lib/src/html/api/crypto.dart index 31d8bf8..9b71172 100644 --- a/lib/src/html/api/crypto.dart +++ b/lib/src/html/api/crypto.dart @@ -59,6 +59,10 @@ abstract class Crypto { } abstract class CryptoKey { + factory CryptoKey._() { + throw UnimplementedError(); + } + Object get algorithm; bool get extractable; @@ -66,8 +70,4 @@ abstract class CryptoKey { String get type; Object get usages; - - factory CryptoKey._() { - throw UnimplementedError(); - } } diff --git a/lib/src/html/api/event_subclasses.dart b/lib/src/html/api/event_subclasses.dart index ce046a6..311e797 100644 --- a/lib/src/html/api/event_subclasses.dart +++ b/lib/src/html/api/event_subclasses.dart @@ -57,13 +57,13 @@ class AbortPaymentEvent extends ExtendableEvent { } abstract class AnimationEvent extends Event { - String? get animationName; - - num? get elapsedTime; - factory AnimationEvent(String type, [Map? eventInitDict]) { throw UnimplementedError(); } + + String? get animationName; + + num? get elapsedTime; } class AnimationPlaybackEvent extends Event { @@ -94,9 +94,9 @@ abstract class BeforeInstallPromptEvent extends Event { } class BeforeUnloadEvent extends Event { - BeforeUnloadEvent._(String type) : super.internal(type); - String? returnValue; + + BeforeUnloadEvent._(String type) : super.internal(type); } class BlobEvent extends Event { @@ -110,6 +110,10 @@ class BlobEvent extends Event { } abstract class CanMakePaymentEvent extends ExtendableEvent { + factory CanMakePaymentEvent(String type, Map eventInitDict) { + throw UnimplementedError(); + } + List get methodData; List get modifiers; @@ -118,21 +122,17 @@ abstract class CanMakePaymentEvent extends ExtendableEvent { String get topLevelOrigin; - factory CanMakePaymentEvent(String type, Map eventInitDict) { - throw UnimplementedError(); - } - void respondWith(Future canMakePaymentResponse) { throw UnimplementedError(); } } abstract class ClipboardEvent extends Event { - DataTransfer? get clipboardData; - factory ClipboardEvent(String type, [Map? eventInitDict]) { throw UnimplementedError(); } + + DataTransfer? get clipboardData; } class CloseEvent extends Event { @@ -188,14 +188,14 @@ class DeviceAcceleration { } abstract class DeviceMotionEvent extends Event { + factory DeviceMotionEvent(String type, [Map? eventInitDict]) { + throw UnimplementedError(); + } DeviceAcceleration? get acceleration; DeviceAcceleration? get accelerationIncludingGravity; num? get interval; - DeviceRotationRate? get rotationRate; - factory DeviceMotionEvent(String type, [Map? eventInitDict]) { - throw UnimplementedError(); - } + DeviceRotationRate? get rotationRate; } class DeviceOrientationEvent extends Event { @@ -256,16 +256,16 @@ class ExtendableEvent extends Event { } abstract class FetchEvent extends ExtendableEvent { + factory FetchEvent(String type, Map eventInitDict) { + throw UnimplementedError(); + } + String get clientId; bool get isReload; Future get preloadResponse; - factory FetchEvent(String type, Map eventInitDict) { - throw UnimplementedError(); - } - void respondWith(Future r) { throw UnimplementedError(); } diff --git a/lib/src/html/api/history.dart b/lib/src/html/api/history.dart index 51a08b8..50e16c0 100644 --- a/lib/src/html/api/history.dart +++ b/lib/src/html/api/history.dart @@ -127,12 +127,12 @@ class History { } class Location extends Object with _UrlBase { - List get ancestorOrigins => []; - String href; Location.internal({required this.href}); + List get ancestorOrigins => []; + @override Uri get _uri => Uri.parse(href); diff --git a/lib/src/html/api/navigator_misc.dart b/lib/src/html/api/navigator_misc.dart index 13dbd23..6db7d4e 100644 --- a/lib/src/html/api/navigator_misc.dart +++ b/lib/src/html/api/navigator_misc.dart @@ -55,11 +55,11 @@ typedef StorageUsageCallback = void Function( int currentUsageInBytes, int currentQuotaInBytes); abstract class Credential { + Credential._(); + String get id; String get type; - - Credential._(); } abstract class CredentialsContainer { @@ -89,6 +89,8 @@ abstract class DeprecatedStorageQuota { } abstract class Gamepad { + Gamepad._(); + List? get axes; List? get buttons; @@ -108,21 +110,21 @@ abstract class Gamepad { GamepadPose? get pose; int? get timestamp; - - Gamepad._(); } abstract class GamepadButton { + GamepadButton._(); + bool? get pressed; bool? get touched; num? get value; - - GamepadButton._(); } abstract class GamepadPose { + GamepadPose._(); + Float32List? get angularAcceleration; Float32List? get angularVelocity; @@ -138,8 +140,6 @@ abstract class GamepadPose { Float32List? get orientation; Float32List? get position; - - GamepadPose._(); } abstract class MediaCapabilities { @@ -151,13 +151,13 @@ abstract class MediaCapabilities { } abstract class MediaCapabilitiesInfo { + MediaCapabilitiesInfo._(); + bool get powerEfficient; bool get smooth; bool get supported; - - MediaCapabilitiesInfo._(); } abstract class MediaMetadata { @@ -189,6 +189,8 @@ abstract class MediaSession { } abstract class MimeType { + MimeType._(); + String? get description; Plugin? get enabledPlugin; @@ -196,14 +198,12 @@ abstract class MimeType { String? get suffixes; String? get type; - - MimeType._(); } abstract class NavigatorAutomationInformation { - bool? get webdriver; - NavigatorAutomationInformation._(); + + bool? get webdriver; } abstract class NavigatorConcurrentHardware { @@ -213,12 +213,14 @@ abstract class NavigatorConcurrentHardware { } abstract class NavigatorCookies { - bool? get cookieEnabled; - NavigatorCookies._(); + + bool? get cookieEnabled; } abstract class NavigatorID { + NavigatorID._(); + String? get appCodeName; String? get appName; @@ -232,44 +234,44 @@ abstract class NavigatorID { String? get product; String? get userAgent; - - NavigatorID._(); } abstract class NavigatorLanguage { + NavigatorLanguage._(); + String? get language; List? get languages; - - NavigatorLanguage._(); } abstract class NavigatorOnLine { - bool? get onLine; - NavigatorOnLine._(); + + bool? get onLine; } abstract class NetworkInformation implements EventTarget { static const EventStreamProvider changeEvent = EventStreamProvider('change'); + NetworkInformation._(); + num? get downlink; num? get downlinkMax; String? get effectiveType; + Stream get onChange => changeEvent.forTarget(this); + int? get rtt; String? get type; - - NetworkInformation._(); - - Stream get onChange => changeEvent.forTarget(this); } abstract class Plugin { + Plugin._(); + String? get description; String? get filename; @@ -278,8 +280,6 @@ abstract class Plugin { String? get name; - Plugin._(); - MimeType item(int index); MimeType namedItem(String name); @@ -297,11 +297,11 @@ abstract class PresentationAvailability implements EventTarget { static const EventStreamProvider changeEvent = EventStreamProvider('change'); - bool? get value; - PresentationAvailability._(); Stream get onChange; + + bool? get value; } abstract class PresentationConnection extends EventTarget { @@ -310,18 +310,18 @@ abstract class PresentationConnection extends EventTarget { String? binaryType; - String? get id; - - String? get state; - - String? get url; - factory PresentationConnection._() { throw UnimplementedError(); } + String? get id; + Stream get onMessage => messageEvent.forTarget(this); + String? get state; + + String? get url; + void close() { throw UnimplementedError(); } @@ -336,29 +336,29 @@ abstract class PresentationConnection extends EventTarget { } abstract class PresentationConnectionAvailableEvent extends Event { - PresentationConnection get connection; - factory PresentationConnectionAvailableEvent(String type, Map eventInitDict) { throw UnimplementedError(); } + + PresentationConnection get connection; } abstract class PresentationConnectionCloseEvent extends Event { - String? get message; - - String? get reason; - factory PresentationConnectionCloseEvent(String type, Map eventInitDict) { throw UnimplementedError(); } + + String? get message; + + String? get reason; } abstract class PresentationConnectionList extends EventTarget { - List get connections; - factory PresentationConnectionList._() { throw UnimplementedError(); } + + List get connections; } class PresentationReceiver { @@ -385,11 +385,11 @@ class PresentationRequest extends EventTarget { } abstract class RelatedApplication { + RelatedApplication._(); String? get id; String? get platform; - String? get url; - RelatedApplication._(); + String? get url; } abstract class StorageManager { diff --git a/lib/src/html/api/payment.dart b/lib/src/html/api/payment.dart index d68f072..73f184e 100644 --- a/lib/src/html/api/payment.dart +++ b/lib/src/html/api/payment.dart @@ -47,6 +47,8 @@ The source code adopted from 'dart:html' had the following license: part of universal_html.internal; abstract class PaymentAddress { + PaymentAddress._(); + List? get addressLine; String? get city; @@ -68,8 +70,6 @@ abstract class PaymentAddress { String? get region; String? get sortingCode; - - PaymentAddress._(); } abstract class PaymentInstruments { @@ -89,11 +89,11 @@ abstract class PaymentInstruments { } abstract class PaymentManager { - PaymentInstruments get instruments; - String? userHint; PaymentManager._(); + + PaymentInstruments get instruments; } abstract class PaymentRequest extends EventTarget { @@ -101,39 +101,39 @@ abstract class PaymentRequest extends EventTarget { throw UnimplementedError(); } - String get id; - - PaymentAddress get shippingAddress; + PaymentAddress? get shippingAddress; - String get shippingOption; + String? get shippingOption; - String get shippingType; + String? get shippingType; - Future abort(); + Future abort() => throw UnimplementedError(); - Future canMakePayment(); + Future canMakePayment() => throw UnimplementedError(); - Future show(); + Future show() => throw UnimplementedError(); } abstract class PaymentResponse { - Object get details; + PaymentResponse._(); - String get methodName; + Object? get details; - String get payerEmail; + String? get methodName; - String get payerName; + String? get payerEmail; - String get payerPhone; + String? get payerName; - String get requestId; + String? get payerPhone; - PaymentAddress get shippingAddress; + String? get requestId; - String get shippingOption; + PaymentAddress? get shippingAddress; - PaymentResponse._(); + String? get shippingOption; - Future complete([String paymentResult]); + Future complete([String? paymentResult]) { + throw UnimplementedError(); + } } diff --git a/lib/src/html/api/performance.dart b/lib/src/html/api/performance.dart index 548f015..31e6426 100644 --- a/lib/src/html/api/performance.dart +++ b/lib/src/html/api/performance.dart @@ -63,10 +63,10 @@ class Performance extends EventTarget { final num timeOrigin = DateTime.now().microsecondsSinceEpoch / 10e6; - Performance._() : super.internal(); - final MemoryInfo memory = MemoryInfo._(); + Performance._() : super.internal(); + void clearMarks(String markName) { throw UnimplementedError(); } diff --git a/lib/src/html/api/scroll.dart b/lib/src/html/api/scroll.dart index f618695..ecb680b 100644 --- a/lib/src/html/api/scroll.dart +++ b/lib/src/html/api/scroll.dart @@ -47,6 +47,10 @@ The source code adopted from 'dart:html' had the following license: part of universal_html.internal; abstract class ScrollState { + factory ScrollState([Map? scrollStateInit]) { + throw UnimplementedError(); + } + num get deltaGranularity; num get deltaX; @@ -71,10 +75,6 @@ abstract class ScrollState { num get velocityY; - factory ScrollState([Map? scrollStateInit]) { - throw UnimplementedError(); - } - void consumeDelta(num x, num y); void distributeToScrollChainDescendant(); diff --git a/lib/src/html/api/speech_synthesis.dart b/lib/src/html/api/speech_synthesis.dart index c85dbc4..6b85e33 100644 --- a/lib/src/html/api/speech_synthesis.dart +++ b/lib/src/html/api/speech_synthesis.dart @@ -69,6 +69,10 @@ abstract class SpeechSynthesis extends EventTarget { } abstract class SpeechSynthesisEvent extends Event { + factory SpeechSynthesisEvent._() { + throw UnimplementedError(); + } + int? get charIndex; num? get elapsedTime; @@ -76,10 +80,6 @@ abstract class SpeechSynthesisEvent extends Event { String? get name; SpeechSynthesisUtterance? get utterance; - - factory SpeechSynthesisEvent._() { - throw UnimplementedError(); - } } abstract class SpeechSynthesisUtterance extends EventTarget { @@ -132,22 +132,12 @@ abstract class SpeechSynthesisUtterance extends EventTarget { static const EventStreamProvider startEvent = EventStreamProvider('start'); - String? get lang; - - num? get pitch; - - num? get rate; - - String? get text; - - SpeechSynthesisVoice? get voice; - - num? get volume; - factory SpeechSynthesisUtterance([String? text]) { throw UnimplementedError(); } + String? get lang; + /// Stream of `boundary` events handled by this [SpeechSynthesisUtterance]. Stream get onBoundary => boundaryEvent.forTarget(this); @@ -168,9 +158,23 @@ abstract class SpeechSynthesisUtterance extends EventTarget { /// Stream of `start` events handled by this [SpeechSynthesisUtterance]. Stream get onStart => startEvent.forTarget(this); + + num? get pitch; + + num? get rate; + + String? get text; + + SpeechSynthesisVoice? get voice; + + num? get volume; } abstract class SpeechSynthesisVoice { + factory SpeechSynthesisVoice._() { + throw UnimplementedError(); + } + bool? get defaultValue; String? get lang; @@ -180,8 +184,4 @@ abstract class SpeechSynthesisVoice { String? get name; String? get voiceUri; - - factory SpeechSynthesisVoice._() { - throw UnimplementedError(); - } } diff --git a/lib/src/html/api/web_socket.dart b/lib/src/html/api/web_socket.dart index 1b643c0..8e765d3 100644 --- a/lib/src/html/api/web_socket.dart +++ b/lib/src/html/api/web_socket.dart @@ -88,20 +88,14 @@ abstract class WebSocket extends EventTarget { String? binaryType; - int? get bufferedAmount; - - String? get extensions; - - String? get protocol; - - int get readyState; - - String get url; - factory WebSocket(String url, [Object? protocols]) { throw UnimplementedError(); } + int? get bufferedAmount; + + String? get extensions; + /// Stream of `close` events handled by this [WebSocket]. Stream get onClose => closeEvent.forTarget(this); @@ -114,6 +108,12 @@ abstract class WebSocket extends EventTarget { /// Stream of `open` events handled by this [WebSocket]. Stream get onOpen => openEvent.forTarget(this); + String? get protocol; + + int get readyState; + + String get url; + void close([int? code, String? reason]) { throw UnimplementedError(); } diff --git a/lib/src/html/api/window.dart b/lib/src/html/api/window.dart index 19ad74a..74458b6 100644 --- a/lib/src/html/api/window.dart +++ b/lib/src/html/api/window.dart @@ -230,6 +230,106 @@ class Window extends EventTarget final WindowController internalWindowController; + final String _initialHref; + + /// The application cache for this window. + /// + /// ## Other resources + /// + /// * [A beginner's guide to using the application + /// cache](http://www.html5rocks.com/en/tutorials/appcache/beginner) + /// from HTML5Rocks. + /// * [Application cache + /// API](https://html.spec.whatwg.org/multipage/browsers.html#application-cache-api) + /// from WHATWG. + late final ApplicationCache applicationCache = ApplicationCache.internal(); + + /// The debugging console for this window. + late final Console console = Console.internal(); + + /// The newest document in this window. + /// + /// ## Other resources + /// + /// * [Loading web + /// pages](https://html.spec.whatwg.org/multipage/browsers.html) + /// from WHATWG. + late final Document document = () { + // Note that `as` expressions are required because of + // "dart:html OR universal_html" confusion by the analyzer. + final window = this as universal_html_in_browser_or_vm.Window; + final document = + internalWindowController.windowBehavior.newDocument(window: window); + return document as Document; + }(); + + late final External external = External.internal(); + + @override + late final History history = History.internal(); + + /// Storage for this window that persists across sessions. + /// + /// ## Other resources + /// + /// * [DOM storage guide](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage) + /// from MDN. + /// * [The past, present & future of local storage for web + /// applications](http://diveintohtml5.info/storage.html) from Dive Into HTML5. + /// * [Local storage specification](http://www.w3.org/TR/webstorage/#the-localstorage-attribute) + /// from W3C. + late final Storage localStorage = Storage._(this); + + /// The current location of this window. + /// + /// Location currentLocation = window.location; + /// print(currentLocation.href); // 'http://www.example.com:80/' + @override + late Location location = Location.internal(href: _initialHref); + + /// The user agent accessing this window. + /// + /// ## Other resources + /// + /// * [The navigator + /// object](https://html.spec.whatwg.org/multipage/webappapis.html#the-navigator-object) + /// from WHATWG. + late final Navigator navigator = () { + // Note that `as` expressions are required because of + // "dart:html OR universal_html" confusion by the analyzer. + final window = this as universal_html_in_browser_or_vm.Window; + final navigator = + internalWindowController.windowBehavior.newNavigator(window: window); + return navigator as Navigator; + }(); + + /// Timing and navigation data for this window. + /// + /// ## Other resources + /// + /// * [Measuring page load speed with navigation + /// timeing](http://www.html5rocks.com/en/tutorials/webperformance/basics/) + /// from HTML5Rocks. + /// * [Navigation timing + /// specification](http://www.w3.org/TR/navigation-timing/) from W3C. + late final Performance performance = Performance._(); + + /// Storage for this window that is cleared when this session ends. + /// + /// ## Other resources + /// + /// * [DOM storage + /// guide](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage) + /// from MDN. + /// * [The past, present & future of local storage for web + /// applications](http://diveintohtml5.info/storage.html) from Dive Into HTML5. + /// * [Local storage + /// specification](http://www.w3.org/TR/webstorage/#dom-sessionstorage) from W3C. + late final Storage sessionStorage = Storage._(this); + + @protected + Selection? internalSelection; + /// An internal constructor that's NOT part of "dart:html". /// /// This API is not for public use. @@ -242,8 +342,6 @@ class Window extends EventTarget }) : _initialHref = href, super.internal(); - final String _initialHref; - /// Returns a Future that completes just before the window is about to /// repaint so the user can draw an animation frame. /// @@ -267,18 +365,6 @@ class Window extends EventTarget _Worklet get animationWorklet => throw UnimplementedError(); - /// The application cache for this window. - /// - /// ## Other resources - /// - /// * [A beginner's guide to using the application - /// cache](http://www.html5rocks.com/en/tutorials/appcache/beginner) - /// from HTML5Rocks. - /// * [Application cache - /// API](https://html.spec.whatwg.org/multipage/browsers.html#application-cache-api) - /// from WHATWG. - late final ApplicationCache applicationCache = ApplicationCache.internal(); - _Worklet get audioWorklet => throw UnimplementedError(); CacheStorage get caches => CacheStorage._(); @@ -286,9 +372,6 @@ class Window extends EventTarget @override bool get closed => _closed; - /// The debugging console for this window. - late final Console console = Console.internal(); - CookieStore get cookieStore => CookieStore._(); /// Entrypoint for the browser's cryptographic functions. @@ -301,10 +384,10 @@ class Window extends EventTarget CustomElementRegistry? get customElements => null; /// *Deprecated*. - String? get defaultstatus => throw UnimplementedError(); + String? get defaultStatus => throw UnimplementedError(); /// *Deprecated*. - String? get defaultStatus => throw UnimplementedError(); + String? get defaultstatus => throw UnimplementedError(); /// The ratio between physical pixels and logical CSS pixels. /// @@ -316,27 +399,6 @@ class Window extends EventTarget /// from quirksmode. num get devicePixelRatio => 1; - /// The newest document in this window. - /// - /// ## Other resources - /// - /// * [Loading web - /// pages](https://html.spec.whatwg.org/multipage/browsers.html) - /// from WHATWG. - late final Document document = () { - // Note that `as` expressions are required because of - // "dart:html OR universal_html" confusion by the analyzer. - final window = this as universal_html_in_browser_or_vm.Window; - final document = - internalWindowController.windowBehavior.newDocument(window: window); - return document as Document; - }(); - - late final External external = External.internal(); - - @override - late final History history = History.internal(); - /// Gets an instance of the Indexed DB factory to being using Indexed DB. /// /// Use [indexed_db.IdbFactory.supported] to check if Indexed DB is supported on the @@ -361,25 +423,6 @@ class Window extends EventTarget bool get isSecureContext => throw UnimplementedError(); - /// Storage for this window that persists across sessions. - /// - /// ## Other resources - /// - /// * [DOM storage guide](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage) - /// from MDN. - /// * [The past, present & future of local storage for web - /// applications](http://diveintohtml5.info/storage.html) from Dive Into HTML5. - /// * [Local storage specification](http://www.w3.org/TR/webstorage/#the-localstorage-attribute) - /// from W3C. - late final Storage localStorage = Storage._(this); - - /// The current location of this window. - /// - /// Location currentLocation = window.location; - /// print(currentLocation.href); // 'http://www.example.com:80/' - @override - late Location location = Location.internal(href: _initialHref); - /// This window's location bar, which displays the URL. /// /// ## Other resources @@ -398,22 +441,6 @@ class Window extends EventTarget /// from WHATWG. _BarProp get menubar => throw UnimplementedError(); - /// The user agent accessing this window. - /// - /// ## Other resources - /// - /// * [The navigator - /// object](https://html.spec.whatwg.org/multipage/webappapis.html#the-navigator-object) - /// from WHATWG. - late final Navigator navigator = () { - // Note that `as` expressions are required because of - // "dart:html OR universal_html" confusion by the analyzer. - final window = this as universal_html_in_browser_or_vm.Window; - final navigator = - internalWindowController.windowBehavior.newNavigator(window: window); - return navigator as Navigator; - }(); - /// Whether objects are drawn offscreen before being displayed. /// /// ## Other resources @@ -551,6 +578,8 @@ class Window extends EventTarget Stream get onMouseLeave => Element.mouseLeaveEvent.forTarget(this); + // From WindowBase64 + /// Stream of `mousemove` events handled by this [Window]. Stream get onMouseMove => Element.mouseMoveEvent.forTarget(this); @@ -560,8 +589,6 @@ class Window extends EventTarget /// Stream of `mouseover` events handled by this [Window]. Stream get onMouseOver => Element.mouseOverEvent.forTarget(this); - // From WindowBase64 - /// Stream of `mouseup` events handled by this [Window]. Stream get onMouseUp => Element.mouseUpEvent.forTarget(this); @@ -676,17 +703,6 @@ class Window extends EventTarget @override WindowBase? get parent => null; - /// Timing and navigation data for this window. - /// - /// ## Other resources - /// - /// * [Measuring page load speed with navigation - /// timeing](http://www.html5rocks.com/en/tutorials/webperformance/basics/) - /// from HTML5Rocks. - /// * [Navigation timing - /// specification](http://www.w3.org/TR/navigation-timing/) from W3C. - late final Performance performance = Performance._(); - /// Information about the screen displaying this window. /// /// ## Other resources @@ -765,19 +781,6 @@ class Window extends EventTarget /// from MDN. WindowBase get self => this; - /// Storage for this window that is cleared when this session ends. - /// - /// ## Other resources - /// - /// * [DOM storage - /// guide](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage) - /// from MDN. - /// * [The past, present & future of local storage for web - /// applications](http://diveintohtml5.info/storage.html) from Dive Into HTML5. - /// * [Local storage - /// specification](http://www.w3.org/TR/webstorage/#dom-sessionstorage) from W3C. - late final Storage sessionStorage = Storage._(this); - /// Access to speech synthesis in the browser. /// /// ## Other resources @@ -892,9 +895,6 @@ class Window extends EventTarget /// from MDN. Selection? getSelection() => internalSelection; - @protected - Selection? internalSelection; - /// Returns a list of media queries for the given query string. /// /// ## Other resources diff --git a/lib/src/html/api/window_misc.dart b/lib/src/html/api/window_misc.dart index 3c76dbf..ef63651 100644 --- a/lib/src/html/api/window_misc.dart +++ b/lib/src/html/api/window_misc.dart @@ -123,14 +123,14 @@ abstract class MediaQueryList extends EventTarget { static const EventStreamProvider changeEvent = EventStreamProvider('change'); - bool get matches; - - String get media; - factory MediaQueryList._() { throw UnimplementedError(); } + bool get matches; + + String get media; + Stream get onChange => changeEvent.forTarget(this); void addListener(EventListener listener) { @@ -303,12 +303,18 @@ abstract class VisualViewport implements EventTarget { static const EventStreamProvider scrollEvent = EventStreamProvider('scroll'); + VisualViewport._(); + num get height; num get offsetLeft; num get offsetTop; + Stream get onResize => resizeEvent.forTarget(this); + + Stream get onScroll => scrollEvent.forTarget(this); + num get pageLeft; num get pageTop; @@ -316,12 +322,6 @@ abstract class VisualViewport implements EventTarget { num get scale; num get width; - - VisualViewport._(); - - Stream get onResize => resizeEvent.forTarget(this); - - Stream get onScroll => scrollEvent.forTarget(this); } class _BarProp { diff --git a/lib/src/html/dom/css.dart b/lib/src/html/dom/css.dart index 4daa157..eeed49f 100644 --- a/lib/src/html/dom/css.dart +++ b/lib/src/html/dom/css.dart @@ -142,9 +142,6 @@ class Dimension { final String _unit; - /// NOT part of 'dart:html'. - String get internalUnit => _unit; - /// Set this CSS Dimension to a centimeter `value`. Dimension.cm(this.value) : _unit = 'cm'; @@ -174,7 +171,6 @@ class Dimension { } return Dimension._(value, unit); } - Dimension._(this.value, this._unit); /// Set this CSS Dimension to the specified number of ems. /// @@ -182,7 +178,6 @@ class Dimension { /// 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, @@ -208,6 +203,11 @@ class Dimension { /// Set this CSS Dimension to a pixel `value`. Dimension.px(this.value) : _unit = 'px'; + Dimension._(this.value, this._unit); + + /// NOT part of 'dart:html'. + String get internalUnit => _unit; + /// Print out the CSS String representation of this value. @override String toString() { diff --git a/lib/src/html/dom/css_style_declaration.dart b/lib/src/html/dom/css_style_declaration.dart index 21a912a..39263f7 100644 --- a/lib/src/html/dom/css_style_declaration.dart +++ b/lib/src/html/dom/css_style_declaration.dart @@ -134,7 +134,7 @@ class _CssStyleDeclaration extends CssStyleDeclaration { @override String getPropertyPriority(String property) { - throw UnimplementedError(); + return ''; } @override diff --git a/lib/src/html/dom/document.dart b/lib/src/html/dom/document.dart index 9b1a20f..1fbe7a1 100644 --- a/lib/src/html/dom/document.dart +++ b/lib/src/html/dom/document.dart @@ -87,6 +87,8 @@ abstract class Document extends Node Element? rootScroller; + final Window window; + factory Document() { return XmlDocument.internal( window: universal_html.window, @@ -363,8 +365,6 @@ abstract class Document extends Node String? get visibilityState => null; - final Window window; - bool get _isXml => false; Node adoptNode(Node node) { diff --git a/lib/src/html/dom/document_fragment.dart b/lib/src/html/dom/document_fragment.dart index 4f5e547..b50d606 100644 --- a/lib/src/html/dom/document_fragment.dart +++ b/lib/src/html/dom/document_fragment.dart @@ -66,6 +66,9 @@ class DocumentFragment extends Node ); } + /// Internal constructor. __Not part of dart:html__. + DocumentFragment.internal(Document ownerDocument) : super._(ownerDocument); + factory DocumentFragment.svg( String input, { NodeValidator? validator, @@ -79,9 +82,6 @@ class DocumentFragment extends Node ); } - /// Internal constructor. __Not part of dart:html__. - DocumentFragment.internal(Document ownerDocument) : super._(ownerDocument); - List get children { return _ElementChildren(this); } @@ -159,28 +159,12 @@ class DocumentFragment extends Node abstract class ShadowRoot extends DocumentFragment { static bool get supported => false; - bool? get delegatesFocus; - - Element? get host; - - String? get mode; - - ShadowRoot? get olderShadowRoot; - - Element? get activeElement; - - // From DocumentOrShadowRoot - - Element? get fullscreenElement; - - Element? get pointerLockElement; - - List? get styleSheets; - factory ShadowRoot._() { throw UnimplementedError(); } + Element? get activeElement; + @deprecated bool get applyAuthorStyles { throw UnimplementedError(); @@ -191,6 +175,20 @@ abstract class ShadowRoot extends DocumentFragment { throw UnimplementedError(); } + bool? get delegatesFocus; + + // From DocumentOrShadowRoot + + Element? get fullscreenElement; + + Element? get host; + + String? get mode; + + ShadowRoot? get olderShadowRoot; + + Element? get pointerLockElement; + @deprecated bool get resetStyleInheritance { throw UnimplementedError(); @@ -201,6 +199,8 @@ abstract class ShadowRoot extends DocumentFragment { throw UnimplementedError(); } + List? get styleSheets; + Element elementFromPoint(int x, int y) { throw UnimplementedError(); } diff --git a/lib/src/html/dom/element_subclasses_for_inputs.dart b/lib/src/html/dom/element_subclasses_for_inputs.dart index 1a2dd62..00d9017 100644 --- a/lib/src/html/dom/element_subclasses_for_inputs.dart +++ b/lib/src/html/dom/element_subclasses_for_inputs.dart @@ -62,10 +62,10 @@ abstract class DateInputElement implements RangeInputElementBase { bool? readOnly; bool required = false; + factory DateInputElement() => InputElement(type: 'date'); DateTime get valueAsDate => throw UnimplementedError(); - set valueAsDate(DateTime value); - factory DateInputElement() => InputElement(type: 'date'); + set valueAsDate(DateTime value); } abstract class EmailInputElement implements TextInputElementBase { @@ -179,10 +179,10 @@ abstract class MonthInputElement implements RangeInputElementBase { bool? readOnly; bool required = false; + factory MonthInputElement() => InputElement(type: 'month'); DateTime get valueAsDate; - set valueAsDate(DateTime value); - factory MonthInputElement() => InputElement(type: 'month'); + set valueAsDate(DateTime value); } abstract class NumberInputElement implements RangeInputElementBase { @@ -192,10 +192,10 @@ abstract class NumberInputElement implements RangeInputElementBase { bool? readOnly; bool required = false; + factory NumberInputElement() => InputElement(type: 'number'); + @override num? get valueAsNumber => throw UnimplementedError(); - - factory NumberInputElement() => InputElement(type: 'number'); } abstract class PasswordInputElement implements TextInputElementBase { @@ -316,7 +316,7 @@ abstract class WeekInputElement implements RangeInputElementBase { bool? readOnly; bool required = false; - DateTime? get valueAsDate => throw UnimplementedError(); - factory WeekInputElement() => InputElement(type: 'week'); + + DateTime? get valueAsDate => throw UnimplementedError(); } diff --git a/lib/src/html/dom/node.dart b/lib/src/html/dom/node.dart index 2b6a64f..ad74dbe 100644 --- a/lib/src/html/dom/node.dart +++ b/lib/src/html/dom/node.dart @@ -776,7 +776,8 @@ mixin _ElementOrDocument implements Node, ParentNode { // A sanity check assert(identical(firstChildOfRoot.parentNode, this)); - assert(identical(firstChildOfRoot.parent, this) || firstChildOfRoot.parent == null); + assert(identical(firstChildOfRoot.parent, this) || + firstChildOfRoot.parent == null); var node = firstChildOfRoot; loop: diff --git a/lib/src/parsing/parsing_impl_browser.dart b/lib/src/parsing/parsing_impl_browser.dart index 5994226..502cdfd 100644 --- a/lib/src/parsing/parsing_impl_browser.dart +++ b/lib/src/parsing/parsing_impl_browser.dart @@ -12,9 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -import 'package:universal_html/html.dart'; import 'dart:html'; +import 'package:universal_html/html.dart'; + HtmlDocument parseHtmlDocument({ required Window window, required String content, diff --git a/pubspec.yaml b/pubspec.yaml index 3f4f1d2..db71573 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: universal_html -version: 2.0.6 +version: 2.0.7 description: A 'dart:html' that works in all platforms, including Flutter and server-side. Eases cross-platform development and HTML / XML processing. @@ -17,7 +17,7 @@ dependencies: meta: ^1.3.0 source_span: ^1.8.0 typed_data: ^1.3.0 - universal_io: ^2.0.2 + universal_io: ^2.0.3 dev_dependencies: pedantic: ^1.11.0 diff --git a/test/main_test.dart b/test/main_test.dart index 7108709..0d4a78d 100644 --- a/test/main_test.dart +++ b/test/main_test.dart @@ -35,11 +35,12 @@ part 'src/html/api/event_target.dart'; part 'src/html/api/file.dart'; part 'src/html/api/history.dart'; part 'src/html/api/navigator.dart'; -part 'src/html/api/networking.dart'; +part 'src/controller/window_controller_networking.dart'; part 'src/html/api/networking_event_source.dart'; part 'src/html/api/networking_http_request.dart'; part 'src/html/api/window.dart'; part 'src/html/dom/cloning.dart'; +part 'src/html/dom/css_queries.dart'; part 'src/html/dom/css_style_declaration.dart'; part 'src/html/dom/document.dart'; part 'src/html/dom/element.dart'; @@ -48,7 +49,6 @@ part 'src/html/dom/element_computed_style.dart'; part 'src/html/dom/element_subclasses.dart'; part 'src/html/dom/helpers.dart'; part 'src/html/dom/node.dart'; -part 'src/html/dom/css_queries.dart'; part 'src/html/dom/parsing.dart'; void main() { @@ -67,25 +67,12 @@ void main() { _sharedTests(); }, testOn: 'node'); } + var _isBrowser = false; var _isVM = false; void _sharedTests() { - setUpAll(() async { - // Do not run in Flutter or Node.JS - if (!(_isVM || _isBrowser)) { - return; - } - - final channel = spawnHybridUri('networking_test_server.dart', message: {}); - final streamQueue = StreamQueue(channel.stream); - addTearDown(() { - channel.sink.close(); - }); - final port = await streamQueue.next; - _httpServerPort = port; - }); // DOM _testCloning(); _testCssStyleDeclaration(); @@ -119,3 +106,38 @@ void _sharedTests() { // testLibraries(); } + +// Local TCP port that has a HTTP server. +const _httpServerWrongPort = 314; + +// Local TCP port hat DOES NOT have HTTP server. +// Used for testing connection failures. +late int _httpServerPort; + +void _testNetworking() { + group( + 'Networking-requiring tests:', + () { + setUpAll(() async { + // Do not run in Flutter or Node.JS + if (!(_isVM || _isBrowser)) { + return; + } + + final channel = spawnHybridUri('server.dart', message: {}); + final streamQueue = StreamQueue(channel.stream); + addTearDown(() { + channel.sink.close(); + }); + final port = ((await streamQueue.next) as num).toInt(); + _httpServerPort = port; + }); + + _testHttpRequest(); + _testEventSource(); + _testWindowControllerNetworking(); + }, + tags: 'networking', + timeout: Timeout(const Duration(seconds: 30)), + ); +} diff --git a/test/reflection_test.dart b/test/reflection_test.dart index efe41d8..f14d2bc 100644 --- a/test/reflection_test.dart +++ b/test/reflection_test.dart @@ -1,7 +1,22 @@ +// Copyright 2019 terrier989@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + @TestOn('vm') library reflection_test; import 'package:test/test.dart'; + import 'reflection_data.dart'; void main() { diff --git a/test/networking_test_server.dart b/test/server.dart similarity index 99% rename from test/networking_test_server.dart rename to test/server.dart index 7d08b9e..42aa1d3 100644 --- a/test/networking_test_server.dart +++ b/test/server.dart @@ -18,25 +18,6 @@ import 'dart:io'; import 'package:stream_channel/stream_channel.dart'; // Called by package:test -void hybridMain(StreamChannel streamChannel, Object message) async { - final httpServer = await HttpServer.bind('localhost', 0); - - print('Listening at: http://localhost:${httpServer.port}/'); - - final subscription = httpServer.listen(handleHttpRequest); - streamChannel.sink.add(httpServer.port); - - Timer(const Duration(minutes: 5), () { - httpServer.close(); - }); - streamChannel.stream.listen((event) {}, onDone: () { - httpServer.close(); - }); - subscription.onDone(() { - streamChannel.sink.close(); - }); -} - Future handleHttpRequest(HttpRequest request) async { print('${request.method} ${request.uri.path}'); final response = request.response; @@ -155,3 +136,21 @@ data: abc await response.close(); } } + +void hybridMain(StreamChannel streamChannel, Object message) async { + final httpServer = await HttpServer.bind('localhost', 0); + print('Listening at: http://localhost:${httpServer.port}/'); + final subscription = httpServer.listen(handleHttpRequest); + + streamChannel.sink.add(httpServer.port); + + Timer(const Duration(minutes: 5), () { + httpServer.close(); + }); + streamChannel.stream.listen((event) {}, onDone: () { + httpServer.close(); + }); + subscription.onDone(() { + streamChannel.sink.close(); + }); +} diff --git a/test/src/controller/window_controller.dart b/test/src/controller/window_controller.dart index c011852..0af0017 100644 --- a/test/src/controller/window_controller.dart +++ b/test/src/controller/window_controller.dart @@ -16,27 +16,6 @@ part of main_test; void _testController() { group('WindowController:', () { - test('openContent(_) throws UnsupportedError in browser', () async { - const content = - '

Hello world!

'; - final windowController = WindowController(); - expect( - () => windowController.openContent(content), - throwsUnsupportedError, - ); - }, testOn: 'browser'); - - test('openHttp(_) throws UnsupportedError in browser', () async { - final uri = Uri.parse( - 'http://localhost:$_httpServerPort/hello_world.html', - ); - final windowController = WindowController(); - expect( - () => windowController.openHttp(uri: uri), - throwsUnsupportedError, - ); - }, tags: 'networking', testOn: 'browser'); - test('openContent(_), sniffing ', () async { const content = '

Hello world!

'; @@ -45,7 +24,7 @@ void _testController() { final document = windowController.window!.document as HtmlDocument; final body = document.body!; expect(body.text, 'Hello world!'); - }, testOn: '!browser'); + }); test('openContent(_, contentType: _)', () async { final windowController = WindowController(); @@ -56,17 +35,6 @@ void _testController() { final document = windowController.window!.document as HtmlDocument; final body = document.body!; expect(body.text, 'Hello world!'); - }, testOn: '!browser'); - - test('openHttp', () async { - final uri = Uri.parse( - 'http://localhost:$_httpServerPort/hello_world.html', - ); - final windowController = WindowController(); - await windowController.openHttp(uri: uri); - final document = windowController.window!.document as HtmlDocument; - final body = document.body!; - expect(body.text, 'Hello world!'); - }, tags: 'networking', testOn: '!browser'); + }); }); } diff --git a/test/src/controller/window_controller_networking.dart b/test/src/controller/window_controller_networking.dart new file mode 100644 index 0000000..3b49a71 --- /dev/null +++ b/test/src/controller/window_controller_networking.dart @@ -0,0 +1,28 @@ +// Copyright 2019 terrier989@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +part of main_test; + +void _testWindowControllerNetworking() { + test('In VM, openHttp(_) returns the content', () async { + final uri = Uri.parse( + 'http://localhost:$_httpServerPort/hello_world.html', + ); + final windowController = WindowController(); + await windowController.openHttp(uri: uri); + final document = windowController.window!.document as HtmlDocument; + final body = document.body!; + expect(body.text, 'Hello world!'); + }, tags: 'networking'); +} diff --git a/test/src/html/dom/cloning.dart b/test/src/html/dom/cloning.dart index ead63f3..ec701b5 100644 --- a/test/src/html/dom/cloning.dart +++ b/test/src/html/dom/cloning.dart @@ -14,39 +14,6 @@ part of main_test; -void _testCloning() { - test('node.clone(true)', () { - // Create an element with many children - final original = DivElement(); - for (var tagName in tagNames) { - original.append(Element.tag(tagName)); - } - final originalOuterHtml = original.outerHtml; - - // Clone the element - final clone = original.clone(true) as Element; - expect(clone.outerHtml, originalOuterHtml); - _expectSaneTree(clone); - }); - - test('document.adoptNode', () { - // Create an element with many children - final original = DivElement(); - for (var tagName in tagNames) { - original.append(Element.tag(tagName)); - } - final originalOuterHtml = original.outerHtml; - - // Create a new document - final document = DomParser().parseFromString('', 'text/html'); - - // Adopt children from the original element - final clone = document.adoptNode(original) as Element; - expect(clone.outerHtml, originalOuterHtml); - _expectSaneTree(clone); - }); -} - const tagNames = [ 'A', 'ABBR', @@ -149,3 +116,36 @@ const tagNames = [ 'VIDEO', 'WBR', ]; + +void _testCloning() { + test('node.clone(true)', () { + // Create an element with many children + final original = DivElement(); + for (var tagName in tagNames) { + original.append(Element.tag(tagName)); + } + final originalOuterHtml = original.outerHtml; + + // Clone the element + final clone = original.clone(true) as Element; + expect(clone.outerHtml, originalOuterHtml); + _expectSaneTree(clone); + }); + + test('document.adoptNode', () { + // Create an element with many children + final original = DivElement(); + for (var tagName in tagNames) { + original.append(Element.tag(tagName)); + } + final originalOuterHtml = original.outerHtml; + + // Create a new document + final document = DomParser().parseFromString('', 'text/html'); + + // Adopt children from the original element + final clone = document.adoptNode(original) as Element; + expect(clone.outerHtml, originalOuterHtml); + _expectSaneTree(clone); + }); +} diff --git a/test/src/html/dom/css_style_declaration.dart b/test/src/html/dom/css_style_declaration.dart index c9bb186..2677f85 100644 --- a/test/src/html/dom/css_style_declaration.dart +++ b/test/src/html/dom/css_style_declaration.dart @@ -2,28 +2,41 @@ part of main_test; void _testCssStyleDeclaration() { group('CssStyleDeclaration:', () { - test('style.color = "red', () { + test('style.supportsProperty("color")', () { + final element = DivElement(); + expect(element.style.supportsProperty('color'), isTrue); + }); + + test('style.color = "red"', () { final element = DivElement(); element.style.color = 'red'; expect(element.style.color, 'red'); + expect(element.style.getPropertyValue('color'), 'red'); + expect(element.style.getPropertyPriority('color'), ''); }); test('style.color = null', () { final element = DivElement(); element.style.color = null; expect(element.style.color, ''); + expect(element.style.getPropertyValue('color'), ''); + expect(element.style.getPropertyPriority('color'), ''); }); - test('style.setProperty("color", "red)', () { + test('style.setProperty("color", "red")', () { final element = DivElement(); element.style.setProperty('color', 'red'); expect(element.style.color, 'red'); + expect(element.style.getPropertyValue('color'), 'red'); + expect(element.style.getPropertyPriority('color'), ''); }); test('style.setProperty("color", null)', () { final element = DivElement(); element.style.setProperty('color', null); expect(element.style.color, ''); + expect(element.style.getPropertyValue('color'), ''); + expect(element.style.getPropertyPriority('color'), ''); }); }); } diff --git a/test/src/html/dom/element_computed_style.dart b/test/src/html/dom/element_computed_style.dart index a998c8a..8f2231c 100644 --- a/test/src/html/dom/element_computed_style.dart +++ b/test/src/html/dom/element_computed_style.dart @@ -21,8 +21,7 @@ void _testElementComputedStyle() { test('Case #1', () { _temporarilyRemoveChildrenFromDocument(root: document.body!); - final styleElement = StyleElement() - ..appendText(''' + final styleElement = StyleElement()..appendText(''' .exampleClass { font-family: exampleFont }'''); @@ -31,16 +30,13 @@ void _testElementComputedStyle() { }); document.head!.insertBefore(styleElement, null); - final element = DivElement() - ..className = 'exampleClass'; + final element = DivElement()..className = 'exampleClass'; document.body!.insertBefore(element, null); addTearDown(() { element.remove(); }); - expect(element - .getComputedStyle() - .fontFamily, 'exampleFont'); + expect(element.getComputedStyle().fontFamily, 'exampleFont'); }); }); -} \ No newline at end of file +} diff --git a/test/src/html/dom/element_subclasses.dart b/test/src/html/dom/element_subclasses.dart index d311851..fd4ddd7 100644 --- a/test/src/html/dom/element_subclasses.dart +++ b/test/src/html/dom/element_subclasses.dart @@ -75,67 +75,6 @@ void _testAttribute({ ); } -void _testNonNullableAttribute( - String name, - T element, - String Function(T e) getter, - void Function(T element, String value) setter, { - String defaultValue = '', - String value = 'x', -}) { - // Test expectations - expect( - getter(element), - defaultValue, - reason: 'Default value is incorrect', - ); - - // Use element.setAttribute - element.setAttribute(name, value); - - // Test expectations - expect( - element.getAttribute(name), - value, - reason: 'Setting with setAttribute fails (getAttribute)', - ); - expect( - getter(element), - value, - reason: 'Setting with setAttribute fails (getter)', - ); - - // Reset - element.removeAttribute(name); - - // Test expectations - expect( - element.getAttribute(name), - null, - reason: 'Removing fails (getAttribute)', - ); - expect( - getter(element), - defaultValue, - reason: 'Removing fails (getter)', - ); - - // Use element.propertyName= - setter(element, value); - - // Test expectations - expect( - getter(element), - value, - reason: 'Setting with setter fails (getter', - ); - expect( - element.getAttribute(name), - value, - reason: 'Setting with setter fails (getAttribute)', - ); -} - void _testAttributeBool(String name, T element, bool? Function(T e) getter, void Function(T element, bool value) setter) { // Test expectations @@ -1062,3 +1001,64 @@ void _testElementSubclasses() { }); }); } + +void _testNonNullableAttribute( + String name, + T element, + String Function(T e) getter, + void Function(T element, String value) setter, { + String defaultValue = '', + String value = 'x', +}) { + // Test expectations + expect( + getter(element), + defaultValue, + reason: 'Default value is incorrect', + ); + + // Use element.setAttribute + element.setAttribute(name, value); + + // Test expectations + expect( + element.getAttribute(name), + value, + reason: 'Setting with setAttribute fails (getAttribute)', + ); + expect( + getter(element), + value, + reason: 'Setting with setAttribute fails (getter)', + ); + + // Reset + element.removeAttribute(name); + + // Test expectations + expect( + element.getAttribute(name), + null, + reason: 'Removing fails (getAttribute)', + ); + expect( + getter(element), + defaultValue, + reason: 'Removing fails (getter)', + ); + + // Use element.propertyName= + setter(element, value); + + // Test expectations + expect( + getter(element), + value, + reason: 'Setting with setter fails (getter', + ); + expect( + element.getAttribute(name), + value, + reason: 'Setting with setter fails (getAttribute)', + ); +} diff --git a/test/src/html/dom/helpers.dart b/test/src/html/dom/helpers.dart index 6d5b076..b221d1f 100644 --- a/test/src/html/dom/helpers.dart +++ b/test/src/html/dom/helpers.dart @@ -14,29 +14,6 @@ part of main_test; -void _temporarilyRemoveChildrenFromDocument({Node? root}) { - // Save nodes - root ??= universal_html.document; - - // Remove nodes - final nodes = List.from(root.childNodes); - for (var node in nodes) { - node.remove(); - } - - final finalRoot = root; - addTearDown(() { - // Removes - while (finalRoot.firstChild != null) { - finalRoot.firstChild!.remove(); - } - // Restore old nodes - for (var node in nodes) { - finalRoot.append(node); - } - }); -} - void _expectSaneDocument(Document document) { _expectSaneTree(document, expectedOwnerDocument: document); } @@ -104,3 +81,26 @@ void _expectSaneTree( } expect(node.lastChild, same(previousChild)); } + +void _temporarilyRemoveChildrenFromDocument({Node? root}) { + // Save nodes + root ??= universal_html.document; + + // Remove nodes + final nodes = List.from(root.childNodes); + for (var node in nodes) { + node.remove(); + } + + final finalRoot = root; + addTearDown(() { + // Removes + while (finalRoot.firstChild != null) { + finalRoot.firstChild!.remove(); + } + // Restore old nodes + for (var node in nodes) { + finalRoot.append(node); + } + }); +} diff --git a/test_in_flutter/dart_test.yaml b/test_in_flutter/dart_test.yaml index 97f72a7..f6200d4 100644 --- a/test_in_flutter/dart_test.yaml +++ b/test_in_flutter/dart_test.yaml @@ -1,3 +1,4 @@ +platforms: [vm] tags: networking: test_on: (browser && !browser) # Never \ No newline at end of file diff --git a/test/src/html/api/networking.dart b/test_in_flutter/lib/main.dart similarity index 59% rename from test/src/html/api/networking.dart rename to test_in_flutter/lib/main.dart index 6a2ef29..8f3cc99 100644 --- a/test/src/html/api/networking.dart +++ b/test_in_flutter/lib/main.dart @@ -12,23 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -part of main_test; +import 'package:universal_html/parsing.dart'; -// Local TCP port that has a HTTP server. -late int _httpServerPort; - -// Local TCP port hat DOES NOT have HTTP server. -// Used for testing connection failures. -const _httpServerWrongPort = 314; - -void _testNetworking() { - group( - 'Networking:', - () { - _testHttpRequest(); - _testEventSource(); - }, - tags: 'networking', - timeout: Timeout(const Duration(seconds: 30)), - ); +void main() { + parseHtmlDocument(''); } diff --git a/test_in_flutter/pubspec.yaml b/test_in_flutter/pubspec.yaml index 4022096..b823c62 100644 --- a/test_in_flutter/pubspec.yaml +++ b/test_in_flutter/pubspec.yaml @@ -14,4 +14,6 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - test: any \ No newline at end of file + pedantic: ^1.11.0 + stream_channel: ^2.1.0 + test: ^1.16.5 \ No newline at end of file diff --git a/test_in_flutter/test/main_test.dart b/test_in_flutter/test/main_test.dart index b1968c9..ac483b7 100644 --- a/test_in_flutter/test/main_test.dart +++ b/test_in_flutter/test/main_test.dart @@ -1,3 +1,17 @@ +// Copyright 2019 terrier989@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + import '../../test/main_test.dart' as tests; void main() { diff --git a/test_in_flutter/test/server.dart b/test_in_flutter/test/server.dart new file mode 100644 index 0000000..c6bab39 --- /dev/null +++ b/test_in_flutter/test/server.dart @@ -0,0 +1,20 @@ +// Copyright 2019 terrier989@gmail.com +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'package:stream_channel/stream_channel.dart'; +import '../../test/server.dart' as impl; + +void hybridMain(StreamChannel streamChannel, Object message) async { + impl.hybridMain(streamChannel, message); +} \ No newline at end of file diff --git a/test_in_flutter/web/favicon.png b/test_in_flutter/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/test_in_flutter/web/icons/Icon-192.png b/test_in_flutter/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/test_in_flutter/web/icons/Icon-512.png b/test_in_flutter/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/test_in_flutter/web/index.html b/test_in_flutter/web/index.html new file mode 100644 index 0000000..1df7b23 --- /dev/null +++ b/test_in_flutter/web/index.html @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + test_in_flutter + + + + + + + + diff --git a/test_in_flutter/web/manifest.json b/test_in_flutter/web/manifest.json new file mode 100644 index 0000000..8c4f9aa --- /dev/null +++ b/test_in_flutter/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "test_in_flutter", + "short_name": "test_in_flutter", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/tool/test.sh b/tool/test.sh index cbd4ad9..9b32d70 100755 --- a/tool/test.sh +++ b/tool/test.sh @@ -7,7 +7,7 @@ echo "-------------------------------------------------------------------------- echo "Running: dart test" echo " (in directory 'test')" echo "----------------------------------------------------------------------------------------------------" -dart get +dart pub get dart test echo "----------------------------------------------------------------------------------------------------" @@ -16,4 +16,5 @@ echo " (in directory 'test_in_flutter')" echo "----------------------------------------------------------------------------------------------------" cd test_in_flutter flutter pub get -flutter test \ No newline at end of file +flutter test +flutter build web \ No newline at end of file