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_backend/js_interop_analysis.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, 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
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
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.
4
5 /// Analysis to determine how to generate code for typed JavaScript interop.
6 library compiler.src.js_backend.js_interop_analysis;
7
8 import '../common/names.dart' show Identifiers;
9 import '../compiler.dart' show Compiler;
10 import '../diagnostics/messages.dart' show MessageKind;
11 import '../constants/values.dart'
12 show
13 ConstantValue,
14 ConstructedConstantValue,
15 ListConstantValue,
16 NullConstantValue,
17 StringConstantValue,
18 TypeConstantValue;
19 import '../elements/elements.dart'
20 show
21 ClassElement,
22 Element,
23 FieldElement,
24 FunctionElement,
25 LibraryElement,
26 MetadataAnnotation;
27
28 import '../js/js.dart' as jsAst;
29 import '../js/js.dart' show js;
30 import '../universe/selector.dart' show Selector;
31 import '../universe/universe.dart' show SelectorConstraints;
32
33 import 'js_backend.dart' show JavaScriptBackend;
34
35 class JsInteropAnalysis {
36 final JavaScriptBackend backend;
37
38 /// The resolved [FieldElement] for `Js.name`.
39 FieldElement nameField;
40 bool enabledJsInterop = false;
41
42 JsInteropAnalysis(this.backend);
43
44 void onQueueClosed() {
45 if (backend.jsAnnotationClass != null) {
46 nameField = backend.jsAnnotationClass.lookupMember('name');
47 backend.compiler.libraryLoader.libraries
48 .forEach(processJsInteropAnnotationsInLibrary);
49 }
50 }
51
52 void processJsInteropAnnotation(Element e) {
53 for (MetadataAnnotation annotation in e.implementation.metadata) {
54 ConstructedConstantValue constant =
55 backend.compiler.constants.getConstantValue(annotation.constant);
Siggi Cherem (dart-lang) 2015/10/13 02:08:53 check first for the type of constant since some an
Jacob 2015/10/13 03:10:42 Done.
56 if (constant != null &&
Siggi Cherem (dart-lang) 2015/10/13 02:08:53 since you'll have more than one check, consider do
Jacob 2015/10/13 03:10:42 done
57 constant.getType(backend.compiler.coreTypes).element ==
Siggi Cherem (dart-lang) 2015/10/13 02:08:53 or simply `constant.type.element` (I believe Const
Jacob 2015/10/13 03:10:43 Done.
58 backend.jsAnnotationClass) {
59 ConstantValue value = constant.fields[nameField];
60 if (value.isString) {
61 StringConstantValue stringValue = value;
62 e.setJsInteropName(stringValue.primitiveValue.slowToString());
63 } else {
64 assert(value.isNull);
65 e.setJsInteropName('');
66 }
67 enabledJsInterop = true;
68 return;
69 }
70 }
71 }
72
73 void processJsInteropAnnotationsInLibrary(LibraryElement library) {
74 processJsInteropAnnotation(library);
75 library.implementation.forEachLocalMember((Element element) {
76 processJsInteropAnnotation(element);
77 if (element.isClass) {
Siggi Cherem (dart-lang) 2015/10/13 02:08:53 nit: to keep the nesting level below smaller, we c
Jacob 2015/10/13 03:10:42 Done.
78 ClassElement classElement = element;
79 if (classElement.isJsInterop) {
80 classElement.forEachMember((_, memberElement) {
81 processJsInteropAnnotation(memberElement);
Siggi Cherem (dart-lang) 2015/10/13 02:08:53 could we move this down and combine with the body
Jacob 2015/10/13 03:10:42 moved it anyway. i think this is slightly as the
82 });
83
84 if (!classElement
85 .implementsInterface(backend.jsJavaScriptObjectClass)) {
86 backend.compiler.reportErrorMessage(classElement,
87 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, {
88 'cls': classElement.name,
89 'superclass': classElement.superclass.name
90 });
91 }
92
93 classElement.forEachMember(
94 (ClassElement classElement, Element member) {
95 if (!member.isSynthesized &&
96 classElement.isJsInterop &&
97 member is FunctionElement) {
98 FunctionElement fn = member;
99 if (!fn.isExternal && !fn.isAbstract) {
100 backend.compiler.reportErrorMessage(
101 fn,
102 MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
103 {'cls': classElement.name, 'member': member.name});
104 }
105 }
106 });
107 }
108 }
109 });
110 }
111
112 jsAst.Statement buildJsInteropBootstrap() {
113 if (!enabledJsInterop) return null;
114 List<jsAst.Statement> statements = <jsAst.Statement>[];
115 backend.compiler.codegenWorld.forEachInvokedName(
116 (String name, Map<Selector, SelectorConstraints> selectors) {
117 selectors.forEach((Selector selector, SelectorConstraints constraints) {
118 if (selector.isClosureCall) {
119 // TODO(jacobr): support named arguments.
120 if (selector.namedArgumentCount > 0) return;
121 int argumentCount = selector.argumentCount;
122 var candidateParameterNames =
123 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMOPQRSTUVWXYZ';
124 var parameters = new List<String>.generate(
125 argumentCount, (i) => candidateParameterNames[i]);
126
127 var name = backend.namer.invocationName(selector);
128 statements.add(js.statement(
129 'Function.prototype.# = function(#) { return this(#) }',
130 [name, parameters, parameters]));
131 }
132 });
133 });
134 return new jsAst.Block(statements);
135 }
136 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698