Bug 901239 - Uplift Add-on SDK to Firefox r=me

This commit is contained in:
Wes Kocher 2013-08-03 09:50:12 -07:00
Родитель 3bd4539a82
Коммит 60bea9af38
18 изменённых файлов: 467 добавлений и 197 удалений

Просмотреть файл

@ -140,6 +140,7 @@ We'd like to thank our many Jetpack project contributors! They include:
* Tim Taubert
* Shane Tomlinson
* Dave Townsend
* [Fraser Tweedale](https://github.com/frasertweedale)
* [Matthias Tylkowski](https://github.com/tylkomat)
### V ###

Просмотреть файл

@ -369,7 +369,7 @@ const WorkerSandbox = EventEmitter.compose({
/**
* Message-passing facility for communication between code running
* in the content and add-on process.
* @see https://jetpack.mozillalabs.com/sdk/latest/docs/#module/api-utils/content/worker
* @see https://addons.mozilla.org/en-US/developers/docs/sdk/latest/modules/sdk/content/worker.html
*/
const Worker = EventEmitter.compose({
on: Trait.required,

Просмотреть файл

@ -5,12 +5,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
module.metadata = {
"stability": "deprecated"
};
const memory = require("./memory");
const { merge } = require("../util/object");
const { union } = require("../util/array");
const { isNil } = require("../lang/type");
// The possible return values of getTypeOf.
const VALID_TYPES = [
"array",
@ -23,6 +27,8 @@ const VALID_TYPES = [
"undefined",
];
const { isArray } = Array;
/**
* Returns a function C that creates instances of privateCtor. C may be called
* with or without the new keyword. The prototype of each instance returned
@ -86,6 +92,7 @@ exports.validateOptions = function validateOptions(options, requirements) {
let validatedOptions = {};
for (let key in requirements) {
let isOptional = false;
let mapThrew = false;
let req = requirements[key];
let [optsVal, keyInOpts] = (key in options) ?
@ -103,17 +110,27 @@ exports.validateOptions = function validateOptions(options, requirements) {
}
}
if (req.is) {
// Sanity check the caller's type names.
req.is.forEach(function (typ) {
if (VALID_TYPES.indexOf(typ) < 0) {
let msg = 'Internal error: invalid requirement type "' + typ + '".';
throw new Error(msg);
}
});
if (req.is.indexOf(getTypeOf(optsVal)) < 0)
throw new RequirementError(key, req);
let types = req.is;
if (!isArray(types) && isArray(types.is))
types = types.is;
if (isArray(types)) {
isOptional = ['undefined', 'null'].every(v => ~types.indexOf(v));
// Sanity check the caller's type names.
types.forEach(function (typ) {
if (VALID_TYPES.indexOf(typ) < 0) {
let msg = 'Internal error: invalid requirement type "' + typ + '".';
throw new Error(msg);
}
});
if (types.indexOf(getTypeOf(optsVal)) < 0)
throw new RequirementError(key, req);
}
}
if (req.ok && !req.ok(optsVal))
if (req.ok && ((!isOptional || !isNil(optsVal)) && !req.ok(optsVal)))
throw new RequirementError(key, req);
if (keyInOpts || (req.map && !mapThrew && optsVal !== undefined))
@ -142,7 +159,7 @@ let getTypeOf = exports.getTypeOf = function getTypeOf(val) {
if (typ === "object") {
if (!val)
return "null";
if (Array.isArray(val))
if (isArray(val))
return "array";
}
return typ;
@ -164,3 +181,38 @@ function RequirementError(key, requirement) {
this.message = msg;
}
RequirementError.prototype = Object.create(Error.prototype);
let string = { is: ['string', 'undefined', 'null'] };
exports.string = string;
let number = { is: ['number', 'undefined', 'null'] };
exports.number = number;
let boolean = { is: ['boolean', 'undefined', 'null'] };
exports.boolean = boolean;
let object = { is: ['object', 'undefined', 'null'] };
exports.object = object;
let isTruthyType = type => !(type === 'undefined' || type === 'null');
let findTypes = v => { while (!isArray(v) && v.is) v = v.is; return v };
function required(req) {
let types = (findTypes(req) || VALID_TYPES).filter(isTruthyType);
return merge({}, req, {is: types});
}
exports.required = required;
function optional(req) {
req = merge({is: []}, req);
req.is = findTypes(req).filter(isTruthyType).concat('undefined', 'null');
return req;
}
exports.optional = optional;
function either(...types) {
return union.apply(null, types.map(findTypes));
}
exports.either = either;

Просмотреть файл

@ -33,6 +33,9 @@ const Tab = Class({
// TabReady
let onReady = tabInternals.onReady = onTabReady.bind(this);
tab.browser.addEventListener(EVENTS.ready.dom, onReady, false);
let onPageShow = tabInternals.onPageShow = onTabPageShow.bind(this);
tab.browser.addEventListener(EVENTS.pageshow.dom, onPageShow, false);
// TabClose
let onClose = tabInternals.onClose = onTabClose.bind(this);
@ -180,8 +183,10 @@ function cleanupTab(tab) {
if (tabInternals.tab.browser) {
tabInternals.tab.browser.removeEventListener(EVENTS.ready.dom, tabInternals.onReady, false);
tabInternals.tab.browser.removeEventListener(EVENTS.pageshow.dom, tabInternals.onPageShow, false);
}
tabInternals.onReady = null;
tabInternals.onPageShow = null;
tabInternals.window.BrowserApp.deck.removeEventListener(EVENTS.close.dom, tabInternals.onClose, false);
tabInternals.onClose = null;
rawTabNS(tabInternals.tab).tab = null;
@ -198,6 +203,12 @@ function onTabReady(event) {
}
}
function onTabPageShow(event) {
let win = event.target.defaultView;
if (win === win.top)
emit(this, 'pageshow', this, event.persisted);
}
// TabClose
function onTabClose(event) {
let rawTab = getTabForBrowser(event.target);

Просмотреть файл

@ -1,7 +1,6 @@
/* 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 = {
@ -277,3 +276,16 @@ let isValidURI = exports.isValidURI = function (uri) {
}
return true;
}
function isLocalURL(url) {
if (String.indexOf(url, './') === 0)
return true;
try {
return ['resource', 'data', 'chrome'].indexOf(URL(url).scheme) > -1;
}
catch(e) {}
return false;
}
exports.isLocalURL = isLocalURL;

Просмотреть файл

@ -72,12 +72,22 @@ exports.remove = function remove(array, element) {
* Source array.
* @returns {Array}
*/
exports.unique = function unique(array) {
return array.reduce(function(values, element) {
add(values, element);
return values;
function unique(array) {
return array.reduce(function(result, item) {
add(result, item);
return result;
}, []);
};
exports.unique = unique;
/**
* Produce an array that contains the union: each distinct element from all
* of the passed-in arrays.
*/
function union() {
return unique(Array.concat.apply(null, arguments));
};
exports.union = union;
exports.flatten = function flatten(array){
var flat = [];

Просмотреть файл

@ -131,9 +131,12 @@ function onTabOpen(event) {
tab.on('ready', function() emit(gTabs, 'ready', tab));
tab.once('close', onTabClose);
tab.on('pageshow', function(_tab, persisted)
emit(gTabs, 'pageshow', tab, persisted));
emit(tab, 'open', tab);
emit(gTabs, 'open', tab);
};
}
// TabSelect
function onTabSelect(event) {
@ -153,10 +156,10 @@ function onTabSelect(event) {
emit(t, 'deactivate', t);
emit(gTabs, 'deactivate', t);
}
};
}
// TabClose
function onTabClose(tab) {
removeTab(tab);
emit(gTabs, EVENTS.close.name, tab);
};
}

Просмотреть файл

@ -172,7 +172,7 @@ parser_groups = (
(("", "--strip-sdk",), dict(dest="bundle_sdk",
help=("Do not ship SDK modules in the xpi"),
action="store_false",
default=True,
default=False,
cmds=['run', 'test', 'testex', 'testpkgs',
'testall', 'xpi'])),
(("", "--force-use-bundled-sdk",), dict(dest="force_use_bundled_sdk",
@ -564,7 +564,7 @@ def initializer(env_root, args, out=sys.stdout, err=sys.stderr):
print >>out, 'Do "cfx test" to test it and "cfx run" to try it. Have fun!'
else:
print >>out, '\nYour sample add-on is now ready in the \'' + args[1] + '\' directory.'
print >>out, 'Change to that directory, then do "cfx test" to test it, \nand "cfx run" to try it. Have fun!'
print >>out, 'Change to that directory, then do "cfx test" to test it, \nand "cfx run" to try it. Have fun!'
return {"result":0, "jid":jid}
def buildJID(target_cfg):
@ -593,7 +593,7 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
(options, args) = parse_args(**parser_kwargs)
config_args = get_config_args(options.config, env_root);
# reparse configs with arguments from local.json
if config_args:
parser_kwargs['arguments'] += config_args

Просмотреть файл

@ -188,16 +188,13 @@ class Contents(unittest.TestCase):
self.failUnlessEqual(e.args[0], 0)
zf = zipfile.ZipFile("seven.xpi", "r")
names = zf.namelist()
# the first problem found in bug 664840 was that cuddlefish.js
# (the loader) was stripped out on windows, due to a /-vs-\ bug
self.assertIn("resources/addon-sdk/lib/sdk/loader/cuddlefish.js", names)
# the second problem found in bug 664840 was that an addon
# problem found in bug 664840 was that an addon
# without an explicit tests/ directory would copy all files from
# the package into a bogus JID-PKGNAME-tests/ directory, so check
# for that
testfiles = [fn for fn in names if "seven/tests" in fn]
self.failUnlessEqual([], testfiles)
# the third problem was that data files were being stripped from
# another problem was that data files were being stripped from
# the XPI. Note that data/ is only supposed to be included if a
# module that actually gets used does a require("self") .
self.assertIn("resources/seven/data/text.data",

Просмотреть файл

@ -406,7 +406,8 @@ class Runner(object):
def find_binary(self):
"""Finds the binary for self.names if one was not provided."""
binary = None
if sys.platform in ('linux2', 'sunos5', 'solaris'):
if sys.platform in ('linux2', 'sunos5', 'solaris') \
or sys.platform.startswith('freebsd'):
for name in reversed(self.names):
binary = findInPath(name)
elif os.name == 'nt' or sys.platform == 'cygwin':
@ -578,7 +579,8 @@ class FirefoxRunner(Runner):
def names(self):
if sys.platform == 'darwin':
return ['firefox', 'nightly', 'shiretoko']
if (sys.platform == 'linux2') or (sys.platform in ('sunos5', 'solaris')):
if sys.platform in ('linux2', 'sunos5', 'solaris') \
or sys.platform.startswith('freebsd'):
return ['firefox', 'mozilla-firefox', 'iceweasel']
if os.name == 'nt' or sys.platform == 'cygwin':
return ['firefox']

Просмотреть файл

@ -257,7 +257,8 @@ class Popen(subprocess.Popen):
self.kill(group)
else:
if (sys.platform == 'linux2') or (sys.platform in ('sunos5', 'solaris')):
if sys.platform in ('linux2', 'sunos5', 'solaris') \
or sys.platform.startswith('freebsd'):
def group_wait(timeout):
try:
os.waitpid(self.pid, 0)

Просмотреть файл

@ -949,40 +949,6 @@ exports.testOnLoadEventWithImage = function(test) {
});
};
exports.testOnPageShowEvent = function (test) {
test.waitUntilDone();
let firstUrl = 'data:text/html;charset=utf-8,First';
let secondUrl = 'data:text/html;charset=utf-8,Second';
openBrowserWindow(function(window, browser) {
let counter = 0;
tabs.on('pageshow', function onPageShow(tab, persisted) {
counter++;
if (counter === 1) {
test.assert(!persisted, 'page should not be cached on initial load');
tab.url = secondUrl;
}
else if (counter === 2) {
test.assert(!persisted, 'second test page should not be cached either');
tab.attach({
contentScript: 'setTimeout(function () { window.history.back(); }, 0)'
});
}
else {
test.assert(persisted, 'when we get back to the fist page, it has to' +
'come from cache');
tabs.removeListener('pageshow', onPageShow);
closeBrowserWindow(window, function() test.done());
}
});
tabs.open({
url: firstUrl
});
});
};
exports.testFaviconGetterDeprecation = function (test) {
const { LoaderWithHookedConsole } = require("sdk/test/loader");
let { loader, messages } = LoaderWithHookedConsole(module);

Просмотреть файл

@ -6,92 +6,94 @@
const apiUtils = require("sdk/deprecated/api-utils");
exports.testPublicConstructor = function (test) {
exports.testPublicConstructor = function (assert) {
function PrivateCtor() {}
PrivateCtor.prototype = {};
let PublicCtor = apiUtils.publicConstructor(PrivateCtor);
test.assert(
assert.ok(
PrivateCtor.prototype.isPrototypeOf(PublicCtor.prototype),
"PrivateCtor.prototype should be prototype of PublicCtor.prototype"
);
function testObj(useNew) {
let obj = useNew ? new PublicCtor() : PublicCtor();
test.assert(obj instanceof PublicCtor,
assert.ok(obj instanceof PublicCtor,
"Object should be instance of PublicCtor");
test.assert(obj instanceof PrivateCtor,
assert.ok(obj instanceof PrivateCtor,
"Object should be instance of PrivateCtor");
test.assert(PublicCtor.prototype.isPrototypeOf(obj),
assert.ok(PublicCtor.prototype.isPrototypeOf(obj),
"PublicCtor's prototype should be prototype of object");
test.assertEqual(obj.constructor, PublicCtor,
assert.equal(obj.constructor, PublicCtor,
"Object constructor should be PublicCtor");
}
testObj(true);
testObj(false);
};
exports.testValidateOptionsEmpty = function (test) {
exports.testValidateOptionsEmpty = function (assert) {
let val = apiUtils.validateOptions(null, {});
assertObjsEqual(test, val, {});
assert.deepEqual(val, {});
val = apiUtils.validateOptions(null, { foo: {} });
assertObjsEqual(test, val, {});
assert.deepEqual(val, {});
val = apiUtils.validateOptions({}, {});
assertObjsEqual(test, val, {});
assert.deepEqual(val, {});
val = apiUtils.validateOptions({}, { foo: {} });
assertObjsEqual(test, val, {});
assert.deepEqual(val, {});
};
exports.testValidateOptionsNonempty = function (test) {
exports.testValidateOptionsNonempty = function (assert) {
let val = apiUtils.validateOptions({ foo: 123 }, {});
assertObjsEqual(test, val, {});
assert.deepEqual(val, {});
val = apiUtils.validateOptions({ foo: 123, bar: 456 },
{ foo: {}, bar: {}, baz: {} });
assertObjsEqual(test, val, { foo: 123, bar: 456 });
assert.deepEqual(val, { foo: 123, bar: 456 });
};
exports.testValidateOptionsMap = function (test) {
exports.testValidateOptionsMap = function (assert) {
let val = apiUtils.validateOptions({ foo: 3, bar: 2 }, {
foo: { map: function (v) v * v },
bar: { map: function (v) undefined }
});
assertObjsEqual(test, val, { foo: 9, bar: undefined });
assert.deepEqual(val, { foo: 9, bar: undefined });
};
exports.testValidateOptionsMapException = function (test) {
exports.testValidateOptionsMapException = function (assert) {
let val = apiUtils.validateOptions({ foo: 3 }, {
foo: { map: function () { throw new Error(); }}
});
assertObjsEqual(test, val, { foo: 3 });
assert.deepEqual(val, { foo: 3 });
};
exports.testValidateOptionsOk = function (test) {
exports.testValidateOptionsOk = function (assert) {
let val = apiUtils.validateOptions({ foo: 3, bar: 2, baz: 1 }, {
foo: { ok: function (v) v },
bar: { ok: function (v) v }
});
assertObjsEqual(test, val, { foo: 3, bar: 2 });
assert.deepEqual(val, { foo: 3, bar: 2 });
test.assertRaises(
assert.throws(
function () apiUtils.validateOptions({ foo: 2, bar: 2 }, {
bar: { ok: function (v) v > 2 }
}),
'The option "bar" is invalid.',
/^The option "bar" is invalid/,
"ok should raise exception on invalid option"
);
test.assertRaises(
assert.throws(
function () apiUtils.validateOptions(null, { foo: { ok: function (v) v }}),
'The option "foo" is invalid.',
/^The option "foo" is invalid/,
"ok should raise exception on invalid option"
);
};
exports.testValidateOptionsIs = function (test) {
exports.testValidateOptionsIs = function (assert) {
let opts = {
array: [],
boolean: true,
@ -114,18 +116,137 @@ exports.testValidateOptionsIs = function (test) {
undef2: { is: ["undefined"] }
};
let val = apiUtils.validateOptions(opts, requirements);
assertObjsEqual(test, val, opts);
assert.deepEqual(val, opts);
test.assertRaises(
assert.throws(
function () apiUtils.validateOptions(null, {
foo: { is: ["object", "number"] }
}),
'The option "foo" must be one of the following types: object, number',
/^The option "foo" must be one of the following types: object, number/,
"Invalid type should raise exception"
);
};
exports.testValidateOptionsMapIsOk = function (test) {
exports.testValidateOptionsIsWithExportedValue = function (assert) {
let { string, number, boolean, object } = apiUtils;
let opts = {
boolean: true,
number: 1337,
object: {},
string: "foo"
};
let requirements = {
string: { is: string },
number: { is: number },
boolean: { is: boolean },
object: { is: object }
};
let val = apiUtils.validateOptions(opts, requirements);
assert.deepEqual(val, opts);
// Test the types are optional by default
val = apiUtils.validateOptions({foo: 'bar'}, requirements);
assert.deepEqual(val, {});
};
exports.testValidateOptionsIsWithEither = function (assert) {
let { string, number, boolean, either } = apiUtils;
let text = { is: either(string, number) };
let requirements = {
text: text,
boolOrText: { is: either(text, boolean) }
};
let val = apiUtils.validateOptions({text: 12}, requirements);
assert.deepEqual(val, {text: 12});
val = apiUtils.validateOptions({text: "12"}, requirements);
assert.deepEqual(val, {text: "12"});
val = apiUtils.validateOptions({boolOrText: true}, requirements);
assert.deepEqual(val, {boolOrText: true});
val = apiUtils.validateOptions({boolOrText: "true"}, requirements);
assert.deepEqual(val, {boolOrText: "true"});
val = apiUtils.validateOptions({boolOrText: 1}, requirements);
assert.deepEqual(val, {boolOrText: 1});
assert.throws(
() => apiUtils.validateOptions({text: true}, requirements),
/^The option "text" must be one of the following types/,
"Invalid type should raise exception"
);
assert.throws(
() => apiUtils.validateOptions({boolOrText: []}, requirements),
/^The option "boolOrText" must be one of the following types/,
"Invalid type should raise exception"
);
};
exports.testValidateOptionsWithRequiredAndOptional = function (assert) {
let { string, number, required, optional } = apiUtils;
let opts = {
number: 1337,
string: "foo"
};
let requirements = {
string: required(string),
number: number
};
let val = apiUtils.validateOptions(opts, requirements);
assert.deepEqual(val, opts);
val = apiUtils.validateOptions({string: "foo"}, requirements);
assert.deepEqual(val, {string: "foo"});
assert.throws(
() => apiUtils.validateOptions({number: 10}, requirements),
/^The option "string" must be one of the following types/,
"Invalid type should raise exception"
);
// Makes string optional
requirements.string = optional(requirements.string);
val = apiUtils.validateOptions({number: 10}, requirements),
assert.deepEqual(val, {number: 10});
};
exports.testValidateOptionsWithExportedValue = function (assert) {
let { string, number, boolean, object } = apiUtils;
let opts = {
boolean: true,
number: 1337,
object: {},
string: "foo"
};
let requirements = {
string: string,
number: number,
boolean: boolean,
object: object
};
let val = apiUtils.validateOptions(opts, requirements);
assert.deepEqual(val, opts);
// Test the types are optional by default
val = apiUtils.validateOptions({foo: 'bar'}, requirements);
assert.deepEqual(val, {});
};
exports.testValidateOptionsMapIsOk = function (assert) {
let [map, is, ok] = [false, false, false];
let val = apiUtils.validateOptions({ foo: 1337 }, {
foo: {
@ -134,48 +255,48 @@ exports.testValidateOptionsMapIsOk = function (test) {
ok: function (v) v.length > 0
}
});
assertObjsEqual(test, val, { foo: "1337" });
assert.deepEqual(val, { foo: "1337" });
let requirements = {
foo: {
is: ["object"],
ok: function () test.fail("is should have caused us to throw by now")
ok: function () assert.fail("is should have caused us to throw by now")
}
};
test.assertRaises(
assert.throws(
function () apiUtils.validateOptions(null, requirements),
'The option "foo" must be one of the following types: object',
/^The option "foo" must be one of the following types: object/,
"is should be used before ok is called"
);
};
exports.testValidateOptionsErrorMsg = function (test) {
test.assertRaises(
exports.testValidateOptionsErrorMsg = function (assert) {
assert.throws(
function () apiUtils.validateOptions(null, {
foo: { ok: function (v) v, msg: "foo!" }
}),
"foo!",
/^foo!/,
"ok should raise exception with customized message"
);
};
exports.testValidateMapWithMissingKey = function (test) {
exports.testValidateMapWithMissingKey = function (assert) {
let val = apiUtils.validateOptions({ }, {
foo: {
map: function (v) v || "bar"
}
});
assertObjsEqual(test, val, { foo: "bar" });
assert.deepEqual(val, { foo: "bar" });
val = apiUtils.validateOptions({ }, {
foo: {
map: function (v) { throw "bar" }
}
});
assertObjsEqual(test, val, { });
assert.deepEqual(val, { });
};
exports.testValidateMapWithMissingKeyAndThrown = function (test) {
exports.testValidateMapWithMissingKeyAndThrown = function (assert) {
let val = apiUtils.validateOptions({}, {
bar: {
map: function(v) { throw "bar" }
@ -184,10 +305,10 @@ exports.testValidateMapWithMissingKeyAndThrown = function (test) {
map: function(v) "foo"
}
});
assertObjsEqual(test, val, { baz: "foo" });
assert.deepEqual(val, { baz: "foo" });
};
exports.testAddIterator = function testAddIterator(test) {
exports.testAddIterator = function testAddIterator (assert) {
let obj = {};
let keys = ["foo", "bar", "baz"];
let vals = [1, 2, 3];
@ -203,34 +324,20 @@ exports.testAddIterator = function testAddIterator(test) {
let keysItr = [];
for (let key in obj)
keysItr.push(key);
test.assertEqual(keysItr.length, keys.length,
assert.equal(keysItr.length, keys.length,
"the keys iterator returns the correct number of items");
for (let i = 0; i < keys.length; i++)
test.assertEqual(keysItr[i], keys[i], "the key is correct");
assert.equal(keysItr[i], keys[i], "the key is correct");
let valsItr = [];
for each (let val in obj)
valsItr.push(val);
test.assertEqual(valsItr.length, vals.length,
assert.equal(valsItr.length, vals.length,
"the vals iterator returns the correct number of items");
for (let i = 0; i < vals.length; i++)
test.assertEqual(valsItr[i], vals[i], "the val is correct");
assert.equal(valsItr[i], vals[i], "the val is correct");
};
function assertObjsEqual(test, obj1, obj2) {
var items = 0;
for (let key in obj1) {
items++;
test.assert(key in obj2, "obj1 key should be present in obj2");
test.assertEqual(obj2[key], obj1[key], "obj1 value should match obj2 value");
}
for (let key in obj2) {
items++;
test.assert(key in obj1, "obj2 key should be present in obj1");
test.assertEqual(obj1[key], obj2[key], "obj2 value should match obj1 value");
}
if (!items)
test.assertEqual(JSON.stringify(obj1), JSON.stringify(obj2),
"obj1 should have same JSON representation as obj2");
}
require('test').run(exports);

Просмотреть файл

@ -5,67 +5,67 @@
const array = require('sdk/util/array');
exports.testHas = function(test) {
exports.testHas = function(assert) {
var testAry = [1, 2, 3];
test.assertEqual(array.has([1, 2, 3], 1), true);
test.assertEqual(testAry.length, 3);
test.assertEqual(testAry[0], 1);
test.assertEqual(testAry[1], 2);
test.assertEqual(testAry[2], 3);
test.assertEqual(array.has(testAry, 2), true);
test.assertEqual(array.has(testAry, 3), true);
test.assertEqual(array.has(testAry, 4), false);
test.assertEqual(array.has(testAry, '1'), false);
assert.equal(array.has([1, 2, 3], 1), true);
assert.equal(testAry.length, 3);
assert.equal(testAry[0], 1);
assert.equal(testAry[1], 2);
assert.equal(testAry[2], 3);
assert.equal(array.has(testAry, 2), true);
assert.equal(array.has(testAry, 3), true);
assert.equal(array.has(testAry, 4), false);
assert.equal(array.has(testAry, '1'), false);
};
exports.testHasAny = function(test) {
exports.testHasAny = function(assert) {
var testAry = [1, 2, 3];
test.assertEqual(array.hasAny([1, 2, 3], [1]), true);
test.assertEqual(array.hasAny([1, 2, 3], [1, 5]), true);
test.assertEqual(array.hasAny([1, 2, 3], [5, 1]), true);
test.assertEqual(array.hasAny([1, 2, 3], [5, 2]), true);
test.assertEqual(array.hasAny([1, 2, 3], [5, 3]), true);
test.assertEqual(array.hasAny([1, 2, 3], [5, 4]), false);
test.assertEqual(testAry.length, 3);
test.assertEqual(testAry[0], 1);
test.assertEqual(testAry[1], 2);
test.assertEqual(testAry[2], 3);
test.assertEqual(array.hasAny(testAry, [2]), true);
test.assertEqual(array.hasAny(testAry, [3]), true);
test.assertEqual(array.hasAny(testAry, [4]), false);
test.assertEqual(array.hasAny(testAry), false);
test.assertEqual(array.hasAny(testAry, '1'), false);
assert.equal(array.hasAny([1, 2, 3], [1]), true);
assert.equal(array.hasAny([1, 2, 3], [1, 5]), true);
assert.equal(array.hasAny([1, 2, 3], [5, 1]), true);
assert.equal(array.hasAny([1, 2, 3], [5, 2]), true);
assert.equal(array.hasAny([1, 2, 3], [5, 3]), true);
assert.equal(array.hasAny([1, 2, 3], [5, 4]), false);
assert.equal(testAry.length, 3);
assert.equal(testAry[0], 1);
assert.equal(testAry[1], 2);
assert.equal(testAry[2], 3);
assert.equal(array.hasAny(testAry, [2]), true);
assert.equal(array.hasAny(testAry, [3]), true);
assert.equal(array.hasAny(testAry, [4]), false);
assert.equal(array.hasAny(testAry), false);
assert.equal(array.hasAny(testAry, '1'), false);
};
exports.testAdd = function(test) {
exports.testAdd = function(assert) {
var testAry = [1];
test.assertEqual(array.add(testAry, 1), false);
test.assertEqual(testAry.length, 1);
test.assertEqual(testAry[0], 1);
test.assertEqual(array.add(testAry, 2), true);
test.assertEqual(testAry.length, 2);
test.assertEqual(testAry[0], 1);
test.assertEqual(testAry[1], 2);
assert.equal(array.add(testAry, 1), false);
assert.equal(testAry.length, 1);
assert.equal(testAry[0], 1);
assert.equal(array.add(testAry, 2), true);
assert.equal(testAry.length, 2);
assert.equal(testAry[0], 1);
assert.equal(testAry[1], 2);
};
exports.testRemove = function(test) {
exports.testRemove = function(assert) {
var testAry = [1, 2];
test.assertEqual(array.remove(testAry, 3), false);
test.assertEqual(testAry.length, 2);
test.assertEqual(testAry[0], 1);
test.assertEqual(testAry[1], 2);
test.assertEqual(array.remove(testAry, 2), true);
test.assertEqual(testAry.length, 1);
test.assertEqual(testAry[0], 1);
assert.equal(array.remove(testAry, 3), false);
assert.equal(testAry.length, 2);
assert.equal(testAry[0], 1);
assert.equal(testAry[1], 2);
assert.equal(array.remove(testAry, 2), true);
assert.equal(testAry.length, 1);
assert.equal(testAry[0], 1);
};
exports.testFlatten = function(test) {
test.assertEqual(array.flatten([1, 2, 3]).length, 3);
test.assertEqual(array.flatten([1, [2, 3]]).length, 3);
test.assertEqual(array.flatten([1, [2, [3]]]).length, 3);
test.assertEqual(array.flatten([[1], [[2, [3]]]]).length, 3);
exports.testFlatten = function(assert) {
assert.equal(array.flatten([1, 2, 3]).length, 3);
assert.equal(array.flatten([1, [2, 3]]).length, 3);
assert.equal(array.flatten([1, [2, [3]]]).length, 3);
assert.equal(array.flatten([[1], [[2, [3]]]]).length, 3);
};
exports.testUnique = function(test) {
exports.testUnique = function(assert) {
var Class = function () {};
var A = {};
var B = new Class();
@ -73,23 +73,31 @@ exports.testUnique = function(test) {
var D = {};
var E = new Class();
compareArray(array.unique([1,2,3,1,2]), [1,2,3]);
compareArray(array.unique([1,1,1,4,9,5,5]), [1,4,9,5]);
compareArray(array.unique([A, A, A, B, B, D]), [A,B,D]);
compareArray(array.unique([A, D, A, E, E, D, A, A, C]), [A, D, E, C])
function compareArray (a, b) {
test.assertEqual(a.length, b.length);
for (let i = 0; i < a.length; i++) {
test.assertEqual(a[i], b[i]);
}
}
assert.deepEqual(array.unique([1,2,3,1,2]), [1,2,3]);
assert.deepEqual(array.unique([1,1,1,4,9,5,5]), [1,4,9,5]);
assert.deepEqual(array.unique([A, A, A, B, B, D]), [A,B,D]);
assert.deepEqual(array.unique([A, D, A, E, E, D, A, A, C]), [A, D, E, C])
};
exports.testFind = function(test) {
exports.testUnion = function(assert) {
var Class = function () {};
var A = {};
var B = new Class();
var C = [ 1, 2, 3 ];
var D = {};
var E = new Class();
assert.deepEqual(array.union([1, 2, 3],[7, 1, 2]), [1, 2, 3, 7]);
assert.deepEqual(array.union([1, 1, 1, 4, 9, 5, 5], [10, 1, 5]), [1, 4, 9, 5, 10]);
assert.deepEqual(array.union([A, B], [A, D]), [A, B, D]);
assert.deepEqual(array.union([A, D], [A, E], [E, D, A], [A, C]), [A, D, E, C]);
};
exports.testFind = function(assert) {
let isOdd = (x) => x % 2;
test.assertEqual(array.find([2, 4, 5, 7, 8, 9], isOdd), 5);
test.assertEqual(array.find([2, 4, 6, 8], isOdd), undefined);
test.assertEqual(array.find([2, 4, 6, 8], isOdd, null), null);
assert.equal(array.find([2, 4, 5, 7, 8, 9], isOdd), 5);
assert.equal(array.find([2, 4, 6, 8], isOdd), undefined);
assert.equal(array.find([2, 4, 6, 8], isOdd, null), null);
};
require('test').run(exports);

Просмотреть файл

@ -4,6 +4,12 @@
"use strict";
module.metadata = {
engines: {
"Firefox": "*"
}
};
const { Loader } = require("sdk/test/loader");
const { open, getMostRecentBrowserWindow, getOuterId } = require("sdk/window/utils");
const { setTimeout } = require("sdk/timers");

Просмотреть файл

@ -44,13 +44,17 @@ exports["test multiple tabs"] = function(assert, done) {
on(events, "data", function({type, target, timeStamp}) {
// ignore about:blank pages and *-document-global-created
// events that are not very consistent.
// ignore http:// requests, as Fennec's `about:home` page
// displays add-ons a user could install
if (target.URL !== "about:blank" &&
target.URL !== "about:home" &&
!target.URL.match(/^https?:\/\//i) &&
type !== "chrome-document-global-created" &&
type !== "content-document-global-created")
actual.push(type + " -> " + target.URL)
});
let window = getMostRecentBrowserWindow();
let window = getMostRecentBrowserWindow();
let firstTab = open("data:text/html,first-tab", window);
when("pageshow", firstTab).

Просмотреть файл

@ -457,3 +457,52 @@ exports.testTabReload = function(test) {
}
});
};
exports.testOnPageShowEvent = function (test) {
test.waitUntilDone();
let events = [];
let firstUrl = 'data:text/html;charset=utf-8,First';
let secondUrl = 'data:text/html;charset=utf-8,Second';
let counter = 0;
function onPageShow (tab, persisted) {
events.push('pageshow');
counter++;
if (counter === 1) {
test.assertEqual(persisted, false, 'page should not be cached on initial load');
tab.url = secondUrl;
}
else if (counter === 2) {
test.assertEqual(persisted, false, 'second test page should not be cached either');
tab.attach({
contentScript: 'setTimeout(function () { window.history.back(); }, 0)'
});
}
else {
test.assertEqual(persisted, true, 'when we get back to the fist page, it has to' +
'come from cache');
tabs.removeListener('pageshow', onPageShow);
tabs.removeListener('open', onOpen);
tabs.removeListener('ready', onReady);
tab.close(() => {
['open', 'ready', 'pageshow', 'ready',
'pageshow', 'pageshow'].map((type, i) => {
test.assertEqual(type, events[i], 'correct ordering of events');
});
test.done()
});
}
}
function onOpen () events.push('open');
function onReady () events.push('ready');
tabs.on('pageshow', onPageShow);
tabs.on('open', onOpen);
tabs.on('ready', onReady);
tabs.open({
url: firstUrl
});
};

Просмотреть файл

@ -3,7 +3,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
const { URL, toFilename, fromFilename, isValidURI, getTLD, DataURL } = require('sdk/url');
const {
URL,
toFilename,
fromFilename,
isValidURI,
getTLD,
DataURL,
isLocalURL } = require('sdk/url');
const { pathFor } = require('sdk/system');
const file = require('sdk/io/file');
const tabs = require('sdk/tabs');
@ -63,11 +71,11 @@ exports.testParseHttpSearchAndHash = function (assert) {
var info = URL('https://www.moz.com/some/page.html');
assert.equal(info.hash, '');
assert.equal(info.search, '');
var hashOnly = URL('https://www.sub.moz.com/page.html#justhash');
assert.equal(hashOnly.search, '');
assert.equal(hashOnly.hash, '#justhash');
var queryOnly = URL('https://www.sub.moz.com/page.html?my=query');
assert.equal(queryOnly.search, '?my=query');
assert.equal(queryOnly.hash, '');
@ -75,11 +83,11 @@ exports.testParseHttpSearchAndHash = function (assert) {
var qMark = URL('http://www.moz.org?');
assert.equal(qMark.search, '');
assert.equal(qMark.hash, '');
var hash = URL('http://www.moz.org#');
assert.equal(hash.search, '');
assert.equal(hash.hash, '');
var empty = URL('http://www.moz.org?#');
assert.equal(hash.search, '');
assert.equal(hash.hash, '');
@ -347,6 +355,39 @@ exports.testWindowLocationMatch = function (assert, done) {
})
};
exports.testURLInRegExpTest = function(assert) {
let url = 'https://mozilla.org';
assert.equal((new RegExp(url).test(URL(url))), true, 'URL instances work in a RegExp test');
}
exports.testLocalURL = function(assert) {
[
'data:text/html;charset=utf-8,foo and bar',
'data:text/plain,foo and bar',
'resource://gre/modules/commonjs/',
'chrome://browser/content/browser.xul'
].forEach(aUri => {
assert.ok(isLocalURL(aUri), aUri + ' is a Local URL');
})
}
exports.testLocalURLwithRemoteURL = function(assert) {
validURIs().filter(url => !url.startsWith('data:')).forEach(aUri => {
assert.ok(!isLocalURL(aUri), aUri + ' is an invalid Local URL');
});
}
exports.testLocalURLwithInvalidURL = function(assert) {
invalidURIs().concat([
'data:foo and bar',
'resource:// must fail',
'chrome:// here too'
]).forEach(aUri => {
assert.ok(!isLocalURL(aUri), aUri + ' is an invalid Local URL');
});
}
function validURIs() {
return [
'http://foo.com/blah_blah',