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

Side by Side Diff: frog/var_member.dart

Issue 8746005: Fix a bunch of issues with 'hidden' DOM types. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: removed dead code Created 9 years 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 /** A dynamic member stub. */ 5 /** A dynamic member stub. */
6 class VarMember { 6 class VarMember {
7 final String name; 7 final String name;
8 8
9 VarMember(this.name); 9 VarMember(this.name);
10 10
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 w.enterBlock('Function.prototype.$name = function(${argsCode}) {'); 105 w.enterBlock('Function.prototype.$name = function(${argsCode}) {');
106 w.writeln('this.$name = this.\$genStub(${args.length}, ["$named"]);'); 106 w.writeln('this.$name = this.\$genStub(${args.length}, ["$named"]);');
107 w.writeln('return this.$name($argsCode);'); 107 w.writeln('return this.$name($argsCode);');
108 w.exitBlock('}'); 108 w.exitBlock('}');
109 } 109 }
110 } 110 }
111 111
112 class VarMethodStub extends VarMember { 112 class VarMethodStub extends VarMember {
113 final Member member; 113 final Member member;
114 final Arguments args; 114 final Arguments args;
115 final Value body; 115 final String body;
116 116
117 VarMethodStub(String name, this.member, this.args, this.body): super(name); 117 VarMethodStub(String name, this.member, this.args, this.body): super(name);
118 118
119 bool get isHidden() =>
120 member != null ? member.declaringType.isHiddenNativeType : false;
121
119 Type get returnType() => 122 Type get returnType() =>
120 member != null ? member.returnType : world.varType; 123 member != null ? member.returnType : world.varType;
121 124
122 String get typeName() => 125 Type get declaringType() =>
123 member != null ? member.declaringType.jsname : 'Object'; 126 member != null ? member.declaringType : world.objectType;
124 127
125 void generate(CodeWriter code) { 128 void generate(CodeWriter code) {
126 code.write('$typeName.prototype.$name = '); 129 code.write(world.gen._prototypeOf(declaringType, name) + ' = ');
127 generateBody(code, ';'); 130 if (!isHidden && _useDirectCall(args)) {
128 } 131 code.writeln('${declaringType.jsname}.prototype.${member.jsname};');
129 132 } else if (_needsExactTypeCheck()) {
130 void generateBody(CodeWriter code, String end) { 133 code.enterBlock('function(${args.getCode()}) {');
131 if (_useDirectCall(member, args)) { 134 code.enterBlock(
132 code.writeln('$typeName.prototype.${member.jsname}$end'); 135 'if (Object.getPrototypeOf(this).hasOwnProperty("$name")) {');
136 code.writeln('$body;');
137 code.exitBlock('}');
138 String argsCode = args.getCode();
139 if (argsCode != '') argsCode = ', ' + argsCode;
140 code.writeln('return Object.prototype.$name.call(this$argsCode);');
141 code.exitBlock('};');
133 } else { 142 } else {
134 code.enterBlock('function(${args.getCode()}) {'); 143 code.enterBlock('function(${args.getCode()}) {');
135 code.writeln('return ${body.code};'); 144 code.writeln('$body;');
136 code.exitBlock('}$end'); 145 code.exitBlock('};');
137 } 146 }
138 } 147 }
139 148
140 bool _useDirectCall(Member member, Arguments args) { 149 /**
141 // Create direct stubs when we can. We don't do this if the type is hidden, 150 * If we have a native method overridden by a hidden native method, we need to
142 // i.e. we can't use "TypeName.prototype" to initialize. We also don't do it 151 * make sure the base one has an exact type test. Otherwise we don't need
143 // for types like Object, that have native subtypes, otherwise things like 152 * this.
153 */
154 bool _needsExactTypeCheck() {
155 if (member == null || member.declaringType.isObject) return false;
156
157 var members = member.declaringType.resolveMember(member.name).members;
158 return members.filter((m) => m != member
159 && m.declaringType.isHiddenNativeType).length >= 1;
160 }
161
162 bool _useDirectCall(Arguments args) {
163 // Create direct stubs when we can. We don't do this in some cases, such as
164 // types that have native subtypes (like Object), otherwise things like
144 // Object.prototype.toString$0 end up calling the toString on Object instead 165 // Object.prototype.toString$0 end up calling the toString on Object instead
145 // of on the derived type. 166 // of on the derived type.
146 if (member is MethodMember && !member.declaringType.isHiddenNativeType 167 if (member is MethodMember && !member.declaringType.hasNativeSubtypes) {
147 && !member.declaringType.hasNativeSubtypes) {
148 MethodMember method = member; 168 MethodMember method = member;
149 if (method.needsArgumentConversion(args)) { 169 if (method.needsArgumentConversion(args)) {
150 return false; 170 return false;
151 } 171 }
152 172
153 // If we have the right number of parameters, or all defaults would be 173 // If we have the right number of parameters, or all defaults would be
154 // filled in as "undefined" anyway, we can just call the method directly. 174 // filled in as "undefined" anyway, we can just call the method directly.
155 for (int i = args.length; i < method.parameters.length; i++) { 175 for (int i = args.length; i < method.parameters.length; i++) {
156 if (method.parameters[i].value.code != 'null') { 176 if (method.parameters[i].value.code != 'null') {
157 return false; 177 return false;
(...skipping 10 matching lines...) Expand all
168 * A special member with a mangled name that represents a dynamic call 188 * A special member with a mangled name that represents a dynamic call
169 * (i.e. a call with multiple valid targets). We generate this if we have 189 * (i.e. a call with multiple valid targets). We generate this if we have
170 * a dynamic call that needs different implementation methods for different 190 * a dynamic call that needs different implementation methods for different
171 * members. 191 * members.
172 */ 192 */
173 class VarMethodSet extends VarMember { 193 class VarMethodSet extends VarMember {
174 final List<Member> members; 194 final List<Member> members;
175 final Type returnType; 195 final Type returnType;
176 final Arguments args; 196 final Arguments args;
177 197
178 /** The fallback stubs that need to be in our Object.prototype stub. */ 198 bool invoked = false;
179 List<VarMethodStub> _fallbackStubs;
180 199
181 VarMethodSet(String name, this.members, Arguments callArgs, this.returnType) 200 VarMethodSet(String name, this.members, Arguments callArgs, this.returnType)
182 : super(name), args = callArgs.toCallStubArgs() { 201 : super(name), args = callArgs.toCallStubArgs() {
183 } 202 }
184 203
185 /** The unmangled member name. */ 204 /** The unmangled member name. */
186 String get baseName() => members[0].name; 205 String get baseName() => members[0].name;
187 206
188 Value invoke(MethodGenerator context, Node node, Value target, Arguments args) { 207 Value invoke(MethodGenerator context, Node node, Value target,
208 Arguments args) {
189 _invokeMembers(context, node); 209 _invokeMembers(context, node);
190 return super.invoke(context, node, target, args); 210 return super.invoke(context, node, target, args);
191 } 211 }
192 212
193 /** Invokes members to ensure they're generated. */ 213 /** Invokes members to ensure they're generated. */
194 _invokeMembers(MethodGenerator context, Node node) { 214 _invokeMembers(MethodGenerator context, Node node) {
195 if (_fallbackStubs != null) return; 215 if (invoked) return;
216 invoked = true;
196 217
197 var objectStub = null; 218 bool hasObjectType = false;
198 _fallbackStubs = [];
199 for (var member in members) { 219 for (var member in members) {
200 // Invoke the member with the stub args (this gives us the method body), 220 // Invoke the member with the stub args (this gives us the method body),
201 // then create the stub method. 221 // then create the stub method.
202 final target = new Value(member.declaringType, 'this', node.span); 222 final type = member.declaringType;
223 final target = new Value(type, 'this', node.span);
203 var result = member.invoke(context, node, target, args, isDynamic:true); 224 var result = member.invoke(context, node, target, args, isDynamic:true);
204 var stub = new VarMethodStub(name, member, args, result); 225 var stub = new VarMethodStub(name, member, args, 'return ' + result.code);
226 type.varStubs[stub.name] = stub;
205 227
206 // Put the stub on the type directly if possible. Otherwise 228 if (type.isObject) hasObjectType = true;
207 // put the stub on Object.prototype.
208 var type = member.declaringType;
209 if (type.isObject) {
210 objectStub = stub;
211 } else if (!type.isHiddenNativeType) {
212 _addVarStub(type, stub);
213 } else {
214 _fallbackStubs.add(stub);
215 }
216 } 229 }
217 230
218 // Create a noSuchMethod fallback on Object if needed. 231 // Create a noSuchMethod fallback on Object if needed.
219 // Some methods, like toString and == already have a fallback on Object. 232 // Some methods, like toString and == already have a fallback on Object.
220 if (objectStub == null) { 233 if (!hasObjectType) {
221 final target = new Value(world.objectType, 'this', node.span); 234 final target = new Value(world.objectType, 'this', node.span);
222 var result = target.invokeNoSuchMethod(context, baseName, node, args); 235 var result = target.invokeNoSuchMethod(context, baseName, node, args);
223 objectStub = new VarMethodStub(name, null, args, result); 236 var stub = new VarMethodStub(name, null, args, 'return ' + result.code);
224 } 237 world.objectType.varStubs[stub.name] = stub;
225 if (_fallbackStubs.length == 0) {
226 _addVarStub(world.objectType, objectStub);
227 } else {
228 _fallbackStubs.add(objectStub);
229 world.gen.corejs.useVarMethod = true;
230 } 238 }
231 } 239 }
232 240
233 static _addVarStub(Type type, VarMember stub) { 241 // TODO(jmesserly): get rid of this as it's unused now
234 if (type.varStubs == null) type.varStubs = {}; 242 void generate(CodeWriter code) {}
235 type.varStubs[stub.name] = stub;
236 }
237
238 /**
239 * Generate var call fallbacks, like this:
240 *
241 * $varMethod('addEventListener$1$capture', {
242 * 'HTMLElement': function($0, capture) {
243 * return this.addEventListener($0, capture);
244 * },
245 * 'SomeOtherDOMType': function($0, capture) {
246 * return this.addEventListener($0, false, true, capture);
247 * },
248 * 'Object': function($0, capture) {
249 * return this.noSuchMethod('addEventListener', [$0],
250 * {'capture': capture});
251 * }
252 * });
253 */
254 void generate(CodeWriter code) {
255 if (_fallbackStubs.length == 0) return;
256
257 code.enterBlock('\$varMethod("$name", {');
258 var lastOne = _fallbackStubs.last();
259 for (var stub in _fallbackStubs) {
260 code.write('"${stub.typeName}": ');
261 stub.generateBody(code, stub == lastOne ? '' : ',');
262 }
263 code.exitBlock('});');
264 }
265 } 243 }
266 244
267 String _getCallStubName(String name, Arguments args) { 245 String _getCallStubName(String name, Arguments args) {
268 final nameBuilder = new StringBuffer('${name}\$${args.bareCount}'); 246 final nameBuilder = new StringBuffer('${name}\$${args.bareCount}');
269 for (int i = args.bareCount; i < args.length; i++) { 247 for (int i = args.bareCount; i < args.length; i++) {
270 nameBuilder.add('\$').add(args.getName(i)); 248 nameBuilder.add('\$').add(args.getName(i));
271 } 249 }
272 return nameBuilder.toString(); 250 return nameBuilder.toString();
273 } 251 }
252
OLDNEW
« frog/lib/corelib.dart ('K') | « frog/value.dart ('k') | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698