load-properties.js (6958B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ 4 5 const { 6 enumEntries, 7 enumIndexedProperties, 8 enumNonIndexedProperties, 9 enumPrivateProperties, 10 enumSymbols, 11 getPrototype, 12 getFullText, 13 getPromiseState, 14 getProxySlots, 15 } = require("resource://devtools/client/shared/components/object-inspector/utils/client.js"); 16 17 const { 18 getClosestGripNode, 19 getClosestNonBucketNode, 20 getFront, 21 getValue, 22 nodeHasAccessors, 23 nodeHasProperties, 24 nodeIsBucket, 25 nodeIsDefaultProperties, 26 nodeIsEntries, 27 nodeIsMapEntry, 28 nodeIsPrimitive, 29 nodeIsPromise, 30 nodeIsProxy, 31 nodeNeedsNumericalBuckets, 32 nodeIsLongString, 33 } = require("resource://devtools/client/shared/components/object-inspector/utils/node.js"); 34 35 function loadItemProperties(item, client, loadedProperties, threadActorID) { 36 const gripItem = getClosestGripNode(item); 37 const value = getValue(gripItem); 38 let front = getFront(gripItem); 39 40 if (!front && value && client && client.getFrontByID) { 41 front = client.getFrontByID(value.actor); 42 } 43 44 const getObjectFront = function() { 45 if (!front) { 46 front = client.createObjectFront( 47 value, 48 client.getFrontByID(threadActorID) 49 ); 50 } 51 52 return front; 53 }; 54 55 const [start, end] = item.meta 56 ? [item.meta.startIndex, item.meta.endIndex] 57 : []; 58 59 const promises = []; 60 61 if (shouldLoadItemIndexedProperties(item, loadedProperties)) { 62 promises.push(enumIndexedProperties(getObjectFront(), start, end)); 63 } 64 65 if (shouldLoadItemNonIndexedProperties(item, loadedProperties)) { 66 promises.push(enumNonIndexedProperties(getObjectFront(), start, end)); 67 } 68 69 if (shouldLoadItemEntries(item, loadedProperties)) { 70 promises.push(enumEntries(getObjectFront(), start, end)); 71 } 72 73 if (shouldLoadItemPrototype(item, loadedProperties)) { 74 promises.push(getPrototype(getObjectFront())); 75 } 76 77 if (shouldLoadItemPrivateProperties(item, loadedProperties)) { 78 promises.push(enumPrivateProperties(getObjectFront(), start, end)); 79 } 80 81 if (shouldLoadItemSymbols(item, loadedProperties)) { 82 promises.push(enumSymbols(getObjectFront(), start, end)); 83 } 84 85 if (shouldLoadItemFullText(item, loadedProperties)) { 86 const longStringFront = front || client.createLongStringFront(value); 87 promises.push(getFullText(longStringFront, item)); 88 } 89 90 if (shouldLoadItemPromiseState(item, loadedProperties)) { 91 promises.push(getPromiseState(getObjectFront())); 92 } 93 94 if (shouldLoadItemProxySlots(item, loadedProperties)) { 95 promises.push(getProxySlots(getObjectFront())); 96 } 97 98 return Promise.all(promises).then(mergeResponses); 99 } 100 101 function mergeResponses(responses) { 102 const data = {}; 103 104 for (const response of responses) { 105 if (response.hasOwnProperty("ownProperties")) { 106 data.ownProperties = { ...data.ownProperties, ...response.ownProperties }; 107 } 108 109 if (response.privateProperties && response.privateProperties.length) { 110 data.privateProperties = response.privateProperties; 111 } 112 113 if (response.ownSymbols && response.ownSymbols.length) { 114 data.ownSymbols = response.ownSymbols; 115 } 116 117 if (response.prototype) { 118 data.prototype = response.prototype; 119 } 120 121 if (response.fullText) { 122 data.fullText = response.fullText; 123 } 124 125 if (response.promiseState) { 126 data.promiseState = response.promiseState; 127 } 128 129 if (response.proxyTarget && response.proxyHandler) { 130 data.proxyTarget = response.proxyTarget; 131 data.proxyHandler = response.proxyHandler; 132 } 133 } 134 135 return data; 136 } 137 138 function shouldLoadItemIndexedProperties(item, loadedProperties = new Map()) { 139 const gripItem = getClosestGripNode(item); 140 const value = getValue(gripItem); 141 142 return ( 143 value && 144 nodeHasProperties(gripItem) && 145 !loadedProperties.has(item.path) && 146 !nodeIsProxy(item) && 147 !nodeNeedsNumericalBuckets(item) && 148 !nodeIsEntries(getClosestNonBucketNode(item)) && 149 // The data is loaded when expanding the window node. 150 !nodeIsDefaultProperties(item) 151 ); 152 } 153 154 function shouldLoadItemNonIndexedProperties( 155 item, 156 loadedProperties = new Map() 157 ) { 158 const gripItem = getClosestGripNode(item); 159 const value = getValue(gripItem); 160 161 return ( 162 value && 163 nodeHasProperties(gripItem) && 164 !loadedProperties.has(item.path) && 165 !nodeIsProxy(item) && 166 !nodeIsEntries(getClosestNonBucketNode(item)) && 167 !nodeIsBucket(item) && 168 // The data is loaded when expanding the window node. 169 !nodeIsDefaultProperties(item) 170 ); 171 } 172 173 function shouldLoadItemEntries(item, loadedProperties = new Map()) { 174 const gripItem = getClosestGripNode(item); 175 const value = getValue(gripItem); 176 177 return ( 178 value && 179 nodeIsEntries(getClosestNonBucketNode(item)) && 180 !loadedProperties.has(item.path) && 181 !nodeNeedsNumericalBuckets(item) 182 ); 183 } 184 185 function shouldLoadItemPrototype(item, loadedProperties = new Map()) { 186 const value = getValue(item); 187 188 return ( 189 value && 190 !loadedProperties.has(item.path) && 191 !nodeIsBucket(item) && 192 !nodeIsMapEntry(item) && 193 !nodeIsEntries(item) && 194 !nodeIsDefaultProperties(item) && 195 !nodeHasAccessors(item) && 196 !nodeIsPrimitive(item) && 197 !nodeIsLongString(item) && 198 !nodeIsProxy(item) 199 ); 200 } 201 202 function shouldLoadItemSymbols(item, loadedProperties = new Map()) { 203 const value = getValue(item); 204 205 return ( 206 value && 207 !loadedProperties.has(item.path) && 208 !nodeIsBucket(item) && 209 !nodeIsMapEntry(item) && 210 !nodeIsEntries(item) && 211 !nodeIsDefaultProperties(item) && 212 !nodeHasAccessors(item) && 213 !nodeIsPrimitive(item) && 214 !nodeIsLongString(item) && 215 !nodeIsProxy(item) 216 ); 217 } 218 219 function shouldLoadItemPrivateProperties(item, loadedProperties = new Map()) { 220 const value = getValue(item); 221 222 return ( 223 value && 224 value?.preview?.privatePropertiesLength && 225 !loadedProperties.has(item.path) && 226 !nodeIsBucket(item) && 227 !nodeIsMapEntry(item) && 228 !nodeIsEntries(item) && 229 !nodeIsDefaultProperties(item) && 230 !nodeHasAccessors(item) && 231 !nodeIsPrimitive(item) && 232 !nodeIsLongString(item) && 233 !nodeIsProxy(item) 234 ); 235 } 236 237 function shouldLoadItemFullText(item, loadedProperties = new Map()) { 238 return !loadedProperties.has(item.path) && nodeIsLongString(item); 239 } 240 241 function shouldLoadItemPromiseState(item, loadedProperties = new Map()) { 242 return !loadedProperties.has(item.path) && nodeIsPromise(item); 243 } 244 245 function shouldLoadItemProxySlots(item, loadedProperties = new Map()) { 246 return !loadedProperties.has(item.path) && nodeIsProxy(item); 247 } 248 249 module.exports = { 250 loadItemProperties, 251 mergeResponses, 252 shouldLoadItemEntries, 253 shouldLoadItemIndexedProperties, 254 shouldLoadItemNonIndexedProperties, 255 shouldLoadItemPrototype, 256 shouldLoadItemSymbols, 257 shouldLoadItemFullText, 258 shouldLoadItemPromiseState, 259 shouldLoadItemProxySlots, 260 };