<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[mozilla - JavaScripting Blog]]></title><description><![CDATA[BLOG]]></description><link>https://blog.javascripting.com/</link><image><url>https://blog.javascripting.com/favicon.png</url><title>mozilla - JavaScripting Blog</title><link>https://blog.javascripting.com/</link></image><generator>Ghost 6.36</generator><lastBuildDate>Thu, 07 May 2026 16:02:54 GMT</lastBuildDate><atom:link href="https://blog.javascripting.com/tag/mozilla/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[DOM Window Wrapper Update]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>A quick update to my previous post about <a href="https://blog.salsitasoft.com/2014/05/19/wrapping-the-dom-window-object/?ref=blog.javascripting.com">creating a DOM window wrapper</a>. My colleague <a href="https://github.com/realyze?ref=blog.javascripting.com">Tomas</a> pointed out that <a href="http://browserify.org/?ref=blog.javascripting.com">Browserify</a> breaks if it is running inside the wrapper, due <a href="https://github.com/defunctzombie/node-process/blob/aac49362a19942d1f8b2fa931b005e57da7b8e14/browser.js?ref=blog.javascripting.com#L20">some code</a> in the shim it uses&#xA0;for the NodeJS process module. The code compares the source of an event</p>]]></description><link>https://blog.javascripting.com/2014/05/27/dom-window-wrapper-update/</link><guid isPermaLink="false">5dc95d688e8ace0018e92865</guid><category><![CDATA[mozilla]]></category><dc:creator><![CDATA[Matthew Gertner]]></dc:creator><pubDate>Tue, 27 May 2014 20:06:48 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>A quick update to my previous post about <a href="https://blog.salsitasoft.com/2014/05/19/wrapping-the-dom-window-object/?ref=blog.javascripting.com">creating a DOM window wrapper</a>. My colleague <a href="https://github.com/realyze?ref=blog.javascripting.com">Tomas</a> pointed out that <a href="http://browserify.org/?ref=blog.javascripting.com">Browserify</a> breaks if it is running inside the wrapper, due <a href="https://github.com/defunctzombie/node-process/blob/aac49362a19942d1f8b2fa931b005e57da7b8e14/browser.js?ref=blog.javascripting.com#L20">some code</a> in the shim it uses&#xA0;for the NodeJS process module. The code compares the source of an event with the window. In our case the <code>window</code> object has been replaced by our wrapper, so the comparison fails and breakage ensues.</p>
<p>To fix this, we need a special version of addEventListener:</p>
<pre><code class="language-language-javascript">wrapper.addEventListener = function(type, listener, useCapture) {
  if (&apos;message&apos; === type) {
    listener = (function(originalListener) {
      return function(event) {
        var newEvent = document.createEvent(&apos;MessageEvent&apos;);
        newEvent.initMessageEvent(
          &apos;message&apos;,
          event.bubbles,
          event.cancelable,
          event.data,
          event.origin,
          event.lastEventId,
          wrapper,
          event.ports
        );
        originalListener(newEvent);
      }
    })(listener);
  }
  window.addEventListener.call(window, type, listener, useCapture);
};
</code></pre>
<p>We&#x2019;re doing our best to avoid exposing&#xA0;the real window to the content script environment, and this fix deals&#xA0;with one particular area where the real window was still leaking&#xA0;through. There are certainly mainly more APIs that will need to be adapted for other use cases, and we&#x2019;d love to hear about any you stumble upon. After a few years of edge cases the wrapper may end up looking like jQuery, but with this adaptation it appears to be holding its own against our current requirements.</p>
<p></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Wrapping the DOM Window Object]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In order to enable <a href="http://www.kitt.com/?ref=blog.javascripting.com">Kitt</a>, our iPhone web browser, to run browser extensions, we needed a way to run content scripts in a webpage. In Chrome, content scripts are run in a sandbox to prevent the two contexts from interfering with each other.&#xA0;They share only the <code>window</code> object.</p>]]></description><link>https://blog.javascripting.com/2014/05/19/wrapping-the-dom-window-object/</link><guid isPermaLink="false">5dc95d688e8ace0018e92864</guid><category><![CDATA[mozilla]]></category><dc:creator><![CDATA[Matthew Gertner]]></dc:creator><pubDate>Mon, 19 May 2014 20:04:27 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>In order to enable <a href="http://www.kitt.com/?ref=blog.javascripting.com">Kitt</a>, our iPhone web browser, to run browser extensions, we needed a way to run content scripts in a webpage. In Chrome, content scripts are run in a sandbox to prevent the two contexts from interfering with each other.&#xA0;They share only the <code>window</code> object. Although there are <a href="http://www.bignerdranch.com/blog/javascriptcore-and-ios-7/?ref=blog.javascripting.com">tantalizing signs</a> that something similar might be possible on iOS 7, we weren&#x2019;t sure whether this would be acceptable to Apple,&#xA0;so&#xA0;we decided to inject content scripts straight into the webpage and isolate&#xA0;them using closures.</p>
<p>This has been surprisingly successful, but we did start to run into problems when a&#xA0;content script&#xA0;uses jQuery on a webpage that also uses jQuery. The problem is the shared DOM. jQuery (and many other JavaScript frameworks) create a global symbol by hanging a new property off the window object. Since the window is shared, the&#xA0;<code>window.$</code>&#xA0;might get overwritten. This doesn&#x2019;t happen in Chrome because the DOM window isn&#x2019;t really shared with the content scripts. Instead, a wrapper is used to isolate the JavaScript contexts so they only see their own&#xA0;expando properties. In this way each&#xA0;context&#xA0;can have a different window.<code>$</code> property.</p>
<p>At first glance, writing a complete wrapper that explicitly wraps every window property seemed like a big effort, so we first tried to solve the immediate problem of jQuery conflicts in the easiest manner possible (some might call this laziness but I prefer to think of it as &#x201C;proof of concept&#x201D;):</p>
<pre><code class="language-language-javascript">var wrapper = Object.create(window);
(function(window) {
  // content script
})(wrapper);
</code></pre>
<p>By using <code>Object.create</code>&#xA0;we get a wrapper whose prototype is the original window. The content scripts can still see the window&#x2019;s expando properties, unless it overrides them, but the reverse is not true. Mission accomplished: loading jQuery into a content script will not mess up the native jQuery of the webpage. Just one problem: when we took this super lightweight wrapper for a test drive, we got an &#x201C;Illegal invocation&#x201D; error every time we tried to call one of its methods. Turns out that when you call methods on a DOM window, the <code>this</code> pointer <a href="http://stackoverflow.com/questions/9677985/uncaught-typeerror-illegal-invocation-in-chrome?ref=blog.javascripting.com">has to point at the actual window object</a>. Attempt number two looked like this:</p>
<pre><code class="language-language-javascript">var wrapper = Object.create(window);
for (var prop in window) {
  if (typeof(window[prop]) === &apos;function&apos;)  {
    (function(prop) {
      wrapper[prop] = function() { return window[prop].apply(window, arguments); }
    })(prop);
  }
}
</code></pre>
<p>This solves the &#x201C;illegal invocation&#x201D; problem. Right away, however, another issue cropped up. Content scripts that use JavaScript are likely to do so by accessing the <code>$</code> symbol on the global object rather than referencing it as <code>window.$</code>. So they will still be using the jQuery from the webpage. We could override the <code>$</code> symbol explicitly, but this would be a jQuery-only solution that wouldn&#x2019;t work for other libraries. After some head-scratching, we realized that we could create our own pseudo-global object using <code>with</code>:</p>
<pre><code class="language-language-javascript">(function(window) {
  with (window) {
    // content script
  }
})(wrapper);
</code></pre>
<p>As my colleague pointed out, usage of&#xA0;<code>with</code>&#xA0;is generally frowned on due&#xA0;to the very characteristic we are exploiting here. Unfortunately, jQuery was <em>still</em> malfunctioning. More investigation revealed that the cause was the <a href="https://github.com/jquery/jquery/blob/ca0086b55a158d8a4347f94254878d6dc5dd90ed/src/core.js?ref=blog.javascripting.com#L211"><code>jQuery.isWindow</code> function</a>. That&#x2019;s right, jQuery doesn&#x2019;t consider an object to be a window unless it is equal to its own&#xA0;<code>window</code> property. And while we never found any explanation for this, our wrapper resisted all efforts to change the value of this property when using the DOM window as its prototype.</p>
<p>At this point, we gave up on the prototype altogther and wrapped everything:</p>
<pre><code class="language-language-javascript">var wrapper = {};
for (var prop in window) {
  (function(prop) {
    if (typeof(window[prop]) === &apos;function&apos;)  {
      wrapper[prop] = function() { return window[prop].apply(window, arguments); }
    }
    else {
      Object.defineProperty(wrapper, prop, {
        &apos;get&apos;: function() {
          if (window[prop] === window) {
            return wrapper;
          }
          else {
            return window[prop];
          }
        },
        &apos;set&apos;: function(value) { wrapper[prop] = value; }
      });
  })(prop);
}
</code></pre>
<p>That&#x2019;s the wrapper we&#x2019;re using now and, combined with usage of <code>with</code> as described above, it seems to be a pretty good approximation of the wrapper used in Chrome content scripts. And while it&#x2019;s considerably longer than our initial naive attempt, it isn&#x2019;t as complex as we had feared. There&#x2019;s a lesson in there somewhere.</p>
<p><strong>Update</strong>: Implementors should also read our <a href="https://blog.salsitasoft.com/2014/05/27/dom-window-wrapper-update/?ref=blog.javascripting.com">follow-up post</a>.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>