OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 library dart2js.kernel.env; | 5 library dart2js.kernel.env; |
6 | 6 |
7 import 'package:kernel/ast.dart' as ir; | 7 import 'package:kernel/ast.dart' as ir; |
8 import 'package:kernel/clone.dart'; | 8 import 'package:kernel/clone.dart'; |
9 import 'package:kernel/type_algebra.dart'; | 9 import 'package:kernel/type_algebra.dart'; |
10 | 10 |
11 import '../common.dart'; | 11 import '../common.dart'; |
12 import '../common/resolution.dart'; | |
13 import '../constants/constructors.dart'; | 12 import '../constants/constructors.dart'; |
14 import '../constants/expressions.dart'; | 13 import '../constants/expressions.dart'; |
15 import '../constants/values.dart'; | 14 import '../constants/values.dart'; |
16 import '../elements/entities.dart'; | 15 import '../elements/entities.dart'; |
17 import '../elements/types.dart'; | 16 import '../elements/types.dart'; |
18 import '../ordered_typeset.dart'; | 17 import '../ordered_typeset.dart'; |
19 import '../ssa/kernel_impact.dart'; | |
20 import 'element_map.dart'; | 18 import 'element_map.dart'; |
21 import 'element_map_impl.dart'; | 19 import 'element_map_impl.dart'; |
22 import 'element_map_mixins.dart'; | 20 import 'element_map_mixins.dart'; |
23 | 21 |
24 /// Environment for fast lookup of program libraries. | 22 /// Environment for fast lookup of program libraries. |
25 class ProgramEnv { | 23 class ProgramEnv { |
26 final Set<ir.Program> _programs = new Set<ir.Program>(); | 24 final Set<ir.Program> _programs = new Set<ir.Program>(); |
27 | 25 |
28 Map<Uri, LibraryEnv> _libraryMap; | 26 Map<Uri, LibraryEnv> _libraryMap; |
29 | 27 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 Map<String, ClassEnv> _classMap; | 77 Map<String, ClassEnv> _classMap; |
80 Map<String, ir.Member> _memberMap; | 78 Map<String, ir.Member> _memberMap; |
81 Map<String, ir.Member> _setterMap; | 79 Map<String, ir.Member> _setterMap; |
82 | 80 |
83 LibraryEnv(this.library); | 81 LibraryEnv(this.library); |
84 | 82 |
85 void _ensureClassMap() { | 83 void _ensureClassMap() { |
86 if (_classMap == null) { | 84 if (_classMap == null) { |
87 _classMap = <String, ClassEnv>{}; | 85 _classMap = <String, ClassEnv>{}; |
88 for (ir.Class cls in library.classes) { | 86 for (ir.Class cls in library.classes) { |
89 _classMap[cls.name] = new ClassEnv(cls); | 87 _classMap[cls.name] = new ClassEnvImpl(cls); |
90 } | 88 } |
91 } | 89 } |
92 } | 90 } |
93 | 91 |
94 /// Return the [ClassEnv] for the class [name] in [library]. | 92 /// Return the [ClassEnv] for the class [name] in [library]. |
95 ClassEnv lookupClass(String name) { | 93 ClassEnv lookupClass(String name) { |
96 _ensureClassMap(); | 94 _ensureClassMap(); |
97 return _classMap[name]; | 95 return _classMap[name]; |
98 } | 96 } |
99 | 97 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 | 156 |
159 Iterable<ConstantValue> getMetadata(KernelToElementMapBase elementMap) { | 157 Iterable<ConstantValue> getMetadata(KernelToElementMapBase elementMap) { |
160 return _metadata ??= elementMap.getMetadata(library.annotations); | 158 return _metadata ??= elementMap.getMetadata(library.annotations); |
161 } | 159 } |
162 | 160 |
163 LibraryData copy() { | 161 LibraryData copy() { |
164 return new LibraryData(library); | 162 return new LibraryData(library); |
165 } | 163 } |
166 } | 164 } |
167 | 165 |
| 166 /// Member data for a class. |
| 167 abstract class ClassEnv { |
| 168 /// The [ir.Class] that defined the class, if any. |
| 169 ir.Class get cls; |
| 170 |
| 171 /// Whether the class is an unnamed mixin application. |
| 172 bool get isUnnamedMixinApplication; |
| 173 |
| 174 /// Return the [MemberEntity] for the member [name] in the class. If [setter] |
| 175 /// is `true`, the setter or assignable field corresponding to [name] is |
| 176 /// returned. |
| 177 MemberEntity lookupMember(KernelToElementMap elementMap, String name, |
| 178 {bool setter: false}); |
| 179 |
| 180 /// Calls [f] for each member of the class. |
| 181 void forEachMember( |
| 182 KernelToElementMap elementMap, void f(MemberEntity member)); |
| 183 |
| 184 /// Return the [ConstructorEntity] for the constructor [name] in the class. |
| 185 ConstructorEntity lookupConstructor( |
| 186 KernelToElementMap elementMap, String name); |
| 187 |
| 188 /// Calls [f] for each constructor of the class. |
| 189 void forEachConstructor( |
| 190 KernelToElementMap elementMap, void f(ConstructorEntity constructor)); |
| 191 |
| 192 /// Calls [f] for each constructor body for the live constructors in the |
| 193 /// class. |
| 194 void forEachConstructorBody(void f(ConstructorBodyEntity constructor)); |
| 195 } |
| 196 |
168 /// Environment for fast lookup of class members. | 197 /// Environment for fast lookup of class members. |
169 class ClassEnv { | 198 class ClassEnvImpl implements ClassEnv { |
170 final ir.Class cls; | 199 final ir.Class cls; |
171 final bool isUnnamedMixinApplication; | 200 final bool isUnnamedMixinApplication; |
172 | 201 |
173 Map<String, ir.Member> _constructorMap; | 202 Map<String, ir.Member> _constructorMap; |
174 Map<String, ir.Member> _memberMap; | 203 Map<String, ir.Member> _memberMap; |
175 Map<String, ir.Member> _setterMap; | 204 Map<String, ir.Member> _setterMap; |
176 | 205 |
177 ClassEnv(this.cls) | 206 /// Constructor bodies created for this class. |
| 207 List<ConstructorBodyEntity> _constructorBodyList; |
| 208 |
| 209 ClassEnvImpl(this.cls) |
178 // TODO(johnniwinther): Change this to use a property on [cls] when such | 210 // TODO(johnniwinther): Change this to use a property on [cls] when such |
179 // is added to kernel. | 211 // is added to kernel. |
180 : isUnnamedMixinApplication = | 212 : isUnnamedMixinApplication = |
181 cls.name.contains('+') || cls.name.contains('&'); | 213 cls.name.contains('+') || cls.name.contains('&'); |
182 | 214 |
183 // TODO(efortuna): This is gross because even though the closure class *has* | |
184 // members, we're not populating this because they aren't ir.Member types. :-( | |
185 ClassEnv.closureClass() | |
186 : cls = null, | |
187 isUnnamedMixinApplication = false, | |
188 _constructorMap = const <String, ir.Member>{}, | |
189 _memberMap = const <String, ir.Member>{}, | |
190 _setterMap = const <String, ir.Member>{}; | |
191 | |
192 /// Copied from 'package:kernel/transformations/mixin_full_resolution.dart'. | 215 /// Copied from 'package:kernel/transformations/mixin_full_resolution.dart'. |
193 ir.Constructor _buildForwardingConstructor( | 216 ir.Constructor _buildForwardingConstructor( |
194 CloneVisitor cloner, ir.Constructor superclassConstructor) { | 217 CloneVisitor cloner, ir.Constructor superclassConstructor) { |
195 var superFunction = superclassConstructor.function; | 218 var superFunction = superclassConstructor.function; |
196 | 219 |
197 // We keep types and default values for the parameters but always mark the | 220 // We keep types and default values for the parameters but always mark the |
198 // parameters as final (since we just forward them to the super | 221 // parameters as final (since we just forward them to the super |
199 // constructor). | 222 // constructor). |
200 ir.VariableDeclaration cloneVariable(ir.VariableDeclaration variable) { | 223 ir.VariableDeclaration cloneVariable(ir.VariableDeclaration variable) { |
201 ir.VariableDeclaration clone = cloner.clone(variable); | 224 ir.VariableDeclaration clone = cloner.clone(variable); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 var forwardingConstructor = _buildForwardingConstructor( | 315 var forwardingConstructor = _buildForwardingConstructor( |
293 superclassCloner, superclassConstructor); | 316 superclassCloner, superclassConstructor); |
294 cls.addMember(forwardingConstructor); | 317 cls.addMember(forwardingConstructor); |
295 _constructorMap[forwardingConstructor.name.name] = | 318 _constructorMap[forwardingConstructor.name.name] = |
296 forwardingConstructor; | 319 forwardingConstructor; |
297 } | 320 } |
298 } | 321 } |
299 } | 322 } |
300 } | 323 } |
301 | 324 |
302 /// Return the [ir.Member] for the member [name] in [library]. | 325 /// Return the [MemberEntity] for the member [name] in [cls]. If [setter] is |
303 ir.Member lookupMember(String name, {bool setter: false}) { | 326 /// `true`, the setter or assignable field corresponding to [name] is |
| 327 /// returned. |
| 328 MemberEntity lookupMember(KernelToElementMap elementMap, String name, |
| 329 {bool setter: false}) { |
304 _ensureMaps(); | 330 _ensureMaps(); |
305 return setter ? _setterMap[name] : _memberMap[name]; | 331 ir.Member member = setter ? _setterMap[name] : _memberMap[name]; |
| 332 return member != null ? elementMap.getMember(member) : null; |
306 } | 333 } |
307 | 334 |
308 /// Return the [ir.Member] for the member [name] in [library]. | 335 /// Calls [f] for each member of [cls]. |
309 ir.Member lookupConstructor(String name) { | 336 void forEachMember( |
| 337 KernelToElementMap elementMap, void f(MemberEntity member)) { |
310 _ensureMaps(); | 338 _ensureMaps(); |
311 return _constructorMap[name]; | 339 _memberMap.values.forEach((ir.Member member) { |
312 } | 340 f(elementMap.getMember(member)); |
313 | 341 }); |
314 void forEachMember(void f(ir.Member member)) { | |
315 _ensureMaps(); | |
316 _memberMap.values.forEach(f); | |
317 for (ir.Member member in _setterMap.values) { | 342 for (ir.Member member in _setterMap.values) { |
318 if (member is ir.Procedure) { | 343 if (member is ir.Procedure) { |
319 f(member); | 344 f(elementMap.getMember(member)); |
320 } else { | 345 } else { |
321 // Skip fields; these are also in _memberMap. | 346 // Skip fields; these are also in _memberMap. |
322 } | 347 } |
323 } | 348 } |
324 } | 349 } |
325 | 350 |
326 void forEachConstructor(void f(ir.Member member)) { | 351 /// Return the [ConstructorEntity] for the constructor [name] in [cls]. |
| 352 ConstructorEntity lookupConstructor( |
| 353 KernelToElementMap elementMap, String name) { |
327 _ensureMaps(); | 354 _ensureMaps(); |
328 _constructorMap.values.forEach(f); | 355 ir.Member constructor = _constructorMap[name]; |
| 356 return constructor != null ? elementMap.getConstructor(constructor) : null; |
| 357 } |
| 358 |
| 359 /// Calls [f] for each constructor of [cls]. |
| 360 void forEachConstructor( |
| 361 KernelToElementMap elementMap, void f(ConstructorEntity constructor)) { |
| 362 _ensureMaps(); |
| 363 _constructorMap.values.forEach((ir.Member constructor) { |
| 364 f(elementMap.getConstructor(constructor)); |
| 365 }); |
| 366 } |
| 367 |
| 368 void addConstructorBody(ConstructorBodyEntity constructorBody) { |
| 369 _constructorBodyList ??= <ConstructorBodyEntity>[]; |
| 370 _constructorBodyList.add(constructorBody); |
| 371 } |
| 372 |
| 373 void forEachConstructorBody(void f(ConstructorBodyEntity constructor)) { |
| 374 _constructorBodyList?.forEach(f); |
329 } | 375 } |
330 } | 376 } |
331 | 377 |
| 378 class ClosureClassEnv implements ClassEnv { |
| 379 final Map<String, MemberEntity> _memberMap; |
| 380 |
| 381 ClosureClassEnv(this._memberMap); |
| 382 |
| 383 @override |
| 384 void forEachConstructorBody(void f(ConstructorBodyEntity constructor)) { |
| 385 // We do not create constructor bodies for closure classes. |
| 386 } |
| 387 |
| 388 @override |
| 389 void forEachConstructor( |
| 390 KernelToElementMap elementMap, void f(ConstructorEntity constructor)) { |
| 391 // We do not create constructors for closure classes. |
| 392 } |
| 393 |
| 394 @override |
| 395 ConstructorEntity lookupConstructor( |
| 396 KernelToElementMap elementMap, String name) { |
| 397 // We do not create constructors for closure classes. |
| 398 return null; |
| 399 } |
| 400 |
| 401 @override |
| 402 void forEachMember( |
| 403 KernelToElementMap elementMap, void f(MemberEntity member)) { |
| 404 _memberMap.values.forEach(f); |
| 405 } |
| 406 |
| 407 @override |
| 408 MemberEntity lookupMember(KernelToElementMap elementMap, String name, |
| 409 {bool setter: false}) { |
| 410 if (setter) { |
| 411 // All closure fields are final. |
| 412 return null; |
| 413 } |
| 414 return _memberMap[name]; |
| 415 } |
| 416 |
| 417 @override |
| 418 bool get isUnnamedMixinApplication => false; |
| 419 |
| 420 @override |
| 421 ir.Class get cls => null; |
| 422 } |
| 423 |
332 class ClassData { | 424 class ClassData { |
333 /// TODO(johnniwinther): Remove this from the [MemberData] interface. Use | 425 /// TODO(johnniwinther): Remove this from the [ClassData] interface. Use |
334 /// `definition.node` instead. | 426 /// `definition.node` instead. |
335 final ir.Class cls; | 427 final ir.Class cls; |
336 final ClassDefinition definition; | 428 final ClassDefinition definition; |
337 bool isMixinApplication; | 429 bool isMixinApplication; |
338 | 430 |
339 InterfaceType thisType; | 431 InterfaceType thisType; |
340 InterfaceType rawType; | 432 InterfaceType rawType; |
341 InterfaceType supertype; | 433 InterfaceType supertype; |
342 InterfaceType mixedInType; | 434 InterfaceType mixedInType; |
343 List<InterfaceType> interfaces; | 435 List<InterfaceType> interfaces; |
344 OrderedTypeSet orderedTypeSet; | 436 OrderedTypeSet orderedTypeSet; |
345 | 437 |
346 Iterable<ConstantValue> _metadata; | 438 Iterable<ConstantValue> _metadata; |
347 | 439 |
348 ClassData(this.cls, this.definition); | 440 ClassData(this.cls, this.definition); |
349 | 441 |
350 Iterable<ConstantValue> getMetadata(KernelToElementMapBase elementMap) { | 442 Iterable<ConstantValue> getMetadata(KernelToElementMapBase elementMap) { |
351 return _metadata ??= elementMap.getMetadata(cls.annotations); | 443 return _metadata ??= elementMap.getMetadata(cls.annotations); |
352 } | 444 } |
353 | 445 |
354 ClassData copy() { | 446 ClassData copy() { |
355 return new ClassData(cls, definition); | 447 return new ClassData(cls, definition); |
356 } | 448 } |
357 } | 449 } |
358 | 450 |
359 class MemberData { | 451 abstract class MemberData { |
| 452 MemberDefinition get definition; |
| 453 |
| 454 Iterable<ConstantValue> getMetadata(KernelToElementMap elementMap); |
| 455 } |
| 456 |
| 457 class MemberDataImpl implements MemberData { |
360 /// TODO(johnniwinther): Remove this from the [MemberData] interface. Use | 458 /// TODO(johnniwinther): Remove this from the [MemberData] interface. Use |
361 /// `definition.node` instead. | 459 /// `definition.node` instead. |
362 final ir.Member node; | 460 final ir.Member node; |
363 | 461 |
364 final MemberDefinition definition; | 462 final MemberDefinition definition; |
365 | 463 |
366 Iterable<ConstantValue> _metadata; | 464 Iterable<ConstantValue> _metadata; |
367 | 465 |
368 MemberData(this.node, this.definition); | 466 MemberDataImpl(this.node, this.definition); |
369 | 467 |
370 ResolutionImpact getWorldImpact(KernelToElementMapForImpact elementMap) { | 468 Iterable<ConstantValue> getMetadata( |
371 return buildKernelImpact(node, elementMap); | 469 covariant KernelToElementMapBase elementMap) { |
372 } | |
373 | |
374 Iterable<ConstantValue> getMetadata(KernelToElementMapBase elementMap) { | |
375 return _metadata ??= elementMap.getMetadata(node.annotations); | 470 return _metadata ??= elementMap.getMetadata(node.annotations); |
376 } | 471 } |
377 | 472 |
378 MemberData copy() { | 473 MemberData copy() { |
379 return new MemberData(node, definition); | 474 return new MemberDataImpl(node, definition); |
380 } | 475 } |
381 } | 476 } |
382 | 477 |
383 class FunctionData extends MemberData { | 478 abstract class FunctionData implements MemberData { |
| 479 FunctionType getFunctionType(KernelToElementMap elementMap); |
| 480 |
| 481 void forEachParameter(KernelToElementMapForBuilding elementMap, |
| 482 void f(DartType type, String name, ConstantValue defaultValue)); |
| 483 } |
| 484 |
| 485 class FunctionDataImpl extends MemberDataImpl implements FunctionData { |
384 final ir.FunctionNode functionNode; | 486 final ir.FunctionNode functionNode; |
385 FunctionType _type; | 487 FunctionType _type; |
386 | 488 |
387 FunctionData(ir.Member node, this.functionNode, MemberDefinition definition) | 489 FunctionDataImpl( |
| 490 ir.Member node, this.functionNode, MemberDefinition definition) |
388 : super(node, definition); | 491 : super(node, definition); |
389 | 492 |
390 FunctionType getFunctionType(KernelToElementMapBase elementMap) { | 493 FunctionType getFunctionType(covariant KernelToElementMapBase elementMap) { |
391 return _type ??= elementMap.getFunctionType(functionNode); | 494 return _type ??= elementMap.getFunctionType(functionNode); |
392 } | 495 } |
393 | 496 |
394 void forEachParameter(KernelToElementMapForBuilding elementMap, | 497 void forEachParameter(KernelToElementMapForBuilding elementMap, |
395 void f(DartType type, String name, ConstantValue defaultValue)) { | 498 void f(DartType type, String name, ConstantValue defaultValue)) { |
396 void handleParameter(ir.VariableDeclaration node, {bool isOptional: true}) { | 499 void handleParameter(ir.VariableDeclaration node, {bool isOptional: true}) { |
397 DartType type = elementMap.getDartType(node.type); | 500 DartType type = elementMap.getDartType(node.type); |
398 String name = node.name; | 501 String name = node.name; |
399 ConstantValue defaultValue; | 502 ConstantValue defaultValue; |
400 if (isOptional) { | 503 if (isOptional) { |
(...skipping 10 matching lines...) Expand all Loading... |
411 handleParameter(functionNode.positionalParameters[i], | 514 handleParameter(functionNode.positionalParameters[i], |
412 isOptional: i < functionNode.requiredParameterCount); | 515 isOptional: i < functionNode.requiredParameterCount); |
413 } | 516 } |
414 functionNode.namedParameters.toList() | 517 functionNode.namedParameters.toList() |
415 ..sort(namedOrdering) | 518 ..sort(namedOrdering) |
416 ..forEach(handleParameter); | 519 ..forEach(handleParameter); |
417 } | 520 } |
418 | 521 |
419 @override | 522 @override |
420 FunctionData copy() { | 523 FunctionData copy() { |
421 return new FunctionData(node, functionNode, definition); | 524 return new FunctionDataImpl(node, functionNode, definition); |
422 } | 525 } |
423 } | 526 } |
424 | 527 |
425 class ConstructorData extends FunctionData { | 528 abstract class ConstructorData extends FunctionData { |
| 529 ConstantConstructor getConstructorConstant( |
| 530 KernelToElementMapBase elementMap, ConstructorEntity constructor); |
| 531 } |
| 532 |
| 533 class ConstructorDataImpl extends FunctionDataImpl implements ConstructorData { |
426 ConstantConstructor _constantConstructor; | 534 ConstantConstructor _constantConstructor; |
427 ConstructorBodyEntity constructorBody; | 535 ConstructorBodyEntity constructorBody; |
428 | 536 |
429 ConstructorData( | 537 ConstructorDataImpl( |
430 ir.Member node, ir.FunctionNode functionNode, MemberDefinition definition) | 538 ir.Member node, ir.FunctionNode functionNode, MemberDefinition definition) |
431 : super(node, functionNode, definition); | 539 : super(node, functionNode, definition); |
432 | 540 |
433 ConstantConstructor getConstructorConstant( | 541 ConstantConstructor getConstructorConstant( |
434 KernelToElementMapBase elementMap, ConstructorEntity constructor) { | 542 KernelToElementMapBase elementMap, ConstructorEntity constructor) { |
435 if (_constantConstructor == null) { | 543 if (_constantConstructor == null) { |
436 if (node is ir.Constructor && constructor.isConst) { | 544 if (node is ir.Constructor && constructor.isConst) { |
437 _constantConstructor = | 545 _constantConstructor = |
438 new Constantifier(elementMap).computeConstantConstructor(node); | 546 new Constantifier(elementMap).computeConstantConstructor(node); |
439 } else { | 547 } else { |
440 failedAt( | 548 failedAt( |
441 constructor, | 549 constructor, |
442 "Unexpected constructor $constructor in " | 550 "Unexpected constructor $constructor in " |
443 "KernelWorldBuilder._getConstructorConstant"); | 551 "ConstructorDataImpl._getConstructorConstant"); |
444 } | 552 } |
445 } | 553 } |
446 return _constantConstructor; | 554 return _constantConstructor; |
447 } | 555 } |
448 | 556 |
449 @override | 557 @override |
450 ConstructorData copy() { | 558 ConstructorData copy() { |
451 return new ConstructorData(node, functionNode, definition); | 559 return new ConstructorDataImpl(node, functionNode, definition); |
452 } | 560 } |
453 } | 561 } |
454 | 562 |
455 class FieldData extends MemberData { | 563 abstract class FieldData extends MemberData { |
| 564 ConstantExpression getFieldConstant( |
| 565 KernelToElementMapBase elementMap, FieldEntity field); |
| 566 } |
| 567 |
| 568 class FieldDataImpl extends MemberDataImpl implements FieldData { |
456 ConstantExpression _constant; | 569 ConstantExpression _constant; |
457 | 570 |
458 FieldData(ir.Field node, MemberDefinition definition) | 571 FieldDataImpl(ir.Field node, MemberDefinition definition) |
459 : super(node, definition); | 572 : super(node, definition); |
460 | 573 |
461 ir.Field get node => super.node; | 574 ir.Field get node => super.node; |
462 | 575 |
463 ConstantExpression getFieldConstant( | 576 ConstantExpression getFieldConstant( |
464 KernelToElementMapBase elementMap, FieldEntity field) { | 577 KernelToElementMapBase elementMap, FieldEntity field) { |
465 if (_constant == null) { | 578 if (_constant == null) { |
466 if (node.isConst) { | 579 if (node.isConst) { |
467 _constant = new Constantifier(elementMap).visit(node.initializer); | 580 _constant = new Constantifier(elementMap).visit(node.initializer); |
468 } else { | 581 } else { |
469 failedAt( | 582 failedAt( |
470 field, | 583 field, |
471 "Unexpected field $field in " | 584 "Unexpected field $field in " |
472 "KernelWorldBuilder._getConstructorConstant"); | 585 "FieldDataImpl.getFieldConstant"); |
473 } | 586 } |
474 } | 587 } |
475 return _constant; | 588 return _constant; |
476 } | 589 } |
477 | 590 |
478 @override | 591 @override |
479 FieldData copy() { | 592 FieldData copy() { |
480 return new FieldData(node, definition); | 593 return new FieldDataImpl(node, definition); |
481 } | 594 } |
482 } | 595 } |
OLD | NEW |