>Форум Mozilla Россия http://forum.mozilla-russia.org/index.php >Разработка http://forum.mozilla-russia.org/viewforum.php?id=18 >JS XPCOM: странности с apply(thisObj) на типизированных параметрах http://forum.mozilla-russia.org/viewtopic.php?id=50193 |
hydrolizer > 13-06-2011 08:46:56 |
Сабж. Имеем такой самописный XPCOM-компонент (ниже приведенный код - тестовый, в реальности всё несколько сложнее, но суть вопроса от от этого не изменяется): Выделить код Код:#include "nsISupports.idl" interface nsIFoo; [function, scriptable, uuid (5bfd9830-5604-40cb-8891-20875f73bc5f)] interface nsIFooMethod : nsISupports { void bar(); }; [scriptable, uuid(d551ecc5-4657-4ba1-922d-c4a4c5b38a7d)] interface nsIFoo : nsISupports { void testApply(in nsIFooMethod aMethod); }; Реализация компонента: Выделить код Код:const { classes: Cc, interfaces: Ci, utils: Cu, Constructor: CC } = Components; Cu.import("resource://foo/utils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); function Foo() {} Foo.prototype= { classDescription: "Foo XPCOM", contractID: "@cycledlm/foo-service;1", classID: Components.ID("{027bf398-cacb-4615-84fc-ad4fe3f677b5}"), QueryInterface: XPCOMUtils.generateQI([Ci.nsIFoo]), applyContext: null, // некоторые действия по формированию applyContext .... testApply: function(aMethod) { aMethod.bar.apply(this.applyContext); // самописный утилитный метод для // вывода внутреннего содержимого объекта utils.dumpMembers(this.applyContext); } }; const NSGetFactory=XPCOMUtils.generateNSGetFactory([Foo]); и далее в коде вызываем метод: Выделить код Код:Components.classes["@cycledlm/foo-service;1"] .getService(Components.interfaces.nsIFoo) .testApply(function(){...}); Вроде бы всё в порядке - передаваемый метод отрабатывает. Только вот при apply() происходит привязка совсем не к тому контексту, к какому надо. К какому контексту в действительности происходит привязка - не знаю. Выделить код Код:var ns={}; var obj=(function() { this.foo="bar"; this.toString=function(){ return "["+this.foo+"]";}; }).apply(ns); utils.dumpMembers(ns); будет таким: foo = bar Если же попробовать такую же функцию передать в testApply() компонента, то наша dumpMembers() не выведет ничего - в top-level нашего контекста не появляется переменная foo и метод toString, создаваемые в функции, контекст которой мы привязываем. И ошибка точно не в утилитном методе дампа содержимого - собственно, мне и хотелось бы знать, в чем моя ошибка заключается. Пока я нашел такой выход из ситуации (для меня критична правильная привязка контекста): экземпляр компонента в его же конструкторе вешаю на wrappedJSObject, и далее через Сomponents.classes["..."].getService().wrappedJSObject получаю чистую javascript-реализацию компонента (но с сохранением XPCOM-специфики, а именно - singletone-поведения). И реализация эта ведет себя вполне предсказуемо, и так, как надо. Но дело в том, что компонент предполагается использовать с достаточно частыми обращениями к его свойствам/методам (и в основном при старте FF), и для таких случаев документация рекомендует в целях оптимизации быстродействия использовать строго типизированные интерфейсы - т.е. вариант без wrappedJSObject имеет бинарную часть в виде откомпилированного в .xpt idl-кода интерфейса. В документации никаких разъяснений по поводу вышеизложенного я не обнаружил. |