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

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: 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
(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 /// Whether the backend is currently processing the codegen queue.
43 bool _inCodegen = false;
44
45 JsInteropAnalysis(this.backend);
46
47 void onQueueClosed() {
48 if (_inCodegen) return;
49
50 if (backend.jsAnnotationClass != null) {
51 nameField = backend.jsAnnotationClass.lookupMember('name');
52 backend.compiler.libraryLoader.libraries
53 .forEach(processJsInteropAnnotationsInLibrary);
54 }
55 }
56
57 void onCodegenStart() {
58 _inCodegen = true;
59 }
60
61 void processJsInteropAnnotation(Element e) {
62 for (MetadataAnnotation annotation in e.implementation.metadata) {
63 ConstantValue constant = backend.compiler.constants.getConstantValue(
64 annotation.constant);
65 if (constant == null || constant is! ConstructedConstantValue) continue;
66 ConstructedConstantValue constructedConstant = constant;
67 if (constructedConstant.type.element == backend.jsAnnotationClass) {
68 ConstantValue value = constructedConstant.fields[nameField];
69 if (value.isString) {
70 StringConstantValue stringValue = value;
71 e.setJsInteropName(stringValue.primitiveValue.slowToString());
72 } else {
73 // TODO(jacobr): report a warning if the value is not a String.
74 e.setJsInteropName('');
75 }
76 enabledJsInterop = true;
77 return;
78 }
79 }
80 }
81
82 void processJsInteropAnnotationsInLibrary(LibraryElement library) {
83 processJsInteropAnnotation(library);
84 library.implementation.forEachLocalMember((Element element) {
85 processJsInteropAnnotation(element);
86 if (!element.isClass || !element.isJsInterop) return;
87
88 ClassElement classElement = element;
89
90 if (!classElement
91 .implementsInterface(backend.jsJavaScriptObjectClass)) {
92 backend.reporter.reportErrorMessage(classElement,
93 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, {
94 'cls': classElement.name,
95 'superclass': classElement.superclass.name
96 });
97 }
98
99 classElement.forEachMember(
100 (ClassElement classElement, Element member) {
101 processJsInteropAnnotation(member);
102
103 if (!member.isSynthesized &&
104 classElement.isJsInterop &&
105 member is FunctionElement) {
106 FunctionElement fn = member;
107 if (!fn.isExternal && !fn.isAbstract) {
108 backend.reporter.reportErrorMessage(
109 fn,
110 MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
111 {'cls': classElement.name, 'member': member.name});
112 }
113 }
114 });
115 });
116 }
117
118 jsAst.Statement buildJsInteropBootstrap() {
119 if (!enabledJsInterop) return null;
120 List<jsAst.Statement> statements = <jsAst.Statement>[];
121 backend.compiler.codegenWorld.forEachInvokedName(
122 (String name, Map<Selector, SelectorConstraints> selectors) {
123 selectors.forEach((Selector selector, SelectorConstraints constraints) {
124 if (selector.isClosureCall) {
125 // TODO(jacobr): support named arguments.
126 if (selector.namedArgumentCount > 0) return;
127 int argumentCount = selector.argumentCount;
128 var candidateParameterNames =
129 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMOPQRSTUVWXYZ';
130 var parameters = new List<String>.generate(
131 argumentCount, (i) => candidateParameterNames[i]);
132
133 var name = backend.namer.invocationName(selector);
134 statements.add(js.statement(
135 'Function.prototype.# = function(#) { return this(#) }',
136 [name, parameters, parameters]));
137 }
138 });
139 });
140 return new jsAst.Block(statements);
141 }
142 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/js_backend.dart ('k') | pkg/compiler/lib/src/js_backend/namer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698