sdk icon indicating copy to clipboard operation
sdk copied to clipboard

[dart:html] Breaking change: delete registerElement* APIs in dart:html

Open sigmundch opened this issue 3 years ago • 3 comments

Long ago dart:html provided methods to access the custom elements API of Web Components based on the specification version 0.5. Since then, the custom element API has changed a lot and today's browsers no longer support the API exposed by dart:html - those APIs are now outdated and simply fail at runtime.

Several years ago we also made the decision to not expose the latest custom elements API through dart:html, but instead encourage using JSInterop to leverage web components directly.

The intent of this breaking change is to remove the broken registerElement and registerElement2 APIs in dart:html. Note that APIs to access shadow dom, template elements, and other features that are part of the web component umbrella are not affected by this breaking change request.

What can break?

These APIs are already broken, but provide errors at runtime. Removing the APIs may potentially introduce compile-time errors.

Some users may not have errors at runtime if they relied on loading the Web Components v0.5 polyfill on all browsers. This polyfill is available on a couple channels, one of which is our web_components package. We think the use of this polyfill is not common (for instance, the web_component package hasn't been updated in 5 years, and is not even compatible with Dart 2.0). So it seems unlikely that developers in our community rely on it.

Mitigation Calls to the removed APIs need to be removed. In the rare scenario that a developer is using the polyfill, they will still be able to use it through JSInterop. They can do so by replacing document.registerElement(args) with js_util.callMethod(document, "registerElement", args).

/cc @itsjustkevin @kevmoo @mit-mit @vsmenon

sigmundch avatar Jul 27 '22 16:07 sigmundch

@vsmenon @grouma @Hixie

itsjustkevin avatar Jul 28 '22 18:07 itsjustkevin

i have no opinion

Hixie avatar Jul 29 '22 16:07 Hixie

Is there a reason we want to encourage JS interop usage instead of fixing the APIs?

As for the extent of this breaking change, I couldn't find any usages in Google3 besides this SDK test: https://github.com/dart-lang/sdk/blob/5d64241186398114529600ed20e20a0025378f06/pkg/compiler/test/deferred/custom_element_test.dart#L49

grouma avatar Aug 01 '22 17:08 grouma

@sigmundch any updates on this request?

itsjustkevin avatar Aug 12 '22 16:08 itsjustkevin

Sorry, just catching up after being on PTO.

Is there a reason we want to encourage JS interop usage instead of fixing the APIs?

Note that the web components API changed substantially, so even if we wanted to expose the latest API, it would not longer match the API we are proposing to delete on this issue, so we'd have to go through this breaking change regardless.

That said, the are a couple reasons to go via JSInterop:

  • Webcomponents are heavily JavaScript centric. Registering custom elements ask that you extend from native DOM types directly and properly plumb the underlying JavaScript constructors to some of the custom element APIs. As a result, these APIs don't just involve a library, but also rope in changes in our compilers to properly model these types and to intertwine Dart and JavaScript semantics for these classes. Our experience implementing that for v 0.5 in dart2js was that this added a lot of complexity in our compiler, and unfortunately it's not easy to just reuse what we have to evolve it to the new web components standard.
  • We are also evolving to make dart:html based on JSInterop. We are moving towards a direction where Dart doesn't couple the browser APIs in its libraries, but instead gives you a powerful interop layer that allows you to access whatever the browser environment provides.

sigmundch avatar Aug 12 '22 17:08 sigmundch

lgtm

vsmenon avatar Aug 16 '22 18:08 vsmenon

Side note: even the JavaScript function Document.registerElement() is deprecated in favor of customElements.define(), which itself doesn't seem to work either (at least in my attempts) potentially without #13836.

GZGavinZhao avatar Aug 18 '22 13:08 GZGavinZhao

@sigmundch looks like this landed in https://dart-review.googlesource.com/c/sdk/+/273541, so we can close this?

mit-mit avatar Dec 12 '22 08:12 mit-mit

Yes, thanks for checking.

sigmundch avatar Dec 12 '22 16:12 sigmundch

@GZGavinZhao I took a look at your attemps, perhaps you should try passing an instance of your custom element:

main.dart:

class NameInfoElement extends HtmlElement {
  static final tag = 'name-info';
  NameInfoElement.created() : super.created();
}

void main() {
  window.customElements?.define(NameInfoElement.tag, NameInfoElement.created());
}

index.html:

<!DOCTYPE html>

<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="scaffolded-by" content="https://github.com/dart-lang/sdk">
    <title>dart_wc</title>
    <link rel="stylesheet" href="styles.css">
    <script defer src="main.dart.js"></script>
</head>

<body>

<name-info>Ja moin</name-info>

</body>
</html>

jksevend avatar Jul 09 '23 14:07 jksevend