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

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: about to land Created 5 years, 2 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.
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 // fixedBackendPath is allowed to have the form foo.bar.baz for
328 // interop. This template is uncached to avoid possibly running out of
329 // memory when Dart2Js is run in server mode. In reality the risk of
330 // caching these templates causing an issue is very low as each class
331 // and library that uses typed JavaScript interop will create only 1
332 // unique template.
333 receiver = js.uncachedExpressionTemplate(
334 backend.namer.fixedBackendPath(member)).instantiate([]);
335 } else {
336 receiver = js('this');
337 }
325 } 338 }
326 statements.add( 339 statements.add(
327 js.statement('return #.#(#)', [receiver, target, arguments])); 340 js.statement('return #.#(#)', [receiver, target, arguments]));
328 341
329 return statements; 342 return statements;
330 } 343 }
331 344
332 bool isSupertypeOfNativeClass(ClassElement element) { 345 bool isSupertypeOfNativeClass(ClassElement element) {
333 if (backend.classesMixedIntoInterceptedClasses.contains(element)) { 346 if (backend.classesMixedIntoInterceptedClasses.contains(element)) {
334 return true; 347 return true;
335 } 348 }
336 349
337 return subtypes[element] != null; 350 return subtypes[element] != null;
338 } 351 }
339 352
340 bool requiresNativeIsCheck(Element element) { 353 bool requiresNativeIsCheck(Element element) {
341 // TODO(sra): Remove this function. It determines if a native type may 354 // 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 355 // 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 356 // 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 357 // 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 358 // 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. 359 // is whether the receiver can be native, not the type of the test.
347 if (element == null || !element.isClass) return false; 360 if (element == null || !element.isClass) return false;
348 ClassElement cls = element; 361 ClassElement cls = element;
349 if (Elements.isNativeOrExtendsNative(cls)) return true; 362 if (Elements.isNativeOrExtendsNative(cls)) return true;
350 return isSupertypeOfNativeClass(element); 363 return isSupertypeOfNativeClass(element);
351 } 364 }
352 } 365 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698