mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-12 09:01:16 +00:00
Bug 1155877 - ObjectUtils.strict. r=mossop
--HG-- extra : rebase_source : e69178e9208b149fc66c61f15d74750d1d765907
This commit is contained in:
parent
ec1aede15a
commit
64d710a064
@ -151,6 +151,13 @@ this.AppConstants = Object.freeze({
|
||||
false,
|
||||
#endif
|
||||
|
||||
DEBUG:
|
||||
#ifdef DEBUG
|
||||
true,
|
||||
#else
|
||||
false,
|
||||
#endif
|
||||
|
||||
MOZ_APP_NAME: "@MOZ_APP_NAME@",
|
||||
MOZ_APP_VERSION: "@MOZ_APP_VERSION@",
|
||||
MOZ_BUILD_APP: "@MOZ_BUILD_APP@",
|
||||
|
@ -14,6 +14,12 @@ this.EXPORTED_SYMBOLS = [
|
||||
|
||||
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
||||
|
||||
// Used only to cause test failures.
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/Promise.jsm");
|
||||
|
||||
this.ObjectUtils = {
|
||||
/**
|
||||
* This tests objects & values for deep equality.
|
||||
@ -30,6 +36,25 @@ this.ObjectUtils = {
|
||||
deepEqual: function(a, b) {
|
||||
return _deepEqual(a, b);
|
||||
},
|
||||
|
||||
/**
|
||||
* A thin wrapper on an object, designed to prevent client code from
|
||||
* accessing non-existent properties because of typos.
|
||||
*
|
||||
* // Without `strict`
|
||||
* let foo = { myProperty: 1 };
|
||||
* foo.MyProperty; // undefined
|
||||
*
|
||||
* // With `strict`
|
||||
* let strictFoo = ObjectUtils.strict(foo);
|
||||
* strictFoo.myProperty; // 1
|
||||
* strictFoo.MyProperty; // TypeError: No such property "MyProperty"
|
||||
*
|
||||
* Note that `strict` has no effect in non-DEBUG mode.
|
||||
*/
|
||||
strict: function(obj) {
|
||||
return _strict(obj);
|
||||
}
|
||||
};
|
||||
|
||||
// ... Start of previously MIT-licensed code.
|
||||
@ -129,3 +154,21 @@ function objEquiv(a, b) {
|
||||
}
|
||||
|
||||
// ... End of previously MIT-licensed code.
|
||||
|
||||
function _strict(obj) {
|
||||
if (typeof obj != "object") {
|
||||
throw new TypeError("Expected an object");
|
||||
}
|
||||
|
||||
return new Proxy(obj, {
|
||||
get: function(target, name) {
|
||||
if (name in obj) {
|
||||
return obj[name];
|
||||
}
|
||||
|
||||
let error = new TypeError(`No such property: "${name}"`);
|
||||
Promise.reject(error); // Cause an xpcshell/mochitest failure.
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
32
toolkit/modules/tests/xpcshell/test_ObjectUtils_strict.js
Normal file
32
toolkit/modules/tests/xpcshell/test_ObjectUtils_strict.js
Normal file
@ -0,0 +1,32 @@
|
||||
"use strict";
|
||||
|
||||
let {ObjectUtils} = Components.utils.import("resource://gre/modules/ObjectUtils.jsm", {});
|
||||
let {Promise} = Components.utils.import("resource://gre/modules/Promise.jsm", {});
|
||||
|
||||
add_task(function* init() {
|
||||
// The code will cause uncaught rejections on purpose.
|
||||
Promise.Debugging.clearUncaughtErrorObservers();
|
||||
});
|
||||
|
||||
add_task(function* test_strict() {
|
||||
let loose = { a: 1 };
|
||||
let strict = ObjectUtils.strict(loose);
|
||||
|
||||
loose.a; // Should not throw.
|
||||
loose.b || undefined; // Should not throw.
|
||||
|
||||
strict.a; // Should not throw.
|
||||
Assert.throws(() => strict.b, /No such property: "b"/);
|
||||
"b" in strict; // Should not throw.
|
||||
strict.b = 2;
|
||||
strict.b; // Should not throw.
|
||||
|
||||
Assert.throws(() => strict.c, /No such property: "c"/);
|
||||
"c" in strict; // Should not throw.
|
||||
loose.c = 3;
|
||||
strict.c; // Should not throw.
|
||||
});
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
@ -17,6 +17,7 @@ support-files =
|
||||
[test_Log.js]
|
||||
[test_NewTabUtils.js]
|
||||
[test_ObjectUtils.js]
|
||||
[test_ObjectUtils_strict.js]
|
||||
[test_PermissionsUtils.js]
|
||||
[test_Preferences.js]
|
||||
[test_Promise.js]
|
||||
|
Loading…
Reference in New Issue
Block a user