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

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

Powered by Google App Engine
This is Rietveld 408576698