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

Side by Side Diff: pkg/compiler/lib/src/js_backend/native_data.dart

Issue 1809533004: Support serialization of WorldImpact (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 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) 2016, 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 library js_backend.native_data;
6
7 import '../common.dart';
8 import '../elements/elements.dart' show
9 ClassElement,
10 Element,
11 FunctionElement,
12 MemberElement;
13
14 class NativeData {
Siggi Cherem (dart-lang) 2016/03/16 23:40:14 +doc on this class
Johnni Winther 2016/03/17 10:49:37 Done.
15 /// The JavaScript names for elements implemented via typed JavaScript
16 /// interop.
17 Map<Element, String> jsInteropNames = <Element, String>{};
18
19 /// The JavaScript names for native JavaScript elements implemented.
20 Map<Element, String> nativeMemberName = <Element, String>{};
21
22 /// Tag info for native JavaScript classes names. See
23 /// [setNativeClassTagInfo].
24 Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{};
25
26 /// Returns `true` if [element] is explicitly marked as part of JsInterop.
27 bool _isJsInterop(Element element) {
28 return jsInteropNames.containsKey(element.declaration);
29 }
30
31 /// Returns [element] as an explicit part of JsInterop. The js interop name is
32 /// expected to be computed later.
33 void markAsJsInterop(Element element) {
34 jsInteropNames[element.declaration] = null;
35 }
36
37 /// Sets the explicit js interop [name] for [element].
38 void setJsInteropName(Element element, String name) {
39 assert(invariant(element,
40 isJsInterop(element),
41 message:
42 'Element $element is not js interop but given a js interop name.'));
43 jsInteropNames[element.declaration] = name;
44 }
45
46 /// Returns the explicit js interop name for [element].
47 String getJsInteropName(Element element) {
48 return jsInteropNames[element.declaration];
49 }
50
51 /// Returns `true` if [element] is part of JsInterop.
52 bool isJsInterop(Element element) {
53 // An function is part of JsInterop in the following cases:
54 // * It has a jsInteropName annotation
55 // * It is external member of a class or library tagged as JsInterop.
56 if (element.isFunction || element.isConstructor || element.isAccessor) {
57 FunctionElement function = element;
58 if (!function.isExternal) return false;
59
60 if (_isJsInterop(function)) return true;
61 if (function.isClassMember) return isJsInterop(function.contextClass);
62 if (function.isTopLevel) return isJsInterop(function.library);
63 return false;
64 } else {
65 return _isJsInterop(element);
66 }
67 }
68
69 /// Returns `true` if the name of [element] is fixed for the generated
70 /// JavaScript.
71 bool hasFixedBackendName(Element element) {
72 return isJsInterop(element) ||
73 nativeMemberName.containsKey(element.declaration);
74 }
75
76 String _jsNameHelper(Element element) {
77 String jsInteropName = jsInteropNames[element.declaration];
78 assert(invariant(element,
79 !(_isJsInterop(element) && jsInteropName == null),
80 message:
81 'Element $element is js interop but js interop name has not yet '
82 'been computed.'));
83 if (jsInteropName != null && jsInteropName.isNotEmpty) {
84 return jsInteropName;
85 }
86 return element.isLibrary ? 'self' : element.name;
87 }
88
89 /// Computes the name for [element] to use in the generated JavaScript. This
90 /// is either given through a native annotation or a js interop annotation.
91 String getFixedBackendName(Element element) {
92 String name = nativeMemberName[element.declaration];
93 if (name == null && isJsInterop(element)) {
94 // If an element isJsInterop but _isJsInterop is false that means it is
95 // considered interop as the parent class is interop.
96 name = _jsNameHelper(
97 element.isConstructor ? element.enclosingClass : element);
98 nativeMemberName[element.declaration] = name;
99 }
100 return name;
101 }
102
103 /// Whether [element] corresponds to a native JavaScript construct either
104 /// through the native mechanism (`@Native(...)` or the `native` pseudo
105 /// keyword) which is only allowed for internal libraries or via the typed
106 /// JavaScriptInterop mechanism which is allowed for user libraries.
107 bool isNative(Element element) {
108 if (isJsInterop(element)) return true;
109 if (element.isClass) {
110 return nativeClassTagInfo.containsKey(element.declaration);
111 } else {
112 return nativeMemberName.containsKey(element.declaration);
113 }
114 }
115
116 /// Sets the native [name] for the member [element]. This name is used for
117 /// [element] in the generated JavaScript.
118 void setNativeMemberName(MemberElement element, String name) {
119 // TODO(johnniwinther): Avoid setting this more than once. The enqueuer
120 // might enqueue [element] several times (before processing it) and computes
121 // name on each call to `internalAddToWorkList`.
122 assert(invariant(element,
123 nativeMemberName[element.declaration] == null ||
124 nativeMemberName[element.declaration] == name,
125 message:
126 "Native member name set inconsistently on $element: "
127 "Existing name '${nativeMemberName[element.declaration]}', "
128 "new name '$name'."));
129 nativeMemberName[element.declaration] = name;
130 }
131
132 /// Sets the native tag info for [cls].
133 ///
134 /// The tag info string contains comma-separated 'words' which are either
135 /// dispatch tags (having JavaScript identifier syntax) and directives that
136 /// begin with `!`.
137 void setNativeClassTagInfo(ClassElement cls, String tagInfo) {
138 // TODO(johnniwinther): Assert that this is only called once. The memory
139 // compiler copies pre-processed elements into a new compiler through
140 // [Compiler.onLibraryScanned] and thereby causes multiple calls to this
141 // method.
142 assert(invariant(cls,
143 nativeClassTagInfo[cls.declaration] == null ||
144 nativeClassTagInfo[cls.declaration] == tagInfo,
145 message:
146 "Native tag info set inconsistently on $cls: "
147 "Existing tag info '${nativeClassTagInfo[cls.declaration]}', "
148 "new tag info '$tagInfo'."));
149 nativeClassTagInfo[cls.declaration] = tagInfo;
150 }
151
152 /// Returns the list of native tag words for [cls].
153 List<String> getNativeTagsOfClassRaw(ClassElement cls) {
154 String quotedName = nativeClassTagInfo[cls.declaration];
155 return quotedName.substring(1, quotedName.length - 1).split(',');
156 }
157
158 /// Returns the list of non-directive native tag words for [cls].
159 List<String> getNativeTagsOfClass(ClassElement cls) {
160 return getNativeTagsOfClassRaw(cls).where(
161 (s) => !s.startsWith('!')).toList();
162 }
163
164 /// Returns `true` if [cls] has a `!nonleaf` tag word.
165 bool hasNativeTagsForcedNonLeaf(ClassElement cls) {
166 return getNativeTagsOfClassRaw(cls).contains('!nonleaf');
167 }
168
169 bool hasNativeName(Element element) {
170 return nativeMemberName.containsKey(element);
171 }
172 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698