Сабж. Имеем такой самописный 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() происходит привязка совсем не к тому контексту, к какому надо. К какому контексту в действительности происходит привязка - не знаю.
Например, в чистом javascript результат отработки

Выделить код

Код:

var ns={};
var obj=(function()
{
    this.foo="bar";
    this.toString=function(){ return "["+this.foo+"]";};
}).apply(ns);
utils.dumpMembers(ns);

будет таким:

foo = bar
------------------------
toString = function (){...}

Если же попробовать такую же функцию передать в testApply() компонента, то наша dumpMembers() не выведет ничего - в top-level нашего контекста не появляется переменная foo и метод toString, создаваемые в функции, контекст которой мы привязываем. И ошибка точно не в утилитном методе дампа содержимого - собственно, мне и хотелось бы знать, в чем моя ошибка заключается. Пока я нашел такой выход из ситуации (для меня критична правильная привязка контекста): экземпляр компонента в его же конструкторе вешаю на wrappedJSObject, и далее через Сomponents.classes["..."].getService().wrappedJSObject получаю чистую javascript-реализацию компонента (но с сохранением XPCOM-специфики, а именно - singletone-поведения). И реализация эта ведет себя вполне предсказуемо, и так, как надо. Но дело в том, что компонент предполагается использовать с достаточно частыми обращениями к его свойствам/методам (и в основном при старте FF), и для таких случаев документация рекомендует в целях оптимизации быстродействия использовать строго типизированные интерфейсы - т.е. вариант без wrappedJSObject имеет бинарную часть в виде откомпилированного в .xpt idl-кода интерфейса. В документации никаких разъяснений по поводу вышеизложенного я не обнаружил.