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

Side by Side Diff: pkg/compiler/lib/src/js/placeholder_safety.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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
6 library js.safety; 5 library js.safety;
7 6
8 import "js.dart" as js; 7 import "js.dart" as js;
9 8
10 typedef bool PositionPredicate(int position); 9 typedef bool PositionPredicate(int position);
11 10
12 /// PlaceholderSafetyAnalysis determines which placeholders in a JavaScript 11 /// PlaceholderSafetyAnalysis determines which placeholders in a JavaScript
13 /// template may be replaced with an arbitrary expression. Placeholders may be 12 /// template may be replaced with an arbitrary expression. Placeholders may be
14 /// replaced with an arbitrary expression providied the template ensures the 13 /// replaced with an arbitrary expression providied the template ensures the
15 /// placeholders are evaluated in the same left-to-right order with no 14 /// placeholders are evaluated in the same left-to-right order with no
16 /// additional effects interleaved. 15 /// additional effects interleaved.
17 /// 16 ///
18 /// The result is semi-conservative, giving reasonable results for many simple 17 /// The result is semi-conservative, giving reasonable results for many simple
19 /// JS fragments. The non-conservative part is the assumption that arithmetic 18 /// JS fragments. The non-conservative part is the assumption that arithmetic
20 /// operators are used on 'good' operands that do not force arbitrary code to be 19 /// operators are used on 'good' operands that do not force arbitrary code to be
21 /// executed via conversions (valueOf() and toString() methods). 20 /// executed via conversions (valueOf() and toString() methods).
22 class PlaceholderSafetyAnalysis extends js.BaseVisitor<int> { 21 class PlaceholderSafetyAnalysis extends js.BaseVisitor<int> {
23 final PositionPredicate isNullableInput; 22 final PositionPredicate isNullableInput;
24 int nextPosition = 0; 23 int nextPosition = 0;
25 int maxSafePosition = -1; 24 int maxSafePosition = -1;
26 bool safe = true; 25 bool safe = true;
27 26
28 // We do a crude abstract interpretation to find operations that might throw 27 // We do a crude abstract interpretation to find operations that might throw
29 // exceptions. The possible values of expressions are represented by 28 // exceptions. The possible values of expressions are represented by
30 // integers. Small non-negative integers 0, 1, 2, ... represent the values of 29 // integers. Small non-negative integers 0, 1, 2, ... represent the values of
31 // the placeholders. Other values are: 30 // the placeholders. Other values are:
32 static const int NONNULL_VALUE = -1; // Unknown but not null. 31 static const int NONNULL_VALUE = -1; // Unknown but not null.
33 static const int UNKNOWN_VALUE = -2; // Unknown and might be null. 32 static const int UNKNOWN_VALUE = -2; // Unknown and might be null.
34 33
35 PlaceholderSafetyAnalysis._(this.isNullableInput); 34 PlaceholderSafetyAnalysis._(this.isNullableInput);
36 35
37 /// Returns the number of placeholders that can be substituted into the 36 /// Returns the number of placeholders that can be substituted into the
38 /// template AST [node] without changing the order of observable effects. 37 /// template AST [node] without changing the order of observable effects.
39 /// [isNullableInput] is a function that takes the 0-based index of a 38 /// [isNullableInput] is a function that takes the 0-based index of a
40 /// placeholder and returns `true` if expression at run time may be null, and 39 /// placeholder and returns `true` if expression at run time may be null, and
41 /// `false` if the value is never null. 40 /// `false` if the value is never null.
42 static int analyze(js.Node node, PositionPredicate isNullableInput) { 41 static int analyze(js.Node node, PositionPredicate isNullableInput) {
43 PlaceholderSafetyAnalysis analysis = 42 PlaceholderSafetyAnalysis analysis =
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 visit(left); 139 visit(left);
141 visit(right); 140 visit(right);
142 return UNKNOWN_VALUE; 141 return UNKNOWN_VALUE;
143 } 142 }
144 143
145 if (left is js.InterpolatedNode) { 144 if (left is js.InterpolatedNode) {
146 // A bare interpolated expression should not be the LHS of an assignment. 145 // A bare interpolated expression should not be the LHS of an assignment.
147 safe = false; 146 safe = false;
148 return leftToRight(); 147 return leftToRight();
149 } 148 }
150 149
151 // Assignment operators dereference the LHS before evaluating the RHS. 150 // Assignment operators dereference the LHS before evaluating the RHS.
152 if (node.op != null) return leftToRight(); 151 if (node.op != null) return leftToRight();
153 152
154 // Assignment (1) evaluates the LHS as a Reference `lval`, (2) evaluates the 153 // Assignment (1) evaluates the LHS as a Reference `lval`, (2) evaluates the
155 // RHS as a value, (3) dereferences the `lval` in PutValue. 154 // RHS as a value, (3) dereferences the `lval` in PutValue.
156 if (left is js.VariableReference) { 155 if (left is js.VariableReference) {
157 int value = visit(right); 156 int value = visit(right);
158 // Assignment could change an observed global or cause a ReferenceError. 157 // Assignment could change an observed global or cause a ReferenceError.
159 safe = false; 158 safe = false;
160 return value; 159 return value;
161 } 160 }
162 if (left is js.PropertyAccess) { 161 if (left is js.PropertyAccess) {
163 // "a.b.x = c.y" gives a TypeError for null values in this order: `a`, 162 // "a.b.x = c.y" gives a TypeError for null values in this order: `a`,
164 // `c`, `a.b`. 163 // `c`, `a.b`.
165 int receiver = visit(left.receiver); 164 int receiver = visit(left.receiver);
166 int selector = visit(left.selector); 165 int selector = visit(left.selector);
167 int value = visit(right); 166 int value = visit(right);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 case ">=": 205 case ">=":
207 case "==": 206 case "==":
208 case "===": 207 case "===":
209 case "!=": 208 case "!=":
210 case "!==": 209 case "!==":
211 case "&": 210 case "&":
212 case "^": 211 case "^":
213 case "|": 212 case "|":
214 int left = visit(node.left); 213 int left = visit(node.left);
215 int right = visit(node.right); 214 int right = visit(node.right);
216 return NONNULL_VALUE; // Number, String, Boolean. 215 return NONNULL_VALUE; // Number, String, Boolean.
217 216
218 case ',': 217 case ',':
219 int left = visit(node.left); 218 int left = visit(node.left);
220 int right = visit(node.right); 219 int right = visit(node.right);
221 return right; 220 return right;
222 221
223 case "&&": 222 case "&&":
224 case "||": 223 case "||":
225 int left = visit(node.left); 224 int left = visit(node.left);
226 // TODO(sra): Might be safe, e.g. "x || 0". 225 // TODO(sra): Might be safe, e.g. "x || 0".
(...skipping 24 matching lines...) Expand all
251 int visitThrow(js.Throw node) { 250 int visitThrow(js.Throw node) {
252 visit(node.expression); 251 visit(node.expression);
253 return unsafe(UNKNOWN_VALUE); 252 return unsafe(UNKNOWN_VALUE);
254 } 253 }
255 254
256 int visitPrefix(js.Prefix node) { 255 int visitPrefix(js.Prefix node) {
257 if (node.op == 'typeof') { 256 if (node.op == 'typeof') {
258 // "typeof a" first evaluates to a Reference. If the Reference is to a 257 // "typeof a" first evaluates to a Reference. If the Reference is to a
259 // variable that is not present, "undefined" is returned without 258 // variable that is not present, "undefined" is returned without
260 // dereferencing. 259 // dereferencing.
261 if (node.argument is js.VariableUse) return NONNULL_VALUE; // A string. 260 if (node.argument is js.VariableUse) return NONNULL_VALUE; // A string.
262 } 261 }
263 262
264 visit(node.argument); 263 visit(node.argument);
265 264
266 switch (node.op) { 265 switch (node.op) {
267 case '+': 266 case '+':
268 case '-': 267 case '-':
269 case '!': 268 case '!':
270 case '~': 269 case '~':
271 // Non-conservative assumption that these operators are used on values 270 // Non-conservative assumption that these operators are used on values
272 // that do not call arbitrary code via valueOf() or toString(). 271 // that do not call arbitrary code via valueOf() or toString().
273 return NONNULL_VALUE; 272 return NONNULL_VALUE;
274 273
275 case 'typeof': 274 case 'typeof':
276 return NONNULL_VALUE; // Always a string. 275 return NONNULL_VALUE; // Always a string.
277 276
278 case 'void': 277 case 'void':
279 return UNKNOWN_VALUE; 278 return UNKNOWN_VALUE;
280 279
281 case '--': 280 case '--':
282 case '++': 281 case '++':
283 return NONNULL_VALUE; // Always a number. 282 return NONNULL_VALUE; // Always a number.
284 283
285 default: 284 default:
286 safe = false; 285 safe = false;
287 return UNKNOWN_VALUE; 286 return UNKNOWN_VALUE;
288 } 287 }
289 } 288 }
290 289
291 int visitPostfix(js.Postfix node) { 290 int visitPostfix(js.Postfix node) {
292 assert(node.op == '--' || node.op == '++'); 291 assert(node.op == '--' || node.op == '++');
293 visit(node.argument); 292 visit(node.argument);
294 return NONNULL_VALUE; // Always a number, even for "(a=null, a++)". 293 return NONNULL_VALUE; // Always a number, even for "(a=null, a++)".
295 } 294 }
296 295
297 int visitVariableUse(js.VariableUse node) { 296 int visitVariableUse(js.VariableUse node) {
298 // We could get a ReferenceError unless the variable is in scope. For JS 297 // We could get a ReferenceError unless the variable is in scope. For JS
299 // fragments, the only use of VariableUse outside a `function(){...}` should 298 // fragments, the only use of VariableUse outside a `function(){...}` should
300 // be for global references. Certain global names are almost certainly not 299 // be for global references. Certain global names are almost certainly not
301 // reference errors, e.g 'Array'. 300 // reference errors, e.g 'Array'.
302 switch (node.name) { 301 switch (node.name) {
303 case 'Array': 302 case 'Array':
304 case 'Date': 303 case 'Date':
(...skipping 14 matching lines...) Expand all
319 int visitFun(js.Fun node) { 318 int visitFun(js.Fun node) {
320 bool oldSafe = safe; 319 bool oldSafe = safe;
321 int oldNextPosition = nextPosition; 320 int oldNextPosition = nextPosition;
322 visit(node.body); 321 visit(node.body);
323 // Creating a function has no effect on order unless there are embedded 322 // Creating a function has no effect on order unless there are embedded
324 // placeholders. 323 // placeholders.
325 safe = (nextPosition == oldNextPosition) && oldSafe; 324 safe = (nextPosition == oldNextPosition) && oldSafe;
326 return NONNULL_VALUE; 325 return NONNULL_VALUE;
327 } 326 }
328 } 327 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js/js_source_mapping.dart ('k') | pkg/compiler/lib/src/js/rewrite_async.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698