michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: "use strict"; michael@0: michael@0: const { resolveURI, Require, michael@0: unload, override, descriptor } = require('../../toolkit/loader'); michael@0: const { ensure } = require('../system/unload'); michael@0: const addonWindow = require('../addon/window'); michael@0: const { PlainTextConsole } = require('sdk/console/plain-text'); michael@0: michael@0: let defaultGlobals = override(require('../system/globals'), { michael@0: console: console michael@0: }); michael@0: michael@0: function CustomLoader(module, globals, packaging, overrides={}) { michael@0: let options = packaging || require("@loader/options"); michael@0: options = override(options, { michael@0: id: overrides.id || options.id, michael@0: globals: override(defaultGlobals, globals || {}), michael@0: modules: override(options.modules || {}, { michael@0: 'sdk/addon/window': addonWindow michael@0: }) michael@0: }); michael@0: michael@0: let loaderModule = options.isNative ? '../../toolkit/loader' : '../loader/cuddlefish'; michael@0: let { Loader } = require(loaderModule); michael@0: let loader = Loader(options); michael@0: let wrapper = Object.create(loader, descriptor({ michael@0: require: Require(loader, module), michael@0: sandbox: function(id) { michael@0: let requirement = loader.resolve(id, module.id); michael@0: let uri = resolveURI(requirement, loader.mapping); michael@0: return loader.sandboxes[uri]; michael@0: }, michael@0: unload: function(reason) { michael@0: unload(loader, reason); michael@0: } michael@0: })); michael@0: ensure(wrapper); michael@0: return wrapper; michael@0: }; michael@0: exports.Loader = CustomLoader; michael@0: michael@0: function HookedPlainTextConsole(hook, print, innerID) { michael@0: this.log = hook.bind(null, "log", innerID); michael@0: this.info = hook.bind(null, "info", innerID); michael@0: this.warn = hook.bind(null, "warn", innerID); michael@0: this.error = hook.bind(null, "error", innerID); michael@0: this.debug = hook.bind(null, "debug", innerID); michael@0: this.exception = hook.bind(null, "exception", innerID); michael@0: this.time = hook.bind(null, "time", innerID); michael@0: this.timeEnd = hook.bind(null, "timeEnd", innerID); michael@0: michael@0: this.__exposedProps__ = { michael@0: log: "rw", info: "rw", warn: "rw", error: "rw", debug: "rw", michael@0: exception: "rw", time: "rw", timeEnd: "rw" michael@0: }; michael@0: } michael@0: michael@0: // Creates a custom loader instance whose console module is hooked in order michael@0: // to avoid printing messages to the console, and instead, expose them in the michael@0: // returned `messages` array attribute michael@0: exports.LoaderWithHookedConsole = function (module, callback) { michael@0: let messages = []; michael@0: function hook(type, innerID, msg) { michael@0: messages.push({ type: type, msg: msg, innerID: innerID }); michael@0: if (callback) michael@0: callback(type, msg, innerID); michael@0: } michael@0: michael@0: return { michael@0: loader: CustomLoader(module, { michael@0: console: new HookedPlainTextConsole(hook, null, null) michael@0: }, override(require("@loader/options"), { michael@0: modules: { michael@0: 'sdk/console/plain-text': { michael@0: PlainTextConsole: HookedPlainTextConsole.bind(null, hook) michael@0: } michael@0: } michael@0: })), michael@0: messages: messages michael@0: }; michael@0: } michael@0: michael@0: // Same than LoaderWithHookedConsole with lower level, instead we get what is michael@0: // actually printed to the command line console michael@0: exports.LoaderWithHookedConsole2 = function (module, callback) { michael@0: let messages = []; michael@0: return { michael@0: loader: CustomLoader(module, { michael@0: console: new PlainTextConsole(function (msg) { michael@0: messages.push(msg); michael@0: if (callback) michael@0: callback(msg); michael@0: }) michael@0: }), michael@0: messages: messages michael@0: }; michael@0: } michael@0: michael@0: // Creates a custom loader with a filtered console. The callback is passed every michael@0: // console message type and message and if it returns false the message will michael@0: // not be logged normally michael@0: exports.LoaderWithFilteredConsole = function (module, callback) { michael@0: function hook(type, innerID, msg) { michael@0: if (callback && callback(type, msg, innerID) == false) michael@0: return; michael@0: console[type](msg); michael@0: } michael@0: michael@0: return CustomLoader(module, { michael@0: console: new HookedPlainTextConsole(hook, null, null) michael@0: }, override(require("@loader/options"), { michael@0: modules: { michael@0: 'sdk/console/plain-text': { michael@0: PlainTextConsole: HookedPlainTextConsole.bind(null, hook) michael@0: } michael@0: } michael@0: })); michael@0: }