Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(230)

Side by Side Diff: lib/src/emitters.dart

Issue 11315020: Add attribute information table so we generate correct setters. (Closed) Base URL: https://github.com/dart-lang/dart-web-components.git@master
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** Collects several code emitters for the template tool. */ 5 /** Collects several code emitters for the template tool. */
6 // TODO(sigmund): add visitor that applies all emitters on a component 6 // TODO(sigmund): add visitor that applies all emitters on a component
7 // TODO(sigmund): add support for conditionals, so context is changed at that 7 // TODO(sigmund): add support for conditionals, so context is changed at that
8 // point. 8 // point.
9 library emitters; 9 library emitters;
10 10
11 import 'package:html5lib/dom.dart'; 11 import 'package:html5lib/dom.dart';
12 import 'package:html5lib/dom_parsing.dart'; 12 import 'package:html5lib/dom_parsing.dart';
13 // TODO(jmesserly): this utility should be somewhere else. 13 // TODO(jmesserly): this utility should be somewhere else.
14 import 'package:html5lib/src/utils.dart' show reversed; 14 import 'package:html5lib/src/utils.dart' show reversed;
15 15
16 import 'code_printer.dart'; 16 import 'code_printer.dart';
17 import 'codegen.dart' as codegen; 17 import 'codegen.dart' as codegen;
18 import 'file_system/path.dart'; 18 import 'file_system/path.dart';
19 import 'files.dart'; 19 import 'files.dart';
20 import 'html5_utils.dart'; 20 import 'html5_utils.dart';
21 import 'html5_setters.g.dart';
21 import 'info.dart'; 22 import 'info.dart';
22 import 'messages.dart'; 23 import 'messages.dart';
23 import 'utils.dart'; 24 import 'utils.dart';
24 25
25 /** 26 /**
26 * An emitter for a web component feature. It collects all the logic for 27 * An emitter for a web component feature. It collects all the logic for
27 * emitting a particular feature (such as data-binding, event hookup) with 28 * emitting a particular feature (such as data-binding, event hookup) with
28 * respect to a single HTML element. 29 * respect to a single HTML element.
29 */ 30 */
30 abstract class Emitter<T extends ElementInfo> { 31 abstract class Emitter<T extends ElementInfo> {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 } 84 }
84 85
85 /** 86 /**
86 * Generates a field for any element that has either event listeners or data 87 * Generates a field for any element that has either event listeners or data
87 * bindings. 88 * bindings.
88 */ 89 */
89 class ElementFieldEmitter extends Emitter<ElementInfo> { 90 class ElementFieldEmitter extends Emitter<ElementInfo> {
90 ElementFieldEmitter(ElementInfo info) : super(info); 91 ElementFieldEmitter(ElementInfo info) : super(info);
91 92
92 void emitDeclarations(Context context) { 93 void emitDeclarations(Context context) {
93 var type = htmlElementNames[elem.tagName]; 94 var type = typeForHtmlTag(elem.tagName);
94 // Note: this will eventually be the component's class name if it is a
95 // known x-tag.
96 if (type == null) type = 'UnknownElement';
97 context.declarations.add('autogenerated.$type ${elemInfo.identifier};'); 95 context.declarations.add('autogenerated.$type ${elemInfo.identifier};');
98 } 96 }
99 97
100 void emitCreated(Context context) { 98 void emitCreated(Context context) {
101 // TODO(jmesserly): there's an asymmetry here. In one case, the child is 99 // TODO(jmesserly): there's an asymmetry here. In one case, the child is
102 // already in the document but not in the other case. 100 // already in the document but not in the other case.
103 if (elemInfo.needsQuery) { 101 if (elemInfo.needsQuery) {
104 var parentId = '_root'; 102 var parentId = '_root';
105 for (var p = elemInfo.parent; p != null; p = p.parent) { 103 for (var p = elemInfo.parent; p != null; p = p.parent) {
106 if (p.identifier != null) { 104 if (p.identifier != null) {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 if (e.oldValue != null && e.oldValue != '') { 221 if (e.oldValue != null && e.oldValue != '') {
224 $elemField.classes.remove(e.oldValue); 222 $elemField.classes.remove(e.oldValue);
225 } 223 }
226 if (e.newValue != null && e.newValue != '') { 224 if (e.newValue != null && e.newValue != '') {
227 $elemField.classes.add(e.newValue); 225 $elemField.classes.add(e.newValue);
228 } 226 }
229 }); 227 });
230 '''); 228 ''');
231 } 229 }
232 } else { 230 } else {
231 // Note: it is important for correctness to use the DOM setter if it
232 // is available. Otherwise changes will not be applied. This is most
233 // easily observed with "InputElement.value", ".checked", etc.
234 var setter = null;
235 var typeName = typeForHtmlTag(elem.tagName);
236 while (typeName != null) {
237 var fields = htmlElementFields[typeName];
238 if (fields != null) setter = fields[name];
239 if (setter != null) break;
240 typeName = htmlElementExtends[typeName];
Siggi Cherem (dart-lang) 2012/11/06 03:20:36 emulating dart semantics, yay! -- sarcasm ;-)
Jennifer Messerly 2012/11/06 03:51:57 Hah, yeah :\. OTOH, it's kind of Web IDL semantics
241 }
242 if (setter == null) setter = 'attributes["$name"]';
243
233 var val = attrInfo.boundValue; 244 var val = attrInfo.boundValue;
234 var stopperName = attrInfo.stopperNames[0]; 245 var stopperName = attrInfo.stopperNames[0];
235 var setter;
236 // TODO(sigmund): use setters when they are available (issue #112)
237 // Need to know if an attr is known for an element.
238 if ((elem.tagName == 'input' &&
239 (name == 'value' || name == 'checked')) ||
240 name == 'hidden') {
241 setter = name;
242 } else {
243 setter = 'attributes["$name"]';
244 }
245 context.insertedMethod.add(''' 246 context.insertedMethod.add('''
246 $stopperName = autogenerated.watchAndInvoke(() => $val, (e) { 247 $stopperName = autogenerated.watchAndInvoke(() => $val, (e) {
247 $elemField.$setter = e.newValue; 248 $elemField.$setter = e.newValue;
248 }); 249 });''');
249 ''');
250 } 250 }
251 }); 251 });
252 252
253 // Emit functions for any data-bound content on this element or children of 253 // Emit functions for any data-bound content on this element or children of
254 // this element. 254 // this element.
255 _emitContentWatchInvoke(context, elemInfo, elemField); 255 _emitContentWatchInvoke(context, elemInfo, elemField);
256 for (var childInfo in elemInfo.children) { 256 for (var childInfo in elemInfo.children) {
257 _emitContentWatchInvoke(context, childInfo, elemField); 257 _emitContentWatchInvoke(context, childInfo, elemField);
258 } 258 }
259 } 259 }
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
737 void _emitHtmlElement(CodePrinter method, ElementInfo info) { 737 void _emitHtmlElement(CodePrinter method, ElementInfo info) {
738 // http://dev.w3.org/html5/spec/namespaces.html#namespaces 738 // http://dev.w3.org/html5/spec/namespaces.html#namespaces
739 const htmlNamespace = 'http://www.w3.org/1999/xhtml'; 739 const htmlNamespace = 'http://www.w3.org/1999/xhtml';
740 740
741 var node = info.node; 741 var node = info.node;
742 742
743 // Generate precise types like "new ButtonElement()" if we can. 743 // Generate precise types like "new ButtonElement()" if we can.
744 if (node.attributes.length == 0 && node.nodes.length == 0 && 744 if (node.attributes.length == 0 && node.nodes.length == 0 &&
745 node.namespace == htmlNamespace) { 745 node.namespace == htmlNamespace) {
746 746
747 var elementName = htmlElementNames[node.tagName]; 747 var elementName = htmlElementNames[node.tagName];
Siggi Cherem (dart-lang) 2012/11/06 03:20:36 you probably want to fix it here too
Jennifer Messerly 2012/11/06 03:51:57 I don't think "new autogenerated.UnknownElement" w
748 if (elementName != null) { 748 if (elementName != null) {
749 method.add("${info.identifier} = new autogenerated.$elementName();"); 749 method.add("${info.identifier} = new autogenerated.$elementName();");
750 return; 750 return;
751 } 751 }
752 } 752 }
753 753
754 method.add("${info.identifier} = new autogenerated.Element.html('''") 754 method.add("${info.identifier} = new autogenerated.Element.html('''")
755 .addRaw(escapeDartString(node.outerHTML, triple: true)) 755 .addRaw(escapeDartString(node.outerHTML, triple: true))
756 .add("''');"); 756 .add("''');");
757 } 757 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698