| OLD | NEW | 
|---|
| 1 // Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 #include "vm/object.h" | 5 #include "vm/object.h" | 
| 6 | 6 | 
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" | 
| 8 #include "vm/assert.h" | 8 #include "vm/assert.h" | 
| 9 #include "vm/bigint_operations.h" | 9 #include "vm/bigint_operations.h" | 
| 10 #include "vm/bootstrap.h" | 10 #include "vm/bootstrap.h" | 
| (...skipping 1267 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1278       if (interface_class.IsMoreSpecificThan(interface_args, | 1278       if (interface_class.IsMoreSpecificThan(interface_args, | 
| 1279                                              other, | 1279                                              other, | 
| 1280                                              other_type_arguments)) { | 1280                                              other_type_arguments)) { | 
| 1281         return true; | 1281         return true; | 
| 1282       } | 1282       } | 
| 1283     } | 1283     } | 
| 1284   } | 1284   } | 
| 1285   if (IsSignatureClass() && other.IsSignatureClass()) { | 1285   if (IsSignatureClass() && other.IsSignatureClass()) { | 
| 1286     const Function& fun = Function::Handle(signature_function()); | 1286     const Function& fun = Function::Handle(signature_function()); | 
| 1287     const Function& other_fun = Function::Handle(other.signature_function()); | 1287     const Function& other_fun = Function::Handle(other.signature_function()); | 
| 1288     // TODO(regis): We need to consider the type arguments. | 1288     return fun.IsSubtypeOf(type_arguments, | 
| 1289     return fun.IsSubtypeOf(other_fun); | 1289                            other_fun, | 
|  | 1290                            other_type_arguments); | 
| 1290   } | 1291   } | 
|  | 1292 | 
| 1291   if (is_interface()) { | 1293   if (is_interface()) { | 
| 1292     // We already checked the case where 'other' is an interface. Now, 'this', | 1294     // We already checked the case where 'other' is an interface. Now, 'this', | 
| 1293     // an interface, cannot be more specific than a class, except class Object, | 1295     // an interface, cannot be more specific than a class, except class Object, | 
| 1294     // because although Object is not considered an interface by the vm, it is | 1296     // because although Object is not considered an interface by the vm, it is | 
| 1295     // one. In other words, all classes implementing this interface also extend | 1297     // one. In other words, all classes implementing this interface also extend | 
| 1296     // class Object. An interface is also more specific than the VarType. | 1298     // class Object. An interface is also more specific than the VarType. | 
| 1297     return (other.IsVarClass() || other.IsObjectClass()); | 1299     return (other.IsVarClass() || other.IsObjectClass()); | 
| 1298   } | 1300   } | 
| 1299   const Class& super_class = Class::Handle(SuperClass()); | 1301   const Class& super_class = Class::Handle(SuperClass()); | 
| 1300   if (super_class.IsNull()) { | 1302   if (super_class.IsNull()) { | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 1312 bool Class::IsTopLevel() const { | 1314 bool Class::IsTopLevel() const { | 
| 1313   return String::Handle(Name()).Length() == 0; | 1315   return String::Handle(Name()).Length() == 0; | 
| 1314 } | 1316 } | 
| 1315 | 1317 | 
| 1316 | 1318 | 
| 1317 bool Class::TestType(TypeTestKind test, | 1319 bool Class::TestType(TypeTestKind test, | 
| 1318                      const TypeArguments& type_arguments, | 1320                      const TypeArguments& type_arguments, | 
| 1319                      const Class& other, | 1321                      const Class& other, | 
| 1320                      const TypeArguments& other_type_arguments) const { | 1322                      const TypeArguments& other_type_arguments) const { | 
| 1321   if (test == kIsAssignableTo) { | 1323   if (test == kIsAssignableTo) { | 
| 1322     // TODO(regis): We do not follow the guide that says that "a type T is | 1324     // The spec states that "a type T is assignable to a type S if T is a | 
| 1323     // assignable to a type S if T is a subtype of S or S is a subtype of T", | 1325     // subtype of S or S is a subtype of T". This is from the perspective of a | 
| 1324     // since this would lead to heap pollution. We only apply that rule to | 1326     // static checker, which does not know the actual type of the assigned | 
| 1325     // parameter types when checking assignability of function types. | 1327     // value. However, this type information is available at run time in checked | 
| 1326     // Revisit if necessary. | 1328     // mode. We therefore apply a more restrictive subtype check, which prevents | 
|  | 1329     // heap pollution. We only keep the assignability check when assigning | 
|  | 1330     // values of a function type. | 
| 1327     if (IsSignatureClass() && other.IsSignatureClass()) { | 1331     if (IsSignatureClass() && other.IsSignatureClass()) { | 
| 1328       const Function& src_fun = Function::Handle(signature_function()); | 1332       const Function& src_fun = Function::Handle(signature_function()); | 
| 1329       const Function& dst_fun = Function::Handle(other.signature_function()); | 1333       const Function& dst_fun = Function::Handle(other.signature_function()); | 
| 1330       // TODO(regis): We need to consider the type arguments. | 1334       return src_fun.IsAssignableTo(type_arguments, | 
| 1331       return src_fun.IsAssignableTo(dst_fun); | 1335                                     dst_fun, | 
|  | 1336                                     other_type_arguments); | 
| 1332     } | 1337     } | 
| 1333     // Continue with a subtype test. | 1338     // Continue with a subtype test. | 
| 1334     test = kIsSubtypeOf; | 1339     test = kIsSubtypeOf; | 
| 1335   } | 1340   } | 
| 1336   ASSERT(test == kIsSubtypeOf); | 1341   ASSERT(test == kIsSubtypeOf); | 
| 1337 | 1342 | 
| 1338   // Check for "more specific" relation. | 1343   // Check for "more specific" relation. | 
| 1339   if (IsMoreSpecificThan(type_arguments, other, other_type_arguments)) { | 1344   if (IsMoreSpecificThan(type_arguments, other, other_type_arguments)) { | 
| 1340     return true; | 1345     return true; | 
| 1341   } | 1346   } | 
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1773   return HasResolvedTypeClass() && | 1778   return HasResolvedTypeClass() && | 
| 1774       (type_class() == Type::Handle(Type::FunctionInterface()).type_class()); | 1779       (type_class() == Type::Handle(Type::FunctionInterface()).type_class()); | 
| 1775 } | 1780 } | 
| 1776 | 1781 | 
| 1777 | 1782 | 
| 1778 bool Type::IsMoreSpecificThan(const Type& other) const { | 1783 bool Type::IsMoreSpecificThan(const Type& other) const { | 
| 1779   ASSERT(IsFinalized()); | 1784   ASSERT(IsFinalized()); | 
| 1780   ASSERT(other.IsFinalized()); | 1785   ASSERT(other.IsFinalized()); | 
| 1781   // Type parameters cannot be handled by Class::IsMoreSpecificThan(). | 1786   // Type parameters cannot be handled by Class::IsMoreSpecificThan(). | 
| 1782   if (IsTypeParameter() || other.IsTypeParameter()) { | 1787   if (IsTypeParameter() || other.IsTypeParameter()) { | 
| 1783     // TODO(regis): Revisit this temporary workaround. See issue 5474672. | 1788     return IsTypeParameter() && other.IsTypeParameter() && | 
| 1784     return | 1789         (Index() == other.Index()); | 
| 1785         (!IsTypeParameter() && other.IsTypeParameter()) || |  | 
| 1786         (IsTypeParameter() && other.IsTypeParameter() && |  | 
| 1787          (Index() == other.Index())); |  | 
| 1788   } | 1790   } | 
| 1789   const Class& cls = Class::Handle(type_class()); | 1791   const Class& cls = Class::Handle(type_class()); | 
| 1790   return cls.IsMoreSpecificThan(TypeArguments::Handle(arguments()), | 1792   return cls.IsMoreSpecificThan(TypeArguments::Handle(arguments()), | 
| 1791                                 Class::Handle(other.type_class()), | 1793                                 Class::Handle(other.type_class()), | 
| 1792                                 TypeArguments::Handle(other.arguments())); | 1794                                 TypeArguments::Handle(other.arguments())); | 
| 1793 } | 1795 } | 
| 1794 | 1796 | 
| 1795 | 1797 | 
| 1796 bool Type::Test(TypeTestKind test, const Type& other) const { | 1798 bool Type::Test(TypeTestKind test, const Type& other) const { | 
| 1797   ASSERT(IsFinalized()); | 1799   ASSERT(IsFinalized()); | 
| 1798   ASSERT(other.IsFinalized()); | 1800   ASSERT(other.IsFinalized()); | 
| 1799   // Type parameters cannot be handled by Class::TestType(). | 1801   // Type parameters cannot be handled by Class::TestType(). | 
| 1800   if (IsTypeParameter() || other.IsTypeParameter()) { | 1802   if (IsTypeParameter() || other.IsTypeParameter()) { | 
| 1801     // TODO(regis): Revisit this temporary workaround. See issue 5474672. | 1803     return IsTypeParameter() && other.IsTypeParameter() && | 
| 1802     return | 1804         (Index() == other.Index()); | 
| 1803         (!IsTypeParameter() && other.IsTypeParameter()) || |  | 
| 1804         (IsTypeParameter() && other.IsTypeParameter() && |  | 
| 1805          (Index() == other.Index())); |  | 
| 1806   } | 1805   } | 
| 1807   const Class& cls = Class::Handle(type_class()); | 1806   const Class& cls = Class::Handle(type_class()); | 
| 1808   if (test == kIsSubtypeOf) { | 1807   if (test == kIsSubtypeOf) { | 
| 1809     return cls.IsSubtypeOf(TypeArguments::Handle(arguments()), | 1808     return cls.IsSubtypeOf(TypeArguments::Handle(arguments()), | 
| 1810                             Class::Handle(other.type_class()), | 1809                             Class::Handle(other.type_class()), | 
| 1811                             TypeArguments::Handle(other.arguments())); | 1810                             TypeArguments::Handle(other.arguments())); | 
| 1812   } else { | 1811   } else { | 
| 1813     ASSERT(test == kIsAssignableTo); | 1812     ASSERT(test == kIsAssignableTo); | 
| 1814     return cls.IsAssignableTo(TypeArguments::Handle(arguments()), | 1813     return cls.IsAssignableTo(TypeArguments::Handle(arguments()), | 
| 1815                               Class::Handle(other.type_class()), | 1814                               Class::Handle(other.type_class()), | 
| (...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2712       } | 2711       } | 
| 2713     } | 2712     } | 
| 2714     if (!found_param_name) { | 2713     if (!found_param_name) { | 
| 2715       return false; | 2714       return false; | 
| 2716     } | 2715     } | 
| 2717   } | 2716   } | 
| 2718   return true; | 2717   return true; | 
| 2719 } | 2718 } | 
| 2720 | 2719 | 
| 2721 | 2720 | 
| 2722 bool Function::TestType(TypeTestKind test, const Function& other) const { | 2721 bool Function::TestType(TypeTestKind test, | 
|  | 2722                         const TypeArguments& type_arguments, | 
|  | 2723                         const Function& other, | 
|  | 2724                         const TypeArguments& other_type_arguments) const { | 
| 2723   const intptr_t num_fixed_params = num_fixed_parameters(); | 2725   const intptr_t num_fixed_params = num_fixed_parameters(); | 
| 2724   const intptr_t num_opt_params = num_optional_parameters(); | 2726   const intptr_t num_opt_params = num_optional_parameters(); | 
| 2725   const intptr_t other_num_fixed_params = other.num_fixed_parameters(); | 2727   const intptr_t other_num_fixed_params = other.num_fixed_parameters(); | 
| 2726   const intptr_t other_num_opt_params = other.num_optional_parameters(); | 2728   const intptr_t other_num_opt_params = other.num_optional_parameters(); | 
| 2727   if ((num_fixed_params != other_num_fixed_params) || | 2729   if ((num_fixed_params != other_num_fixed_params) || | 
| 2728       ((test == Type::kIsSubtypeOf) && | 2730       ((test == Type::kIsSubtypeOf) && | 
| 2729        (num_opt_params < other_num_opt_params))) { | 2731        (num_opt_params < other_num_opt_params))) { | 
| 2730     return false; | 2732     return false; | 
| 2731   } | 2733   } | 
| 2732   // TODO(regis): We currently ignore type parameters. We need to consider the |  | 
| 2733   // parameter type upper bound, if any. |  | 
| 2734   // Note that unless we use this code to check function overrides at compile |  | 
| 2735   // time, all parameter types should be instantiated and we can remove code |  | 
| 2736   // checking for type parameters. |  | 
| 2737 |  | 
| 2738   // Check the result type. | 2734   // Check the result type. | 
| 2739   const Type& other_res_type = Type::Handle(other.result_type()); | 2735   Type& other_res_type = Type::Handle(other.result_type()); | 
| 2740   if (!other_res_type.IsTypeParameter() && | 2736   if (!other_res_type.IsInstantiated()) { | 
| 2741       !other_res_type.IsVarType() && | 2737     other_res_type = other_res_type.InstantiateFrom(other_type_arguments, 0); | 
| 2742       !other_res_type.IsVoidType()) { | 2738   } | 
| 2743     const Type& res_type = Type::Handle(result_type()); | 2739   if (!other_res_type.IsVarType() && !other_res_type.IsVoidType()) { | 
| 2744     if (!res_type.IsTypeParameter() && | 2740     Type& res_type = Type::Handle(result_type()); | 
| 2745         !res_type.IsVarType() && | 2741     if (!res_type.IsInstantiated()) { | 
| 2746         (res_type.IsVoidType() || !res_type.IsSubtypeOf(other_res_type)) && | 2742       res_type = res_type.InstantiateFrom(type_arguments, 0); | 
| 2747         ((test == Type::kIsSubtypeOf) || | 2743     } | 
| 2748          (!other_res_type.IsSubtypeOf(res_type)))) { | 2744     if (!res_type.IsVarType() && | 
|  | 2745         (res_type.IsVoidType() || !res_type.IsAssignableTo(other_res_type))) { | 
| 2749       return false; | 2746       return false; | 
| 2750     } | 2747     } | 
| 2751   } | 2748   } | 
| 2752   // Check the types of fixed parameters. | 2749   // Check the types of fixed parameters. | 
| 2753   Type& param_type = Type::Handle(); | 2750   Type& param_type = Type::Handle(); | 
| 2754   Type& other_param_type = Type::Handle(); | 2751   Type& other_param_type = Type::Handle(); | 
| 2755   for (intptr_t i = 0; i < num_fixed_params; i++) { | 2752   for (intptr_t i = 0; i < num_fixed_params; i++) { | 
| 2756     param_type = ParameterTypeAt(i); | 2753     param_type = ParameterTypeAt(i); | 
| 2757     if (param_type.IsTypeParameter() || param_type.IsVarType()) { | 2754     if (!param_type.IsInstantiated()) { | 
|  | 2755       param_type = param_type.InstantiateFrom(type_arguments, 0); | 
|  | 2756     } | 
|  | 2757     if (param_type.IsVarType()) { | 
| 2758       continue; | 2758       continue; | 
| 2759     } | 2759     } | 
| 2760     other_param_type = other.ParameterTypeAt(i); | 2760     other_param_type = other.ParameterTypeAt(i); | 
| 2761     if (other_param_type.IsTypeParameter() || other_param_type.IsVarType()) { | 2761     if (!other_param_type.IsInstantiated()) { | 
|  | 2762       other_param_type = | 
|  | 2763           other_param_type.InstantiateFrom(other_type_arguments, 0); | 
|  | 2764     } | 
|  | 2765     if (other_param_type.IsVarType()) { | 
| 2762       continue; | 2766       continue; | 
| 2763     } | 2767     } | 
| 2764     // Subtyping and assignability rules are identical when applied to parameter | 2768     // Subtyping and assignability rules are identical when applied to parameter | 
| 2765     // types. | 2769     // types. | 
| 2766     ASSERT((test == Type::kIsSubtypeOf) || (test == Type::kIsAssignableTo)); | 2770     ASSERT((test == Type::kIsSubtypeOf) || (test == Type::kIsAssignableTo)); | 
| 2767     if (!param_type.IsSubtypeOf(other_param_type) && | 2771     if (!param_type.IsSubtypeOf(other_param_type) && | 
| 2768         !other_param_type.IsSubtypeOf(param_type)) { | 2772         !other_param_type.IsSubtypeOf(param_type)) { | 
| 2769       return false; | 2773       return false; | 
| 2770     } | 2774     } | 
| 2771   } | 2775   } | 
| 2772   // Check the names and types of optional parameters. | 2776   // Check the names and types of optional parameters. | 
| 2773   // First, check that for each optional named parameter of type T of the other | 2777   // First, check that for each optional named parameter of type T of the other | 
| 2774   // function type, there exists an optional named parameter of this function | 2778   // function type, there exists an optional named parameter of this function | 
| 2775   // type with an identical name and with a Type S that is a subtype or | 2779   // type with an identical name and with a Type S that is a subtype or | 
| 2776   // supertype of T. | 2780   // supertype of T. | 
| 2777   // Note that SetParameterNameAt() guarantees that names are symbols, so we can | 2781   // Note that SetParameterNameAt() guarantees that names are symbols, so we can | 
| 2778   // compare their raw pointers. | 2782   // compare their raw pointers. | 
| 2779   const int num_params = num_fixed_params + num_opt_params; | 2783   const int num_params = num_fixed_params + num_opt_params; | 
| 2780   const int other_num_params = other_num_fixed_params + other_num_opt_params; | 2784   const int other_num_params = other_num_fixed_params + other_num_opt_params; | 
| 2781   bool is_subtype = true; | 2785   bool is_subtype = true; | 
| 2782   bool found_param_name; | 2786   bool found_param_name; | 
| 2783   String& other_param_name = String::Handle(); | 2787   String& other_param_name = String::Handle(); | 
| 2784   for (intptr_t i = other_num_fixed_params; i < other_num_params; i++) { | 2788   for (intptr_t i = other_num_fixed_params; i < other_num_params; i++) { | 
| 2785     other_param_name = other.ParameterNameAt(i); | 2789     other_param_name = other.ParameterNameAt(i); | 
| 2786     found_param_name = false; | 2790     found_param_name = false; | 
| 2787     for (intptr_t j = num_fixed_params; j < num_params; j++) { | 2791     for (intptr_t j = num_fixed_params; j < num_params; j++) { | 
| 2788       if (ParameterNameAt(j) == other_param_name.raw()) { | 2792       if (ParameterNameAt(j) == other_param_name.raw()) { | 
| 2789         found_param_name = true; | 2793         found_param_name = true; | 
| 2790         param_type = ParameterTypeAt(j); | 2794         param_type = ParameterTypeAt(j); | 
| 2791         if (param_type.IsTypeParameter() || param_type.IsVarType()) { | 2795         if (!param_type.IsInstantiated()) { | 
|  | 2796           param_type = param_type.InstantiateFrom(type_arguments, 0); | 
|  | 2797         } | 
|  | 2798         if (param_type.IsVarType()) { | 
| 2792           break; | 2799           break; | 
| 2793         } | 2800         } | 
| 2794         other_param_type = other.ParameterTypeAt(i); | 2801         other_param_type = other.ParameterTypeAt(i); | 
| 2795         if (other_param_type.IsTypeParameter() || | 2802         if (!other_param_type.IsInstantiated()) { | 
| 2796             other_param_type.IsVarType()) { | 2803           other_param_type = | 
|  | 2804               other_param_type.InstantiateFrom(other_type_arguments, 0); | 
|  | 2805         } | 
|  | 2806         if (other_param_type.IsVarType()) { | 
| 2797           break; | 2807           break; | 
| 2798         } | 2808         } | 
| 2799         if (!param_type.IsSubtypeOf(other_param_type) && | 2809         if (!param_type.IsSubtypeOf(other_param_type) && | 
| 2800             !other_param_type.IsSubtypeOf(param_type)) { | 2810             !other_param_type.IsSubtypeOf(param_type)) { | 
| 2801           is_subtype = false; | 2811           is_subtype = false; | 
| 2802         } | 2812         } | 
| 2803         break; | 2813         break; | 
| 2804       } | 2814       } | 
| 2805     } | 2815     } | 
| 2806     if (!found_param_name) { | 2816     if (!found_param_name) { | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 2823   ASSERT(test == Type::kIsAssignableTo); | 2833   ASSERT(test == Type::kIsAssignableTo); | 
| 2824   String& param_name = String::Handle(); | 2834   String& param_name = String::Handle(); | 
| 2825   is_subtype = true; | 2835   is_subtype = true; | 
| 2826   for (intptr_t i = num_fixed_params; i < num_params; i++) { | 2836   for (intptr_t i = num_fixed_params; i < num_params; i++) { | 
| 2827     param_name = ParameterNameAt(i); | 2837     param_name = ParameterNameAt(i); | 
| 2828     found_param_name = false; | 2838     found_param_name = false; | 
| 2829     for (intptr_t j = other_num_fixed_params; j < other_num_params; j++) { | 2839     for (intptr_t j = other_num_fixed_params; j < other_num_params; j++) { | 
| 2830       if (other.ParameterNameAt(j) == param_name.raw()) { | 2840       if (other.ParameterNameAt(j) == param_name.raw()) { | 
| 2831         found_param_name = true; | 2841         found_param_name = true; | 
| 2832         other_param_type = other.ParameterTypeAt(j); | 2842         other_param_type = other.ParameterTypeAt(j); | 
| 2833         if (other_param_type.IsTypeParameter() || | 2843         if (!other_param_type.IsInstantiated()) { | 
| 2834             other_param_type.IsVarType()) { | 2844           other_param_type = | 
|  | 2845               other_param_type.InstantiateFrom(other_type_arguments, 0); | 
|  | 2846         } | 
|  | 2847         if (other_param_type.IsVarType()) { | 
| 2835           break; | 2848           break; | 
| 2836         } | 2849         } | 
| 2837         param_type = ParameterTypeAt(i); | 2850         param_type = ParameterTypeAt(i); | 
| 2838         if (param_type.IsTypeParameter() || param_type.IsVarType()) { | 2851         if (!param_type.IsInstantiated()) { | 
|  | 2852           param_type = param_type.InstantiateFrom(type_arguments, 0); | 
|  | 2853         } | 
|  | 2854         if (param_type.IsVarType()) { | 
| 2839           break; | 2855           break; | 
| 2840         } | 2856         } | 
| 2841         if (!other_param_type.IsSubtypeOf(param_type) && | 2857         if (!other_param_type.IsSubtypeOf(param_type) && | 
| 2842             !param_type.IsSubtypeOf(other_param_type)) { | 2858             !param_type.IsSubtypeOf(other_param_type)) { | 
| 2843           return false; | 2859           return false; | 
| 2844         } | 2860         } | 
| 2845         break; | 2861         break; | 
| 2846       } | 2862       } | 
| 2847     } | 2863     } | 
| 2848     if (!found_param_name) { | 2864     if (!found_param_name) { | 
| (...skipping 3935 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 6784   const String& str = String::Handle(pattern()); | 6800   const String& str = String::Handle(pattern()); | 
| 6785   const char* format = "JSRegExp: pattern=%s flags=%s"; | 6801   const char* format = "JSRegExp: pattern=%s flags=%s"; | 
| 6786   intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags()); | 6802   intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags()); | 
| 6787   char* chars = reinterpret_cast<char*>( | 6803   char* chars = reinterpret_cast<char*>( | 
| 6788       Isolate::Current()->current_zone()->Allocate(len + 1)); | 6804       Isolate::Current()->current_zone()->Allocate(len + 1)); | 
| 6789   OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags()); | 6805   OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags()); | 
| 6790   return chars; | 6806   return chars; | 
| 6791 } | 6807 } | 
| 6792 | 6808 | 
| 6793 }  // namespace dart | 6809 }  // namespace dart | 
| OLD | NEW | 
|---|