[Pkg-mozext-commits] [ubiquity-extension] 02/08: Imported Upstream version 0.6.4~pre20140729

Gabriele Giacone gg0-guest at moszumanska.debian.org
Wed Jul 30 00:24:15 UTC 2014


This is an automated email from the git hooks/post-receive script.

gg0-guest pushed a commit to branch master
in repository ubiquity-extension.

commit 6a359ee7962248b3754c1e6ab0cab5f17e9a6724
Author: Gabriele Giacone <1o5g4r8o at gmail.com>
Date:   Tue Jul 29 16:54:36 2014 +0200

    Imported Upstream version 0.6.4~pre20140729
---
 chrome.manifest                    |   2 -
 chrome/content/browser.js          |   2 +-
 chrome/content/console.js          |  21 -
 chrome/content/console.xul         |   5 -
 chrome/content/editor.js           |   1 -
 chrome/skin/skins/default.css      |   1 +
 chrome/skin/skins/experimental.css |   4 +-
 install.rdf                        |   4 +-
 modules/annotation_memory.js       |  10 +-
 modules/default_feed_plugin.js     |   4 +-
 modules/nountypes.js               |  59 ---
 modules/parser/original/parser.js  |   5 +-
 modules/sandboxfactory.js          |  35 +-
 modules/setup.js                   |  24 +-
 modules/utils.js                   |  47 +-
 modules/webjsm.js                  |  28 +-
 scripts/jquery_setup.js            |   2 +-
 scripts/math_parser.js             | 920 +++++++++++++++++++++++++++++++++++++
 standard-feeds/developer.js        |   2 +-
 standard-feeds/general.js          | 137 ++----
 standard-feeds/search.xhtml        | 230 ++--------
 tests/test_all.js                  |   6 +-
 22 files changed, 1039 insertions(+), 510 deletions(-)

diff --git a/chrome.manifest b/chrome.manifest
index c7f7baa..4060b6b 100644
--- a/chrome.manifest
+++ b/chrome.manifest
@@ -15,8 +15,6 @@ content ubiquity chrome/content/
 skin ubiquity skin chrome/skin/
 
 overlay chrome://browser/content/browser.xul   chrome://ubiquity/content/browser.xul
-overlay chrome://global/content/console.xul    chrome://ubiquity/content/console.xul
-overlay chrome://console2/content/console2.xul chrome://ubiquity/content/console.xul
 
 style chrome://global/content/customizeToolbar.xul chrome://ubiquity/skin/browser.css
 
diff --git a/chrome/content/browser.js b/chrome/content/browser.js
index 64d63c6..9285f45 100755
--- a/chrome/content/browser.js
+++ b/chrome/content/browser.js
@@ -79,7 +79,7 @@ addEventListener("load", function ubiquityBoot() {
     });
 
     var suggFrame = document.getElementById("ubiquity-suggest");
-    MutationObserver(function resizeSuggs(ms) {
+    new MutationObserver(function resizeSuggs(ms) {
       var doc = suggFrame.contentDocument;
       suggFrame.height = (doc.body || doc.documentElement).clientHeight;
     }).observe(suggFrame.contentDocument.body, {childList: true});
diff --git a/chrome/content/console.js b/chrome/content/console.js
deleted file mode 100644
index 7fb0282..0000000
--- a/chrome/content/console.js
+++ /dev/null
@@ -1,21 +0,0 @@
-Components.utils.import("resource://ubiquity/modules/sandboxfactory.js");
-
-function maybeFixUpUbiquityMessage(target) {
-  var href = target && target.getAttribute("href");
-  if (href && href != (href = SandboxFactory.unmungeUrl(href)))
-    target.setAttribute("href", href);
-}
-
-{
-  let box = document.getElementById("ConsoleBox");
-  box = box.mConsoleRowBox || /* Console2 */ box;
-  setTimeout(function () {
-    Array.forEach(box.children, maybeFixUpUbiquityMessage);
-  });
-  MutationObserver(function (ms) {
-    for (let m of ms) if (m.type == 'childList') {
-      Array.forEach(m.addedNodes, maybeFixUpUbiquityMessage);
-      break;
-    }
-  }).observe(box, {childList: true});
-}
diff --git a/chrome/content/console.xul b/chrome/content/console.xul
deleted file mode 100644
index 58cc8eb..0000000
--- a/chrome/content/console.xul
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0"?>
-<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-  <script type="application/javascript;version=1.8"
-          src="chrome://ubiquity/content/console.js"/>
-</overlay>
diff --git a/chrome/content/editor.js b/chrome/content/editor.js
index 6bff5eb..bafbe67 100644
--- a/chrome/content/editor.js
+++ b/chrome/content/editor.js
@@ -1,6 +1,5 @@
 Cu.import("resource://ubiquity/modules/prefcommands.js");
 Cu.import("resource://ubiquity/modules/localization_utils.js");
-Cu.import("resource:///modules/source-editor.jsm");
 
 var L = LocalizationUtils.propertySelector(
   "chrome://ubiquity/locale/aboutubiquity.properties");
diff --git a/chrome/skin/skins/default.css b/chrome/skin/skins/default.css
index c83f07d..b570bc3 100644
--- a/chrome/skin/skins/default.css
+++ b/chrome/skin/skins/default.css
@@ -78,6 +78,7 @@
 
 #suggestions {
   margin: 0;
+  overflow: hidden;
 }
 
 .hilited {
diff --git a/chrome/skin/skins/experimental.css b/chrome/skin/skins/experimental.css
index a1a6b36..2550d3c 100755
--- a/chrome/skin/skins/experimental.css
+++ b/chrome/skin/skins/experimental.css
@@ -47,6 +47,7 @@
   font-size: 26px;
   color: black;
   width: 100%;
+  height: 32px;
   font-family: Geneva, Tahoma, Verdana;
   text-shadow: #AFAFAF 0px 1px .2px;
 }
@@ -63,6 +64,7 @@
   background-image: url(chrome://ubiquity/skin/icons/suggestion_bd.png);
   background-position: top right;
   background-repeat: repeat-y;
+  overflow: visible;
 }
 
 #ubiquity-suggest {
@@ -70,7 +72,6 @@
   border: none;
   width: 300px;
   height: 500px;
-  overflow: hidden;
 }
 
 #ubiquity-preview-container {
@@ -106,6 +107,7 @@
   font-family: Geneva, Tahoma, Verdana;
   text-shadow: #333 0px 1px .2px;
   color: #fff;
+  overflow: hidden;
 }
 
 /* below are the only Parser 2 debug changes*/
diff --git a/install.rdf b/install.rdf
index 00be2ac..194c3ec 100755
--- a/install.rdf
+++ b/install.rdf
@@ -11,8 +11,8 @@
          with minimum and maximum supported versions. -->
     <targetApplication><rdf:Description>
       <!--Firefox--><id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</id>
-      <minVersion>20.0</minVersion>
-      <maxVersion>23.0a1</maxVersion>
+      <minVersion>28.0</minVersion>
+      <maxVersion>31.0a1</maxVersion>
     </rdf:Description></targetApplication>
 
     <!-- Front End MetaData -->
diff --git a/modules/annotation_memory.js b/modules/annotation_memory.js
index 9369bec..ea80314 100644
--- a/modules/annotation_memory.js
+++ b/modules/annotation_memory.js
@@ -65,7 +65,10 @@ function NiceConnection(connection) {
   if (connection.constructor === NiceConnection)
     return connection;
 
-  this.createStatement = function nice_createStatement(sql) {
+  var me = Object.create(connection);
+  me.constructor = NiceConnection;
+
+  me.createStatement = function nice_createStatement(sql) {
     try {
       return connection.createStatement(sql);
     } catch (e if e.result === Components.results.NS_ERROR_FAILURE) {
@@ -75,7 +78,7 @@ function NiceConnection(connection) {
     }
   };
 
-  this.executeSimpleSQL = function nice_executeSimpleSQL(sql) {
+  me.executeSimpleSQL = function nice_executeSimpleSQL(sql) {
     try {
       connection.executeSimpleSQL(sql);
     } catch (e if e.result === Components.results.NS_ERROR_FAILURE) {
@@ -85,8 +88,7 @@ function NiceConnection(connection) {
     }
   };
 
-  this.constructor = NiceConnection;
-  this.__proto__ = connection;
+  return me;
 }
 
 // == The AnnotationService Class ==
diff --git a/modules/default_feed_plugin.js b/modules/default_feed_plugin.js
index d17e2d3..378c2f9 100644
--- a/modules/default_feed_plugin.js
+++ b/modules/default_feed_plugin.js
@@ -46,6 +46,7 @@ Cu.import("resource://ubiquity/modules/utils.js");
 Cu.import("resource://ubiquity/modules/codesource.js");
 Cu.import("resource://ubiquity/modules/sandboxfactory.js");
 Cu.import("resource://ubiquity/modules/feed_plugin_utils.js");
+Cu.import("resource://gre/modules/devtools/Console.jsm");
 
 const Global = this;
 const CONFIRM_URL = "chrome://ubiquity/content/confirm-add-command.xhtml";
@@ -308,8 +309,6 @@ DFPFeed.prototype = {
 };
 
 function makeBuiltinGlobalsMaker(msgService, webJsm) {
-  webJsm.importScript("resource://ubiquity/scripts/jquery.js");
-  webJsm.importScript("resource://ubiquity/scripts/jquery_setup.js");
   webJsm.importScript("resource://ubiquity/scripts/template.js");
   webJsm.importScript("resource://ubiquity/scripts/date.js");
 
@@ -338,6 +337,7 @@ function makeBuiltinGlobalsMaker(msgService, webJsm) {
       globals: globalObjects[id] || (globalObjects[id] = {}),
       displayMessage: displayMessage,
       Template: webJsm.TrimPath,
+      console: console,
     };
     for (let key of jsmExports) globals[key] = Global[key];
     for (let key of webExports) globals[key] = webJsm[key];
diff --git a/modules/nountypes.js b/modules/nountypes.js
index 097048e..1749410 100644
--- a/modules/nountypes.js
+++ b/modules/nountypes.js
@@ -1139,65 +1139,6 @@ function NounAsync(label, checker) {
   };
 }
 
-// === {{{ noun_type_async_restaurant }}} ===
-// **//FIXME//**
-// * {{{text}}} :
-// * {{{html}}} :
-// * {{{data}}} :
-
-var noun_type_async_restaurant = NounAsync("restaurant", getRestaurants);
-
-function getRestaurants(query, callback, selectionIndices) {
-  if (!query) return;
-
-  var baseUrl = "http://api.yelp.com/business_review_search";
-  var queryToMatch = query.toLowerCase().replace(/\s+/g, '');
-  var loc = CmdUtils.getGeoLocation();
-  var near = loc ? loc.city + "," + loc.state : "";
-
-  return jQuery.ajax({
-    url: baseUrl + Utils.paramsToString({
-      term: query,
-      num_biz_requested: 1,
-      location: near,
-      category: "restaurants",
-      ywsid: "HbSZ2zXYuMnu1VTImlyA9A",
-    }),
-    dataType: "json",
-    error: function () {
-      callback([]);
-    },
-    success: function (data) {
-      var allBusinesses = data.businesses.map(
-        function (business) {
-          return {name: business.name.toLowerCase().replace(/\s+/g, ''),
-            categories: business.categories};
-        });
-      // if the business's name or category overlaps with the query
-      // then consider it a restaurant match
-      for (let business of allBusinesses) {
-        if (business.name.indexOf(queryToMatch) !== -1 ||
-            queryToMatch.indexOf(business.name) !== -1) {
-          callback([CmdUtils.makeSugg(query, null, null, .9,
-                                      selectionIndices)]);
-          return;
-        }
-        else {
-          for (let category of business.categories) {
-            if (category.name.indexOf(queryToMatch) !== -1 ||
-                queryToMatch.indexOf(category.name) !== -1) {
-              callback([CmdUtils.makeSugg(query, null, null, .9,
-                                          selectionIndices)]);
-              return;
-            }
-          }
-        }
-      }
-      callback([]);
-    }
-  });
-}
-
 // === {{{ noun_type_geo_country }}} ===
 // === {{{ noun_type_geo_region }}} ===
 // === {{{ noun_type_geo_subregion }}} ===
diff --git a/modules/parser/original/parser.js b/modules/parser/original/parser.js
index 716e0c4..36ddbe8 100644
--- a/modules/parser/original/parser.js
+++ b/modules/parser/original/parser.js
@@ -462,8 +462,9 @@ ParsedSentence.prototype = {
           ams += _argSuggs[name].score || 1;
       this.argMatchScore = ams;
     }
-    return (this.verbMatchScore * this.duplicateDefaultMatchScore +
-            this.argMatchScore * this.frequencyMatchScore / 99);
+    return (this.verbMatchScore + this.argMatchScore / 99)
+           * this.duplicateDefaultMatchScore
+           * this.frequencyMatchScore;
   }
 };
 
diff --git a/modules/sandboxfactory.js b/modules/sandboxfactory.js
index 6ff7ba3..67a78e5 100644
--- a/modules/sandboxfactory.js
+++ b/modules/sandboxfactory.js
@@ -43,39 +43,13 @@ Cu.import("resource://ubiquity/modules/utils.js");
 
 var defaultTarget = this;
 
-function SandboxFactory(globals, target, ignoreForcedProtection) {
-  maybeInitialize();
+function SandboxFactory(globals, target) {
   globals = globals || {};
   this._target = target || defaultTarget;
-  this._ignoreForcedProtection = ignoreForcedProtection;
   this._makeGlobals = typeof globals == "function" ?
     globals : function defaultMakeGlobals(id) globals;
 }
 
-SandboxFactory.protectedFileUriPrefix = "";
-SandboxFactory.fileUri = "";
-SandboxFactory.isInitialized = false;
-
-SandboxFactory.unmungeUrl = function unmungeUrl(url) {
-  if (this.isInitialized && ~url.lastIndexOf(this.protectedFileUriPrefix, 0))
-    return url.slice(this.protectedFileUriPrefix.length);
-  return url;
-};
-
-function maybeInitialize() {
-  if (SandboxFactory.isInitialized) return;
-
-  SandboxFactory.fileUri =
-    Utils.ResProtocolHandler.resolveURI(
-      Utils.uri("resource://ubiquity/modules/sandboxfactory.js"));
-  // We need to prefix any source code URI's with a known
-  // "protected" file URI so that XPConnect wrappers are implicitly
-  // made for them.
-  SandboxFactory.protectedFileUriPrefix = SandboxFactory.fileUri + "#";
-
-  SandboxFactory.isInitialized = true;
-}
-
 Utils.extend(SandboxFactory.prototype, {
   makeSandbox: function makeSandbox(codeSource) {
     var sandbox = Cu.Sandbox(this._target);
@@ -88,13 +62,10 @@ Utils.extend(SandboxFactory.prototype, {
     codeSections = codeSections ||
       [{filename: "<string>", lineNumber: 0, length: code.length}];
     var retVal, currIndex = 0;
-    for each (let section in codeSections) {
+    for (let section of codeSections) {
       let sourceCode = code.slice(currIndex, currIndex += section.length);
-      let filename = section.filename;
-      if (!this._ignoreForcedProtection)
-        filename = SandboxFactory.protectedFileUriPrefix + filename;
       retVal = Cu.evalInSandbox(sourceCode, sandbox,
-                                1.8, filename, section.lineNumber);
+                                1.8, section.filename, section.lineNumber);
     }
     return retVal;
   }
diff --git a/modules/setup.js b/modules/setup.js
index dcbf09b..6aa3dda 100755
--- a/modules/setup.js
+++ b/modules/setup.js
@@ -108,21 +108,37 @@ var UbiquitySetup = {
     return !this.baseUrl.lastIndexOf(profileUrl, 0);
   },
 
+  _preloadCBs: [],
+
   preload: function preload(callback) {
     if (gWebJsModule) {
       callback();
       return;
     }
 
+    this._preloadCBs.push(callback);
+    if (this._preloaded) return;
+    this._preloaded = true;
+
     this.__maybeReset();
 
+    var self = this, wjm;
+
     Utils.AddonManager.getAddonByID(
       "ubiquity at labs.mozilla.com",
       function setAddonInfo(addon) {
-        this.version = addon.version;
-        this.baseUrl = addon.getResourceURI("").spec;
-        gWebJsModule = new WebJsModule(callback);
-      }.bind(this));
+        self.version = addon.version;
+        self.baseUrl = addon.getResourceURI("").spec;
+        wjm = new WebJsModule(onWJMLoad);
+      });
+
+    function onWJMLoad() {
+      wjm.importScript("resource://ubiquity/scripts/jquery.js", function () {
+        wjm.importScript("resource://ubiquity/scripts/jquery_setup.js");
+        gWebJsModule = wjm;
+        for (var cb; cb = self._preloadCBs.pop();) cb();
+      });
+    }
   },
 
   get isResetScheduled()
diff --git a/modules/utils.js b/modules/utils.js
index bdd0f2f..dcc66f1 100755
--- a/modules/utils.js
+++ b/modules/utils.js
@@ -171,53 +171,12 @@ delete Utils.QueryInterface;
 }) = Services;
 
 Cu.import("resource://gre/modules/AddonManager.jsm", Utils);
+Cu.import("resource://gre/modules/devtools/Console.jsm");
 
 // === {{{ Utils.log(a, b, c, ...) }}} ===
-// One of the most useful functions to know both for development and debugging.
-// This logging function takes an arbitrary number of arguments and
-// will log them to the most appropriate output. If you have Firebug,
-// the output will go to its console.
-// Otherwise, the output will be routed to the Javascript Console.
-//
-// {{{Utils.log()}}} implements smart pretty print, so you
-// can use it for inspecting arrays and objects.
-// See http://getfirebug.com/console.html for details.
-//
-// {{{a, b, c, ...}}} is an arbitrary list of things to be logged.
-
-function log(what) {
-  if (!arguments.length) return;
-
-  var args = Array.slice(arguments), formatting = typeof what === "string";
-
-  var {Firebug} = Utils.currentChromeWindow;
-  if (Firebug && Firebug.Console.isEnabled() &&
-      Firebug.toggleBar(true, "console")) {
-    if (formatting) args[0] = LOG_PREFIX + what;
-    else args.unshift(LOG_PREFIX);
-    Firebug.Console.logFormatted(args);
-    return;
-  }
+// Left for compatibility.
 
-  function log_pp(o) {
-    try { var p = uneval(o) } catch ([]) {}
-    return p && p !== "({})" && (p !== "null" || o === null) ? p : o;
-  }
-  var lead = !formatting ? log_pp(args.shift()) :
-  args.shift().replace(/%[sdifo]/g, function log_format($) {
-    if (!args.length) return $;
-    var a = args.shift();
-    switch ($) {
-      case "%s": return a;
-      case "%d":
-      case "%i": return parseInt(a);
-      case "%f": return parseFloat(a);
-    }
-    return log_pp(a);
-  });
-  Utils.reportInfo(
-    args.reduce(function log_acc(msg, arg) msg + " " + log_pp(arg), lead));
-}
+Utils.log = console.log;
 
 // === {{{ Utils.dump(a, b, c, ...) }}} ===
 // A nicer {{{dump()}}} variant that
diff --git a/modules/webjsm.js b/modules/webjsm.js
index 9d6da0d..cf74f2c 100644
--- a/modules/webjsm.js
+++ b/modules/webjsm.js
@@ -62,29 +62,22 @@ const Ci = Components.interfaces;
 // use to host any JS code. If unspecified, the hidden DOM window is
 // used.
 
+Components.utils.import("resource://ubiquity/modules/utils.js");
+
 function WebJsModule(callback, window) {
-  if (!window)
-    window = Cc["@mozilla.org/appshell/appShellService;1"]
-             .getService(Ci.nsIAppShellService)
-             .hiddenDOMWindow;
+  if (!window) window = Utils.hiddenWindow;
 
   var importedScripts = {};
 
   var self = this;
   var iframe = window.document.createElement("iframe");
   iframe.setAttribute("src", "chrome://ubiquity/content/hiddenframe.html");
-  iframe.addEventListener(
-    "pageshow",
-    function WJM__onPageShow() {
-      iframe.removeEventListener("pageshow", arguments.callee, false);
-
-      // Have our instance dynamically inherit the properties of the
-      // hidden window.
-      self.__proto__ = iframe.contentWindow;
-      callback();
-    },
-    false
-  );
+  Utils.listenOnce(iframe, "pageshow", function WJM__onPageShow() {
+    // Have our instance dynamically inherit the properties of the
+    // hidden window.
+    self.__proto__ = iframe.contentWindow;
+    callback();
+  });
   window.document.documentElement.appendChild(iframe);
 
   // === {{{WebJsModule#importScript()}}} ===
@@ -96,10 +89,11 @@ function WebJsModule(callback, window) {
   // Once the script is imported, any globals it created can be
   // directly accessed as properties of the {{{WebJsModule}}} instance.
 
-  this.importScript = function WJM_importScript(url) {
+  this.importScript = function WJM_importScript(url, callback) {
     if (url in importedScripts) return;
     var doc = iframe.contentDocument, script = doc.createElement('script');
     script.setAttribute('src', url);
+    if (callback) Utils.listenOnce(script, 'load', callback);
     doc.documentElement.appendChild(script);
     doc.documentElement.removeChild(script);
     importedScripts[url] = true;
diff --git a/scripts/jquery_setup.js b/scripts/jquery_setup.js
index 8a00f28..92c865f 100644
--- a/scripts/jquery_setup.js
+++ b/scripts/jquery_setup.js
@@ -10,7 +10,7 @@ jQuery.ajaxSetup({
     // that needs to be brought up as a result of the XHR is shown
     // to the user, rather than being invisible and locking up the
     // application.
-    return Utils.currentChromeWindow.XMLHttpRequest();
+    return new Utils.currentChromeWindow.XMLHttpRequest;
   }
 });
 
diff --git a/scripts/math_parser.js b/scripts/math_parser.js
new file mode 100644
index 0000000..8b4f604
--- /dev/null
+++ b/scripts/math_parser.js
@@ -0,0 +1,920 @@
+/*
+ Based on ndef.parser, by Raphael Graf(r at undefined.ch)
+ http://www.undefined.ch/mparser/index.html
+
+ Ported to JavaScript and modified by Matthew Crumley (email at matthewcrumley.com, http://silentmatt.com/)
+
+ You are free to use and modify this code in anyway you find useful. Please leave this comment in the code
+ to acknowledge its original source. If you feel like it, I enjoy hearing about projects that use my code,
+ but don't feel like you have to let me know or ask permission.
+*/
+
+//  Added by stlsmiths 6/13/2011
+//  re-define Array.indexOf, because IE doesn't know it ...
+//
+//  from http://stellapower.net/content/javascript-support-and-arrayindexof-ie
+	if (!Array.indexOf) {
+		Array.prototype.indexOf = function (obj, start) {
+			for (var i = (start || 0); i < this.length; i++) {
+				if (this[i] === obj) {
+					return i;
+				}
+			}
+			return -1;
+		}
+	}
+
+var Parser = (function (scope) {
+	function object(o) {
+		function F() {}
+		F.prototype = o;
+		return new F();
+	}
+
+	var TNUMBER = 0;
+	var TOP1 = 1;
+	var TOP2 = 2;
+	var TVAR = 3;
+	var TFUNCALL = 4;
+
+	function Token(type_, index_, prio_, number_) {
+		this.type_ = type_;
+		this.index_ = index_ || 0;
+		this.prio_ = prio_ || 0;
+		this.number_ = (number_ !== undefined && number_ !== null) ? number_ : 0;
+		this.toString = function () {
+			switch (this.type_) {
+			case TNUMBER:
+				return this.number_;
+			case TOP1:
+			case TOP2:
+			case TVAR:
+				return this.index_;
+			case TFUNCALL:
+				return "CALL";
+			default:
+				return "Invalid Token";
+			}
+		};
+	}
+
+	function Expression(tokens, ops1, ops2, functions) {
+		this.tokens = tokens;
+		this.ops1 = ops1;
+		this.ops2 = ops2;
+		this.functions = functions;
+	}
+
+	// Based on http://www.json.org/json2.js
+    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+        escapable = /[\\\'\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+        meta = {    // table of character substitutions
+            '\b': '\\b',
+            '\t': '\\t',
+            '\n': '\\n',
+            '\f': '\\f',
+            '\r': '\\r',
+            "'" : "\\'",
+            '\\': '\\\\'
+        };
+
+	function escapeValue(v) {
+		if (typeof v === "string") {
+			escapable.lastIndex = 0;
+	        return escapable.test(v) ?
+	            "'" + v.replace(escapable, function (a) {
+	                var c = meta[a];
+	                return typeof c === 'string' ? c :
+	                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+	            }) + "'" :
+	            "'" + v + "'";
+		}
+		return v;
+	}
+
+	Expression.prototype = {
+		simplify: function (values) {
+			values = values || {};
+			var nstack = [];
+			var newexpression = [];
+			var n1;
+			var n2;
+			var f;
+			var L = this.tokens.length;
+			var item;
+			var i = 0;
+			for (i = 0; i < L; i++) {
+				item = this.tokens[i];
+				var type_ = item.type_;
+				if (type_ === TNUMBER) {
+					nstack.push(item);
+				}
+				else if (type_ === TVAR && (item.index_ in values)) {
+					item = new Token(TNUMBER, 0, 0, values[item.index_]);
+					nstack.push(item);
+				}
+				else if (type_ === TOP2 && nstack.length > 1) {
+					n2 = nstack.pop();
+					n1 = nstack.pop();
+					f = this.ops2[item.index_];
+					item = new Token(TNUMBER, 0, 0, f(n1.number_, n2.number_));
+					nstack.push(item);
+				}
+				else if (type_ === TOP1 && nstack.length > 0) {
+					n1 = nstack.pop();
+					f = this.ops1[item.index_];
+					item = new Token(TNUMBER, 0, 0, f(n1.number_));
+					nstack.push(item);
+				}
+				else {
+					while (nstack.length > 0) {
+						newexpression.push(nstack.shift());
+					}
+					newexpression.push(item);
+				}
+			}
+			while (nstack.length > 0) {
+				newexpression.push(nstack.shift());
+			}
+
+			return new Expression(newexpression, object(this.ops1), object(this.ops2), object(this.functions));
+		},
+
+		substitute: function (variable, expr) {
+			if (!(expr instanceof Expression)) {
+				expr = new Parser().parse(String(expr));
+			}
+			var newexpression = [];
+			var L = this.tokens.length;
+			var item;
+			var i = 0;
+			for (i = 0; i < L; i++) {
+				item = this.tokens[i];
+				var type_ = item.type_;
+				if (type_ === TVAR && item.index_ === variable) {
+					for (var j = 0; j < expr.tokens.length; j++) {
+						var expritem = expr.tokens[j];
+						var replitem = new Token(expritem.type_, expritem.index_, expritem.prio_, expritem.number_);
+						newexpression.push(replitem);
+					}
+				}
+				else {
+					newexpression.push(item);
+				}
+			}
+
+			var ret = new Expression(newexpression, object(this.ops1), object(this.ops2), object(this.functions));
+			return ret;
+		},
+
+		evaluate: function (values) {
+			values = values || {};
+			var nstack = [];
+			var n1;
+			var n2;
+			var f;
+			var L = this.tokens.length;
+			var item;
+			var i = 0;
+			for (i = 0; i < L; i++) {
+				item = this.tokens[i];
+				var type_ = item.type_;
+				if (type_ === TNUMBER) {
+					nstack.push(item.number_);
+				}
+				else if (type_ === TOP2) {
+					n2 = nstack.pop();
+					n1 = nstack.pop();
+					f = this.ops2[item.index_];
+					nstack.push(f(n1, n2));
+				}
+				else if (type_ === TVAR) {
+					if (item.index_ in values) {
+						nstack.push(values[item.index_]);
+					}
+					else if (item.index_ in this.functions) {
+						nstack.push(this.functions[item.index_]);
+					}
+					else {
+						throw new Error("undefined variable: " + item.index_);
+					}
+				}
+				else if (type_ === TOP1) {
+					n1 = nstack.pop();
+					f = this.ops1[item.index_];
+					nstack.push(f(n1));
+				}
+				else if (type_ === TFUNCALL) {
+					n1 = nstack.pop();
+					f = nstack.pop();
+					if (f.apply && f.call) {
+						if (Object.prototype.toString.call(n1) == "[object Array]") {
+							nstack.push(f.apply(undefined, n1));
+						}
+						else {
+							nstack.push(f.call(undefined, n1));
+						}
+					}
+					else {
+						throw new Error(f + " is not a function");
+					}
+				}
+				else {
+					throw new Error("invalid Expression");
+				}
+			}
+			if (nstack.length > 1) {
+				throw new Error("invalid Expression (parity)");
+			}
+			return nstack[0];
+		},
+
+		toString: function (toJS) {
+			var nstack = [];
+			var n1;
+			var n2;
+			var f;
+			var L = this.tokens.length;
+			var item;
+			var i = 0;
+			for (i = 0; i < L; i++) {
+				item = this.tokens[i];
+				var type_ = item.type_;
+				if (type_ === TNUMBER) {
+					nstack.push(escapeValue(item.number_));
+				}
+				else if (type_ === TOP2) {
+					n2 = nstack.pop();
+					n1 = nstack.pop();
+					f = item.index_;
+					if (toJS && f == "^") {
+						nstack.push("Math.pow(" + n1 + "," + n2 + ")");
+					}
+					else {
+						nstack.push("(" + n1 + f + n2 + ")");
+					}
+				}
+				else if (type_ === TVAR) {
+					nstack.push(item.index_);
+				}
+				else if (type_ === TOP1) {
+					n1 = nstack.pop();
+					f = item.index_;
+					if (f === "-") {
+						nstack.push("(" + f + n1 + ")");
+					}
+					else {
+						nstack.push(f + "(" + n1 + ")");
+					}
+				}
+				else if (type_ === TFUNCALL) {
+					n1 = nstack.pop();
+					f = nstack.pop();
+					nstack.push(f + "(" + n1 + ")");
+				}
+				else {
+					throw new Error("invalid Expression");
+				}
+			}
+			if (nstack.length > 1) {
+				throw new Error("invalid Expression (parity)");
+			}
+			return nstack[0];
+		},
+
+		variables: function () {
+			var L = this.tokens.length;
+			var vars = [];
+			for (var i = 0; i < L; i++) {
+				var item = this.tokens[i];
+				if (item.type_ === TVAR && (vars.indexOf(item.index_) == -1)) {
+					vars.push(item.index_);
+				}
+			}
+
+			return vars;
+		},
+
+		toJSFunction: function (param, variables) {
+			var f = new Function(param, "with(Parser.values) { return " + this.simplify(variables).toString(true) + "; }");
+			return f;
+		}
+	};
+
+	function add(a, b) {
+		return Number(a) + Number(b);
+	}
+	function sub(a, b) {
+		return a - b; 
+	}
+	function mul(a, b) {
+		return a * b;
+	}
+	function div(a, b) {
+		return a / b;
+	}
+	function mod(a, b) {
+		return a % b;
+	}
+	function concat(a, b) {
+		return "" + a + b;
+	}
+
+	function neg(a) {
+		return -a;
+	}
+
+	function random(a) {
+		return Math.random() * (a || 1);
+	}
+	function fac(a) { //a!
+		a = Math.floor(a);
+		var b = a;
+		while (a > 1) {
+			b = b * (--a);
+		}
+		return b;
+	}
+
+	// TODO: use hypot that doesn't overflow
+	function pyt(a, b) {
+		return Math.sqrt(a * a + b * b);
+	}
+
+	function append(a, b) {
+		if (Object.prototype.toString.call(a) != "[object Array]") {
+			return [a, b];
+		}
+		a = a.slice();
+		a.push(b);
+		return a;
+	}
+
+	function Parser() {
+		this.success = false;
+		this.errormsg = "";
+		this.expression = "";
+
+		this.pos = 0;
+
+		this.tokennumber = 0;
+		this.tokenprio = 0;
+		this.tokenindex = 0;
+		this.tmpprio = 0;
+
+		this.ops1 = {
+			"sin": Math.sin,
+			"cos": Math.cos,
+			"tan": Math.tan,
+			"asin": Math.asin,
+			"acos": Math.acos,
+			"atan": Math.atan,
+			"sqrt": Math.sqrt,
+			"log": Math.log,
+			"abs": Math.abs,
+			"ceil": Math.ceil,
+			"floor": Math.floor,
+			"round": Math.round,
+			"-": neg,
+			"exp": Math.exp
+		};
+
+		this.ops2 = {
+			"+": add,
+			"-": sub,
+			"*": mul,
+			"/": div,
+			"%": mod,
+			"^": Math.pow,
+			",": append,
+			"||": concat
+		};
+
+		this.functions = {
+			"random": random,
+			"fac": fac,
+			"min": Math.min,
+			"max": Math.max,
+			"pyt": pyt,
+			"pow": Math.pow,
+			"atan2": Math.atan2
+		};
+
+		this.consts = {
+			"E": Math.E,
+			"PI": Math.PI
+		};
+	}
+
+	Parser.parse = function (expr) {
+		return new Parser().parse(expr);
+	};
+
+	Parser.evaluate = function (expr, variables) {
+		return Parser.parse(expr).evaluate(variables);
+	};
+
+	Parser.Expression = Expression;
+
+	Parser.values = {
+		sin: Math.sin,
+		cos: Math.cos,
+		tan: Math.tan,
+		asin: Math.asin,
+		acos: Math.acos,
+		atan: Math.atan,
+		sqrt: Math.sqrt,
+		log: Math.log,
+		abs: Math.abs,
+		ceil: Math.ceil,
+		floor: Math.floor,
+		round: Math.round,
+		random: random,
+		fac: fac,
+		exp: Math.exp,
+		min: Math.min,
+		max: Math.max,
+		pyt: pyt,
+		pow: Math.pow,
+		atan2: Math.atan2,
+		E: Math.E,
+		PI: Math.PI
+	};
+
+	var PRIMARY      = 1 << 0;
+	var OPERATOR     = 1 << 1;
+	var FUNCTION     = 1 << 2;
+	var LPAREN       = 1 << 3;
+	var RPAREN       = 1 << 4;
+	var COMMA        = 1 << 5;
+	var SIGN         = 1 << 6;
+	var CALL         = 1 << 7;
+	var NULLARY_CALL = 1 << 8;
+
+	Parser.prototype = {
+		parse: function (expr) {
+			this.errormsg = "";
+			this.success = true;
+			var operstack = [];
+			var tokenstack = [];
+			this.tmpprio = 0;
+			var expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
+			var noperators = 0;
+			this.expression = expr;
+			this.pos = 0;
+
+			while (this.pos < this.expression.length) {
+				if (this.isOperator()) {
+					if (this.isSign() && (expected & SIGN)) {
+						if (this.isNegativeSign()) {
+							this.tokenprio = 2;
+							this.tokenindex = "-";
+							noperators++;
+							this.addfunc(tokenstack, operstack, TOP1);
+						}
+						expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
+					}
+					else if (this.isComment()) {
+
+					}
+					else {
+						if ((expected & OPERATOR) === 0) {
+							this.error_parsing(this.pos, "unexpected operator");
+						}
+						noperators += 2;
+						this.addfunc(tokenstack, operstack, TOP2);
+						expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
+					}
+				}
+				else if (this.isNumber()) {
+					if ((expected & PRIMARY) === 0) {
+						this.error_parsing(this.pos, "unexpected number");
+					}
+					var token = new Token(TNUMBER, 0, 0, this.tokennumber);
+					tokenstack.push(token);
+
+					expected = (OPERATOR | RPAREN | COMMA);
+				}
+				else if (this.isString()) {
+					if ((expected & PRIMARY) === 0) {
+						this.error_parsing(this.pos, "unexpected string");
+					}
+					var token = new Token(TNUMBER, 0, 0, this.tokennumber);
+					tokenstack.push(token);
+
+					expected = (OPERATOR | RPAREN | COMMA);
+				}
+				else if (this.isLeftParenth()) {
+					if ((expected & LPAREN) === 0) {
+						this.error_parsing(this.pos, "unexpected \"(\"");
+					}
+
+					if (expected & CALL) {
+						noperators += 2;
+						this.tokenprio = -2;
+						this.tokenindex = -1;
+						this.addfunc(tokenstack, operstack, TFUNCALL);
+					}
+
+					expected = (PRIMARY | LPAREN | FUNCTION | SIGN | NULLARY_CALL);
+				}
+				else if (this.isRightParenth()) {
+				    if (expected & NULLARY_CALL) {
+						var token = new Token(TNUMBER, 0, 0, []);
+						tokenstack.push(token);
+					}
+					else if ((expected & RPAREN) === 0) {
+						this.error_parsing(this.pos, "unexpected \")\"");
+					}
+
+					expected = (OPERATOR | RPAREN | COMMA | LPAREN | CALL);
+				}
+				else if (this.isComma()) {
+					if ((expected & COMMA) === 0) {
+						this.error_parsing(this.pos, "unexpected \",\"");
+					}
+					this.addfunc(tokenstack, operstack, TOP2);
+					noperators += 2;
+					expected = (PRIMARY | LPAREN | FUNCTION | SIGN);
+				}
+				else if (this.isConst()) {
+					if ((expected & PRIMARY) === 0) {
+						this.error_parsing(this.pos, "unexpected constant");
+					}
+					var consttoken = new Token(TNUMBER, 0, 0, this.tokennumber);
+					tokenstack.push(consttoken);
+					expected = (OPERATOR | RPAREN | COMMA);
+				}
+				else if (this.isOp2()) {
+					if ((expected & FUNCTION) === 0) {
+						this.error_parsing(this.pos, "unexpected function");
+					}
+					this.addfunc(tokenstack, operstack, TOP2);
+					noperators += 2;
+					expected = (LPAREN);
+				}
+				else if (this.isOp1()) {
+					if ((expected & FUNCTION) === 0) {
+						this.error_parsing(this.pos, "unexpected function");
+					}
+					this.addfunc(tokenstack, operstack, TOP1);
+					noperators++;
+					expected = (LPAREN);
+				}
+				else if (this.isVar()) {
+					if ((expected & PRIMARY) === 0) {
+						this.error_parsing(this.pos, "unexpected variable");
+					}
+					var vartoken = new Token(TVAR, this.tokenindex, 0, 0);
+					tokenstack.push(vartoken);
+
+					expected = (OPERATOR | RPAREN | COMMA | LPAREN | CALL);
+				}
+				else if (this.isWhite()) {
+				}
+				else {
+					if (this.errormsg === "") {
+						this.error_parsing(this.pos, "unknown character");
+					}
+					else {
+						this.error_parsing(this.pos, this.errormsg);
+					}
+				}
+			}
+			if (this.tmpprio < 0 || this.tmpprio >= 10) {
+				this.error_parsing(this.pos, "unmatched \"()\"");
+			}
+			while (operstack.length > 0) {
+				var tmp = operstack.pop();
+				tokenstack.push(tmp);
+			}
+			if (noperators + 1 !== tokenstack.length) {
+				//print(noperators + 1);
+				//print(tokenstack);
+				this.error_parsing(this.pos, "parity");
+			}
+
+			return new Expression(tokenstack, object(this.ops1), object(this.ops2), object(this.functions));
+		},
+
+		evaluate: function (expr, variables) {
+			return this.parse(expr).evaluate(variables);
+		},
+
+		error_parsing: function (column, msg) {
+			this.success = false;
+			this.errormsg = "parse error [column " + (column) + "]: " + msg;
+			throw new Error(this.errormsg);
+		},
+
+//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
+
+		addfunc: function (tokenstack, operstack, type_) {
+			var operator = new Token(type_, this.tokenindex, this.tokenprio + this.tmpprio, 0);
+			while (operstack.length > 0) {
+				if (operator.prio_ <= operstack[operstack.length - 1].prio_) {
+					tokenstack.push(operstack.pop());
+				}
+				else {
+					break;
+				}
+			}
+			operstack.push(operator);
+		},
+
+		isNumber: function () {
+			var r = false;
+			var str = "";
+			while (this.pos < this.expression.length) {
+				var code = this.expression.charCodeAt(this.pos);
+				if ((code >= 48 && code <= 57) || code === 46) {
+					str += this.expression.charAt(this.pos);
+					this.pos++;
+					this.tokennumber = parseFloat(str);
+					r = true;
+				}
+				else {
+					break;
+				}
+			}
+			return r;
+		},
+
+		// Ported from the yajjl JSON parser at http://code.google.com/p/yajjl/
+		unescape: function(v, pos) {
+			var buffer = [];
+			var escaping = false;
+
+			for (var i = 0; i < v.length; i++) {
+				var c = v.charAt(i);
+	
+				if (escaping) {
+					switch (c) {
+					case "'":
+						buffer.push("'");
+						break;
+					case '\\':
+						buffer.push('\\');
+						break;
+					case '/':
+						buffer.push('/');
+						break;
+					case 'b':
+						buffer.push('\b');
+						break;
+					case 'f':
+						buffer.push('\f');
+						break;
+					case 'n':
+						buffer.push('\n');
+						break;
+					case 'r':
+						buffer.push('\r');
+						break;
+					case 't':
+						buffer.push('\t');
+						break;
+					case 'u':
+						// interpret the following 4 characters as the hex of the unicode code point
+						var codePoint = parseInt(v.substring(i + 1, i + 5), 16);
+						buffer.push(String.fromCharCode(codePoint));
+						i += 4;
+						break;
+					default:
+						throw this.error_parsing(pos + i, "Illegal escape sequence: '\\" + c + "'");
+					}
+					escaping = false;
+				} else {
+					if (c == '\\') {
+						escaping = true;
+					} else {
+						buffer.push(c);
+					}
+				}
+			}
+	
+			return buffer.join('');
+		},
+
+		isString: function () {
+			var r = false;
+			var str = "";
+			var startpos = this.pos;
+			if (this.pos < this.expression.length && this.expression.charAt(this.pos) == "'") {
+				this.pos++;
+				while (this.pos < this.expression.length) {
+					var code = this.expression.charAt(this.pos);
+					if (code != "'" || str.slice(-1) == "\\") {
+						str += this.expression.charAt(this.pos);
+						this.pos++;
+					}
+					else {
+						this.pos++;
+						this.tokennumber = this.unescape(str, startpos);
+						r = true;
+						break;
+					}
+				}
+			}
+			return r;
+		},
+
+		isConst: function () {
+			var str;
+			for (var i in this.consts) {
+				if (true) {
+					var L = i.length;
+					str = this.expression.substr(this.pos, L);
+					if (i === str) {
+						this.tokennumber = this.consts[i];
+						this.pos += L;
+						return true;
+					}
+				}
+			}
+			return false;
+		},
+
+		isOperator: function () {
+			var code = this.expression.charCodeAt(this.pos);
+			if (code === 43) { // +
+				this.tokenprio = 0;
+				this.tokenindex = "+";
+			}
+			else if (code === 45) { // -
+				this.tokenprio = 0;
+				this.tokenindex = "-";
+			}
+			else if (code === 124) { // |
+				if (this.expression.charCodeAt(this.pos + 1) === 124) {
+					this.pos++;
+					this.tokenprio = 0;
+					this.tokenindex = "||";
+				}
+				else {
+					return false;
+				}
+			}
+			else if (code === 42) { // *
+				this.tokenprio = 1;
+				this.tokenindex = "*";
+			}
+			else if (code === 47) { // /
+				this.tokenprio = 2;
+				this.tokenindex = "/";
+			}
+			else if (code === 37) { // %
+				this.tokenprio = 2;
+				this.tokenindex = "%";
+			}
+			else if (code === 94) { // ^
+				this.tokenprio = 3;
+				this.tokenindex = "^";
+			}
+			else {
+				return false;
+			}
+			this.pos++;
+			return true;
+		},
+
+		isSign: function () {
+			var code = this.expression.charCodeAt(this.pos - 1);
+			if (code === 45 || code === 43) { // -
+				return true;
+			}
+			return false;
+		},
+
+		isPositiveSign: function () {
+			var code = this.expression.charCodeAt(this.pos - 1);
+			if (code === 43) { // -
+				return true;
+			}
+			return false;
+		},
+
+		isNegativeSign: function () {
+			var code = this.expression.charCodeAt(this.pos - 1);
+			if (code === 45) { // -
+				return true;
+			}
+			return false;
+		},
+
+		isLeftParenth: function () {
+			var code = this.expression.charCodeAt(this.pos);
+			if (code === 40) { // (
+				this.pos++;
+				this.tmpprio += 10;
+				return true;
+			}
+			return false;
+		},
+
+		isRightParenth: function () {
+			var code = this.expression.charCodeAt(this.pos);
+			if (code === 41) { // )
+				this.pos++;
+				this.tmpprio -= 10;
+				return true;
+			}
+			return false;
+		},
+
+		isComma: function () {
+			var code = this.expression.charCodeAt(this.pos);
+			if (code === 44) { // ,
+				this.pos++;
+				this.tokenprio = -1;
+				this.tokenindex = ",";
+				return true;
+			}
+			return false;
+		},
+
+		isWhite: function () {
+			var code = this.expression.charCodeAt(this.pos);
+			if (code === 32 || code === 9 || code === 10 || code === 13) {
+				this.pos++;
+				return true;
+			}
+			return false;
+		},
+
+		isOp1: function () {
+			var str = "";
+			for (var i = this.pos; i < this.expression.length; i++) {
+				var c = this.expression.charAt(i);
+				if (c.toUpperCase() === c.toLowerCase()) {
+					if (i === this.pos || (c != '_' && (c < '0' || c > '9'))) {
+						break;
+					}
+				}
+				str += c;
+			}
+			if (str.length > 0 && (str in this.ops1)) {
+				this.tokenindex = str;
+				this.tokenprio = 5;
+				this.pos += str.length;
+				return true;
+			}
+			return false;
+		},
+
+		isOp2: function () {
+			var str = "";
+			for (var i = this.pos; i < this.expression.length; i++) {
+				var c = this.expression.charAt(i);
+				if (c.toUpperCase() === c.toLowerCase()) {
+					if (i === this.pos || (c != '_' && (c < '0' || c > '9'))) {
+						break;
+					}
+				}
+				str += c;
+			}
+			if (str.length > 0 && (str in this.ops2)) {
+				this.tokenindex = str;
+				this.tokenprio = 5;
+				this.pos += str.length;
+				return true;
+			}
+			return false;
+		},
+
+		isVar: function () {
+			var str = "";
+			for (var i = this.pos; i < this.expression.length; i++) {
+				var c = this.expression.charAt(i);
+				if (c.toUpperCase() === c.toLowerCase()) {
+					if (i === this.pos || (c != '_' && (c < '0' || c > '9'))) {
+						break;
+					}
+				}
+				str += c;
+			}
+			if (str.length > 0) {
+				this.tokenindex = str;
+				this.tokenprio = 4;
+				this.pos += str.length;
+				return true;
+			}
+			return false;
+		},
+
+		isComment: function () {
+			var code = this.expression.charCodeAt(this.pos - 1);
+			if (code === 47 && this.expression.charCodeAt(this.pos) === 42) {
+				this.pos = this.expression.indexOf("*/", this.pos) + 2;
+				if (this.pos === 1) {
+					this.pos = this.expression.length;
+				}
+				return true;
+			}
+			return false;
+		}
+	};
+
+	scope.Parser = Parser;
+	return Parser
+})(typeof exports === 'undefined' ? {} : exports);
diff --git a/standard-feeds/developer.js b/standard-feeds/developer.js
index bda85e6..d28e569 100644
--- a/standard-feeds/developer.js
+++ b/standard-feeds/developer.js
@@ -2,7 +2,7 @@
 // DEVELOPER COMMANDS
 // -----------------------------------------------------------------
 
-var {slice} = Array, gXS = XMLSerializer(), H = Utils.escapeHtml;
+var {slice} = Array, gXS = new XMLSerializer(), H = Utils.escapeHtml;
 function qsaa(lm, sl) slice(lm.querySelectorAll(sl));
 function qstc(lm, sl) (lm = lm.querySelector(sl)) ? lm.textContent : "";
 function qsxs(lm, sl) (
diff --git a/standard-feeds/general.js b/standard-feeds/general.js
index 37e63fc..8c7fda8 100644
--- a/standard-feeds/general.js
+++ b/standard-feeds/general.js
@@ -2,6 +2,8 @@
 // TEXT COMMANDS
 // -----------------------------------------------------------------
 
+Cu.import("resource://gre/modules/Services.jsm")
+
 var H = Utils.escapeHtml;
 
 /* Note that these text formatting commands are a little weird in that
@@ -118,121 +120,44 @@ CmdUtils.CreateCommand({
 // CALCULATE COMMANDS
 // -----------------------------------------------------------------
 
-//+ Carlos R. L. Rodrigues
-//@ http://jsfromhell.com/classes/math-parser [rev. #2]
-function MathParser(){
-  var o = this, p = o.operator = {};
-  p["+"] = function(n, m){return n + m;};
-  p["-"] = function(n, m){return n - m;};
-  p["*"] = function(n, m){return n * m;};
-  p["/"] = function(m, n){return n / m;};
-  p["%"] = function(m, n){return n % m;};
-  p["^"] = function(m, n){return Math.pow(n, m);};
-  p["~"] = function(m, n){return Math.sqrt(n, m);};
-  o.custom = {}, p.f = function(s, n){
-    if(Math[s]) return Math[s](n);
-    else if(o.custom[s]) return o.custom[s].apply(o, n);
-    else throw new Error("Function \"" + s + "\" not defined.");
-  }, o.add = function(n, f){this.custom[n] = f;}
-};
-MathParser.prototype.eval = function(e){
-  var e = e.split(""), v = [], p = [], a, c = 0, s = 0, x, t, d = 0;
-  var n = "0123456789.", o = "+-*/^%~", f = this.operator;
-  for(var i = 0, l = e.length; i < l; i++)
-    if(o.indexOf(e[i]) > -1)
-      e[i] == "-" && (s > 1 || !d) && ++s, !s && d && (p.push(e[i]), s = 2), "+-".indexOf(e[i]) < (d = 0) && (c = 1);
-    else if(a = n.indexOf(e[i]) + 1 ? e[i++] : ""){
-      while(n.indexOf(e[i]) + 1) a += e[i++];
-      v.push(d = (s & 1 ? -1 : 1) * a), c && v.push(f[p.pop()](v.pop(), v.pop())) && (c = 0), --i, s = 0;
-    }
-  for(c = v[0], i = 0, l = p.length; l--; c = f[p[i]](c, v[++i]));
-  return c;
-};
-MathParser.prototype.parse = function(e){
-  var p = [], f = [], ag, n, c, a, o = this, v = "0123456789.+-*/^%~(, )";
-  for(var x, i = 0, l = e.length; i < l; i++){
-    if(v.indexOf(c = e.charAt(i)) < 0){
-      for(a = c; v.indexOf(c = e.charAt(++i)) < 0; a += c); f.push((--i, a));
-    }
-    else if(!(c == "(" && p.push(i)) && c == ")"){
-      if(a = e.slice(0, (n = p.pop()) - (x = v.indexOf(e.charAt(n - 1)) < 0 ? y = (c = f.pop()).length : 0)), x)
-        for(var j = (ag = e.slice(n, ++i).split(",")).length; j--; ag[j] = o.eval(ag[j]));
-      l = (e = a + (x ? o.operator.f(c, ag) : o.eval(e.slice(n, ++i))) + e.slice(i)).length, i -= i - n + c.length;
-    }
-  }
-  return o.eval(e);
-};
-
-const GCalcHelp = "http://www.googleguide.com/help/calculator.html";
 const noun_calc = {
-  name: "calc",
   label: "expression",
-  rankLast: true,
-  noExternalCalls: true,
-  suggest: function n_calc_suggest(text, html, cb, selIndices) {
-    var simple = this._simple.test(text);
-    return [CmdUtils.makeSugg(text, "", simple, simple ? 1 : .5, selIndices)];
+  suggest: function (txt, htm, cb, si) {
+    if (!this._mathlike.test(txt)) return []
+    try {
+      var result = this.Parser.evaluate(txt)
+        , score  = result === txt ? .3 : 1
+    }
+    catch (e) {
+      result = e.message
+      score  = .1
+    }
+    return [CmdUtils.makeSugg(txt, htm, result, score, si)];
   },
-  _simple: /^[\d.+\-*\/^%~(, )]+$/,
-};
+  _mathlike: /^[\w.+\-*\/^%(, )|]+$/,
+}
+Services.scriptloader.loadSubScript
+("resource://ubiquity/scripts/math_parser.js", noun_calc)
 
 CmdUtils.CreateCommand({
-  names: ["calculate", "gcalculate"],
-  argument: noun_calc,
-  description: '\
-    Calculates using <a href="' + GCalcHelp +'">Google Calculator</a>\
-    which has all the features of a scientific calculator,\
-    knows constants such as the speed of light,\
-    and can convert between units and currencies.<br/>\
-    Uses <a href="http://jsfromhell.com/classes/math-parser">MathParser</a>\
-    instead for simple expressions like <code>22/7</code>.',
-  help: ("Try <code>22/7, 25% of 700, sin(sqrt(ln(pi))), (1+i)^3, " +
-         "15 mod 9, (5 choose 2) / 3!, speed of light in miles per hour, " +
-         "3 dollars in euros, 242 in hex, MCMXVI in decimal</code>."),
+  names: "calculate",
+  description:
+    'Calculates using\
+     <a href="http://silentmatt.com/javascript-expression-evaluator/">\
+     JavaScript Expression Evaluator</a>.',
+  help: "Try: <code>22/7, 3^4^5, sin(sqrt(log(PI)))</code>",
   icon: "chrome://ubiquity/skin/icons/calculator.png",
-  author: {name: "Axel Boldt", email: "axelboldt at yahoo.com"},
-  contributor: {name: "satyr", email: "murky.satyr at gmail.com"},
-  homepage: "http://math-www.uni-paderborn.de/~axel/",
+  author: "satyr",
   license: "Public domain",
-  _math_parser: new MathParser,
-  // URL of Google page to which expression is to be appended.
-  // We want only 1 result.
-  _google_url: function (q) ("http://www.google.com/search?hl=en&num=1&q=" +
-                             encodeURIComponent(q)),
-  _calc: function ({text: exp, data: simple}, cb, pb) {
-    if (simple) {
-      try { var result = this._math_parser.parse(exp) } catch (e) {}
-      if (result != null) {
-        cb(result);
-        return;
-      }
-    }
-    var url = this._google_url(exp), fn = function gcalc(result_page) {
-      cb((/\/calculator-40\.gif.*?<b>(.*?)<\/b>/i.exec(result_page) || ",?")[1]);
-    };
-    pb ? CmdUtils.previewGet(pb, url, fn) : $.get(url, fn);
+  argument: noun_calc,
+  execute: function ({object: {data, score}}) {
+    if (score > .3) CmdUtils.setSelection(data)
+    displayMessage(data)
   },
-  execute: function ({object}) {
-    this._calc(object, function (result) {
-      CmdUtils.setSelection(result);
-    });
+  preview: function (pb, {object: {data, score}}) {
+    pb.innerHTML = (score < .3 ? "<em class=error>" : "<strong>") + data
   },
-  preview: function (pb, {object}) {
-    if (!object.text) {
-      this.previewDefault(pb);
-      return;
-    }
-    this._calc(object, function (result) {
-      pb.innerHTML = (
-        '<div class="calculate">' +
-        '<b style="font-size:larger">' + result + '</b>' +
-        (typeof result === "string"
-         ? '<p><a href="' + GCalcHelp + '">Quick Reference</a></p>'
-         : "") +
-        '</div>');
-    }, pb);
-  }
-});
+})
 
 // -----------------------------------------------------------------
 // TRANSLATE COMMANDS
diff --git a/standard-feeds/search.xhtml b/standard-feeds/search.xhtml
index 996c853..6acefd3 100644
--- a/standard-feeds/search.xhtml
+++ b/standard-feeds/search.xhtml
@@ -234,7 +234,7 @@ body {margin:0; padding:0}
 .adp-listheader, .adp-legal {display:none}
 #trips, #addrs {
   max-width: 40%;
-  position:absolute; top:30px; right:4px; z-index:5;
+  position:absolute; bottom:12px; right:4px; z-index:5;
   background-color:#000; opacity:0.666; font-size:76%;
   border-radius:6px;
 }
@@ -436,20 +436,6 @@ CmdUtils.CreateCommand({
 });
 
 CmdUtils.makeSearchCommand({
-  names: ["IMDb", "internet movie database", "movie", "actor"],
-  url: "http://www.imdb.com/find?s=all&q={QUERY}",
-  defaultUrl: "http://www.imdb.com/",
-  icon: "chrome://ubiquity/skin/icons/imdb.ico",
-  parser: {
-    container: "#main > table > tbody > tr",
-    title: "td + td + td > a",
-    thumbnail: "td:first > a > img",
-    body: "td + td + td > a ~ *",
-    maxResults: 8,
-  },
-});
-
-CmdUtils.makeSearchCommand({
   names: ["Yahoo!"],
   url: "http://search.yahoo.com/search?ei=UTF-8&p={QUERY}",
   defaultUrl: "http://www.yahoo.com",
@@ -637,40 +623,6 @@ CmdUtils.CreateCommand({
   }
 });
 
-CmdUtils.CreateCommand({
-  names: ["VideoSurf", "videos"],
-  homepage: "http://www.videosurf.com/",
-  author: {name: "Udi Falkson", email: "udi at videosurf.com"},
-  description: "Performs a VideoSurf video search with advanced preview.",
-  help: ("Please email us at feedback at videosurf.com " +
-         "if you have any trouble or feature ideas!"),
-  icon: "chrome://ubiquity/skin/icons/videosurf.ico",
-  arguments: [{role: "object", nountype: noun_arb_text, label: SEARCH_TERM}],
-  preview: function vsurf_preview(pblock, {object: {text}}) {
-    pblock.innerHTML = _("Loading videos...");
-    var url = "http://www.videosurf.com/api/ext/services/ubiquityService.php";
-    $.get(url, {query: text}, function vsurf_success(response) {
-      pblock.innerHTML = response;
-      function getThumb(img) $("#vs_thumb_" + img.id.split("_")[2], pblock)[0];
-      var originalSrc = null;
-      $(".tiles li a img", pblock).hover(
-        function vsurf_mouseover({target: img}) {
-          var thumb = getThumb(img);
-          originalSrc = thumb.src;
-          thumb.src = img.src;
-        },
-        function vsurf_mouseout({target: img}) {
-          getThumb(img).src = originalSrc;
-        });
-    });
-  },
-  execute: function vsurf_execute({object: {text}}) {
-    Utils.openUrlInBrowser(
-      "http://www.videosurf.com/videos/" +
-      encodeURI(text.trim()).replace(/%20/g, "+") + "?vlt=ubiquity");
-  }
-});
-
 CmdUtils.makeSearchCommand({
   names: ["YouTube"],
   url: ("http://www.youtube.com/results?search_type=search_videos" +
@@ -747,7 +699,7 @@ CmdUtils.makeSearchCommand({
 CmdUtils.makeSearchCommand({
   names: ["Bugzilla"],
   url: "https://bugzilla.mozilla.org/buglist.cgi?quicksearch=%s",
-  defaultUrl: "https://bugzilla.mozilla.com",
+  defaultUrl: "https://bugzilla.mozilla.org",
   help: "Bugzilla QuickSearch".link(
     "https://bugzilla.mozilla.org/page.cgi?id=quicksearch.html"),
   icon: "chrome://ubiquity/skin/icons/mozilla.ico",
@@ -781,148 +733,18 @@ CmdUtils.makeSearchCommand({
 });
 
 CmdUtils.makeSearchCommand({
-  names: ["eBay"],
-  url: "http://search.ebay.com/search/search.dll?satitle={QUERY}",
-  defaultUrl: "http://www.ebay.com/",
-  icon: "chrome://ubiquity/skin/icons/ebay.ico",
-  parser: {
-    container: "#ResultSet .li, #ResultSet .pcell, #ResultSet .tri-i",
-    title: ".ttl, a.ittl",
-    body: ".bids, .prc, .tme, .pctr, .fc",
-    thumbnail: ".pic img",
-    maxResults: 30,
-  },
-});
-
-CmdUtils.makeSearchCommand({
-  names: ["Ask.com"],
-  url: "http://www.ask.com/web?q={QUERY}",
-  defaultUrl: "http://www.ask.com/",
-  icon: "chrome://ubiquity/skin/icons/ask.ico",
-  parser: {
-    container: "#teoma-results > div > div",
-    title: ".title",
-    body: ".abstract",
-    maxResults: 10,
-  },
-});
-
-CmdUtils.makeSearchCommand({
-  names: ["Answers.com"],
-  url: "http://www.answers.com/{QUERY}",
-  defaultUrl: "http://www.answers.com",
-  icon: "chrome://ubiquity/skin/icons/answers.ico",
+  name: "IMDb",
+  url: "http://www.imdb.com/find?q=%s",
+  defaultUrl: "http://www.imdb.com",
+  icon: "chrome://ubiquity/skin/icons/imdb.ico",
   parser: {
-    container: "#new_left > a + div",
-    title: ".DsAndEntryName a",
-    body: ".content",
+    container  : ".findResult",
+    title      : ".result_text",
+    thumbnail  : ".primary_photo",
+    maxResults : 8,
   },
 });
 
-var formatYelpBusiness = function(biz) {
-  var phone = biz.phone.replace(/(\d\d\d)(\d\d\d)(\d\d\d\d)/, "$1.$2.$3");
-  var name = CmdUtils.renderTemplate('<span class="name"><a href="${url}">${name}</a></span>',biz);
-  return _("${name} in ${city} {if phone}(${phone}){/if} ? ${avg_rating} stars.",
-           {name:name, phone:phone, city: biz.city, avg_rating: biz.avg_rating});
-};
-
-CmdUtils.CreateCommand({
-  names: ["Yelp"],
-  arguments: [
-    {role: "object", label: "restaurant", nountype: noun_type_async_restaurant},
-    {role: "location", nountype: noun_type_geo_town}
-  ],
-  icon: "chrome://ubiquity/skin/icons/yelp.ico",
-  description: "Searches <a href=\"http://www.yelp.com\">Yelp</a> for restaurants matching your words.  Previews the top results.",
-  help: "You can search for restaurants near a certain location using the <i>near</i> modifier.  For example, try "yelp pizza near boston".",
-  execute: function( args ) {
-    var object = args.object;
-    var location = args.location;
-
-    // if no location was specified, use geolocation
-    var near = "";
-    if (location.text) {
-      near = location.text;
-    } else {
-      var loc = CmdUtils.getGeoLocation();
-      if (loc)
-        near = loc.city + ", " + loc.state;
-    }
-
-    var doc = context.focusedWindow.document;
-    var focused = context.focusedElement;
-
-    if (doc.designMode == "on") {
-      var data = globals.yelp[0];
-
-      var name = CmdUtils.renderTemplate(
-                   "<img style='float:left;margin:5px;border:solid #ccc 5px;' src='${photoUrl}'/><a href='${url}'>${name}</a>",
-                   { url: data.url,
-                     photoUrl: data.photo_url_small,
-                     name: data.name });
-
-      var stars = CmdUtils.renderTemplate(
-                    "<img style='position:relative;top:5px;' src='${starUrl}'/>",
-                    {starUrl: data.rating_img_url});
-
-      var templateParams = { city: data.city, name: name, stars: stars };
-      if( data.neighborhoods.length > 0 ) {
-        templateParams.whereUrl = data.neighborhoods[0].url;
-        templateParams.where = data.neighborhoods[0].name;
-      }
-
-      var msg = _("${name} is a ${stars} restaurant in{if defined('where')} <a href='${whereUrl}'>${where},</a>{/if} ${city}.", templateParams)
-                + "<br/>"
-                + _("It's been reviewed ${times} times.", {times: data.review_count});
-
-      CmdUtils.setSelection( msg );
-      return;
-    }
-
-    var query = object.text;
-    var url = "http://www.yelp.com/search?find_desc={QUERY}&find_loc={NEAR}";
-    url = url.replace( /{QUERY}/g, query);
-    url = url.replace( /{NEAR}/g, near);
-
-    Utils.openUrlInBrowser( url );
-  },
-
-  preview: function( pblock, args ) {
-    var {object, location} = args;
-    var query = object.text;
-    var url = "http://api.yelp.com/business_review_search?";
-
-    if(!query.length && !location.text){
-      pblock.innerHTML = _("Searches yelp for restaurants in your area");
-      return;
-    }
-
-    var near = "";
-    if (location.text) {
-      near = location.text;
-    } else {
-      var loc = CmdUtils.getGeoLocation();
-      if (loc)
-        near = loc.city + ", " + loc.state;
-    }
-
-    var params = {
-      term: query,
-      num_biz_requested: 4,
-      location: near,
-      ywsid: "HbSZ2zXYuMnu1VTImlyA9A"
-    };
-
-    CmdUtils.previewGet( pblock, url, params, function(data) {
-      globals.yelp = data.businesses;
-      pblock.innerHTML = CmdUtils.renderTemplate(
-        feed.dom.getElementById("yelp-search").innerHTML,
-        {businesses: data.businesses,
-         _MODIFIERS: {yelpBusiness: formatYelpBusiness}}
-      );
-    }, "json");
-  }
-});
 
 // -----------------------------------------------------------------
 // WEATHER COMMANDS
@@ -1520,9 +1342,12 @@ MAP_INIT = '!'+ function init([lat, lng, type, zoom]){
     'tied' in it || it.addEventListener('click', fn, it.tied = true)
   }
   function mapact(key, url){
-    var ev = document.createEvent('MessageEvent')
-    ev.initMessageEvent('action', 0, 0, url || '', '*', key || '', self)
-    dispatchEvent(ev)
+    dispatchEvent(new MessageEvent('action', {
+      data: url || '',
+      origin: '*',
+      lastEventId: key || '',
+      source: self,
+    }))
   }
 }
 { let loc = CmdUtils.geoLocation
@@ -1592,16 +1417,19 @@ CmdUtils.CreateCommand({
         '('+ uneval([gCoords.lat, gCoords.lon, dat.type, dat.zoom]) +')'
       pb.appendChild(script)
     }
-    var win = doc.defaultView, ev = doc.createEvent('MessageEvent')
-    ev.initMessageEvent('go', 0, 0, JSON.stringify({
-      q: q, dest: dest,
-      lat: gCoords.lat,
-      lon: gCoords.lon,
-      lang: lang || 'en',
-      type: dat.type,
-      zoom: dat.zoom,
-    }), '*', '', win)
-    win.dispatchEvent(ev)
+    var win = doc.defaultView
+    win.dispatchEvent(new win.MessageEvent('go', {
+      data: JSON.stringify({
+        q: q, dest: dest,
+        lat: gCoords.lat,
+        lon: gCoords.lon,
+        lang: lang || 'en',
+        type: dat.type,
+        zoom: dat.zoom,
+      }),
+      origin: '*',
+      source: win,
+    }))
     win.addEventListener('action', this._act, false)
     this._act.me = this
   },
diff --git a/tests/test_all.js b/tests/test_all.js
index 47ab0e3..bfd80c6 100755
--- a/tests/test_all.js
+++ b/tests/test_all.js
@@ -573,10 +573,8 @@ function testUtilsEllipsify() {
 }
 
 function testL10nUtilsPropertySelector() {
-  var ps = LocalizationUtils.propertySelector("data:," + encodeURI(<![CDATA[
-    foo=%S %S
-    colon:works too
-    ]]>));
+  var ps = LocalizationUtils.propertySelector(
+    "data:," + encodeURI("\n  foo=%S %S\n  colon:works too\n"));
   this.assertEquals(ps("foo", "bar", "baz"), "bar baz");
   this.assertEquals(ps("colon"), "works too");
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/ubiquity-extension.git



More information about the Pkg-mozext-commits mailing list