Bug 1430970 - Fix FxAccounts internal mocking.
MozReview-Commit-ID: 7ATwZTJ4w5K
--- a/services/fxaccounts/FxAccounts.jsm
+++ b/services/fxaccounts/FxAccounts.jsm
@@ -284,78 +284,71 @@ AccountState.prototype = {
};
/* Given an array of scopes, make a string key by normalizing. */
function getScopeKey(scopeArray) {
let normalizedScopes = scopeArray.map(item => item.toLowerCase());
return normalizedScopes.sort().join("|");
}
+function getPropertyDescriptor(obj, prop) {
+ return Object.getOwnPropertyDescriptor(obj, prop) ||
+ getPropertyDescriptor(Object.getPrototypeOf(obj), prop);
+}
+
/**
* Copies properties from a given object to another object.
*
* @param from (object)
* The object we read property descriptors from.
* @param to (object)
* The object that we set property descriptors on.
- * @param options (object) (optional)
- * {keys: [...]}
- * Lets the caller pass the names of all properties they want to be
- * copied. Will copy all properties of the given source object by
- * default.
- * {bind: object}
- * Lets the caller specify the object that will be used to .bind()
- * all function properties we find to. Will bind to the given target
- * object by default.
+ * @param thisObj (object)
+ * The object that will be used to .bind() all function properties we find to.
+ * @param keys ([...])
+ * The names of all properties to be copied.
*/
-function copyObjectProperties(from, to, opts = {}) {
- let keys = (opts && opts.keys) || Object.keys(from);
- let thisArg = (opts && opts.bind) || to;
-
+function copyObjectProperties(from, to, thisObj, keys) {
for (let prop of keys) {
- let desc = Object.getOwnPropertyDescriptor(from, prop);
+ // Look for the prop in the prototype chain.
+ let desc = getPropertyDescriptor(from, prop);
if (typeof(desc.value) == "function") {
- desc.value = desc.value.bind(thisArg);
+ desc.value = desc.value.bind(thisObj);
}
if (desc.get) {
- desc.get = desc.get.bind(thisArg);
+ desc.get = desc.get.bind(thisObj);
}
if (desc.set) {
- desc.set = desc.set.bind(thisArg);
+ desc.set = desc.set.bind(thisObj);
}
Object.defineProperty(to, prop, desc);
}
}
function urlsafeBase64Encode(key) {
return ChromeUtils.base64URLEncode(new Uint8Array(key), { pad: false });
}
/**
* The public API's constructor.
*/
this.FxAccounts = function(mockInternal) {
- let internal = new FxAccountsInternal();
let external = {};
+ let internal;
- // Copy all public properties to the 'external' object.
- let prototype = FxAccountsInternal.prototype;
- let options = {keys: publicProperties, bind: internal};
- copyObjectProperties(prototype, external, options);
-
- // Copy all of the mock's properties to the internal object.
- if (mockInternal && !mockInternal.onlySetInternal) {
- copyObjectProperties(mockInternal, internal);
- }
-
- if (mockInternal) {
+ if (!mockInternal) {
+ internal = new FxAccountsInternal();
+ copyObjectProperties(FxAccountsInternal.prototype, external, internal, publicProperties);
+ } else {
+ internal = Object.create(FxAccountsInternal.prototype, Object.getOwnPropertyDescriptors(mockInternal));
+ copyObjectProperties(internal, external, internal, publicProperties);
// Exposes the internal object for testing only.
external.internal = internal;
}
if (!internal.fxaPushService) {
// internal.fxaPushService option is used in testing.
// Otherwise we load the service lazily.
XPCOMUtils.defineLazyGetter(internal, "fxaPushService", function() {