displayName.js (3628B)
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 // Decodes an anonymous naming scheme that 6 // spider monkey implements based on "Naming Anonymous JavaScript Functions" 7 // http://johnjbarton.github.io/nonymous/index.html 8 const objectProperty = /([\w\d\$#]+)$/; 9 const arrayProperty = /\[(.*?)\]$/; 10 const functionProperty = /([\w\d]+)[\/\.<]*?$/; 11 const annonymousProperty = /([\w\d]+)\(\^\)$/; 12 const displayNameScenarios = [ 13 objectProperty, 14 arrayProperty, 15 functionProperty, 16 annonymousProperty, 17 ]; 18 const includeSpace = /\s/; 19 export function simplifyDisplayName(displayName) { 20 // if the display name has a space it has already been mapped 21 if (!displayName || includeSpace.exec(displayName)) { 22 return displayName; 23 } 24 25 for (const reg of displayNameScenarios) { 26 const match = reg.exec(displayName); 27 if (match) { 28 return match[1]; 29 } 30 } 31 32 return displayName; 33 } 34 35 const displayNameLibraryMap = { 36 Babel: { 37 tryCatch: "Async", 38 }, 39 Backbone: { 40 "extend/child": "Create Class", 41 ".create": "Create Model", 42 }, 43 jQuery: { 44 "jQuery.event.dispatch": "Dispatch Event", 45 }, 46 React: { 47 // eslint-disable-next-line max-len 48 "ReactCompositeComponent._renderValidatedComponentWithoutOwnerOrContext/renderedElement<": 49 "Render", 50 _renderValidatedComponentWithoutOwnerOrContext: "Render", 51 }, 52 VueJS: { 53 "renderMixin/Vue.prototype._render": "Render", 54 }, 55 Webpack: { 56 // eslint-disable-next-line camelcase 57 __webpack_require__: "Bootstrap", 58 }, 59 }; 60 61 /** 62 * Compute the typical way to show a frame or function to the user. 63 * 64 * @param {object} frameOrFunc 65 * Either a frame or a func object. 66 * Frame object is typically created via create.js::createFrame 67 * Func object comes from ast reducer. 68 * @param {boolean} shouldMapDisplayName 69 * True by default, will try to translate internal framework function name 70 * into a most explicit and simplier name. 71 * @param {object} l10n 72 * The localization object. 73 */ 74 export function formatDisplayName( 75 frameOrFunc, 76 { shouldMapDisplayName = true } = {}, 77 l10n 78 ) { 79 // All the following attributes are only available on Frame objects 80 const { library, displayName, originalDisplayName } = frameOrFunc; 81 let displayedName; 82 83 // If the frame was identified to relate to a library, 84 // lookup for pretty name for the most important method of some frameworks 85 if (library && shouldMapDisplayName) { 86 displayedName = displayNameLibraryMap[library]?.[displayName]; 87 } 88 89 // Frames for original sources may have both displayName for the generated source, 90 // or originalDisplayName for the original source. 91 // (in case original and generated have distinct function names in uglified sources) 92 // 93 // Also fallback to "name" attribute when the passed object is a Func object. 94 if (!displayedName) { 95 displayedName = originalDisplayName || displayName || frameOrFunc.name; 96 } 97 98 if (!displayedName) { 99 return l10n.getStr("anonymousFunction"); 100 } 101 102 return simplifyDisplayName(displayedName); 103 } 104 105 export function formatCopyName(frame, l10n, shouldDisplayOriginalLocation) { 106 const displayName = formatDisplayName(frame, undefined, l10n); 107 const location = shouldDisplayOriginalLocation 108 ? frame.location 109 : frame.generatedLocation; 110 const fileName = location.source.url || location.source.id; 111 const frameLocation = frame.location.line; 112 113 return `${displayName} (${fileName}#${frameLocation})`; 114 }