| 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 ClassStubGenerator { | 7 class ClassStubGenerator { |
| 8 final Namer namer; | 8 final Namer namer; |
| 9 final Compiler compiler; | 9 final Compiler compiler; |
| 10 final JavaScriptBackend backend; | 10 final JavaScriptBackend backend; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 'function(#) { return #.#(#); }', | 105 'function(#) { return #.#(#); }', |
| 106 [ parameters, buildGetter(), closureCallName, arguments]); | 106 [ parameters, buildGetter(), closureCallName, arguments]); |
| 107 | 107 |
| 108 generatedStubs[invocationName] = function; | 108 generatedStubs[invocationName] = function; |
| 109 } | 109 } |
| 110 } | 110 } |
| 111 | 111 |
| 112 return generatedStubs; | 112 return generatedStubs; |
| 113 } | 113 } |
| 114 } | 114 } |
| 115 |
| 116 /// Creates two JavaScript functions: `tearOffGetter` and `tearOff`. |
| 117 /// |
| 118 /// `tearOffGetter` is internal and only used by `tearOff`. |
| 119 /// |
| 120 /// `tearOff` takes the following arguments: |
| 121 /// * `funcs`: a list of functions. These are the functions representing the |
| 122 /// member that is torn off. There can be more than one, since a member |
| 123 /// can have several stubs. |
| 124 /// Each function must have the `$callName` property set. |
| 125 /// * `reflectionInfo`: contains reflective information, and the function |
| 126 /// type. TODO(floitsch): point to where this is specified. |
| 127 /// * `isStatic`. |
| 128 /// * `name`. |
| 129 /// * `isIntercepted. |
| 130 List<jsAst.Statement> buildTearOffCode(JavaScriptBackend backend) { |
| 131 Namer namer = backend.namer; |
| 132 Compiler compiler = backend.compiler; |
| 133 |
| 134 Element closureFromTearOff = backend.findHelper('closureFromTearOff'); |
| 135 String tearOffAccessText; |
| 136 jsAst.Expression tearOffAccessExpression; |
| 137 String tearOffGlobalObjectName; |
| 138 String tearOffGlobalObject; |
| 139 if (closureFromTearOff != null) { |
| 140 // We need both the AST that references [closureFromTearOff] and a string |
| 141 // for the NoCsp version that constructs a function. |
| 142 tearOffAccessExpression = |
| 143 backend.emitter.staticFunctionAccess(closureFromTearOff); |
| 144 tearOffAccessText = |
| 145 jsAst.prettyPrint(tearOffAccessExpression, compiler).getText(); |
| 146 tearOffGlobalObjectName = tearOffGlobalObject = |
| 147 namer.globalObjectFor(closureFromTearOff); |
| 148 } else { |
| 149 // Default values for mocked-up test libraries. |
| 150 tearOffAccessText = |
| 151 r'''function() { throw 'Helper \'closureFromTearOff\' missing.' }'''; |
| 152 tearOffAccessExpression = js(tearOffAccessText); |
| 153 tearOffGlobalObjectName = 'MissingHelperFunction'; |
| 154 tearOffGlobalObject = '($tearOffAccessText())'; |
| 155 } |
| 156 |
| 157 jsAst.Statement tearOffGetter; |
| 158 if (!compiler.useContentSecurityPolicy) { |
| 159 // This template is uncached because it is constructed from code fragments |
| 160 // that can change from compilation to compilation. Some of these could be |
| 161 // avoided, except for the string literals that contain the compiled access |
| 162 // path to 'closureFromTearOff'. |
| 163 tearOffGetter = js.uncachedStatementTemplate(''' |
| 164 function tearOffGetter(funcs, reflectionInfo, name, isIntercepted) { |
| 165 return isIntercepted |
| 166 ? new Function("funcs", "reflectionInfo", "name", |
| 167 "$tearOffGlobalObjectName", "c", |
| 168 "return function tearOff_" + name + (functionCounter++)+ "(x)
{" + |
| 169 "if (c === null) c = $tearOffAccessText(" + |
| 170 "this, funcs, reflectionInfo, false, [x], name);" + |
| 171 "return new c(this, funcs[0], x, name);" + |
| 172 "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null) |
| 173 : new Function("funcs", "reflectionInfo", "name", |
| 174 "$tearOffGlobalObjectName", "c", |
| 175 "return function tearOff_" + name + (functionCounter++)+ "() {
" + |
| 176 "if (c === null) c = $tearOffAccessText(" + |
| 177 "this, funcs, reflectionInfo, false, [], name);" + |
| 178 "return new c(this, funcs[0], null, name);" + |
| 179 "}")(funcs, reflectionInfo, name, $tearOffGlobalObject, null); |
| 180 }''').instantiate([]); |
| 181 } else { |
| 182 tearOffGetter = js.statement(''' |
| 183 function tearOffGetter(funcs, reflectionInfo, name, isIntercepted) { |
| 184 var cache = null; |
| 185 return isIntercepted |
| 186 ? function(x) { |
| 187 if (cache === null) cache = #( |
| 188 this, funcs, reflectionInfo, false, [x], name); |
| 189 return new cache(this, funcs[0], x, name); |
| 190 } |
| 191 : function() { |
| 192 if (cache === null) cache = #( |
| 193 this, funcs, reflectionInfo, false, [], name); |
| 194 return new cache(this, funcs[0], null, name); |
| 195 }; |
| 196 }''', [tearOffAccessExpression, tearOffAccessExpression]); |
| 197 } |
| 198 |
| 199 jsAst.Statement tearOff = js.statement(''' |
| 200 function tearOff(funcs, reflectionInfo, isStatic, name, isIntercepted) { |
| 201 var cache; |
| 202 return isStatic |
| 203 ? function() { |
| 204 if (cache === void 0) cache = #tearOff( |
| 205 this, funcs, reflectionInfo, true, [], name).prototype; |
| 206 return cache; |
| 207 } |
| 208 : tearOffGetter(funcs, reflectionInfo, name, isIntercepted); |
| 209 }''', {'tearOff': tearOffAccessExpression}); |
| 210 |
| 211 return <jsAst.Statement>[tearOffGetter, tearOff]; |
| 212 } |
| OLD | NEW |