| 102 | */ |
| 103 | bot.inject.wrapValue = function (value) { |
| 104 | var _wrap = function (value, seen) { |
| 105 | switch (goog.utils.typeOf(value)) { |
| 106 | case 'string': |
| 107 | case 'number': |
| 108 | case 'boolean': |
| 109 | return value; |
| 110 | |
| 111 | case 'function': |
| 112 | return value.toString(); |
| 113 | |
| 114 | case 'array': |
| 115 | return goog.array.map(/**@type {IArrayLike}*/(value), |
| 116 | function (v) { return _wrap(v, seen); }); |
| 117 | |
| 118 | case 'object': |
| 119 | // Since {*} expands to {Object|boolean|number|string|undefined}, the |
| 120 | // JSCompiler complains that it is too broad a type for the remainder of |
| 121 | // this block where {!Object} is expected. Downcast to prevent generating |
| 122 | // a ton of compiler warnings. |
| 123 | value = /**@type {!Object}*/ (value); |
| 124 | if (seen.indexOf(value) >= 0) { |
| 125 | throw new bot.Error(bot.ErrorCode.JAVASCRIPT_ERROR, |
| 126 | 'Recursive object cannot be transferred'); |
| 127 | } |
| 128 | |
| 129 | // Sniff out DOM elements. We're using duck-typing instead of an |
| 130 | // instanceof check since the instanceof might not always work |
| 131 | // (e.g. if the value originated from another Firefox component) |
| 132 | if (goog.object.containsKey(value, 'nodeType') && |
| 133 | (value['nodeType'] == goog.dom.NodeType.ELEMENT || |
| 134 | value['nodeType'] == goog.dom.NodeType.DOCUMENT)) { |
| 135 | var ret = {}; |
| 136 | ret[bot.inject.ELEMENT_KEY] = |
| 137 | bot.inject.cache.addElement(/**@type {!Element}*/(value)); |
| 138 | return ret; |
| 139 | } |
| 140 | |
| 141 | // Check if this is a Window |
| 142 | if (goog.object.containsKey(value, 'document')) { |
| 143 | var ret = {}; |
| 144 | ret[bot.inject.WINDOW_KEY] = |
| 145 | bot.inject.cache.addElement(/**@type{!Window}*/(value)); |
| 146 | return ret; |
| 147 | } |
| 148 | |
| 149 | seen.push(value); |
| 150 | if (goog.utils.isArrayLike(value)) { |
| 151 | return goog.array.map(/**@type {IArrayLike}*/(value), |
| 152 | function (v) { return _wrap(v, seen); }); |
| 153 | } |
| 154 | |
| 155 | var filtered = goog.object.filter(value, function (val, key) { |
| 156 | return typeof key === 'number' || typeof key === 'string'; |
| 157 | }); |
| 158 | return goog.object.map(filtered, function (v) { return _wrap(v, seen); }); |
| 159 | |
| 160 | default: // goog.typeOf(value) == 'undefined' || 'null' |
| 161 | return null; |