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 |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #include "include/dart_api.h" |
6 | #include "platform/assert.h" |
7 | #include "vm/dart_api_impl.h" |
8 | #include "vm/unit_test.h" |
9 | |
10 | namespace dart { |
11 | |
12 | #define FUNCTION_NAME(name) UnhandledExcp_##name |
13 | #define REGISTER_FUNCTION(name, count) {"" #name, FUNCTION_NAME(name), count}, |
14 | |
15 | void FUNCTION_NAME(Unhandled_equals)(Dart_NativeArguments args) { |
16 | NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
17 | TransitionNativeToVM transition(arguments->thread()); |
18 | Zone* zone = arguments->thread()->zone(); |
19 | const Instance& expected = |
20 | Instance::CheckedHandle(zone, arguments->NativeArgAt(0)); |
21 | const Instance& actual = |
22 | Instance::CheckedHandle(zone, arguments->NativeArgAt(1)); |
23 | if (!expected.CanonicalizeEquals(actual)) { |
24 | OS::PrintErr("expected: '%s' actual: '%s'\n" , expected.ToCString(), |
25 | actual.ToCString()); |
26 | FATAL("Unhandled_equals fails.\n" ); |
27 | } |
28 | } |
29 | |
30 | void FUNCTION_NAME(Unhandled_invoke)(Dart_NativeArguments args) { |
31 | // Invoke the specified entry point. |
32 | Dart_Handle cls = Dart_GetClass(TestCase::lib(), NewString("Second" )); |
33 | Dart_Handle result = Dart_Invoke(cls, NewString("method2" ), 0, NULL); |
34 | ASSERT(Dart_IsError(result)); |
35 | ASSERT(Dart_ErrorHasException(result)); |
36 | return; |
37 | } |
38 | |
39 | void FUNCTION_NAME(Unhandled_invoke2)(Dart_NativeArguments args) { |
40 | // Invoke the specified entry point. |
41 | Dart_Handle cls = Dart_GetClass(TestCase::lib(), NewString("Second" )); |
42 | Dart_Handle result = Dart_Invoke(cls, NewString("method2" ), 0, NULL); |
43 | ASSERT(Dart_IsError(result)); |
44 | ASSERT(Dart_ErrorHasException(result)); |
45 | Dart_Handle exception = Dart_ErrorGetException(result); |
46 | ASSERT(!Dart_IsError(exception)); |
47 | Dart_ThrowException(exception); |
48 | UNREACHABLE(); |
49 | return; |
50 | } |
51 | |
52 | // List all native functions implemented in the vm or core boot strap dart |
53 | // libraries so that we can resolve the native function to it's entry |
54 | // point. |
55 | #define UNHANDLED_NATIVE_LIST(V) \ |
56 | V(Unhandled_equals, 2) \ |
57 | V(Unhandled_invoke, 0) \ |
58 | V(Unhandled_invoke2, 0) |
59 | |
60 | static struct NativeEntries { |
61 | const char* name_; |
62 | Dart_NativeFunction function_; |
63 | int argument_count_; |
64 | } BuiltinEntries[] = {UNHANDLED_NATIVE_LIST(REGISTER_FUNCTION)}; |
65 | |
66 | static Dart_NativeFunction native_lookup(Dart_Handle name, |
67 | int argument_count, |
68 | bool* auto_setup_scope) { |
69 | ASSERT(auto_setup_scope != NULL); |
70 | *auto_setup_scope = true; |
71 | TransitionNativeToVM transition(Thread::Current()); |
72 | const Object& obj = Object::Handle(Api::UnwrapHandle(name)); |
73 | ASSERT(obj.IsString()); |
74 | const char* function_name = obj.ToCString(); |
75 | ASSERT(function_name != NULL); |
76 | int num_entries = sizeof(BuiltinEntries) / sizeof(struct NativeEntries); |
77 | for (int i = 0; i < num_entries; i++) { |
78 | struct NativeEntries* entry = &(BuiltinEntries[i]); |
79 | if ((strcmp(function_name, entry->name_) == 0) && |
80 | (argument_count == entry->argument_count_)) { |
81 | return reinterpret_cast<Dart_NativeFunction>(entry->function_); |
82 | } |
83 | } |
84 | return NULL; |
85 | } |
86 | |
87 | // Unit test case to verify unhandled exceptions. |
88 | TEST_CASE(UnhandledExceptions) { |
89 | const char* kScriptChars = |
90 | "class UnhandledExceptions {\n" |
91 | " static equals(var obj1, var obj2) native \"Unhandled_equals\";" |
92 | " static invoke() native \"Unhandled_invoke\";\n" |
93 | " static invoke2() native \"Unhandled_invoke2\";\n" |
94 | "}\n" |
95 | "class Second {\n" |
96 | " Second() { }\n" |
97 | " static int method1(int param) {\n" |
98 | " UnhandledExceptions.invoke();\n" |
99 | " return 2;\n" |
100 | " }\n" |
101 | " static int method2() {\n" |
102 | " throw new Second();\n" |
103 | " }\n" |
104 | " static int method3(int param) {\n" |
105 | " try {\n" |
106 | " UnhandledExceptions.invoke2();\n" |
107 | " } on Second catch (e) {\n" |
108 | " return 3;\n" |
109 | " }\n" |
110 | " return 2;\n" |
111 | " }\n" |
112 | "}\n" |
113 | "testMain() {\n" |
114 | " UnhandledExceptions.equals(2, Second.method1(1));\n" |
115 | " UnhandledExceptions.equals(3, Second.method3(1));\n" |
116 | "}" ; |
117 | Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, native_lookup); |
118 | EXPECT_VALID(Dart_Invoke(lib, NewString("testMain" ), 0, NULL)); |
119 | } |
120 | |
121 | } // namespace dart |
122 | |