[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]