| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 NativeGenerator { | 7 class NativeGenerator { |
| 8 | |
| 9 static bool needsIsolateAffinityTagInitialization(JavaScriptBackend backend) { | 8 static bool needsIsolateAffinityTagInitialization(JavaScriptBackend backend) { |
| 10 return backend.needToInitializeIsolateAffinityTag; | 9 return backend.needToInitializeIsolateAffinityTag; |
| 11 } | 10 } |
| 12 | 11 |
| 13 /// Generates the code for isolate affinity tags. | 12 /// Generates the code for isolate affinity tags. |
| 14 /// | 13 /// |
| 15 /// Independently Dart programs on the same page must not interfer and | 14 /// Independently Dart programs on the same page must not interfer and |
| 16 /// this code sets up the variables needed to guarantee that behavior. | 15 /// this code sets up the variables needed to guarantee that behavior. |
| 17 static jsAst.Statement generateIsolateAffinityTagInitialization( | 16 static jsAst.Statement generateIsolateAffinityTagInitialization( |
| 18 JavaScriptBackend backend, | 17 JavaScriptBackend backend, |
| 19 jsAst.Expression generateEmbeddedGlobalAccess(String global), | 18 jsAst.Expression generateEmbeddedGlobalAccess(String global), |
| 20 jsAst.Expression internStringFunction) { | 19 jsAst.Expression internStringFunction) { |
| 21 assert(backend.needToInitializeIsolateAffinityTag); | 20 assert(backend.needToInitializeIsolateAffinityTag); |
| 22 | 21 |
| 23 jsAst.Expression getIsolateTagAccess = | 22 jsAst.Expression getIsolateTagAccess = |
| 24 generateEmbeddedGlobalAccess(embeddedNames.GET_ISOLATE_TAG); | 23 generateEmbeddedGlobalAccess(embeddedNames.GET_ISOLATE_TAG); |
| 25 jsAst.Expression isolateTagAccess = | 24 jsAst.Expression isolateTagAccess = |
| 26 generateEmbeddedGlobalAccess(embeddedNames.ISOLATE_TAG); | 25 generateEmbeddedGlobalAccess(embeddedNames.ISOLATE_TAG); |
| 27 jsAst.Expression dispatchPropertyNameAccess = | 26 jsAst.Expression dispatchPropertyNameAccess = |
| 28 generateEmbeddedGlobalAccess(embeddedNames.DISPATCH_PROPERTY_NAME); | 27 generateEmbeddedGlobalAccess(embeddedNames.DISPATCH_PROPERTY_NAME); |
| 29 | 28 |
| 30 return js.statement(''' | 29 return js.statement( |
| 30 ''' |
| 31 !function() { | 31 !function() { |
| 32 var intern = #internStringFunction; | 32 var intern = #internStringFunction; |
| 33 | 33 |
| 34 #getIsolateTag = function(name) { | 34 #getIsolateTag = function(name) { |
| 35 return intern("___dart_" + name + #isolateTag); | 35 return intern("___dart_" + name + #isolateTag); |
| 36 }; | 36 }; |
| 37 | 37 |
| 38 // To ensure that different programs loaded into the same context (page) | 38 // To ensure that different programs loaded into the same context (page) |
| 39 // use distinct dispatch properies, we place an object on `Object` to | 39 // use distinct dispatch properies, we place an object on `Object` to |
| 40 // contain the names already in use. | 40 // contain the names already in use. |
| 41 var tableProperty = "___dart_isolate_tags_"; | 41 var tableProperty = "___dart_isolate_tags_"; |
| 42 var usedProperties = Object[tableProperty] || | 42 var usedProperties = Object[tableProperty] || |
| 43 (Object[tableProperty] = Object.create(null)); | 43 (Object[tableProperty] = Object.create(null)); |
| 44 | 44 |
| 45 var rootProperty = "_${generateIsolateTagRoot()}"; | 45 var rootProperty = "_${generateIsolateTagRoot()}"; |
| 46 for (var i = 0; ; i++) { | 46 for (var i = 0; ; i++) { |
| 47 var property = intern(rootProperty + "_" + i + "_"); | 47 var property = intern(rootProperty + "_" + i + "_"); |
| 48 if (!(property in usedProperties)) { | 48 if (!(property in usedProperties)) { |
| 49 usedProperties[property] = 1; | 49 usedProperties[property] = 1; |
| 50 #isolateTag = property; | 50 #isolateTag = property; |
| 51 break; | 51 break; |
| 52 } | 52 } |
| 53 } | 53 } |
| 54 if (#initializeDispatchProperty) { | 54 if (#initializeDispatchProperty) { |
| 55 #dispatchPropertyName = #getIsolateTag("dispatch_record"); | 55 #dispatchPropertyName = #getIsolateTag("dispatch_record"); |
| 56 } | 56 } |
| 57 }(); | 57 }(); |
| 58 ''', | 58 ''', |
| 59 {'initializeDispatchProperty': backend.needToInitializeDispatchProperty, | 59 { |
| 60 'internStringFunction': internStringFunction, | 60 'initializeDispatchProperty': |
| 61 'getIsolateTag': getIsolateTagAccess, | 61 backend.needToInitializeDispatchProperty, |
| 62 'isolateTag': isolateTagAccess, | 62 'internStringFunction': internStringFunction, |
| 63 'dispatchPropertyName': dispatchPropertyNameAccess}); | 63 'getIsolateTag': getIsolateTagAccess, |
| 64 'isolateTag': isolateTagAccess, |
| 65 'dispatchPropertyName': dispatchPropertyNameAccess |
| 66 }); |
| 64 } | 67 } |
| 65 | 68 |
| 66 static String generateIsolateTagRoot() { | 69 static String generateIsolateTagRoot() { |
| 67 // TODO(sra): MD5 of contributing source code or URIs? | 70 // TODO(sra): MD5 of contributing source code or URIs? |
| 68 return 'ZxYxX'; | 71 return 'ZxYxX'; |
| 69 } | 72 } |
| 70 | 73 |
| 71 /// Encodes the collected native information so that it can be treated by | 74 /// Encodes the collected native information so that it can be treated by |
| 72 /// the native info-handler below. | 75 /// the native info-handler below. |
| 73 /// | 76 /// |
| 74 /// The encoded information has the form: | 77 /// The encoded information has the form: |
| 75 /// | 78 /// |
| 76 // "%": "leafTag1|leafTag2|...;nonleafTag1|...;Class1|Class2|...", | 79 // "%": "leafTag1|leafTag2|...;nonleafTag1|...;Class1|Class2|...", |
| 77 // | 80 // |
| 78 // If there is no data following a semicolon, the semicolon can be omitted. | 81 // If there is no data following a semicolon, the semicolon can be omitted. |
| 79 static jsAst.Expression encodeNativeInfo(Class cls) { | 82 static jsAst.Expression encodeNativeInfo(Class cls) { |
| 80 List<String> leafTags = cls.nativeLeafTags; | 83 List<String> leafTags = cls.nativeLeafTags; |
| 81 List<String> nonLeafTags = cls.nativeNonLeafTags; | 84 List<String> nonLeafTags = cls.nativeNonLeafTags; |
| 82 List<Class> extensions = cls.nativeExtensions; | 85 List<Class> extensions = cls.nativeExtensions; |
| 83 | 86 |
| 84 String formatTags(Iterable<String> tags) { | 87 String formatTags(Iterable<String> tags) { |
| 85 if (tags == null) return ''; | 88 if (tags == null) return ''; |
| 86 return (tags.toList() | 89 return (tags.toList()..sort()).join('|'); |
| 87 ..sort()).join('|'); | |
| 88 } | 90 } |
| 89 | 91 |
| 90 String leafStr = formatTags(leafTags); | 92 String leafStr = formatTags(leafTags); |
| 91 String nonLeafStr = formatTags(nonLeafTags); | 93 String nonLeafStr = formatTags(nonLeafTags); |
| 92 | 94 |
| 93 StringBuffer sb = new StringBuffer(leafStr); | 95 StringBuffer sb = new StringBuffer(leafStr); |
| 94 if (nonLeafStr != '') { | 96 if (nonLeafStr != '') { |
| 95 sb | 97 sb..write(';')..write(nonLeafStr); |
| 96 ..write(';') | |
| 97 ..write(nonLeafStr); | |
| 98 } | 98 } |
| 99 | 99 |
| 100 String encoding = sb.toString(); | 100 String encoding = sb.toString(); |
| 101 | 101 |
| 102 if (cls.isNative || encoding != '' || extensions != null) { | 102 if (cls.isNative || encoding != '' || extensions != null) { |
| 103 List<jsAst.Literal> parts = <jsAst.Literal>[js.stringPart(encoding)]; | 103 List<jsAst.Literal> parts = <jsAst.Literal>[js.stringPart(encoding)]; |
| 104 if (extensions != null) { | 104 if (extensions != null) { |
| 105 parts | 105 parts |
| 106 ..add(js.stringPart(';')) | 106 ..add(js.stringPart(';')) |
| 107 ..addAll( | 107 ..addAll(js.joinLiterals( |
| 108 js.joinLiterals(extensions.map((Class cls) => cls.name), | 108 extensions.map((Class cls) => cls.name), js.stringPart('|'))); |
| 109 js.stringPart('|'))); | |
| 110 } | 109 } |
| 111 return jsAst.concatenateStrings(parts, addQuotes: true); | 110 return jsAst.concatenateStrings(parts, addQuotes: true); |
| 112 } | 111 } |
| 113 return null; | 112 return null; |
| 114 } | 113 } |
| 115 | 114 |
| 116 /// Returns a JavaScript template that fills the embedded globals referenced | 115 /// Returns a JavaScript template that fills the embedded globals referenced |
| 117 /// by [interceptorsByTagAccess] and [leafTagsAccess]. | 116 /// by [interceptorsByTagAccess] and [leafTagsAccess]. |
| 118 /// | 117 /// |
| 119 /// This code must be invoked for every class that has a native info before | 118 /// This code must be invoked for every class that has a native info before |
| (...skipping 21 matching lines...) Expand all Loading... |
| 141 /// Both variables are passed in (instead of creating the access here) to | 140 /// Both variables are passed in (instead of creating the access here) to |
| 142 /// make sure the caller is aware of these globals. | 141 /// make sure the caller is aware of these globals. |
| 143 static jsAst.Statement buildNativeInfoHandler( | 142 static jsAst.Statement buildNativeInfoHandler( |
| 144 jsAst.Expression infoAccess, | 143 jsAst.Expression infoAccess, |
| 145 jsAst.Expression constructorAccess, | 144 jsAst.Expression constructorAccess, |
| 146 jsAst.Expression subclassReadGenerator(jsAst.Expression subclass), | 145 jsAst.Expression subclassReadGenerator(jsAst.Expression subclass), |
| 147 jsAst.Expression interceptorsByTagAccess, | 146 jsAst.Expression interceptorsByTagAccess, |
| 148 jsAst.Expression leafTagsAccess) { | 147 jsAst.Expression leafTagsAccess) { |
| 149 jsAst.Expression subclassRead = | 148 jsAst.Expression subclassRead = |
| 150 subclassReadGenerator(js('subclasses[i]', [])); | 149 subclassReadGenerator(js('subclasses[i]', [])); |
| 151 return js.statement(''' | 150 return js.statement( |
| 151 ''' |
| 152 // The native info looks like this: | 152 // The native info looks like this: |
| 153 // | 153 // |
| 154 // HtmlElement: { | 154 // HtmlElement: { |
| 155 // "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton" | 155 // "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton" |
| 156 // | 156 // |
| 157 // The first two semicolon-separated parts contain dispatch tags, the | 157 // The first two semicolon-separated parts contain dispatch tags, the |
| 158 // third contains the JavaScript names for classes. | 158 // third contains the JavaScript names for classes. |
| 159 // | 159 // |
| 160 // The tags indicate that JavaScript objects with the dispatch tags | 160 // The tags indicate that JavaScript objects with the dispatch tags |
| 161 // (usually constructor names) HTMLDivElement, HTMLAnchorElement and | 161 // (usually constructor names) HTMLDivElement, HTMLAnchorElement and |
| (...skipping 27 matching lines...) Expand all Loading... |
| 189 subclass.#nativeSuperclassTagName = tags[0]; | 189 subclass.#nativeSuperclassTagName = tags[0]; |
| 190 } | 190 } |
| 191 } | 191 } |
| 192 for (i = 0; i < tags.length; i++) { | 192 for (i = 0; i < tags.length; i++) { |
| 193 #interceptorsByTagAccess[tags[i]] = #constructor; | 193 #interceptorsByTagAccess[tags[i]] = #constructor; |
| 194 #leafTagsAccess[tags[i]] = false; | 194 #leafTagsAccess[tags[i]] = false; |
| 195 } | 195 } |
| 196 } | 196 } |
| 197 } | 197 } |
| 198 } | 198 } |
| 199 ''', {'info': infoAccess, | 199 ''', |
| 200 { |
| 201 'info': infoAccess, |
| 200 'constructor': constructorAccess, | 202 'constructor': constructorAccess, |
| 201 'subclassRead': subclassRead, | 203 'subclassRead': subclassRead, |
| 202 'interceptorsByTagAccess': interceptorsByTagAccess, | 204 'interceptorsByTagAccess': interceptorsByTagAccess, |
| 203 'leafTagsAccess': leafTagsAccess, | 205 'leafTagsAccess': leafTagsAccess, |
| 204 'nativeSuperclassTagName': embeddedNames.NATIVE_SUPERCLASS_TAG_NAME, | 206 'nativeSuperclassTagName': embeddedNames.NATIVE_SUPERCLASS_TAG_NAME, |
| 205 'allowNativesSubclassing': true}); | 207 'allowNativesSubclassing': true |
| 208 }); |
| 206 } | 209 } |
| 207 } | 210 } |
| OLD | NEW |