ruby-changes:6408
From: shyouhei <ko1@a...>
Date: Mon, 7 Jul 2008 12:10:17 +0900 (JST)
Subject: [ruby-changes:6408] Ruby:r17924 (ruby_1_8_6): merge revision(s) 17827,17846:17848:
shyouhei 2008-07-07 12:10:04 +0900 (Mon, 07 Jul 2008) New Revision: 17924 Added files: branches/ruby_1_8_6/ext/win32ole/tests/test_win32ole_event.rb Removed files: branches/ruby_1_8_6/ext/win32ole/tests/testOLEEVENT.rb Modified files: branches/ruby_1_8_6/ChangeLog branches/ruby_1_8_6/ext/win32ole/tests/testWIN32OLE.rb branches/ruby_1_8_6/ext/win32ole/tests/testall.rb branches/ruby_1_8_6/ext/win32ole/win32ole.c branches/ruby_1_8_6/gc.c branches/ruby_1_8_6/intern.h branches/ruby_1_8_6/version.h Log: merge revision(s) 17827,17846:17848: * gc.c: add rb_during_gc(). based on a patch from arton <artonx AT yahoo.co.jp> at [ruby-dev:35313]. * intern.h: ditto. * ext/win32ole/win32ole.c: avoid creating Ruby object during GC. thanks to arton <artonx AT yahoo.co.jp>. [ruby-dev:35313] * ext/win32ole/tests: add test_win32ole_event.rb, remove testOLEEVENT.rb * ext/win32ole/tests/testWIN32OLE.rb(test_convert_bignum): fix test. http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=17924 Index: ruby_1_8_6/intern.h =================================================================== --- ruby_1_8_6/intern.h (revision 17923) +++ ruby_1_8_6/intern.h (revision 17924) @@ -239,6 +239,7 @@ NORETURN(void rb_memerror __((void))); int ruby_stack_check _((void)); int ruby_stack_length _((VALUE**)); +int rb_during_gc _((void)); char *rb_source_filename _((const char*)); void rb_gc_mark_locations _((VALUE*, VALUE*)); void rb_mark_tbl _((struct st_table*)); Index: ruby_1_8_6/ext/win32ole/tests/testOLEEVENT.rb =================================================================== --- ruby_1_8_6/ext/win32ole/tests/testOLEEVENT.rb (revision 17923) +++ ruby_1_8_6/ext/win32ole/tests/testOLEEVENT.rb (revision 17924) @@ -1,91 +0,0 @@ -require 'rubyunit' -require 'win32ole' - -class TestWIN32OLE_EVENT < RUNIT::TestCase - def setup - @excel = WIN32OLE.new("Excel.Application") - @excel.visible = true - @event = "" - @event2 = "" - end - def test_on_event - book = @excel.workbooks.Add - value = "" - begin - ev = WIN32OLE_EVENT.new(book, 'WorkbookEvents') - ev.on_event('SheetChange'){|arg1, arg2| - begin - value = arg1.value - rescue - value = $!.message - end - } - book.Worksheets(1).Range("A1").value = "OK" - ensure - book.saved = true - end - assert_equal("OK", value) - end - - def handler1 - @event += "handler1" - end - def handler2 - @event += "handler2" - end - - def handler3 - @event += "handler3" - end - - def test_on_event2 - book = @excel.workbooks.Add - begin - ev = WIN32OLE_EVENT.new(book, 'WorkbookEvents') - ev.on_event('SheetChange'){|arg1, arg2| - handler1 - } - ev.on_event('SheetChange'){|arg1, arg2| - handler2 - } - book.Worksheets(1).Range("A1").value = "OK" - ensure - book.saved = true - end - assert_equal("handler2", @event) - end - - def test_on_event3 - book = @excel.workbooks.Add - begin - ev = WIN32OLE_EVENT.new(book, 'WorkbookEvents') - ev.on_event{ handler1 } - ev.on_event{ handler2 } - book.Worksheets(1).Range("A1").value = "OK" - ensure - book.saved = true - end - assert_equal("handler2", @event) - end - - def test_on_event4 - book = @excel.workbooks.Add - begin - ev = WIN32OLE_EVENT.new(book, 'WorkbookEvents') - ev.on_event{ handler1 } - ev.on_event{ handler2 } - ev.on_event('SheetChange'){|arg1, arg2| handler3 } - book.Worksheets(1).Range("A1").value = "OK" - ensure - book.saved = true - end - assert_equal("handler3", @event) - end - - def teardown - @excel.quit - @excel = nil - GC.start - end -end - Index: ruby_1_8_6/ext/win32ole/tests/testWIN32OLE.rb =================================================================== --- ruby_1_8_6/ext/win32ole/tests/testWIN32OLE.rb (revision 17923) +++ ruby_1_8_6/ext/win32ole/tests/testWIN32OLE.rb (revision 17924) @@ -156,7 +156,8 @@ sheet.range("A3").value = "=A1*10 + 9" assert_equal(9999999999, sheet.range("A2").value) assert_equal(9999999999, sheet.range("A3").value) - + sheet.range("A4").value = "2008/03/04" + assert_equal("2008/03/04 00:00:00", sheet.range("A4").value) ensure book.saved = true end Index: ruby_1_8_6/ext/win32ole/tests/test_win32ole_event.rb =================================================================== --- ruby_1_8_6/ext/win32ole/tests/test_win32ole_event.rb (revision 0) +++ ruby_1_8_6/ext/win32ole/tests/test_win32ole_event.rb (revision 17924) @@ -0,0 +1,133 @@ +begin + require 'win32ole' +rescue LoadError +end +require 'test/unit' + +if defined?(WIN32OLE_EVENT) + class TestWIN32OLE_EVENT < Test::Unit::TestCase + def create_temp_html + fso = WIN32OLE.new('Scripting.FileSystemObject') + dummy_file = fso.GetTempName + ".html" + cfolder = fso.getFolder(".") + f = cfolder.CreateTextFile(dummy_file) + f.writeLine("<html><body>This is test HTML file for Win32OLE.</body></html>") + f.close + dummy_path = cfolder.path + "\\" + dummy_file + dummy_path + end + + def setup + @ie = WIN32OLE.new("InternetExplorer.Application") + @ie.visible = true + @event = "" + @event2 = "" + @event3 = "" + @f = create_temp_html + end + + def default_handler(event, *args) + @event += event + end + + def test_on_event + ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents') + ev.on_event {|*args| default_handler(*args)} + @ie.navigate("file:///#{@f}") + while @ie.busy + WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents') + GC.start + sleep 0.1 + end + assert_match(/BeforeNavigate/, @event) + assert_match(/NavigateComplete/, @event) + end + + def test_on_event2 + ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents') + ev.on_event('BeforeNavigate') {|*args| handler1} + ev.on_event('BeforeNavigate') {|*args| handler2} + @ie.navigate("file:///#{@f}") + while @ie.busy + sleep 0.1 + end + assert_equal("handler2", @event2) + end + + def test_on_event3 + ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents') + ev.on_event {|*args| handler1} + ev.on_event {|*args| handler2} + @ie.navigate("file:///#{@f}") + while @ie.busy + sleep 0.1 + end + assert_equal("handler2", @event2) + end + + def test_on_event4 + ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents') + ev.on_event{|*args| handler1} + ev.on_event{|*args| handler2} + ev.on_event('NavigateComplete'){|*args| handler3(*args)} + @ie.navigate("file:///#{@f}") + while @ie.busy + sleep 0.1 + end + assert(@event3!="") + assert("handler2", @event2) + end + + def test_on_event5 + ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents') + ev.on_event {|*args| default_handler(*args)} + ev.on_event('NavigateComplete'){|*args| handler3(*args)} + @ie.navigate("file:///#{@f}") + while @ie.busy + sleep 0.1 + end + assert_match(/BeforeNavigate/, @event) + assert(/NavigateComplete/ !~ @event) + assert(@event!="") + end + + def test_unadvise + ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents') + ev.on_event {|*args| default_handler(*args)} + @ie.navigate("file:///#{@f}") + while @ie.busy + sleep 0.1 + end + assert_match(/BeforeNavigate/, @event) + ev.unadvise + @event = "" + @ie.navigate("file:///#{@f}") + while @ie.busy + sleep 0.1 + end + assert_equal("", @event); + assert_raise(WIN32OLERuntimeError) { + ev.on_event {|*args| default_handler(*args)} + } + end + + def handler1 + @event2 = "handler1" + end + + def handler2 + @event2 = "handler2" + end + + def handler3(url) + @event3 += url + end + + def teardown + @ie.quit + @ie = nil + File.unlink(@f) + GC.start + end + end +end Index: ruby_1_8_6/ext/win32ole/tests/testall.rb =================================================================== --- ruby_1_8_6/ext/win32ole/tests/testall.rb (revision 17923) +++ ruby_1_8_6/ext/win32ole/tests/testall.rb (revision 17924) @@ -12,4 +12,5 @@ require "test_ole_methods.rb" require "test_propertyputref.rb" require "test_word.rb" +require "test_win32ole_event.rb" # require "testOLEEVENT" Index: ruby_1_8_6/ext/win32ole/win32ole.c =================================================================== --- ruby_1_8_6/ext/win32ole/win32ole.c (revision 17923) +++ ruby_1_8_6/ext/win32ole/win32ole.c (revision 17924) @@ -29,8 +29,8 @@ #include <varargs.h> #define va_init_list(a,b) va_start(a) #endif +#include <objidl.h> - #define DOUT fprintf(stderr,"[%d]\n",__LINE__) #define DOUTS(x) fprintf(stderr,"[%d]:" #x "=%s\n",__LINE__,x) #define DOUTMSG(x) fprintf(stderr, "[%d]:" #x "\n",__LINE__) @@ -79,7 +79,7 @@ #define WC2VSTR(x) ole_wc2vstr((x), TRUE) -#define WIN32OLE_VERSION "0.7.5" +#define WIN32OLE_VERSION "0.7.6" typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX) (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*); @@ -157,6 +157,9 @@ static IDispatchVtbl com_vtbl; static UINT cWIN32OLE_cp = CP_ACP; static VARTYPE g_nil_to = VT_ERROR; +static IMessageFilterVtbl message_filter; +static IMessageFilter imessage_filter = { &message_filter }; +static IMessageFilter* previous_filter; struct oledata { IDispatch *pDispatch; @@ -203,6 +206,101 @@ static VALUE ole_variant2val(VARIANT*); static void ole_val2variant(VALUE, VARIANT*); +static HRESULT (STDMETHODCALLTYPE mf_QueryInterface)( + IMessageFilter __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) +{ + if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0 + || MEMCMP(riid, &IID_IMessageFilter, GUID, 1) == 0) + { + *ppvObject = &message_filter; + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG (STDMETHODCALLTYPE mf_AddRef)( + IMessageFilter __RPC_FAR * This) +{ + return 1; +} + +static ULONG (STDMETHODCALLTYPE mf_Release)( + IMessageFilter __RPC_FAR * This) +{ + return 1; +} + +static DWORD (STDMETHODCALLTYPE mf_HandleInComingCall)( + IMessageFilter __RPC_FAR * pThis, + DWORD dwCallType, //Type of incoming call + HTASK threadIDCaller, //Task handle calling this task + DWORD dwTickCount, //Elapsed tick count + LPINTERFACEINFO lpInterfaceInfo //Pointer to INTERFACEINFO structure + ) +{ +#ifdef DEBUG_MESSAGEFILTER + printf("incoming %08X, %08X, %d\n", dwCallType, threadIDCaller, dwTickCount); + fflush(stdout); +#endif + switch (dwCallType) + { + case CALLTYPE_ASYNC: + case CALLTYPE_TOPLEVEL_CALLPENDING: + case CALLTYPE_ASYNC_CALLPENDING: + if (rb_during_gc()) { + return SERVERCALL_RETRYLATER; + } + break; + default: + break; + } + if (previous_filter) { + return previous_filter->lpVtbl->HandleInComingCall(previous_filter, + dwCallType, + threadIDCaller, + dwTickCount, + lpInterfaceInfo); + } + return SERVERCALL_ISHANDLED; +} + +static DWORD (STDMETHODCALLTYPE mf_RetryRejectedCall)( + IMessageFilter* pThis, + HTASK threadIDCallee, //Server task handle + DWORD dwTickCount, //Elapsed tick count + DWORD dwRejectType //Returned rejection message + ) +{ + if (previous_filter) { + return previous_filter->lpVtbl->RetryRejectedCall(previous_filter, + threadIDCallee, + dwTickCount, + dwRejectType); + } + return 1000; +} + +static DWORD (STDMETHODCALLTYPE mf_MessagePending)( + IMessageFilter* pThis, + HTASK threadIDCallee, //Called applications task handle + DWORD dwTickCount, //Elapsed tick count + DWORD dwPendingType //Call type + ) +{ + if (rb_during_gc()) { + return PENDINGMSG_WAITNOPROCESS; + } + if (previous_filter) { + return previous_filter->lpVtbl->MessagePending(previous_filter, + threadIDCallee, + dwTickCount, + dwPendingType); + } + return PENDINGMSG_WAITNOPROCESS; +} + typedef struct _Win32OLEIDispatch { IDispatch dispatch; @@ -625,6 +723,11 @@ /* atexit((void (*)(void))ole_uninitialize); */ + hr = CoRegisterMessageFilter(&imessage_filter, &previous_filter); + if(FAILED(hr)) { + previous_filter = NULL; + ole_raise(hr, rb_eRuntimeError, "fail: install OLE MessageFilter"); + } } } @@ -6135,6 +6238,14 @@ com_vtbl.GetTypeInfo = GetTypeInfo; com_vtbl.GetIDsOfNames = GetIDsOfNames; com_vtbl.Invoke = Invoke; + + message_filter.QueryInterface = mf_QueryInterface; + message_filter.AddRef = mf_AddRef; + message_filter.Release = mf_Release; + message_filter.HandleInComingCall = mf_HandleInComingCall; + message_filter.RetryRejectedCall = mf_RetryRejectedCall; + message_filter.MessagePending = mf_MessagePending; + com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable()); cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject); Index: ruby_1_8_6/ChangeLog =================================================================== --- ruby_1_8_6/ChangeLog (revision 17923) +++ ruby_1_8_6/ChangeLog (revision 17924) @@ -1,3 +1,21 @@ +Mon Jul 7 12:07:28 2008 Masaki Suketa <masaki.suketa@n...> + + * ext/win32ole/win32ole.c: avoid creating Ruby object during + GC. thanks to arton <artonx AT yahoo.co.jp>. [ruby-dev:35313] + + * ext/win32ole/tests: add test_win32ole_event.rb, remove + testOLEEVENT.rb + + * ext/win32ole/tests/testWIN32OLE.rb(test_convert_bignum): + fix test. + +Mon Jul 7 12:07:28 2008 Masaki Suketa <masaki.suketa@n...> + + * gc.c: add rb_during_gc(). based on a patch from arton <artonx AT + yahoo.co.jp> at [ruby-dev:35313]. + + * intern.h: ditto. + Thu Jul 3 17:15:04 2008 URABE Shyouhei <shyouhei@r...> * win32/win32.c: revert r17290, requested by NAKAMURA Usaku Index: ruby_1_8_6/version.h =================================================================== --- ruby_1_8_6/version.h (revision 17923) +++ ruby_1_8_6/version.h (revision 17924) @@ -2,7 +2,7 @@ #define RUBY_RELEASE_DATE "2008-07-07" #define RUBY_VERSION_CODE 186 #define RUBY_RELEASE_CODE 20080707 -#define RUBY_PATCHLEVEL 266 +#define RUBY_PATCHLEVEL 267 #define RUBY_VERSION_MAJOR 1 #define RUBY_VERSION_MINOR 8 Index: ruby_1_8_6/gc.c =================================================================== --- ruby_1_8_6/gc.c (revision 17923) +++ ruby_1_8_6/gc.c (revision 17924) @@ -373,6 +373,12 @@ } #define RANY(o) ((RVALUE*)(o)) +int +rb_during_gc() +{ + return during_gc; +} + VALUE rb_newobj() { -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/