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

Side by Side Diff: pkg/compiler/lib/src/js_emitter/native_emitter.dart

Issue 1318043005: Support user generated custom native JS classes. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: ptal Created 5 years, 3 months 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 part of dart2js.js_emitter; 5 part of dart2js.js_emitter;
6 6
7 class NativeEmitter { 7 class NativeEmitter {
8 8
9 // TODO(floitsch): the native-emitter should not know about ClassBuilders. 9 // TODO(floitsch): the native-emitter should not know about ClassBuilders.
10 final Map<Element, full_js_emitter.ClassBuilder> cachedBuilders; 10 final Map<Element, full_js_emitter.ClassBuilder> cachedBuilders;
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 needed = true; 127 needed = true;
128 } else if (interceptorClassesNeededByConstants.contains(classElement)) { 128 } else if (interceptorClassesNeededByConstants.contains(classElement)) {
129 needed = true; 129 needed = true;
130 } else if (classesModifiedByEmitRTISupport.contains(classElement)) { 130 } else if (classesModifiedByEmitRTISupport.contains(classElement)) {
131 // TODO(9556): Remove this test when [emitRuntimeTypeSupport] no longer 131 // TODO(9556): Remove this test when [emitRuntimeTypeSupport] no longer
132 // adds information to a class prototype or constructor. 132 // adds information to a class prototype or constructor.
133 needed = true; 133 needed = true;
134 } else if (extensionPoints.containsKey(cls)) { 134 } else if (extensionPoints.containsKey(cls)) {
135 needed = true; 135 needed = true;
136 } 136 }
137 if (cls.isNative && 137 if (classElement.isJsInterop) {
138 native.nativeTagsForcedNonLeaf(classElement)) { 138 needed = true; // TODO(jacobr): we don't need all interop classes.
Siggi Cherem (dart-lang) 2015/09/18 20:34:10 what are your thoughts on determining what is need
Jacob 2015/10/01 00:47:33 types allocated from Dart isn't adequate types ret
139 } else if (cls.isNative && native.nativeTagsForcedNonLeaf(classElement)) {
139 needed = true; 140 needed = true;
140 nonLeafClasses.add(cls); 141 nonLeafClasses.add(cls);
141 } 142 }
142 143
143 if (needed || neededClasses.contains(cls)) { 144 if (needed || neededClasses.contains(cls)) {
144 neededClasses.add(cls); 145 neededClasses.add(cls);
145 neededClasses.add(cls.superclass); 146 neededClasses.add(cls.superclass);
146 nonLeafClasses.add(cls.superclass); 147 nonLeafClasses.add(cls.superclass);
147 } 148 }
148 } 149 }
149 150
150 // Collect all the tags that map to each native class. 151 // Collect all the tags that map to each native class.
151 152
152 Map<Class, Set<String>> leafTags = new Map<Class, Set<String>>(); 153 Map<Class, Set<String>> leafTags = new Map<Class, Set<String>>();
153 Map<Class, Set<String>> nonleafTags = new Map<Class, Set<String>>(); 154 Map<Class, Set<String>> nonleafTags = new Map<Class, Set<String>>();
154 155
155 for (Class cls in classes) { 156 for (Class cls in classes) {
156 if (!cls.isNative) continue; 157 if (!cls.isNative) continue;
158 if (cls.element.isJsInterop) continue;
157 List<String> nativeTags = native.nativeTagsOfClass(cls.element); 159 List<String> nativeTags = native.nativeTagsOfClass(cls.element);
158 160
159 if (nonLeafClasses.contains(cls) || 161 if (nonLeafClasses.contains(cls) ||
160 extensionPoints.containsKey(cls)) { 162 extensionPoints.containsKey(cls)) {
161 nonleafTags 163 nonleafTags
162 .putIfAbsent(cls, () => new Set<String>()) 164 .putIfAbsent(cls, () => new Set<String>())
163 .addAll(nativeTags); 165 .addAll(nativeTags);
164 } else { 166 } else {
165 Class sufficingInterceptor = cls; 167 Class sufficingInterceptor = cls;
166 while (!neededClasses.contains(sufficingInterceptor)) { 168 while (!neededClasses.contains(sufficingInterceptor)) {
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 List<jsAst.Statement> generateParameterStubStatements( 289 List<jsAst.Statement> generateParameterStubStatements(
288 FunctionElement member, 290 FunctionElement member,
289 bool isInterceptedMethod, 291 bool isInterceptedMethod,
290 jsAst.Name invocationName, 292 jsAst.Name invocationName,
291 List<jsAst.Parameter> stubParameters, 293 List<jsAst.Parameter> stubParameters,
292 List<jsAst.Expression> argumentsBuffer, 294 List<jsAst.Expression> argumentsBuffer,
293 int indexOfLastOptionalArgumentInParameters) { 295 int indexOfLastOptionalArgumentInParameters) {
294 // The target JS function may check arguments.length so we need to 296 // The target JS function may check arguments.length so we need to
295 // make sure not to pass any unspecified optional arguments to it. 297 // make sure not to pass any unspecified optional arguments to it.
296 // For example, for the following Dart method: 298 // For example, for the following Dart method:
297 // foo([x, y, z]); 299 // foo({x, y, z});
298 // The call: 300 // The call:
299 // foo(y: 1) 301 // foo(y: 1)
300 // must be turned into a JS call to: 302 // must be turned into a JS call to:
301 // foo(null, y). 303 // foo(null, y).
302 304
303 List<jsAst.Statement> statements = <jsAst.Statement>[]; 305 List<jsAst.Statement> statements = <jsAst.Statement>[];
304 potentiallyConvertDartClosuresToJs(statements, member, stubParameters); 306 potentiallyConvertDartClosuresToJs(statements, member, stubParameters);
305 307
306 String target; 308 String target;
307 jsAst.Expression receiver; 309 jsAst.Expression receiver;
308 List<jsAst.Expression> arguments; 310 List<jsAst.Expression> arguments;
309 311
310 assert(invariant(member, nativeMethods.contains(member))); 312 assert(invariant(member, nativeMethods.contains(member)));
311 // When calling a JS method, we call it with the native name, and only the 313 // When calling a JS method, we call it with the native name, and only the
312 // arguments up until the last one provided. 314 // arguments up until the last one provided.
313 target = member.fixedBackendName; 315 target = member.fixedBackendName;
314 316
315 if (isInterceptedMethod) { 317 if (isInterceptedMethod) {
316 receiver = argumentsBuffer[0]; 318 receiver = argumentsBuffer[0];
317 arguments = argumentsBuffer.sublist(1, 319 arguments = argumentsBuffer.sublist(1,
318 indexOfLastOptionalArgumentInParameters + 1); 320 indexOfLastOptionalArgumentInParameters + 1);
319 } else { 321 } else {
320 // Native methods that are not intercepted must be static. 322 // Native methods that are not intercepted must be static.
321 assert(invariant(member, member.isStatic)); 323 assert(invariant(member, member.isStatic));
322 receiver = js('this');
323 arguments = argumentsBuffer.sublist(0, 324 arguments = argumentsBuffer.sublist(0,
324 indexOfLastOptionalArgumentInParameters + 1); 325 indexOfLastOptionalArgumentInParameters + 1);
326 if (member.isJsInterop) {
327 // target is allowed to have the form foo.bar.baz for interop.
328 // TODO(jacobr): replace js(target) with a version that doesn't cache.
329 statements.add(
330 js.statement('return #(#)', [js(target), arguments]));
Siggi Cherem (dart-lang) 2015/09/18 20:34:10 style nit: might be nice to keep the statements.ad
Jacob 2015/10/01 00:47:33 yeah this code was ugly. done.
331 return statements;
332 } else {
333 receiver = js('this');
334 }
325 } 335 }
326 statements.add( 336 statements.add(
327 js.statement('return #.#(#)', [receiver, target, arguments])); 337 js.statement('return #.#(#)', [receiver, target, arguments]));
328 338
329 return statements; 339 return statements;
330 } 340 }
331 341
332 bool isSupertypeOfNativeClass(ClassElement element) { 342 bool isSupertypeOfNativeClass(ClassElement element) {
333 if (backend.classesMixedIntoInterceptedClasses.contains(element)) { 343 if (backend.classesMixedIntoInterceptedClasses.contains(element)) {
334 return true; 344 return true;
335 } 345 }
336 346
337 return subtypes[element] != null; 347 return subtypes[element] != null;
338 } 348 }
339 349
340 bool requiresNativeIsCheck(Element element) { 350 bool requiresNativeIsCheck(Element element) {
341 // TODO(sra): Remove this function. It determines if a native type may 351 // TODO(sra): Remove this function. It determines if a native type may
342 // satisfy a check against [element], in which case an interceptor must be 352 // satisfy a check against [element], in which case an interceptor must be
343 // used. We should also use an interceptor if the check can't be satisfied 353 // used. We should also use an interceptor if the check can't be satisfied
344 // by a native class in case we get a native instance that tries to spoof 354 // by a native class in case we get a native instance that tries to spoof
345 // the type info. i.e the criteria for whether or not to use an interceptor 355 // the type info. i.e the criteria for whether or not to use an interceptor
346 // is whether the receiver can be native, not the type of the test. 356 // is whether the receiver can be native, not the type of the test.
347 if (element == null || !element.isClass) return false; 357 if (element == null || !element.isClass) return false;
348 ClassElement cls = element; 358 ClassElement cls = element;
349 if (Elements.isNativeOrExtendsNative(cls)) return true; 359 if (Elements.isNativeOrExtendsNative(cls)) return true;
350 return isSupertypeOfNativeClass(element); 360 return isSupertypeOfNativeClass(element);
351 } 361 }
352 } 362 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698