LEFT | RIGHT |
1 // Copyright (C) 2012 Google Inc. | 1 // Copyright (C) 2012 Google Inc. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 /** | 15 /** |
16 * @fileoverview Mitigate deviations between SES and ES5-strict code | 16 * @fileoverview Mitigate deviations between SES and ES5-strict code |
17 * by rewriting programs where possible. The output of this stage is | 17 * by rewriting programs where possible. The output of this stage is |
18 * outside the TCB. | 18 * outside the TCB. |
| 19 * See http://code.google.com/p/google-caja/wiki/SES#Source-SES_vs_Target-SES |
| 20 * for a list of these differences. |
19 * | 21 * |
20 * Note the parse tree manipulated in this file uses the SpiderMonkey | 22 * TODO(jasvir): Rewrite top level function declarations |
| 23 * |
| 24 * Note that the parse tree manipulated in this file uses the SpiderMonkey |
21 * AST format | 25 * AST format |
22 * (https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API) | 26 * (https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API) |
23 * | 27 * |
24 * @author Jasvir Nagra (jasvir@google.com) | 28 * @author Jasvir Nagra (jasvir@google.com) |
25 * @requires estraverse, acorn, escodegen | |
26 * @overrides ses | 29 * @overrides ses |
27 | |
28 */ | 30 */ |
29 | 31 |
30 (function() { | 32 (function() { |
31 function introducesScope(node) { | 33 function introducesScope(node) { |
32 return node.type === 'FunctionExpression' || | 34 return node.type === 'FunctionExpression' || |
33 node.type === 'FunctionDeclaration'; | 35 node.type === 'FunctionDeclaration'; |
34 } | 36 } |
35 ·· | 37 ·· |
36 function isTypeOf(node) { | 38 function isTypeOf(node) { |
37 return (node.type === 'UnaryExpression' && | 39 return (node.type === 'UnaryExpression' && |
38 node.operator === 'typeof' && | 40 node.operator === 'typeof' && |
39 !node.synthetic); | 41 !node.synthetic); |
40 } | 42 } |
41 ·· | 43 ·· |
42 function isVariableDecl(node) { | 44 function isVariableDecl(node) { |
43 return (node.type === 'VariableDeclaration'); | 45 return (node.type === 'VariableDeclaration'); |
44 } | 46 } |
45 | 47 |
46 /** | 48 /** |
47 * Rewrite var decls in place into assignments on the global object | 49 * Rewrite var decls in place into assignments on the global object |
48 * turning expression "var x, y = 2, z" to | 50 * turning expression "var x, y = 2, z" to |
49 * window.x = window.x, window.y = 2, window.z = window.z | 51 * window.x = window.x, window.y = 2, window.z = window.z |
50 */ | 52 */ |
51 function rewriteVars(node) { | 53 function rewriteVars(node) { |
52 var assignments = []; | 54 var assignments = []; |
53 node.declarations.forEach(function(decl) { | 55 node.declarations.forEach(function(decl) { |
54 assignments.push({ | 56 assignments.push({ |
55 "type": "AssignmentExpression", | 57 "type": "AssignmentExpression", |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 function resolve(opt, defaultOption) { | 140 function resolve(opt, defaultOption) { |
139 return (options && opt in options) ? opt : defaultOption; | 141 return (options && opt in options) ? opt : defaultOption; |
140 } | 142 } |
141 var resolved = {}; | 143 var resolved = {}; |
142 resolved.rewriteTopLevelVars = resolve('rewriteTopLevelVars', true); | 144 resolved.rewriteTopLevelVars = resolve('rewriteTopLevelVars', true); |
143 resolved.rewriteTypeOf = resolve('rewriteTypeOf', true); | 145 resolved.rewriteTypeOf = resolve('rewriteTypeOf', true); |
144 return resolved; | 146 return resolved; |
145 } | 147 } |
146 | 148 |
147 ses.mitigateGotchas = function(programSrc, options) { | 149 ses.mitigateGotchas = function(programSrc, options) { |
148 options = resolveOptions(options); | 150 try { |
149 var scopeLevel = 0; | 151 options = resolveOptions(options); |
150 var ast = acorn.parse(programSrc); | 152 var scopeLevel = 0; |
151 estraverse.traverse(ast, { | 153 var ast = ses.rewriter_.parse(programSrc); |
152 enter: function enter(node) { | 154 ses.rewriter_.traverse(ast, { |
153 if (introducesScope(node)) { | 155 enter: function enter(node) { |
154 scopeLevel++; | 156 if (introducesScope(node)) { |
155 } else if (options.rewriteTypeOf && isTypeOf(node)) { | 157 scopeLevel++; |
156 rewriteTypeOf(node); | 158 } else if (options.rewriteTypeOf && isTypeOf(node)) { |
157 } else if (options.rewriteTopLevelVars && | 159 rewriteTypeOf(node); |
158 isVariableDecl(node) && scopeLevel === 0) { | 160 } else if (options.rewriteTopLevelVars && |
159 rewriteVars(node); | 161 isVariableDecl(node) && scopeLevel === 0) { |
160 } | 162 rewriteVars(node); |
161 }, | 163 } |
162 leave: function leave(node) { | 164 }, |
163 if (introducesScope(node)) { | 165 leave: function leave(node) { |
164 scopeLevel--; | 166 if (introducesScope(node)) { |
165 } | 167 scopeLevel--; |
166 } | 168 } |
167 }); | 169 } |
168 return escodegen.generate(ast); | 170 }); |
| 171 return ses.rewriter_.generate(ast); |
| 172 } catch (e) { |
| 173 ses.logger.warn("Failed to mitigate SES gotchas. Proceeding anyways.", e); |
| 174 return programSrc; |
| 175 } |
169 }; | 176 }; |
170 | 177 |
171 })(); | 178 })(); |
LEFT | RIGHT |