(function() { var _modules = {}; var _requires = {}; var _callbacks = []; var _initialized = false; var _pending = []; var _contexts = {}; var _applyRequired = function(names, callback) { if (names === null) callback.call(this, _modules); else { var modules = []; var name, detail; for (var j=0, m=names.length; jnull was passed to require the callback will only * have one parameter that contains all modules. * * @example * require(["foo", "bar"], function(foo, bar) { * ... * }); * require(null, function(modules) { * var foo = modules.foo; * var bar = modules.bar; * }); * * * */ if (callback) callback.apply(callback, modules); } }; Object.defineProperties(this, { "Glob" : { value : (function() { var esc = new RegExp("[-\/\\^$+.()|[\]{}]", "g"); var matcher = new RegExp("(\\\\)?([*?])", "g"); var cnstr = function (m, f, s) { return f ? m : s == "?" ? "." : ".*"; }; /** * Constructs a new Glob * * @name Glob * @class Globs are similar to regular expressions but much * simpler, can be used for pattern matching. They * only match against wildcard * and joker * ? where the wildcard character matches * any number of unknown characters and the joker * matches exactly one unkown character. Note that * internally regular expressions are used, so Glob * matching is not faster than RegExp matching. * @constructs Glob * * @param {String} pattern The pattern to match against * * @example * var g = new Glob("foo*ba?baz"); * */ return function(p) { var inner = p.replace(esc, '\\$&').replace(matcher, cnstr); var regex = new RegExp("^" + inner + "$"); var searchPattern = new RegExp(inner); return Object.create(Object.prototype, { /** * Match against a text * @name match * @memberOf Glob.prototype * @function * @example * var glob = new Glob("foo*ba?"); * glob.match("foobarbaz"); // true * glob.match("foobaz"); // true * glob.match("foobarbazx"); // false * glob.match("fooba"); // false * * @param {String} text The text to match * against * @returns {Boolean} * true if the pattern was found * */ match : { value : function(string) { return regex.test(string); } }, /** * Searches for the first occurence of the pattern * in a string and returns the position. * * @name search * @memberOf Glob.prototype * @function * * @param {String} string * The string to search for the pattern * * @returns {Number} * The first occurence or -1 if the pattern was * not found * * @example * var glob = new Glob("l?si*"); * glob.search("Melosine"); // 2 * */ search : { value : function(string) { return string.search(searchPattern); } }, /** * Searches for the first occurence of the pattern * in a string and returns the match. * * @name exec * @memberOf Glob.prototype * @function * * @param {String} string * The string to search for the pattern * * @returns {String} * The match or null if the pattern * wasn't found * @example * var glob = new Glob("l*si?"); * glob.exec("Melosine"); // "losin" * */ exec : { value : function(string) { var match = searchPattern.exec(string); return match ? match[0] : null; } }, /** * Converts a glob to string * @name toString * @memberOf Glob.prototype * @function * * @returns {String} * The original pattern passed to the constructor * */ toString : { value : function() { return p; } } }); }; })() }, /** * Define a module that can be retrieved with require in other scripts * @name provide * @function * * @param {String} name The name of the module * @param {Object} module The module * @param {Boolean} overwrite * Whether to overwrite existing module with * the same name * @example * provide("foo", { * baz : 37, * bar : function() { ... } * }); * * */ "provide" : { value : function(name, module, overwrite) { if (overwrite) { if (!module && _modules[name]) { for (var key in _modules[name]) delete _modules[name][key]; delete _modules[name]; } } if (!overwrite && _modules[name]) { io.debug({ offset : 1, arguments : arguments, error : new Error("provide: Module " + name + " is already defined!") }); } else _modules[name] = module; var pl = _pending.length; if (pl > 0) { var pending = []; var finished = []; for (var i=0; iscript * refers to the encapsulating function. * * @namespace * @name script * * */ Object.defineProperties(self, { /** * The path of the script * * @name path * @memberOf script * @constant * */ "path" : { value : path }, /** * Print debug messages. Basically the same as * {@link io.debug} but prints some additional * information. * * @name debug * @memberOf script * @function * @param {Object|Function} params|Function * Parameters passed to {@link io.debug} or a function to debug, see also {@link Function} * * @example * script.debug({ message : "foobar" }); * * var myFunction = function() { * ... * }; * * bind("xx", script.debug(myFunction)); * * // Equivalent to * bind("xx", myFunction.debug(script)); * * */ "debug" : { value : io.debug.bind(self) }, "_arguments" : { value : arguments }, /** * Generates a unique id. Successive calls will * generate new ids. * * @name generateId * @memberOf script * @function * * @returns {String} * A unique id * */ "generateId" : { value : generateId }, /** * * Convenience function to set a private property on an object that doesn’t conflict * with properties set in other scripts. It uses a random unique id to set the property, so * the property can most likely only be retrieved with {@link script.getPrivate|getPrivate}. This is * mostly useful for objects derived from GObject since GObjects are shared between all * scripts. * * @name setPrivate * @memberOf script * @function * * @param {Object} object * The object whichs property will be set * @param {String} key The property name * @param {Object} value The value to set * @example * signals.connect("loadFinished", function(wv) { * // would conflict if another script also sets foo on the same webview * wv.foo = "bar" * // secure, won't conflict with other scripts * script.setPrivate(wv, "foo", "bar"); * }); * */ "setPrivate" : { value : function(id, object, key, value) { var realKey = key + id; if (object[realKey]) object[realKey] = value; else { Object.defineProperty(object, realKey, { value : value, writable : true }); } }.bind(self, id) }, /** * Gets a private property of an object previously set with {@link script.setPrivate|setPrivate} * * @name getPrivate * @memberOf script * @function * * @param {Object} object The object on which the value was set * @param {String} key The property name * * @returns {Object} * The private value * */ "getPrivate" : { value : function(id, object, key) { return object[key + id]; }.bind(self, id) } }); Object.freeze(self); }; })() }, // Called after all scripts have been loaded and executed // Immediately deleted from the global object, so it is not callable // from other scripts "_initAfter" : { value : function() { var i, l; _initialized = true; for (i=0, l=_callbacks.length; i DEBUG [FILE] : /path/to/script.js * ==> DEBUG [ERROR] : Error in line 4: Can't find variable: y * ==> DEBUG [STACK] : [onNavigation] [[native code]] [value] [[native code]] * ==> DEBUG [SOURCE] * ... * 4 > function onNavigation( { * --> 5 > var x = y; * 6 > } * ... * */ if (!Function.prototype.debug) { Object.defineProperty(Function.prototype, "debug", { value : function(scope) { return function() { try { return this.apply(this, arguments); } catch (e) { if (scope) scope.debug(e); else io.debug(e); } return undefined; }.bind(this); } }); } /** * Standard javascript array with additional methods * @name Array * @class * */ /** * Basically the same as Array.indexOf but without typechecking * @name fastIndexOf * @memberOf Array.prototype * @function * * @param {Object} object Object to search for * * @returns {Number} * The index of the object or -1 if the array doesn't contain the * object * */ if (Array.prototype.fastIndexOf === undefined) { Object.defineProperty(Array.prototype, "fastIndexOf", { value : function (v) { for (var i=0, l=this.length; i=0; --i) { if (this[i] == v) return i; } return -1; } }); } /** * Standard RegExp object with additional methods * @name RegExp * @class * */ /** * Escapes special characters that are used in regular expressions * @name escape * @memberOf RegExp * @function * * @param {String} string String to escape * * @returns {String} * The escaped string * @example * // /.*foo\.bar\[\].*$/ * var r = new RegExp(".*" + RegExp.escape("foo.bar[]") + ".*$"); * */ if (! RegExp.escape) { Object.defineProperty(RegExp, "escape", { value : function(string) { return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); } }); } })(); Object.preventExtensions(this);