OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/service.h" | 5 #include "vm/service.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 #include "include/dart_native_api.h" | 8 #include "include/dart_native_api.h" |
9 #include "platform/globals.h" | 9 #include "platform/globals.h" |
10 | 10 |
11 #include "vm/compiler.h" | 11 #include "vm/compiler.h" |
12 #include "vm/cpu.h" | 12 #include "vm/cpu.h" |
13 #include "vm/dart_api_impl.h" | 13 #include "vm/dart_api_impl.h" |
14 #include "vm/dart_api_state.h" | 14 #include "vm/dart_api_state.h" |
15 #include "vm/dart_entry.h" | 15 #include "vm/dart_entry.h" |
16 #include "vm/debugger.h" | 16 #include "vm/debugger.h" |
| 17 #include "vm/dev_fs.h" |
17 #include "vm/isolate.h" | 18 #include "vm/isolate.h" |
18 #include "vm/lockers.h" | 19 #include "vm/lockers.h" |
19 #include "vm/message.h" | 20 #include "vm/message.h" |
20 #include "vm/message_handler.h" | 21 #include "vm/message_handler.h" |
21 #include "vm/native_entry.h" | 22 #include "vm/native_entry.h" |
22 #include "vm/native_arguments.h" | 23 #include "vm/native_arguments.h" |
23 #include "vm/native_symbol.h" | 24 #include "vm/native_symbol.h" |
24 #include "vm/object.h" | 25 #include "vm/object.h" |
25 #include "vm/object_graph.h" | 26 #include "vm/object_graph.h" |
26 #include "vm/object_id_ring.h" | 27 #include "vm/object_id_ring.h" |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 MethodParameter(const char* name, bool required) | 407 MethodParameter(const char* name, bool required) |
407 : name_(name), required_(required) { | 408 : name_(name), required_(required) { |
408 } | 409 } |
409 | 410 |
410 virtual ~MethodParameter() { } | 411 virtual ~MethodParameter() { } |
411 | 412 |
412 virtual bool Validate(const char* value) const { | 413 virtual bool Validate(const char* value) const { |
413 return true; | 414 return true; |
414 } | 415 } |
415 | 416 |
| 417 virtual bool ValidateObject(const Object& value) const { |
| 418 return true; |
| 419 } |
| 420 |
416 const char* name() const { | 421 const char* name() const { |
417 return name_; | 422 return name_; |
418 } | 423 } |
419 | 424 |
420 bool required() const { | 425 bool required() const { |
421 return required_; | 426 return required_; |
422 } | 427 } |
423 | 428 |
424 virtual void PrintError(const char* name, | 429 virtual void PrintError(const char* name, |
425 const char* value, | 430 const char* value, |
426 JSONStream* js) const { | 431 JSONStream* js) const { |
427 PrintInvalidParamError(js, name); | 432 PrintInvalidParamError(js, name); |
428 } | 433 } |
429 | 434 |
| 435 virtual void PrintErrorObject(const char* name, |
| 436 const Object& value, |
| 437 JSONStream* js) const { |
| 438 PrintInvalidParamError(js, name); |
| 439 } |
| 440 |
430 private: | 441 private: |
431 const char* name_; | 442 const char* name_; |
432 bool required_; | 443 bool required_; |
433 }; | 444 }; |
434 | 445 |
435 | 446 |
| 447 class DartStringParameter : public MethodParameter { |
| 448 public: |
| 449 DartStringParameter(const char* name, bool required) |
| 450 : MethodParameter(name, required) { |
| 451 } |
| 452 |
| 453 virtual bool ValidateObject(const Object& value) const { |
| 454 return value.IsString(); |
| 455 } |
| 456 }; |
| 457 |
| 458 |
| 459 class DartListParameter : public MethodParameter { |
| 460 public: |
| 461 DartListParameter(const char* name, bool required) |
| 462 : MethodParameter(name, required) { |
| 463 } |
| 464 |
| 465 virtual bool ValidateObject(const Object& value) const { |
| 466 return value.IsArray() || value.IsGrowableObjectArray(); |
| 467 } |
| 468 }; |
| 469 |
| 470 |
436 class NoSuchParameter : public MethodParameter { | 471 class NoSuchParameter : public MethodParameter { |
437 public: | 472 public: |
438 explicit NoSuchParameter(const char* name) | 473 explicit NoSuchParameter(const char* name) |
439 : MethodParameter(name, false) { | 474 : MethodParameter(name, false) { |
440 } | 475 } |
441 | 476 |
442 virtual bool Validate(const char* value) const { | 477 virtual bool Validate(const char* value) const { |
443 return (value == NULL); | 478 return (value == NULL); |
444 } | 479 } |
| 480 |
| 481 virtual bool ValidateObject(const Object& value) const { |
| 482 return value.IsNull(); |
| 483 } |
445 }; | 484 }; |
446 | 485 |
447 | 486 |
448 class BoolParameter : public MethodParameter { | 487 class BoolParameter : public MethodParameter { |
449 public: | 488 public: |
450 BoolParameter(const char* name, bool required) | 489 BoolParameter(const char* name, bool required) |
451 : MethodParameter(name, required) { | 490 : MethodParameter(name, required) { |
452 } | 491 } |
453 | 492 |
454 virtual bool Validate(const char* value) const { | 493 virtual bool Validate(const char* value) const { |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 const MethodParameter* const * parameters; | 769 const MethodParameter* const * parameters; |
731 }; | 770 }; |
732 | 771 |
733 | 772 |
734 // TODO(johnmccutchan): Do we reject unexpected parameters? | 773 // TODO(johnmccutchan): Do we reject unexpected parameters? |
735 static bool ValidateParameters(const MethodParameter* const* parameters, | 774 static bool ValidateParameters(const MethodParameter* const* parameters, |
736 JSONStream* js) { | 775 JSONStream* js) { |
737 if (parameters == NULL) { | 776 if (parameters == NULL) { |
738 return true; | 777 return true; |
739 } | 778 } |
740 for (intptr_t i = 0; parameters[i] != NULL; i++) { | 779 if (js->NumObjectParameters() > 0) { |
741 const MethodParameter* parameter = parameters[i]; | 780 Object& value = Object::Handle(); |
742 const char* name = parameter->name(); | 781 for (intptr_t i = 0; parameters[i] != NULL; i++) { |
743 const bool required = parameter->required(); | 782 const MethodParameter* parameter = parameters[i]; |
744 const char* value = js->LookupParam(name); | 783 const char* name = parameter->name(); |
745 const bool has_parameter = (value != NULL); | 784 const bool required = parameter->required(); |
746 if (required && !has_parameter) { | 785 value = js->LookupObjectParam(name); |
747 PrintMissingParamError(js, name); | 786 const bool has_parameter = !value.IsNull(); |
748 return false; | 787 if (required && !has_parameter) { |
| 788 PrintMissingParamError(js, name); |
| 789 return false; |
| 790 } |
| 791 if (has_parameter && !parameter->ValidateObject(value)) { |
| 792 parameter->PrintErrorObject(name, value, js); |
| 793 return false; |
| 794 } |
749 } | 795 } |
750 if (has_parameter && !parameter->Validate(value)) { | 796 } else { |
751 parameter->PrintError(name, value, js); | 797 for (intptr_t i = 0; parameters[i] != NULL; i++) { |
752 return false; | 798 const MethodParameter* parameter = parameters[i]; |
| 799 const char* name = parameter->name(); |
| 800 const bool required = parameter->required(); |
| 801 const char* value = js->LookupParam(name); |
| 802 const bool has_parameter = (value != NULL); |
| 803 if (required && !has_parameter) { |
| 804 PrintMissingParamError(js, name); |
| 805 return false; |
| 806 } |
| 807 if (has_parameter && !parameter->Validate(value)) { |
| 808 parameter->PrintError(name, value, js); |
| 809 return false; |
| 810 } |
753 } | 811 } |
754 } | 812 } |
755 return true; | 813 return true; |
756 } | 814 } |
757 | 815 |
758 | 816 |
759 void Service::PostError(const String& method_name, | 817 void Service::PostError(const String& method_name, |
760 const Array& parameter_keys, | 818 const Array& parameter_keys, |
761 const Array& parameter_values, | 819 const Array& parameter_values, |
762 const Instance& reply_port, | 820 const Instance& reply_port, |
763 const Instance& id, | 821 const Instance& id, |
764 const Error& error) { | 822 const Error& error) { |
765 Thread* T = Thread::Current(); | 823 Thread* T = Thread::Current(); |
766 StackZone zone(T); | 824 StackZone zone(T); |
767 HANDLESCOPE(T); | 825 HANDLESCOPE(T); |
768 JSONStream js; | 826 JSONStream js; |
769 js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(), | 827 js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(), |
770 id, method_name, parameter_keys, parameter_values); | 828 id, method_name, parameter_keys, parameter_values); |
771 js.PrintError(kExtensionError, | 829 js.PrintError(kExtensionError, |
772 "Error in extension `%s`: %s", | 830 "Error in extension `%s`: %s", |
773 js.method(), error.ToErrorCString()); | 831 js.method(), error.ToErrorCString()); |
774 js.PostReply(); | 832 js.PostReply(); |
775 } | 833 } |
776 | 834 |
777 | 835 |
778 void Service::InvokeMethod(Isolate* I, const Array& msg) { | 836 void Service::InvokeMethod(Isolate* I, |
| 837 const Array& msg, |
| 838 bool parameters_are_dart_objects) { |
779 Thread* T = Thread::Current(); | 839 Thread* T = Thread::Current(); |
780 ASSERT(I == T->isolate()); | 840 ASSERT(I == T->isolate()); |
781 ASSERT(I != NULL); | 841 ASSERT(I != NULL); |
782 ASSERT(!msg.IsNull()); | 842 ASSERT(!msg.IsNull()); |
783 ASSERT(msg.Length() == 6); | 843 ASSERT(msg.Length() == 6); |
784 | 844 |
785 { | 845 { |
786 StackZone zone(T); | 846 StackZone zone(T); |
787 HANDLESCOPE(T); | 847 HANDLESCOPE(T); |
788 | 848 |
(...skipping 13 matching lines...) Expand all Loading... |
802 ASSERT(!param_keys.IsNull()); | 862 ASSERT(!param_keys.IsNull()); |
803 ASSERT(!param_values.IsNull()); | 863 ASSERT(!param_values.IsNull()); |
804 ASSERT(param_keys.Length() == param_values.Length()); | 864 ASSERT(param_keys.Length() == param_values.Length()); |
805 | 865 |
806 if (!reply_port.IsSendPort()) { | 866 if (!reply_port.IsSendPort()) { |
807 FATAL("SendPort expected."); | 867 FATAL("SendPort expected."); |
808 } | 868 } |
809 | 869 |
810 JSONStream js; | 870 JSONStream js; |
811 js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(), | 871 js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(), |
812 seq, method_name, param_keys, param_values); | 872 seq, |
| 873 method_name, |
| 874 param_keys, |
| 875 param_values, |
| 876 parameters_are_dart_objects); |
813 | 877 |
814 // RPC came in with a custom service id zone. | 878 // RPC came in with a custom service id zone. |
815 const char* id_zone_param = js.LookupParam("_idZone"); | 879 const char* id_zone_param = js.LookupParam("_idZone"); |
816 | 880 |
817 if (id_zone_param != NULL) { | 881 if (id_zone_param != NULL) { |
818 // Override id zone. | 882 // Override id zone. |
819 if (strcmp("default", id_zone_param) == 0) { | 883 if (strcmp("default", id_zone_param) == 0) { |
820 // Ring with eager id allocation. This is the default ring and default | 884 // Ring with eager id allocation. This is the default ring and default |
821 // policy. | 885 // policy. |
822 // Nothing to do. | 886 // Nothing to do. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
882 } | 946 } |
883 } | 947 } |
884 | 948 |
885 | 949 |
886 void Service::HandleRootMessage(const Array& msg_instance) { | 950 void Service::HandleRootMessage(const Array& msg_instance) { |
887 Isolate* isolate = Isolate::Current(); | 951 Isolate* isolate = Isolate::Current(); |
888 InvokeMethod(isolate, msg_instance); | 952 InvokeMethod(isolate, msg_instance); |
889 } | 953 } |
890 | 954 |
891 | 955 |
| 956 void Service::HandleObjectRootMessage(const Array& msg_instance) { |
| 957 Isolate* isolate = Isolate::Current(); |
| 958 InvokeMethod(isolate, msg_instance, true); |
| 959 } |
| 960 |
| 961 |
892 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) { | 962 void Service::HandleIsolateMessage(Isolate* isolate, const Array& msg) { |
893 ASSERT(isolate != NULL); | 963 ASSERT(isolate != NULL); |
894 InvokeMethod(isolate, msg); | 964 InvokeMethod(isolate, msg); |
895 } | 965 } |
896 | 966 |
897 | 967 |
898 void Service::SendEvent(const char* stream_id, | 968 void Service::SendEvent(const char* stream_id, |
899 const char* event_type, | 969 const char* event_type, |
900 const Object& event_message) { | 970 const Object& event_message) { |
901 Thread* thread = Thread::Current(); | 971 Thread* thread = Thread::Current(); |
(...skipping 2974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3876 if (Service::isolate_stream.enabled()) { | 3946 if (Service::isolate_stream.enabled()) { |
3877 ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate); | 3947 ServiceEvent event(isolate, ServiceEvent::kIsolateUpdate); |
3878 Service::HandleEvent(&event); | 3948 Service::HandleEvent(&event); |
3879 } | 3949 } |
3880 PrintSuccess(js); | 3950 PrintSuccess(js); |
3881 return true; | 3951 return true; |
3882 } | 3952 } |
3883 | 3953 |
3884 | 3954 |
3885 static const MethodParameter* set_vm_name_params[] = { | 3955 static const MethodParameter* set_vm_name_params[] = { |
| 3956 NO_ISOLATE_PARAMETER, |
3886 new MethodParameter("name", true), | 3957 new MethodParameter("name", true), |
3887 NULL, | 3958 NULL, |
3888 }; | 3959 }; |
3889 | 3960 |
3890 | 3961 |
3891 static bool SetVMName(Thread* thread, JSONStream* js) { | 3962 static bool SetVMName(Thread* thread, JSONStream* js) { |
3892 const char* name_param = js->LookupParam("name"); | 3963 const char* name_param = js->LookupParam("name"); |
3893 free(vm_name); | 3964 free(vm_name); |
3894 vm_name = strdup(name_param); | 3965 vm_name = strdup(name_param); |
3895 if (Service::vm_stream.enabled()) { | 3966 if (Service::vm_stream.enabled()) { |
(...skipping 29 matching lines...) Expand all Loading... |
3925 return true; | 3996 return true; |
3926 } | 3997 } |
3927 const Class& cls = Class::Handle(GetClassForId(isolate, cid)); | 3998 const Class& cls = Class::Handle(GetClassForId(isolate, cid)); |
3928 ASSERT(!cls.IsNull()); | 3999 ASSERT(!cls.IsNull()); |
3929 cls.SetTraceAllocation(enable); | 4000 cls.SetTraceAllocation(enable); |
3930 PrintSuccess(js); | 4001 PrintSuccess(js); |
3931 return true; | 4002 return true; |
3932 } | 4003 } |
3933 | 4004 |
3934 | 4005 |
| 4006 static const MethodParameter* create_dev_fs_params[] = { |
| 4007 NO_ISOLATE_PARAMETER, |
| 4008 new DartStringParameter("fsName", true), |
| 4009 NULL, |
| 4010 }; |
| 4011 |
| 4012 |
| 4013 static bool CreateDevFS(Thread* thread, JSONStream* js) { |
| 4014 const String& fs_name = |
| 4015 String::Handle(String::RawCast(js->LookupObjectParam("fsName"))); |
| 4016 DevFS::CreateFileSystem(js, fs_name); |
| 4017 return true; |
| 4018 } |
| 4019 |
| 4020 |
| 4021 static const MethodParameter* delete_dev_fs_params[] = { |
| 4022 NO_ISOLATE_PARAMETER, |
| 4023 new DartStringParameter("fsName", true), |
| 4024 NULL, |
| 4025 }; |
| 4026 |
| 4027 |
| 4028 static bool DeleteDevFS(Thread* thread, JSONStream* js) { |
| 4029 const String& fs_name = |
| 4030 String::Handle(String::RawCast(js->LookupObjectParam("fsName"))); |
| 4031 DevFS::DeleteFileSystem(js, fs_name); |
| 4032 return true; |
| 4033 } |
| 4034 |
| 4035 |
| 4036 static const MethodParameter* list_dev_fs_params[] = { |
| 4037 NO_ISOLATE_PARAMETER, |
| 4038 NULL, |
| 4039 }; |
| 4040 |
| 4041 |
| 4042 static bool ListDevFS(Thread* thread, JSONStream* js) { |
| 4043 DevFS::ListFileSystems(js); |
| 4044 return true; |
| 4045 } |
| 4046 |
| 4047 |
| 4048 static const MethodParameter* write_dev_fs_file_params[] = { |
| 4049 NO_ISOLATE_PARAMETER, |
| 4050 new DartStringParameter("fsName", true), |
| 4051 new DartStringParameter("path", true), |
| 4052 new DartStringParameter("fileContents", true), |
| 4053 NULL, |
| 4054 }; |
| 4055 |
| 4056 |
| 4057 static bool WriteDevFSFile(Thread* thread, JSONStream* js) { |
| 4058 const String& fs_name = |
| 4059 String::Handle(String::RawCast(js->LookupObjectParam("fsName"))); |
| 4060 const String& path = |
| 4061 String::Handle(String::RawCast(js->LookupObjectParam("path"))); |
| 4062 const String& file_contents = |
| 4063 String::Handle(String::RawCast(js->LookupObjectParam("fileContents"))); |
| 4064 DevFS::WriteFile(js, fs_name, path, file_contents); |
| 4065 return true; |
| 4066 } |
| 4067 |
| 4068 |
| 4069 static const MethodParameter* write_dev_fs_files_params[] = { |
| 4070 NO_ISOLATE_PARAMETER, |
| 4071 new DartStringParameter("fsName", true), |
| 4072 new DartListParameter("files", true), |
| 4073 NULL, |
| 4074 }; |
| 4075 |
| 4076 |
| 4077 static bool WriteDevFSFiles(Thread* thread, JSONStream* js) { |
| 4078 const String& fs_name = |
| 4079 String::Handle(String::RawCast(js->LookupObjectParam("fsName"))); |
| 4080 Array& files = Array::Handle(); |
| 4081 const Object& files_param = Object::Handle(js->LookupObjectParam("files")); |
| 4082 if (files_param.IsArray()) { |
| 4083 files ^= files_param.raw(); |
| 4084 } else { |
| 4085 ASSERT(files_param.IsGrowableObjectArray()); |
| 4086 files ^= GrowableObjectArray::Cast(files_param).data(); |
| 4087 } |
| 4088 ASSERT(!files.IsNull()); |
| 4089 DevFS::WriteFiles(js, fs_name, files); |
| 4090 return true; |
| 4091 } |
| 4092 |
| 4093 |
| 4094 static const MethodParameter* read_dev_fs_file_params[] = { |
| 4095 NO_ISOLATE_PARAMETER, |
| 4096 new DartStringParameter("fsName", true), |
| 4097 new DartStringParameter("path", true), |
| 4098 NULL, |
| 4099 }; |
| 4100 |
| 4101 |
| 4102 static bool ReadDevFSFile(Thread* thread, JSONStream* js) { |
| 4103 const String& fs_name = |
| 4104 String::Handle(String::RawCast(js->LookupObjectParam("fsName"))); |
| 4105 const String& path = |
| 4106 String::Handle(String::RawCast(js->LookupObjectParam("path"))); |
| 4107 DevFS::ReadFile(js, fs_name, path); |
| 4108 return true; |
| 4109 } |
| 4110 |
| 4111 |
| 4112 static const MethodParameter* list_dev_fs_files_params[] = { |
| 4113 NO_ISOLATE_PARAMETER, |
| 4114 new DartStringParameter("fsName", true), |
| 4115 NULL, |
| 4116 }; |
| 4117 |
| 4118 |
| 4119 static bool ListDevFSFiles(Thread* thread, JSONStream* js) { |
| 4120 const String& fs_name = |
| 4121 String::Handle(String::RawCast(js->LookupObjectParam("fsName"))); |
| 4122 DevFS::ListFiles(js, fs_name); |
| 4123 return true; |
| 4124 } |
| 4125 |
| 4126 |
3935 static const ServiceMethodDescriptor service_methods_[] = { | 4127 static const ServiceMethodDescriptor service_methods_[] = { |
3936 { "_dumpIdZone", DumpIdZone, NULL }, | 4128 { "_dumpIdZone", DumpIdZone, NULL }, |
3937 { "_echo", Echo, | 4129 { "_echo", Echo, |
3938 NULL }, | 4130 NULL }, |
3939 { "_respondWithMalformedJson", RespondWithMalformedJson, | 4131 { "_respondWithMalformedJson", RespondWithMalformedJson, |
3940 NULL }, | 4132 NULL }, |
3941 { "_respondWithMalformedObject", RespondWithMalformedObject, | 4133 { "_respondWithMalformedObject", RespondWithMalformedObject, |
3942 NULL }, | 4134 NULL }, |
3943 { "_triggerEchoEvent", TriggerEchoEvent, | 4135 { "_triggerEchoEvent", TriggerEchoEvent, |
3944 NULL }, | 4136 NULL }, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4037 { "setLibraryDebuggable", SetLibraryDebuggable, | 4229 { "setLibraryDebuggable", SetLibraryDebuggable, |
4038 set_library_debuggable_params }, | 4230 set_library_debuggable_params }, |
4039 { "setName", SetName, | 4231 { "setName", SetName, |
4040 set_name_params }, | 4232 set_name_params }, |
4041 { "_setTraceClassAllocation", SetTraceClassAllocation, | 4233 { "_setTraceClassAllocation", SetTraceClassAllocation, |
4042 set_trace_class_allocation_params }, | 4234 set_trace_class_allocation_params }, |
4043 { "setVMName", SetVMName, | 4235 { "setVMName", SetVMName, |
4044 set_vm_name_params }, | 4236 set_vm_name_params }, |
4045 { "_setVMTimelineFlags", SetVMTimelineFlags, | 4237 { "_setVMTimelineFlags", SetVMTimelineFlags, |
4046 set_vm_timeline_flags_params }, | 4238 set_vm_timeline_flags_params }, |
| 4239 { "_createDevFS", CreateDevFS, |
| 4240 create_dev_fs_params }, |
| 4241 { "_deleteDevFS", DeleteDevFS, |
| 4242 delete_dev_fs_params }, |
| 4243 { "_listDevFS", ListDevFS, |
| 4244 list_dev_fs_params }, |
| 4245 { "_writeDevFSFile", WriteDevFSFile, |
| 4246 write_dev_fs_file_params }, |
| 4247 { "_writeDevFSFiles", WriteDevFSFiles, |
| 4248 write_dev_fs_files_params }, |
| 4249 { "_readDevFSFile", ReadDevFSFile, |
| 4250 read_dev_fs_file_params }, |
| 4251 { "_listDevFSFiles", ListDevFSFiles, |
| 4252 list_dev_fs_files_params }, |
4047 }; | 4253 }; |
4048 | 4254 |
4049 | 4255 |
4050 const ServiceMethodDescriptor* FindMethod(const char* method_name) { | 4256 const ServiceMethodDescriptor* FindMethod(const char* method_name) { |
4051 intptr_t num_methods = sizeof(service_methods_) / | 4257 intptr_t num_methods = sizeof(service_methods_) / |
4052 sizeof(service_methods_[0]); | 4258 sizeof(service_methods_[0]); |
4053 for (intptr_t i = 0; i < num_methods; i++) { | 4259 for (intptr_t i = 0; i < num_methods; i++) { |
4054 const ServiceMethodDescriptor& method = service_methods_[i]; | 4260 const ServiceMethodDescriptor& method = service_methods_[i]; |
4055 if (strcmp(method_name, method.name) == 0) { | 4261 if (strcmp(method_name, method.name) == 0) { |
4056 return &method; | 4262 return &method; |
4057 } | 4263 } |
4058 } | 4264 } |
4059 return NULL; | 4265 return NULL; |
4060 } | 4266 } |
4061 | 4267 |
4062 #endif // !PRODUCT | 4268 #endif // !PRODUCT |
4063 | 4269 |
4064 } // namespace dart | 4270 } // namespace dart |
OLD | NEW |