@@ -20171,6 +20171,39 @@ class HtmlDocument extends Document {
2017120171 return isElement ? jsClassName : null;
2017220172 }
2017320173
20174+ /**
20175+ * Does this CustomElement class have:
20176+ *
20177+ * - a created constructor with no arguments?
20178+ * - a created constructor with a super.created() initializer?
20179+ *
20180+ * e.g., MyCustomClass.created() : super.created();
20181+ */
20182+ bool _hasCreatedConstructor(ClassMirror classMirror) {
20183+ var createdParametersValid = false;
20184+ var superCreatedCalled = false;
20185+ var className = MirrorSystem.getName(classMirror.simpleName);
20186+ var methodMirror = classMirror.declarations[new Symbol("$className.created")];
20187+ if (methodMirror != null) {
20188+ createdParametersValid = methodMirror.parameters.length == 0;
20189+
20190+ // Get the created constructor source and look at the initializer;
20191+ // Must call super.created() if not its as an error.
20192+ var createdSource = methodMirror.source;
20193+ RegExp regExp = new RegExp(r":(.*?)(;|}|\n)");
20194+ var match = regExp.firstMatch(createdSource);
20195+ superCreatedCalled = match.input.substring(match.start,match.end).contains("super.created()");
20196+ }
20197+
20198+ if (!superCreatedCalled) {
20199+ throw new DomException.jsInterop('created constructor initializer must call super.created()');
20200+ } else if (!createdParametersValid) {
20201+ throw new DomException.jsInterop('created constructor must have no parameters');
20202+ }
20203+
20204+ return true;
20205+ }
20206+
2017420207 @Experimental()
2017520208 /**
2017620209 * Register a custom subclass of Element to be instantiatable by the DOM.
@@ -20225,68 +20258,71 @@ class HtmlDocument extends Document {
2022520258 throw new DomException.jsInterop("HierarchyRequestError: Only HTML elements can be customized.");
2022620259 }
2022720260
20228- // Start the hookup the JS way create an <x-foo> element that extends the
20229- // <x-base> custom element. Inherit its prototype and signal what tag is
20230- // inherited:
20231- //
20232- // var myProto = Object.create(HTMLElement.prototype);
20233- // var myElement = document.registerElement('x-foo', {prototype: myProto});
20234- var baseElement = js.context[jsClassName];
20235- if (baseElement == null) {
20236- // Couldn't find the HTML element so use a generic one.
20237- baseElement = js.context['HTMLElement'];
20238- }
20239- var elemProto = js.context['Object'].callMethod("create", [baseElement['prototype']]);
20240-
20241- // TODO(terry): Hack to stop recursion re-creating custom element when the
20242- // created() constructor of the custom element does e.g.,
20243- //
20244- // MyElement.created() : super.created() {
20245- // this.innerHtml = "<b>I'm an x-foo-with-markup!</b>";
20246- // }
20247- //
20248- // sanitizing causes custom element to created recursively
20249- // until stack overflow.
20250- //
20251- // See https://github.com/dart-lang/sdk/issues/23666
20252- int creating = 0;
20253- elemProto['createdCallback'] = new js.JsFunction.withThis(($this) {
20254- if (_getJSClassName(reflectClass(customElementClass).superclass) != null && creating < 2) {
20255- creating++;
20256-
20257- var dartClass;
20258- try {
20259- dartClass = _blink.Blink_Utils.constructElement(customElementClass, $this);
20260- } catch (e) {
20261- dartClass = null;
20262- } finally {
20263- // Need to remember the Dart class that was created for this custom so
20264- // return it and setup the blink_jsObject to the $this that we'll be working
20265- // with as we talk to blink.
20266- $this['dart_class'] = dartClass;
20267-
20268- creating--;
20269- }
20270- }
20271- });
20272- elemProto['attributeChangedCallback'] = new js.JsFunction.withThis(($this, attrName, oldVal, newVal) {
20273- if ($this["dart_class"] != null && $this['dart_class'].attributeChanged != null) {
20274- $this['dart_class'].attributeChanged(attrName, oldVal, newVal);
20275- }
20276- });
20277- elemProto['attachedCallback'] = new js.JsFunction.withThis(($this) {
20278- if ($this["dart_class"] != null && $this['dart_class'].attached != null) {
20279- $this['dart_class'].attached();
20261+ if (_hasCreatedConstructor(classMirror)) {
20262+ // Start the hookup the JS way create an <x-foo> element that extends the
20263+ // <x-base> custom element. Inherit its prototype and signal what tag is
20264+ // inherited:
20265+ //
20266+ // var myProto = Object.create(HTMLElement.prototype);
20267+ // var myElement = document.registerElement('x-foo', {prototype: myProto});
20268+ var baseElement = js.context[jsClassName];
20269+ if (baseElement == null) {
20270+ // Couldn't find the HTML element so use a generic one.
20271+ baseElement = js.context['HTMLElement'];
2028020272 }
20281- });
20282- elemProto['detachedCallback'] = new js.JsFunction.withThis(($this) {
20283- if ($this["dart_class"] != null && $this['dart_class'].detached != null) {
20284- $this['dart_class'].detached();
20285- }
20286- });
20287- // document.registerElement('x-foo', {prototype: elemProto, extends: extendsTag});
20288- var jsMap = new js.JsObject.jsify({'prototype': elemProto, 'extends': extendsTag});
20289- js.context['document'].callMethod('registerElement', [tag, jsMap]);
20273+ var elemProto = js.context['Object'].callMethod("create", [baseElement['prototype']]);
20274+
20275+ // TODO(terry): Hack to stop recursion re-creating custom element when the
20276+ // created() constructor of the custom element does e.g.,
20277+ //
20278+ // MyElement.created() : super.created() {
20279+ // this.innerHtml = "<b>I'm an x-foo-with-markup!</b>";
20280+ // }
20281+ //
20282+ // sanitizing causes custom element to created recursively
20283+ // until stack overflow.
20284+ //
20285+ // See https://github.com/dart-lang/sdk/issues/23666
20286+ int creating = 0;
20287+ elemProto['createdCallback'] = new js.JsFunction.withThis(($this) {
20288+ if (_getJSClassName(reflectClass(customElementClass).superclass) != null && creating < 2) {
20289+ creating++;
20290+
20291+ var dartClass;
20292+ try {
20293+ dartClass = _blink.Blink_Utils.constructElement(customElementClass, $this);
20294+ } catch (e) {
20295+ dartClass = HtmlElement.internalCreateHtmlElement();
20296+ throw e;
20297+ } finally {
20298+ // Need to remember the Dart class that was created for this custom so
20299+ // return it and setup the blink_jsObject to the $this that we'll be working
20300+ // with as we talk to blink.
20301+ $this['dart_class'] = dartClass;
20302+
20303+ creating--;
20304+ }
20305+ }
20306+ });
20307+ elemProto['attributeChangedCallback'] = new js.JsFunction.withThis(($this, attrName, oldVal, newVal) {
20308+ if ($this["dart_class"] != null && $this['dart_class'].attributeChanged != null) {
20309+ $this['dart_class'].attributeChanged(attrName, oldVal, newVal);
20310+ }
20311+ });
20312+ elemProto['attachedCallback'] = new js.JsFunction.withThis(($this) {
20313+ if ($this["dart_class"] != null && $this['dart_class'].attached != null) {
20314+ $this['dart_class'].attached();
20315+ }
20316+ });
20317+ elemProto['detachedCallback'] = new js.JsFunction.withThis(($this) {
20318+ if ($this["dart_class"] != null && $this['dart_class'].detached != null) {
20319+ $this['dart_class'].detached();
20320+ }
20321+ });
20322+ // document.registerElement('x-foo', {prototype: elemProto, extends: extendsTag});
20323+ var jsMap = new js.JsObject.jsify({'prototype': elemProto, 'extends': extendsTag});
20324+ js.context['document'].callMethod('registerElement', [tag, jsMap]);
20325+ }
2029020326 }
2029120327
2029220328 /** *Deprecated*: use [registerElement] instead. */
@@ -27928,7 +27964,14 @@ class _ChildNodeListLazy extends ListBase<Node> implements NodeListWrapper {
2792827964class Node extends EventTarget {
2792927965
2793027966 // Custom element created callback.
27931- Node._created() : super._created();
27967+ Node._created() : super._created() {
27968+ // By this point blink_jsObject should be setup if it's not then we weren't
27969+ // called by the registerElement createdCallback - probably created() was
27970+ // called directly which is verboten.
27971+ if (this.blink_jsObject == null) {
27972+ throw new DomException.jsInterop("the created constructor cannot be called directly");
27973+ }
27974+ }
2793227975
2793327976 /**
2793427977 * A modifiable list of this node's children.
@@ -37076,10 +37119,10 @@ class Url extends NativeFieldWrapperClass2 implements UrlUtils {
3707637119 if ((blob_OR_source_OR_stream is Blob || blob_OR_source_OR_stream == null)) {
3707737120 return _blink.BlinkURL.instance.createObjectURL_Callback_1_(unwrap_jso(blob_OR_source_OR_stream));
3707837121 }
37079- if ((blob_OR_source_OR_stream is MediaSource )) {
37122+ if ((blob_OR_source_OR_stream is MediaStream )) {
3708037123 return _blink.BlinkURL.instance.createObjectURL_Callback_1_(unwrap_jso(blob_OR_source_OR_stream));
3708137124 }
37082- if ((blob_OR_source_OR_stream is MediaStream )) {
37125+ if ((blob_OR_source_OR_stream is MediaSource )) {
3708337126 return _blink.BlinkURL.instance.createObjectURL_Callback_1_(unwrap_jso(blob_OR_source_OR_stream));
3708437127 }
3708537128 throw new ArgumentError("Incorrect number or type of arguments");
0 commit comments