OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "bin/builtin.h" | 5 #include "bin/builtin.h" |
6 #include "vm/compiler.h" | 6 #include "vm/compiler.h" |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "include/dart_mirrors_api.h" | 8 #include "include/dart_mirrors_api.h" |
9 #include "include/dart_native_api.h" | 9 #include "include/dart_native_api.h" |
10 #include "include/dart_tools_api.h" | 10 #include "include/dart_tools_api.h" |
11 #include "platform/assert.h" | 11 #include "platform/assert.h" |
12 #include "platform/text_buffer.h" | 12 #include "platform/text_buffer.h" |
13 #include "platform/utils.h" | 13 #include "platform/utils.h" |
14 #include "vm/class_finalizer.h" | 14 #include "vm/class_finalizer.h" |
15 #include "vm/dart_api_impl.h" | 15 #include "vm/dart_api_impl.h" |
16 #include "vm/dart_api_state.h" | 16 #include "vm/dart_api_state.h" |
17 #include "vm/lockers.h" | 17 #include "vm/lockers.h" |
18 #include "vm/timeline.h" | 18 #include "vm/timeline.h" |
19 #include "vm/unit_test.h" | 19 #include "vm/unit_test.h" |
20 #include "vm/verifier.h" | 20 #include "vm/verifier.h" |
21 | 21 |
22 namespace dart { | 22 namespace dart { |
23 | 23 |
24 DECLARE_FLAG(bool, verify_acquired_data); | 24 DECLARE_FLAG(bool, verify_acquired_data); |
25 DECLARE_FLAG(bool, ignore_patch_signature_mismatch); | 25 DECLARE_FLAG(bool, ignore_patch_signature_mismatch); |
26 DECLARE_FLAG(bool, support_externalizable_strings); | |
26 | 27 |
27 #ifndef PRODUCT | 28 #ifndef PRODUCT |
28 | 29 |
29 TEST_CASE(ErrorHandleBasics) { | 30 TEST_CASE(ErrorHandleBasics) { |
30 const char* kScriptChars = | 31 const char* kScriptChars = |
31 "void testMain() {\n" | 32 "void testMain() {\n" |
32 " throw new Exception(\"bad news\");\n" | 33 " throw new Exception(\"bad news\");\n" |
33 "}\n"; | 34 "}\n"; |
34 | 35 |
35 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 36 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
(...skipping 5532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5568 if (!strcmp(function_name, "NativeArgument_Create")) { | 5569 if (!strcmp(function_name, "NativeArgument_Create")) { |
5569 return reinterpret_cast<Dart_NativeFunction>(&NativeArgumentCreate); | 5570 return reinterpret_cast<Dart_NativeFunction>(&NativeArgumentCreate); |
5570 } else if (!strcmp(function_name, "NativeArgument_Access")) { | 5571 } else if (!strcmp(function_name, "NativeArgument_Access")) { |
5571 return reinterpret_cast<Dart_NativeFunction>(&NativeArgumentAccess); | 5572 return reinterpret_cast<Dart_NativeFunction>(&NativeArgumentAccess); |
5572 } | 5573 } |
5573 return NULL; | 5574 return NULL; |
5574 } | 5575 } |
5575 | 5576 |
5576 | 5577 |
5577 TEST_CASE(GetNativeArguments) { | 5578 TEST_CASE(GetNativeArguments) { |
5579 FLAG_support_externalizable_strings = true; | |
srdjan
2016/04/07 16:47:36
It seems that we are not that consistent, but many
rmacnak
2016/04/07 20:22:37
Added a restore for these changes.
| |
5580 | |
5578 const char* kScriptChars = | 5581 const char* kScriptChars = |
5579 "import 'dart:nativewrappers';" | 5582 "import 'dart:nativewrappers';" |
5580 "class MyObject extends NativeFieldWrapperClass2 {" | 5583 "class MyObject extends NativeFieldWrapperClass2 {" |
5581 " static MyObject createObject() native 'NativeArgument_Create';" | 5584 " static MyObject createObject() native 'NativeArgument_Create';" |
5582 " int accessFields(int arg1," | 5585 " int accessFields(int arg1," |
5583 " int arg2," | 5586 " int arg2," |
5584 " bool arg3," | 5587 " bool arg3," |
5585 " double arg4," | 5588 " double arg4," |
5586 " String arg5," | 5589 " String arg5," |
5587 " String arg6," | 5590 " String arg6," |
(...skipping 2902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8490 } | 8493 } |
8491 | 8494 |
8492 | 8495 |
8493 // Test API call to make strings external. | 8496 // Test API call to make strings external. |
8494 static void MakeExternalCback(void* peer) { | 8497 static void MakeExternalCback(void* peer) { |
8495 *static_cast<int*>(peer) *= 2; | 8498 *static_cast<int*>(peer) *= 2; |
8496 } | 8499 } |
8497 | 8500 |
8498 | 8501 |
8499 TEST_CASE(MakeExternalString) { | 8502 TEST_CASE(MakeExternalString) { |
8503 FLAG_support_externalizable_strings = true; | |
8504 | |
8500 static int peer8 = 40; | 8505 static int peer8 = 40; |
8501 static int peer16 = 41; | 8506 static int peer16 = 41; |
8502 static int canonical_str_peer = 42; | 8507 static int canonical_str_peer = 42; |
8503 intptr_t length = 0; | 8508 intptr_t length = 0; |
8504 intptr_t expected_length = 0; | 8509 intptr_t expected_length = 0; |
8505 { | 8510 { |
8506 Dart_EnterScope(); | 8511 Dart_EnterScope(); |
8507 | 8512 |
8508 // First test some negative conditions. | 8513 // First test some negative conditions. |
8509 uint8_t data8[] = { 'h', 'e', 'l', 'l', 'o' }; | 8514 uint8_t data8[] = { 'h', 'e', 'l', 'l', 'o' }; |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8697 TransitionNativeToVM transition(thread); | 8702 TransitionNativeToVM transition(thread); |
8698 Isolate::Current()->heap()->CollectAllGarbage(); | 8703 Isolate::Current()->heap()->CollectAllGarbage(); |
8699 } | 8704 } |
8700 EXPECT_EQ(80, peer8); | 8705 EXPECT_EQ(80, peer8); |
8701 EXPECT_EQ(82, peer16); | 8706 EXPECT_EQ(82, peer16); |
8702 EXPECT_EQ(42, canonical_str_peer); // "*" Symbol is not removed on GC. | 8707 EXPECT_EQ(42, canonical_str_peer); // "*" Symbol is not removed on GC. |
8703 } | 8708 } |
8704 | 8709 |
8705 | 8710 |
8706 TEST_CASE(ExternalizeConstantStrings) { | 8711 TEST_CASE(ExternalizeConstantStrings) { |
8712 FLAG_support_externalizable_strings = true; | |
8713 | |
8707 const char* kScriptChars = | 8714 const char* kScriptChars = |
8708 "String testMain() {\n" | 8715 "String testMain() {\n" |
8709 " return 'constant string';\n" | 8716 " return 'constant string';\n" |
8710 "}\n"; | 8717 "}\n"; |
8711 | 8718 |
8712 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); | 8719 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
8713 Dart_Handle result = Dart_Invoke(lib, | 8720 Dart_Handle result = Dart_Invoke(lib, |
8714 NewString("testMain"), | 8721 NewString("testMain"), |
8715 0, | 8722 0, |
8716 NULL); | 8723 NULL); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8809 Dart_Handle name, int argument_count, bool* auto_setup_scope) { | 8816 Dart_Handle name, int argument_count, bool* auto_setup_scope) { |
8810 ASSERT(auto_setup_scope != NULL); | 8817 ASSERT(auto_setup_scope != NULL); |
8811 *auto_setup_scope = true; | 8818 *auto_setup_scope = true; |
8812 return reinterpret_cast<Dart_NativeFunction>(&A_change_str_native); | 8819 return reinterpret_cast<Dart_NativeFunction>(&A_change_str_native); |
8813 } | 8820 } |
8814 | 8821 |
8815 | 8822 |
8816 // Do not use guarding mechanism on externalizable classes, since their class | 8823 // Do not use guarding mechanism on externalizable classes, since their class |
8817 // can change on the fly, | 8824 // can change on the fly, |
8818 TEST_CASE(GuardExternalizedString) { | 8825 TEST_CASE(GuardExternalizedString) { |
8826 FLAG_support_externalizable_strings = true; | |
8827 | |
8819 const char* kScriptChars = | 8828 const char* kScriptChars = |
8820 "main() {\n" | 8829 "main() {\n" |
8821 " var a = new A('hello');\n" | 8830 " var a = new A('hello');\n" |
8822 " var res = runOne(a);\n" | 8831 " var res = runOne(a);\n" |
8823 " if (res != 10640000) return -1;\n" | 8832 " if (res != 10640000) return -1;\n" |
8824 " change_str(a.f);\n" | 8833 " change_str(a.f);\n" |
8825 " res = runOne(a);\n" | 8834 " res = runOne(a);\n" |
8826 " return res;\n" | 8835 " return res;\n" |
8827 "}\n" | 8836 "}\n" |
8828 "runOne(a) {\n" | 8837 "runOne(a) {\n" |
(...skipping 19 matching lines...) Expand all Loading... | |
8848 0, | 8857 0, |
8849 NULL); | 8858 NULL); |
8850 int64_t value = 0; | 8859 int64_t value = 0; |
8851 result = Dart_IntegerToInt64(result, &value); | 8860 result = Dart_IntegerToInt64(result, &value); |
8852 EXPECT_VALID(result); | 8861 EXPECT_VALID(result); |
8853 EXPECT_EQ(10640000, value); | 8862 EXPECT_EQ(10640000, value); |
8854 } | 8863 } |
8855 | 8864 |
8856 | 8865 |
8857 TEST_CASE(ExternalStringDeoptimize) { | 8866 TEST_CASE(ExternalStringDeoptimize) { |
8867 FLAG_support_externalizable_strings = true; | |
8868 | |
8858 const char* kScriptChars = | 8869 const char* kScriptChars = |
8859 "String str = 'A';\n" | 8870 "String str = 'A';\n" |
8860 "class A {\n" | 8871 "class A {\n" |
8861 " static change_str(String s) native 'A_change_str';\n" | 8872 " static change_str(String s) native 'A_change_str';\n" |
8862 "}\n" | 8873 "}\n" |
8863 "sum_chars(String s, bool b) {\n" | 8874 "sum_chars(String s, bool b) {\n" |
8864 " var result = 0;\n" | 8875 " var result = 0;\n" |
8865 " for (var i = 0; i < s.length; i++) {\n" | 8876 " for (var i = 0; i < s.length; i++) {\n" |
8866 " if (b && i == 0) A.change_str(str);\n" | 8877 " if (b && i == 0) A.change_str(str);\n" |
8867 " result += s.codeUnitAt(i);" | 8878 " result += s.codeUnitAt(i);" |
(...skipping 15 matching lines...) Expand all Loading... | |
8883 0, | 8894 0, |
8884 NULL); | 8895 NULL); |
8885 int64_t value = 0; | 8896 int64_t value = 0; |
8886 result = Dart_IntegerToInt64(result, &value); | 8897 result = Dart_IntegerToInt64(result, &value); |
8887 EXPECT_VALID(result); | 8898 EXPECT_VALID(result); |
8888 EXPECT_EQ(260, value); | 8899 EXPECT_EQ(260, value); |
8889 } | 8900 } |
8890 | 8901 |
8891 | 8902 |
8892 TEST_CASE(ExternalStringPolymorphicDeoptimize) { | 8903 TEST_CASE(ExternalStringPolymorphicDeoptimize) { |
8904 FLAG_support_externalizable_strings = true; | |
8905 | |
8893 const char* kScriptChars = | 8906 const char* kScriptChars = |
8894 "const strA = 'AAAA';\n" | 8907 "const strA = 'AAAA';\n" |
8895 "class A {\n" | 8908 "class A {\n" |
8896 " static change_str(String s) native 'A_change_str';\n" | 8909 " static change_str(String s) native 'A_change_str';\n" |
8897 "}\n" | 8910 "}\n" |
8898 "compare(a, b, [i = 0]) {\n" | 8911 "compare(a, b, [i = 0]) {\n" |
8899 " return a.codeUnitAt(i) == b.codeUnitAt(i);\n" | 8912 " return a.codeUnitAt(i) == b.codeUnitAt(i);\n" |
8900 "}\n" | 8913 "}\n" |
8901 "compareA(b, [i = 0]) {\n" | 8914 "compareA(b, [i = 0]) {\n" |
8902 " return compare(strA, b, i);\n" | 8915 " return compare(strA, b, i);\n" |
(...skipping 16 matching lines...) Expand all Loading... | |
8919 NULL); | 8932 NULL); |
8920 EXPECT_VALID(result); | 8933 EXPECT_VALID(result); |
8921 bool value = false; | 8934 bool value = false; |
8922 result = Dart_BooleanValue(result, &value); | 8935 result = Dart_BooleanValue(result, &value); |
8923 EXPECT_VALID(result); | 8936 EXPECT_VALID(result); |
8924 EXPECT(value); | 8937 EXPECT(value); |
8925 } | 8938 } |
8926 | 8939 |
8927 | 8940 |
8928 TEST_CASE(ExternalStringGuardFieldDeoptimize) { | 8941 TEST_CASE(ExternalStringGuardFieldDeoptimize) { |
8942 FLAG_support_externalizable_strings = true; | |
8943 | |
8929 const char* kScriptChars = | 8944 const char* kScriptChars = |
8930 "const strA = 'AAAA';\n" | 8945 "const strA = 'AAAA';\n" |
8931 "class A {\n" | 8946 "class A {\n" |
8932 " static change_str(String s) native 'A_change_str';\n" | 8947 " static change_str(String s) native 'A_change_str';\n" |
8933 "}\n" | 8948 "}\n" |
8934 "class G { var f = 'A'; }\n" | 8949 "class G { var f = 'A'; }\n" |
8935 "final guard = new G();\n" | 8950 "final guard = new G();\n" |
8936 "var shouldExternalize = false;\n" | 8951 "var shouldExternalize = false;\n" |
8937 "ext() { if (shouldExternalize) A.change_str(strA); }\n" | 8952 "ext() { if (shouldExternalize) A.change_str(strA); }\n" |
8938 "compare(a, b, [i = 0]) {\n" | 8953 "compare(a, b, [i = 0]) {\n" |
(...skipping 21 matching lines...) Expand all Loading... | |
8960 NULL); | 8975 NULL); |
8961 EXPECT_VALID(result); | 8976 EXPECT_VALID(result); |
8962 bool value = false; | 8977 bool value = false; |
8963 result = Dart_BooleanValue(result, &value); | 8978 result = Dart_BooleanValue(result, &value); |
8964 EXPECT_VALID(result); | 8979 EXPECT_VALID(result); |
8965 EXPECT(value); | 8980 EXPECT(value); |
8966 } | 8981 } |
8967 | 8982 |
8968 | 8983 |
8969 TEST_CASE(ExternalStringStaticFieldDeoptimize) { | 8984 TEST_CASE(ExternalStringStaticFieldDeoptimize) { |
8985 FLAG_support_externalizable_strings = true; | |
8986 | |
8970 const char* kScriptChars = | 8987 const char* kScriptChars = |
8971 "const strA = 'AAAA';\n" | 8988 "const strA = 'AAAA';\n" |
8972 "class A {\n" | 8989 "class A {\n" |
8973 " static change_str(String s) native 'A_change_str';\n" | 8990 " static change_str(String s) native 'A_change_str';\n" |
8974 "}\n" | 8991 "}\n" |
8975 "class G { static final f = strA; }\n" | 8992 "class G { static final f = strA; }\n" |
8976 "compare(a, b, [i = 0]) {\n" | 8993 "compare(a, b, [i = 0]) {\n" |
8977 " return a.codeUnitAt(i) == b.codeUnitAt(i);\n" | 8994 " return a.codeUnitAt(i) == b.codeUnitAt(i);\n" |
8978 "}\n" | 8995 "}\n" |
8979 "compareA(b, [i = 0]) {\n" | 8996 "compareA(b, [i = 0]) {\n" |
(...skipping 16 matching lines...) Expand all Loading... | |
8996 NULL); | 9013 NULL); |
8997 EXPECT_VALID(result); | 9014 EXPECT_VALID(result); |
8998 bool value = false; | 9015 bool value = false; |
8999 result = Dart_BooleanValue(result, &value); | 9016 result = Dart_BooleanValue(result, &value); |
9000 EXPECT_VALID(result); | 9017 EXPECT_VALID(result); |
9001 EXPECT(value); | 9018 EXPECT(value); |
9002 } | 9019 } |
9003 | 9020 |
9004 | 9021 |
9005 TEST_CASE(ExternalStringTrimDoubleParse) { | 9022 TEST_CASE(ExternalStringTrimDoubleParse) { |
9023 FLAG_support_externalizable_strings = true; | |
9024 | |
9006 const char* kScriptChars = | 9025 const char* kScriptChars = |
9007 "String str = 'A';\n" | 9026 "String str = 'A';\n" |
9008 "class A {\n" | 9027 "class A {\n" |
9009 " static change_str(String s) native 'A_change_str';\n" | 9028 " static change_str(String s) native 'A_change_str';\n" |
9010 "}\n" | 9029 "}\n" |
9011 "main() {\n" | 9030 "main() {\n" |
9012 " var externalOneByteString = ' 0.2\\xA0 ';\n;" | 9031 " var externalOneByteString = ' 0.2\\xA0 ';\n;" |
9013 " A.change_str(externalOneByteString);\n" | 9032 " A.change_str(externalOneByteString);\n" |
9014 " var externalTwoByteString = ' \\u{2029}0.6\\u{2029} ';\n" | 9033 " var externalTwoByteString = ' \\u{2029}0.6\\u{2029} ';\n" |
9015 " A.change_str(externalTwoByteString);\n" | 9034 " A.change_str(externalTwoByteString);\n" |
9016 " var x = double.parse(externalOneByteString);\n" | 9035 " var x = double.parse(externalOneByteString);\n" |
9017 " var y = double.parse(externalTwoByteString);\n" | 9036 " var y = double.parse(externalTwoByteString);\n" |
9018 " return ((x + y) * 10).toInt();\n" | 9037 " return ((x + y) * 10).toInt();\n" |
9019 "}\n"; | 9038 "}\n"; |
9020 Dart_Handle lib = | 9039 Dart_Handle lib = |
9021 TestCase::LoadTestScript(kScriptChars, | 9040 TestCase::LoadTestScript(kScriptChars, |
9022 &ExternalStringDeoptimize_native_lookup); | 9041 &ExternalStringDeoptimize_native_lookup); |
9023 Dart_Handle result = Dart_Invoke(lib, | 9042 Dart_Handle result = Dart_Invoke(lib, |
9024 NewString("main"), | 9043 NewString("main"), |
9025 0, | 9044 0, |
9026 NULL); | 9045 NULL); |
9027 int64_t value = 0; | 9046 int64_t value = 0; |
9028 result = Dart_IntegerToInt64(result, &value); | 9047 result = Dart_IntegerToInt64(result, &value); |
9029 EXPECT_VALID(result); | 9048 EXPECT_VALID(result); |
9030 EXPECT_EQ(8, value); | 9049 EXPECT_EQ(8, value); |
9031 } | 9050 } |
9032 | 9051 |
9033 | 9052 |
9034 TEST_CASE(ExternalStringDoubleParse) { | 9053 TEST_CASE(ExternalStringDoubleParse) { |
9054 FLAG_support_externalizable_strings = true; | |
9055 | |
9035 const char* kScriptChars = | 9056 const char* kScriptChars = |
9036 "String str = 'A';\n" | 9057 "String str = 'A';\n" |
9037 "class A {\n" | 9058 "class A {\n" |
9038 " static change_str(String s) native 'A_change_str';\n" | 9059 " static change_str(String s) native 'A_change_str';\n" |
9039 "}\n" | 9060 "}\n" |
9040 "main() {\n" | 9061 "main() {\n" |
9041 " var externalOneByteString = '0.2';\n;" | 9062 " var externalOneByteString = '0.2';\n;" |
9042 " A.change_str(externalOneByteString);\n" | 9063 " A.change_str(externalOneByteString);\n" |
9043 " var externalTwoByteString = '0.6';\n" | 9064 " var externalTwoByteString = '0.6';\n" |
9044 " A.change_str(externalTwoByteString);\n" | 9065 " A.change_str(externalTwoByteString);\n" |
9045 " var x = double.parse(externalOneByteString);\n" | 9066 " var x = double.parse(externalOneByteString);\n" |
9046 " var y = double.parse(externalTwoByteString);\n" | 9067 " var y = double.parse(externalTwoByteString);\n" |
9047 " return ((x + y) * 10).toInt();\n" | 9068 " return ((x + y) * 10).toInt();\n" |
9048 "}\n"; | 9069 "}\n"; |
9049 Dart_Handle lib = | 9070 Dart_Handle lib = |
9050 TestCase::LoadTestScript(kScriptChars, | 9071 TestCase::LoadTestScript(kScriptChars, |
9051 &ExternalStringDeoptimize_native_lookup); | 9072 &ExternalStringDeoptimize_native_lookup); |
9052 Dart_Handle result = Dart_Invoke(lib, | 9073 Dart_Handle result = Dart_Invoke(lib, |
9053 NewString("main"), | 9074 NewString("main"), |
9054 0, | 9075 0, |
9055 NULL); | 9076 NULL); |
9056 int64_t value = 0; | 9077 int64_t value = 0; |
9057 result = Dart_IntegerToInt64(result, &value); | 9078 result = Dart_IntegerToInt64(result, &value); |
9058 EXPECT_VALID(result); | 9079 EXPECT_VALID(result); |
9059 EXPECT_EQ(8, value); | 9080 EXPECT_EQ(8, value); |
9060 } | 9081 } |
9061 | 9082 |
9062 | 9083 |
9063 TEST_CASE(ExternalStringIndexOf) { | 9084 TEST_CASE(ExternalStringIndexOf) { |
9064 const char* kScriptChars = | 9085 const char* kScriptChars = |
9065 "main(String pattern) {\n" | 9086 "main(String pattern) {\n" |
9066 " var str = 'Hello World';\n" | 9087 " var str = 'Hello World';\n" |
9067 " return str.indexOf(pattern);\n" | 9088 " return str.indexOf(pattern);\n" |
9068 "}\n"; | 9089 "}\n"; |
9069 Dart_Handle lib = | 9090 Dart_Handle lib = |
9070 TestCase::LoadTestScript(kScriptChars, NULL); | 9091 TestCase::LoadTestScript(kScriptChars, NULL); |
9071 | 9092 |
9072 uint8_t data8[] = { 'W' }; | 9093 uint8_t data8[] = { 'W' }; |
9073 Dart_Handle ext8 = Dart_NewExternalLatin1String(data8, ARRAY_SIZE(data8), | 9094 Dart_Handle ext8 = Dart_NewExternalLatin1String(data8, ARRAY_SIZE(data8), |
9074 data8, NULL); | 9095 data8, NULL); |
(...skipping 926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10001 result = Dart_Invoke(lib, | 10022 result = Dart_Invoke(lib, |
10002 NewString("foozoo"), | 10023 NewString("foozoo"), |
10003 0, | 10024 0, |
10004 NULL); | 10025 NULL); |
10005 EXPECT(Dart_IsError(result)); | 10026 EXPECT(Dart_IsError(result)); |
10006 } | 10027 } |
10007 | 10028 |
10008 #endif // !PRODUCT | 10029 #endif // !PRODUCT |
10009 | 10030 |
10010 } // namespace dart | 10031 } // namespace dart |
OLD | NEW |