| 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 import '../js/js.dart' as js; | 5 import '../js/js.dart' as js; |
| 6 import '../universe/side_effects.dart' show SideEffects; | 6 import '../universe/side_effects.dart' show SideEffects; |
| 7 | 7 |
| 8 import 'behavior.dart'; | 8 import 'behavior.dart'; |
| 9 | 9 |
| 10 class HasCapturedPlaceholders extends js.BaseVisitor { | 10 class HasCapturedPlaceholders extends js.BaseVisitor { |
| 11 | |
| 12 HasCapturedPlaceholders._(); | 11 HasCapturedPlaceholders._(); |
| 13 | 12 |
| 14 static bool check(js.Node node) { | 13 static bool check(js.Node node) { |
| 15 HasCapturedPlaceholders visitor = new HasCapturedPlaceholders._(); | 14 HasCapturedPlaceholders visitor = new HasCapturedPlaceholders._(); |
| 16 node.accept(visitor); | 15 node.accept(visitor); |
| 17 return visitor.found; | 16 return visitor.found; |
| 18 } | 17 } |
| 19 | 18 |
| 20 int enclosingFunctions = 0; | 19 int enclosingFunctions = 0; |
| 21 bool found = false; | 20 bool found = false; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 } | 105 } |
| 107 | 106 |
| 108 void visitAccess(js.PropertyAccess node) { | 107 void visitAccess(js.PropertyAccess node) { |
| 109 sideEffects.setDependsOnIndexStore(); | 108 sideEffects.setDependsOnIndexStore(); |
| 110 sideEffects.setDependsOnInstancePropertyStore(); | 109 sideEffects.setDependsOnInstancePropertyStore(); |
| 111 sideEffects.setDependsOnStaticPropertyStore(); | 110 sideEffects.setDependsOnStaticPropertyStore(); |
| 112 node.visitChildren(this); | 111 node.visitChildren(this); |
| 113 } | 112 } |
| 114 } | 113 } |
| 115 | 114 |
| 116 | |
| 117 /// ThrowBehaviorVisitor generates a NativeThrowBehavior describing the | 115 /// ThrowBehaviorVisitor generates a NativeThrowBehavior describing the |
| 118 /// exception behavior of a JavaScript expression. | 116 /// exception behavior of a JavaScript expression. |
| 119 /// | 117 /// |
| 120 /// The result is semi-conservative, giving reasonable results for many simple | 118 /// The result is semi-conservative, giving reasonable results for many simple |
| 121 /// JS fragments. The non-conservative part is the assumption that binary | 119 /// JS fragments. The non-conservative part is the assumption that binary |
| 122 /// operators are used on 'good' operands that do not force arbirary code to be | 120 /// operators are used on 'good' operands that do not force arbirary code to be |
| 123 /// executed via conversions (valueOf() and toString() methods). | 121 /// executed via conversions (valueOf() and toString() methods). |
| 124 /// | 122 /// |
| 125 /// In many cases a JS fragment has more precise behavior. In these cases the | 123 /// In many cases a JS fragment has more precise behavior. In these cases the |
| 126 /// behavior should be described as a property of the JS fragment. For example, | 124 /// behavior should be described as a property of the JS fragment. For example, |
| 127 /// Object.keys(#) has a TypeError on null / undefined, which can only be known | 125 /// Object.keys(#) has a TypeError on null / undefined, which can only be known |
| 128 /// in the calling context. | 126 /// in the calling context. |
| 129 /// | 127 /// |
| 130 class ThrowBehaviorVisitor extends js.BaseVisitor<NativeThrowBehavior> { | 128 class ThrowBehaviorVisitor extends js.BaseVisitor<NativeThrowBehavior> { |
| 131 | |
| 132 ThrowBehaviorVisitor(); | 129 ThrowBehaviorVisitor(); |
| 133 | 130 |
| 134 NativeThrowBehavior analyze(js.Node node) { | 131 NativeThrowBehavior analyze(js.Node node) { |
| 135 return visit(node); | 132 return visit(node); |
| 136 } | 133 } |
| 137 | 134 |
| 138 // TODO(sra): Add [sequence] functionality to NativeThrowBehavior. | 135 // TODO(sra): Add [sequence] functionality to NativeThrowBehavior. |
| 139 /// Returns the combined behavior of sequential execution of code having | 136 /// Returns the combined behavior of sequential execution of code having |
| 140 /// behavior [first] followed by code having behavior [second]. | 137 /// behavior [first] followed by code having behavior [second]. |
| 141 static NativeThrowBehavior sequence(NativeThrowBehavior first, | 138 static NativeThrowBehavior sequence( |
| 142 NativeThrowBehavior second) { | 139 NativeThrowBehavior first, NativeThrowBehavior second) { |
| 143 if (first == NativeThrowBehavior.MUST) return first; | 140 if (first == NativeThrowBehavior.MUST) return first; |
| 144 if (second == NativeThrowBehavior.MUST) return second; | 141 if (second == NativeThrowBehavior.MUST) return second; |
| 145 if (second == NativeThrowBehavior.NEVER) return first; | 142 if (second == NativeThrowBehavior.NEVER) return first; |
| 146 if (first == NativeThrowBehavior.NEVER) return second; | 143 if (first == NativeThrowBehavior.NEVER) return second; |
| 147 // Both are one of MAY or MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS. | 144 // Both are one of MAY or MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS. |
| 148 return NativeThrowBehavior.MAY; | 145 return NativeThrowBehavior.MAY; |
| 149 } | 146 } |
| 150 | 147 |
| 151 // TODO(sra): Add [choice] functionality to NativeThrowBehavior. | 148 // TODO(sra): Add [choice] functionality to NativeThrowBehavior. |
| 152 /// Returns the combined behavior of a choice between two paths with behaviors | 149 /// Returns the combined behavior of a choice between two paths with behaviors |
| 153 /// [first] and [second]. | 150 /// [first] and [second]. |
| 154 static NativeThrowBehavior choice(NativeThrowBehavior first, | 151 static NativeThrowBehavior choice( |
| 155 NativeThrowBehavior second) { | 152 NativeThrowBehavior first, NativeThrowBehavior second) { |
| 156 if (first == second) return first; // Both paths have same behaviour. | 153 if (first == second) return first; // Both paths have same behaviour. |
| 157 return NativeThrowBehavior.MAY; | 154 return NativeThrowBehavior.MAY; |
| 158 } | 155 } |
| 159 | 156 |
| 160 NativeThrowBehavior visit(js.Node node) { | 157 NativeThrowBehavior visit(js.Node node) { |
| 161 return node.accept(this); | 158 return node.accept(this); |
| 162 } | 159 } |
| 163 | 160 |
| 164 NativeThrowBehavior visitNode(js.Node node) { | 161 NativeThrowBehavior visitNode(js.Node node) { |
| 165 return NativeThrowBehavior.MAY; | 162 return NativeThrowBehavior.MAY; |
| 166 } | 163 } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 receiver.isPositional && | 288 receiver.isPositional && |
| 292 receiver.nameOrPosition == 0) { | 289 receiver.nameOrPosition == 0) { |
| 293 first = NativeThrowBehavior.MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS; | 290 first = NativeThrowBehavior.MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS; |
| 294 } else { | 291 } else { |
| 295 first = NativeThrowBehavior.MAY; | 292 first = NativeThrowBehavior.MAY; |
| 296 } | 293 } |
| 297 | 294 |
| 298 return sequence(first, second); | 295 return sequence(first, second); |
| 299 } | 296 } |
| 300 } | 297 } |
| OLD | NEW |