Bug 907077 - Fix up jetpack for for-of changes. r=rFobic
☠☠ backed out by cc64d4aa1117 ☠ ☠
authorAndy Wingo <wingo@igalia.com>
Tue, 01 Oct 2013 13:05:15 -0400
changeset 149465 6d72b823b67fc23a055a925b0a3aa888bc6a909d
parent 149464 f90880fb52481b016d19844b28b574227edf7bdb
child 149466 48f4c5347dadfd3ef22d144103ef32e8c9cb391e
push id34570
push userryanvm@gmail.com
push dateTue, 01 Oct 2013 17:05:30 +0000
treeherdermozilla-inbound@6d72b823b67f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrFobic
bugs907077
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 907077 - Fix up jetpack for for-of changes. r=rFobic
addon-sdk/source/lib/sdk/deprecated/list.js
addon-sdk/source/lib/sdk/selection.js
addon-sdk/source/lib/sdk/util/iteration.js
addon-sdk/source/lib/sdk/util/list.js
--- a/addon-sdk/source/lib/sdk/deprecated/list.js
+++ b/addon-sdk/source/lib/sdk/deprecated/list.js
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 module.metadata = {
   "stability": "experimental"
 };
 
 const { Trait } = require('../deprecated/traits');
+const { iteratorSymbol } = require('../util/iteration');
 
 /**
  * @see https://jetpack.mozillalabs.com/sdk/latest/docs/#module/api-utils/list
  */
 const Iterable = Trait.compose({
   /**
    * Hash map of key-values to iterate over.
    * Note: That this property can be a getter if you need dynamic behavior.
@@ -33,17 +34,17 @@ exports.Iterable = Iterable;
 
 /**
  * An ordered collection (also known as a sequence) disallowing duplicate
  * elements. List is composed out of `Iterable` there for it provides custom
  * enumeration behavior that is similar to array (enumerates only on the
  * elements of the list). List is a base trait and is meant to be a part of
  * composition, since all of it's API is private except length property.
  */
-const List = Trait.resolve({ toString: null }).compose({
+const listOptions = {
   _keyValueMap: null,
   /**
    * List constructor can take any number of element to populate itself.
    * @params {Object|String|Number} element
    * @example
    *    List(1,2,3).length == 3 // true
    */
   constructor: function List() {
@@ -109,17 +110,17 @@ const List = Trait.resolve({ toString: n
    * @param {Boolean} onKeys
    */
   __iterator__: function __iterator__(onKeys, onKeyValue) {
     let array = this._keyValueMap.slice(0),
         i = -1;
     for (let element of array)
       yield onKeyValue ? [++i, element] : onKeys ? ++i : element;
   },
-  iterator: function iterator() {
-    let array = this._keyValueMap.slice(0);
+};
+listOptions[iteratorSymbol] = function* iterator() {
+  let array = this._keyValueMap.slice(0);
 
-    for (let element of array)
-      yield element;
-  }
-
-});
+  for (let element of array)
+    yield element;
+}
+const List = Trait.resolve({ toString: null }).compose(listOptions);
 exports.List = List;
--- a/addon-sdk/source/lib/sdk/selection.js
+++ b/addon-sdk/source/lib/sdk/selection.js
@@ -17,17 +17,18 @@ const { Ci, Cc } = require("chrome"),
     { Class, obscure } = require("./core/heritage"),
     { EventTarget } = require("./event/target"),
     { ns } = require("./core/namespace"),
     { when: unload } = require("./system/unload"),
     { ignoreWindow } = require('./private-browsing/utils'),
     { getTabs, getTabContentWindow, getTabForContentWindow,
       getAllTabContentWindows } = require('./tabs/utils'),
     winUtils = require("./window/utils"),
-    events = require("./system/events");
+    events = require("./system/events"),
+    { iteratorSymbol, forInIterator } = require("./util/iteration");
 
 // The selection types
 const HTML = 0x01,
       TEXT = 0x02,
       DOM  = 0x03; // internal use only
 
 // A more developer-friendly message than the caught exception when is not
 // possible change a selection.
@@ -94,35 +95,36 @@ const selectionListener = {
 /**
  * Defines iterators so that discontiguous selections can be iterated.
  * Empty selections are skipped - see `safeGetRange` for further details.
  *
  * If discontiguous selections are in a text field, only the first one
  * is returned because the text field selection APIs doesn't support
  * multiple selections.
  */
-function iterator() {
-    let selection = getSelection(DOM);
-    let count = 0;
+function* forOfIterator() {
+  let selection = getSelection(DOM);
+  let count = 0;
 
-    if (selection)
-      count = selection.rangeCount || (getElementWithSelection() ? 1 : 0);
+  if (selection)
+    count = selection.rangeCount || (getElementWithSelection() ? 1 : 0);
 
-    for (let i = 0; i < count; i++) {
-      let sel = Selection(i);
+  for (let i = 0; i < count; i++) {
+    let sel = Selection(i);
 
-      if (sel.text)
-        yield Selection(i);
-    }
+    if (sel.text)
+      yield Selection(i);
+  }
 }
 
-const selectionIterator = obscure({
-  __iterator__: iterator, // for...in; for each...in
-  iterator: iterator // for....of
-});
+const selectionIteratorOptions = {
+  __iterator__: forInIterator
+}
+selectionIteratorOptions[iteratorSymbol] = forOfIterator;
+const selectionIterator = obscure(selectionIteratorOptions);
 
 /**
  * Returns the most recent focused window.
  * if private browsing window is most recent and not supported,
  * then ignore it and return `null`, because the focused window
  * can't be targeted.
  */
 function getFocusedWindow() {
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/sdk/util/iteration.js
@@ -0,0 +1,33 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+'use strict';
+
+module.metadata = {
+  "stability": "experimental"
+};
+
+// This is known as @@iterator in the ES6 spec.  Until it is bound to
+// some well-known name, find the @@iterator object by expecting it as
+// the first property accessed on a for-of iterable.
+const iteratorSymbol = (function() {
+  try {
+    for (var _ of Proxy.create({get: function(_, name) { throw name; } }))
+      break;
+  } catch (name) {
+    return name;
+  }
+  throw new TypeError;
+})();
+
+exports.iteratorSymbol = iteratorSymbol;
+
+// An adaptor that, given an object that is iterable with for-of, is
+// suitable for being bound to __iterator__ in order to make the object
+// iterable in the same way via for-in.
+function forInIterator() {
+    for (let item of this)
+        yield item;
+}
+
+exports.forInIterator = forInIterator;
--- a/addon-sdk/source/lib/sdk/util/list.js
+++ b/addon-sdk/source/lib/sdk/util/list.js
@@ -4,18 +4,19 @@
 'use strict';
 
 module.metadata = {
   "stability": "experimental"
 };
 
 const { Class } = require('../core/heritage');
 const listNS = require('../core/namespace').ns();
+const { iteratorSymbol } = require('../util/iteration');
 
-const List = Class({
+const listOptions = {
   /**
    * List constructor can take any number of element to populate itself.
    * @params {Object|String|Number} element
    * @example
    *    List(1,2,3).length == 3 // true
    */
   initialize: function List() {
     listNS(this).keyValueMap = [];
@@ -41,24 +42,21 @@ const List = Class({
    * @param {Boolean} onKeys
    */
   __iterator__: function __iterator__(onKeys, onKeyValue) {
     let array = listNS(this).keyValueMap.slice(0),
                 i = -1;
     for each(let element in array)
       yield onKeyValue ? [++i, element] : onKeys ? ++i : element;
   },
-  iterator: function iterator() {
-    let array = listNS(this).keyValueMap.slice(0),
-                i = -1;
-
-    for (let element of array)
-      yield element;
-  }
-});
+};
+listOptions[iteratorSymbol] = function iterator() {
+    return listNS(this).keyValueMap.slice(0)[iteratorSymbol]();
+};
+const List = Class(listOptions);
 exports.List = List;
 
 function addListItem(that, value) {
   let list = listNS(that).keyValueMap,
       index = list.indexOf(value);
 
   if (-1 === index) {
     try {