{"ScriptPreparationCode":" var generateName = function(prefix) {\r\n return (prefix || \u0027\u0027) \u002B Math.random().toString(36).substr(2);\r\n };\r\n\r\n var generateValue = function(onlyTrivial) {\r\n var variants = [\r\n /* real number */\r\n function() { return Math.random(); },\r\n\r\n /* integer number */\r\n function() { return Math.floor(Math.random() * 1e16); },\r\n\r\n /* string */\r\n function() { return generateName(); },\r\n\r\n /* boolean */\r\n function() { return !Math.floor(Math.random() * 2); },\r\n\r\n /* array */\r\n function() {\r\n var result = [];\r\n\r\n for (var x = Math.floor(Math.random() * 3); x; x--) {\r\n result.push(generateValue());\r\n }\r\n\r\n return result;\r\n },\r\n\r\n /* object */\r\n function() {\r\n var result = {};\r\n\r\n for (var x = Math.floor(Math.random() * 3); x; x--) {\r\n result[generateName(\u0027x\u0027)] = generateValue();\r\n }\r\n\r\n return result;\r\n }\r\n ];\r\n\r\n if (onlyTrivial) {\r\n /* drop array and object variant */\r\n variants.pop();\r\n variants.pop();\r\n }\r\n\r\n return variants[Math.floor(Math.random() * variants.length)]();\r\n };\r\n\r\n var generateTree = function() {\r\n var args = Array.prototype.slice.call(arguments);\r\n var result = {};\r\n var loop = args.shift();\r\n var onlyTrivial = false;\r\n\r\n if (loop === false || loop === true) {\r\n onlyTrivial = loop;\r\n loop = args.shift();\r\n }\r\n\r\n args.unshift(onlyTrivial);\r\n\r\n for (; loop; loop--) {\r\n result[generateName(\u0027x\u0027)] = (args.length === 1) ? generateValue(onlyTrivial) : generateTree.apply(null, args);\r\n }\r\n\r\n return result;\r\n };\r\n\r\n var forbiddenElement = /^\\[object (DIV|DOM|CSS|HTML|NamedNode|Node|Window)/;\r\n\r\n var isInvalidElement = function(element) {\r\n if (element) {\r\n if (element instanceof window.Node) {\r\n return true;\r\n }\r\n\r\n if ((element instanceof $) || (typeof element.css === \u0027function\u0027)) {\r\n return true;\r\n }\r\n\r\n if ((typeof element.toString === \u0027function\u0027) \u0026\u0026 forbiddenElement.test(element.toString())) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n };\r\n\r\n var getKeys1 = function(tree, parent, order, skipEmpty) {\r\n parent = parent || \u0027/\u0027;\r\n var keys = [];\r\n var type = $.type(tree);\r\n\r\n if ((type === \u0027object\u0027) \u0026\u0026 isInvalidElement(tree)) {\r\n type = \u0027invalid\u0027;\r\n }\r\n\r\n if (type === \u0027object\u0027 || type === \u0027array\u0027) {\r\n /* iterate over tree items */\r\n $.each(tree, function(key, value) {\r\n var leaf = parent \u002B key;\r\n var valueType = $.type(value);\r\n\r\n keys.push(leaf);\r\n\r\n /* make sure that invalid elements (like: dom, $, window, etc) won\u0027t be parsed */\r\n if ((valueType === \u0027object\u0027) \u0026\u0026 isInvalidElement(value)) {\r\n valueType = \u0027invalid\u0027;\r\n }\r\n\r\n /* if item is object or array, perform recursive call to get it\u0027s keys as well */\r\n if (valueType === \u0027object\u0027 || valueType === \u0027array\u0027) {\r\n $.merge(keys, getKeys1(value, leaf \u002B \u0027/\u0027, null, skipEmpty));\r\n }\r\n });\r\n }\r\n\r\n return (typeof order === \u0027function\u0027) ? keys.sort(order) : keys.sort();\r\n };\r\n\r\n var getKeys2 = function(tree, parent, order, skipEmpty, level) {\r\n parent = parent || \u0027/\u0027;\r\n level = level || 0;\r\n var result;\r\n var keys = [];\r\n var type = $.type(tree);\r\n\r\n if ((type === \u0027object\u0027) \u0026\u0026 isInvalidElement(tree)) {\r\n type = \u0027invalid\u0027;\r\n }\r\n\r\n if (type === \u0027object\u0027 || type === \u0027array\u0027) {\r\n /* iterate over tree items */\r\n for (var key in tree) {\r\n if (tree.hasOwnProperty(key)) {\r\n \r\n \r\n var value = tree[key];\r\n var leaf = parent \u002B key;\r\n var valueType = $.type(value);\r\n\r\n keys.push(leaf);\r\n\r\n /* make sure that invalid elements (like: dom, $, window, etc) won\u0027t be parsed */\r\n if ((valueType === \u0027object\u0027) \u0026\u0026 isInvalidElement(value)) {\r\n valueType = \u0027invalid\u0027;\r\n }\r\n\r\n /* if item is object or array, perform recursive call to get it\u0027s keys as well */\r\n if (valueType === \u0027object\u0027 || valueType === \u0027array\u0027) {\r\n $.merge(keys, getKeys2(value, leaf \u002B \u0027/\u0027, null, skipEmpty, level \u002B 1));\r\n }\r\n\r\n \r\n }\r\n }\r\n }\r\n\r\n if (level === 0) {\r\n result = (typeof order === \u0027function\u0027) ? keys.sort(order) : keys.sort();\r\n } else {\r\n result = keys;\r\n }\r\n\r\n return result;\r\n };\r\n\r\n","TestCases":[{"Name":"each","Code":"var z = window.zzz1;\r\nif (!z) {\r\n z = generateTree(3, 3, 3, 3, 2, 4);\r\n window.zzz1 = z;\r\n}\r\ngetKeys1(z);","IsDeferred":false},{"Name":"for","Code":"var z = window.zzz2;\r\nif (!z) {\r\n z = generateTree(3, 3, 3, 3, 2, 4);\r\n window.zzz2 = z;\r\n}\r\ngetKeys2(z);","IsDeferred":false}]}