MOBILE-3068 utils: Fix max stack size reached when cloning

main
Dani Palou 2019-08-27 16:13:41 +02:00
parent ebd4577be2
commit 3da30f665a
2 changed files with 19 additions and 4 deletions

View File

@ -337,7 +337,7 @@ export class AddonModDataHelperProvider {
approved: !data.approval || data.manageapproved, approved: !data.approval || data.manageapproved,
canmanageentry: true, canmanageentry: true,
fullname: site.getInfo().fullname, fullname: site.getInfo().fullname,
contents: [], contents: {},
} }
}); });
} }

View File

@ -58,6 +58,7 @@ export interface PromiseDefer {
*/ */
@Injectable() @Injectable()
export class CoreUtilsProvider { export class CoreUtilsProvider {
protected DONT_CLONE = ['[object FileEntry]', '[object DirectoryEntry]', '[object DOMFileSystem]'];
protected logger; protected logger;
protected iabInstance: InAppBrowserObject; protected iabInstance: InAppBrowserObject;
protected uniqueIds: {[name: string]: number} = {}; protected uniqueIds: {[name: string]: number} = {};
@ -267,22 +268,36 @@ export class CoreUtilsProvider {
* Clone a variable. It should be an object, array or primitive type. * Clone a variable. It should be an object, array or primitive type.
* *
* @param {any} source The variable to clone. * @param {any} source The variable to clone.
* @param {number} [level=0] Depth we are right now inside a cloned object. It's used to prevent reaching max call stack size.
* @return {any} Cloned variable. * @return {any} Cloned variable.
*/ */
clone(source: any): any { clone(source: any, level: number = 0): any {
if (level >= 20) {
// Max 20 levels.
this.logger.error('Max depth reached when cloning object.', source);
return source;
}
if (Array.isArray(source)) { if (Array.isArray(source)) {
// Clone the array and all the entries. // Clone the array and all the entries.
const newArray = []; const newArray = [];
for (let i = 0; i < source.length; i++) { for (let i = 0; i < source.length; i++) {
newArray[i] = this.clone(source[i]); newArray[i] = this.clone(source[i], level + 1);
} }
return newArray; return newArray;
} else if (typeof source == 'object' && source !== null) { } else if (typeof source == 'object' && source !== null) {
// Check if the object shouldn't be copied.
if (source && source.toString && this.DONT_CLONE.indexOf(source.toString()) != -1) {
// Object shouldn't be copied, return it as it is.
return source;
}
// Clone the object and all the subproperties. // Clone the object and all the subproperties.
const newObject = {}; const newObject = {};
for (const name in source) { for (const name in source) {
newObject[name] = this.clone(source[name]); newObject[name] = this.clone(source[name], level + 1);
} }
return newObject; return newObject;