-
Notifications
You must be signed in to change notification settings - Fork 33
Custom element's 'created' constructor called twice #248
Comments
<img src="https://avatars.githubusercontent.com/u/2049220?v=3" align="left" width="48" height="48"hspace="10"> Comment by sigmundch Thanks for the bug report and the nice repro instructions! Sounds like this is a duplicate of issue dart-lang/sdk#15844. I'll make a note in that bug to try to use the instructions you provide here to investigate further. Added Duplicate label. |
<img src="https://avatars.githubusercontent.com/u/2152569?v=3" align="left" width="48" height="48"hspace="10"> Comment by blois I cannot repro 15844 but can repro this bug, so unlinking. cc @sigmundch. |
<img src="https://avatars.githubusercontent.com/u/2152569?v=3" align="left" width="48" height="48"hspace="10"> Comment by blois The root of the issue appears to be that the child element class (confusingly named MyParent in the repro, but the intention is clear) extends from PolymerElement, but has an extends attribute for 'my-parent'. document.registerElement validates the extends tag, but since that only gets the native element name, it is passed null for the extends tag (native element is HtmlElement). The second parent creation is occurring within Polymer.js during registration of the my-child element. |
<img src="https://avatars.githubusercontent.com/u/3486855?v=3" align="left" width="48" height="48"hspace="10"> Comment by almstrand The initial sample code is updated below to:
warning: more than one Dart script tag in http://localhost:8080/index.html. Dartium currently only allows a single Dart script tag per document. pubspec.yaml name: myapp web/index.html <!DOCTYPE html> <my-parent>parent element</my-parent> <script type="application/dart">export 'package:polymer/init.dart';</script> web/my-parent.html <link rel="import" href="packages/polymer/polymer.html"> web/my-child.html <link rel="import" href="packages/polymer/polymer.html"> web/MyParent.dart import 'package:polymer/polymer.dart'; @CustomTag("my-parent") web/MyChild.dart import 'package:polymer/polymer.dart'; @CustomTag("my-child") This produces the same console output as in the original report, i.e.: parent created (:1) Per comment #3, I updated MyChild.dart as follows: web/MyChild.dart import 'MyParent.dart'; // <-- changed @CustomTag("my-child") And then the base class constructor is invoked trice! : parent created (:1) Assuming this implementation is correct, the issue seems fairly important as invoking a constructor more than once is bound to cause bugs due to initialization problems that may be hard to track down. |
<img src="https://avatars.githubusercontent.com/u/984921?v=3" align="left" width="48" height="48"hspace="10"> Comment by jakemac53 Just to narrow things down, below is a slightly smaller and possibly more telling repro, https://gist.github.com/jakemac53/06adf5aca6c3a3aa1684. I am not adding any parent or child tags (only definitions), yet I still get a log from the parent. It seems that adding the extends="foo" causes an instance of the extended class to be created, at least temporarily. |
<img src="https://avatars.githubusercontent.com/u/984921?v=3" align="left" width="48" height="48"hspace="10"> Comment by jakemac53 Ran across this in a test I was porting as well, it looks like ready() is also being fired on the extra element. |
<img src="https://avatars.githubusercontent.com/u/984921?v=3" align="left" width="48" height="48"hspace="10"> Comment by jakemac53 Discovered the actual cause of this when investigating issue #334. Whenever registering a custom element that extends from another element, dart:html creates an instance of the base element and compares its type to make sure you are actually extending that class. When registering a custom element in javascript, there is no such check. You can register an element which claims to extend 'input' with any arbitrary prototype. This seems pretty broken to me, since custom elements can have static state that is affected whenever a new element is created, and they can be potentially expensive to create (firing off ajax requests for example). |
<img src="https://avatars.githubusercontent.com/u/984921?v=3" align="left" width="48" height="48"hspace="10"> Comment by jakemac53 Edit: It actually looks like this only happens when extending native html types, which is much safer. Polymer.js was creating instances of the base tag when trying to figure out if the element had been registered or not. We are now registering all dart custom elements with polymer so that it doesn't have to do that. |
<img src="https://avatars.githubusercontent.com/u/984921?v=3" align="left" width="48" height="48"hspace="10"> Comment by jakemac53 Set owner to @jakemac53. |
<img src="https://avatars.githubusercontent.com/u/3486855?v=3" align="left" width="96" height="96"hspace="10"> Issue by almstrand
Originally opened as dart-lang/sdk#20197
The following is the minimal code I came up with which demonstrates the problem.
pubspec.yaml
=============================
name: myapp
dependencies:
polymer: ">=0.12.0-dev <0.12.0"
transformers:
entry_points: web/index.html
web/index.html:
=============================
<!DOCTYPE html>
<html>
<head>
<title>index</title>
<script src="packages/web_components/platform.js"></script>
<script src="packages/web_components/dart_support.js"></script>
</head>
<body>
<link rel="import" href="packages/polymer/polymer.html">
<!-- parent element -->
<polymer-element name="my-parent">
<script type="application/dart">
import 'package:polymer/polymer.dart';
@CustomTag("my-parent")
class MyParent extends PolymerElement {
MyParent.created() : super.created() {
print("parent created");
}
}
</script>
</polymer-element>
<!-- child element -->
<polymer-element name="my-child" extends="my-parent">
<script type="application/dart">
import 'package:polymer/polymer.dart';
@CustomTag("my-child")
class MyParent extends PolymerElement {
MyParent.created() : super.created() {
print("child created");
}
}
</script>
</polymer-element>
<my-parent>parent elment</my-parent>
<my-child>child element</my-child>
<script type="application/dart">export 'package:polymer/init.dart';</script>
</body>
</html>
Expected console log:
parent created (:1)
child created (:1)
Actual console log:
parent created (:1)
parent created (http://127.0.0.1:8080/packages/polymer/src/js/polymer/polymer.js:12)
child created (:1)
Reproduced in:
Dart SDK version: 1.5.3
Polymer package version: 0.12.0-dev
Operating system: Ubuntu 14.04 64-bit
Browser (if any): Dartium, version 36.0.1985.97 (280598)
The text was updated successfully, but these errors were encountered: