{"version":3,"file":"yett.min.js","sources":["../src/variables.js","../src/checks.js","../src/observer.js","../src/monkey.js","../src/unblock.js"],"sourcesContent":["export const TYPE_ATTRIBUTE = 'javascript/blocked'\n\nexport const patterns = {\n blacklist: window.YETT_BLACKLIST,\n whitelist: window.YETT_WHITELIST\n}\n\n// Backup list containing the original blacklisted script elements\nexport const backupScripts = {\n blacklisted: []\n}","import { patterns, TYPE_ATTRIBUTE } from './variables'\n\nexport const isOnBlacklist = (src, type) => (\n src &&\n (!type || type !== TYPE_ATTRIBUTE) &&\n (\n (!patterns.blacklist || patterns.blacklist.some(pattern => pattern.test(src))) &&\n (!patterns.whitelist || patterns.whitelist.every(pattern => !pattern.test(src)))\n )\n)\n\nexport const willBeUnblocked = function(script) {\n const src = script.getAttribute('src')\n return (\n patterns.blacklist && patterns.blacklist.every(entry => !entry.test(src)) ||\n patterns.whitelist && patterns.whitelist.some(entry => entry.test(src))\n )\n}","import { backupScripts, TYPE_ATTRIBUTE } from './variables'\nimport { isOnBlacklist } from './checks'\n\n// Setup a mutation observer to track DOM insertion\nexport const observer = new MutationObserver(mutations => {\n for (let i = 0; i < mutations.length; i++) {\n const { addedNodes } = mutations[i];\n for(let i = 0; i < addedNodes.length; i++) {\n const node = addedNodes[i]\n // For each added script tag\n if(node.nodeType === 1 && node.tagName === 'SCRIPT') {\n const src = node.src\n const type = node.type\n // If the src is inside the blacklist and is not inside the whitelist\n if(isOnBlacklist(src, type)) {\n // We backup the node\n backupScripts.blacklisted.push([node, node.type])\n\n // Blocks inline script execution in Safari & Chrome\n node.type = TYPE_ATTRIBUTE\n\n // Firefox has this additional event which prevents scripts from beeing executed\n const beforeScriptExecuteListener = function (event) {\n // Prevent only marked scripts from executing\n if(node.getAttribute('type') === TYPE_ATTRIBUTE)\n event.preventDefault()\n node.removeEventListener('beforescriptexecute', beforeScriptExecuteListener)\n }\n node.addEventListener('beforescriptexecute', beforeScriptExecuteListener)\n\n // Remove the node from the DOM\n node.parentElement && node.parentElement.removeChild(node)\n }\n }\n }\n }\n})\n\n// Starts the monitoring\nobserver.observe(document.documentElement, {\n childList: true,\n subtree: true\n})","import { TYPE_ATTRIBUTE } from './variables'\nimport { isOnBlacklist } from './checks'\n\nconst createElementBackup = document.createElement\n\nconst originalDescriptors = {\n src: Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype, 'src'),\n type: Object.getOwnPropertyDescriptor(HTMLScriptElement.prototype, 'type')\n}\n\n// Monkey patch the createElement method to prevent dynamic scripts from executing\ndocument.createElement = function(...args) {\n // If this is not a script tag, bypass\n if(args[0].toLowerCase() !== 'script')\n return createElementBackup.bind(document)(...args)\n\n const scriptElt = createElementBackup.bind(document)(...args)\n\n // Define getters / setters to ensure that the script type is properly set\n try {\n Object.defineProperties(scriptElt, {\n 'src': {\n ...originalDescriptors.src,\n set(value) {\n if(isOnBlacklist(value, scriptElt.type)) {\n originalDescriptors.type.set.call(this, TYPE_ATTRIBUTE)\n }\n originalDescriptors.src.set.call(this, value)\n }\n },\n 'type': {\n ...originalDescriptors.type,\n get() {\n const typeValue = originalDescriptors.type.get.call(this);\n if(typeValue === TYPE_ATTRIBUTE || isOnBlacklist(this.src, typeValue)) {\n // Prevent script execution.\n return null\n }\n return typeValue\n },\n set(value) {\n const typeValue = isOnBlacklist(scriptElt.src, scriptElt.type) ? TYPE_ATTRIBUTE : value\n originalDescriptors.type.set.call(this, typeValue)\n }\n }\n })\n\n // Monkey patch the setAttribute function so that the setter is called instead\n scriptElt.setAttribute = function(name, value) {\n if(name === 'type' || name === 'src')\n scriptElt[name] = value\n else\n HTMLScriptElement.prototype.setAttribute.call(scriptElt, name, value)\n }\n } catch (error) {\n // eslint-disable-next-line\n console.warn(\n 'Yett: unable to prevent script execution for script src ', scriptElt.src, '.\\n',\n 'A likely cause would be because you are using a third-party browser extension that monkey patches the \"document.createElement\" function.'\n )\n }\n return scriptElt\n}","import {\n patterns,\n backupScripts,\n TYPE_ATTRIBUTE\n} from './variables'\n\nimport {\n willBeUnblocked\n} from './checks'\n\nimport {\n observer\n} from './observer'\n\nconst URL_REPLACER_REGEXP = new RegExp('[|\\\\{}()[\\\\]^$+*?.]', 'g')\n\n// Unblocks all (or a selection of) blacklisted scripts.\nexport const unblock = function(...scriptUrlsOrRegexes) {\n if(scriptUrlsOrRegexes.length < 1) {\n patterns.blacklist = []\n patterns.whitelist = []\n } else {\n if(patterns.blacklist) {\n patterns.blacklist = patterns.blacklist.filter(pattern => (\n scriptUrlsOrRegexes.every(urlOrRegexp => {\n if(typeof urlOrRegexp === 'string')\n return !pattern.test(urlOrRegexp)\n else if(urlOrRegexp instanceof RegExp)\n return pattern.toString() !== urlOrRegexp.toString()\n })\n ))\n }\n if(patterns.whitelist) {\n patterns.whitelist = [\n ...patterns.whitelist,\n ...scriptUrlsOrRegexes\n .map(urlOrRegexp => {\n if(typeof urlOrRegexp === 'string') {\n const escapedUrl = urlOrRegexp.replace(URL_REPLACER_REGEXP, '\\\\$&')\n const permissiveRegexp = '.*' + escapedUrl + '.*'\n if(patterns.whitelist.every(p => p.toString() !== permissiveRegexp.toString())) {\n return new RegExp(permissiveRegexp)\n }\n } else if(urlOrRegexp instanceof RegExp) {\n if(patterns.whitelist.every(p => p.toString() !== urlOrRegexp.toString())) {\n return urlOrRegexp\n }\n }\n return null\n })\n .filter(Boolean)\n ]\n }\n }\n\n\n // Parse existing script tags with a marked type\n const tags = document.querySelectorAll(`script[type=\"${TYPE_ATTRIBUTE}\"]`)\n for(let i = 0; i < tags.length; i++) {\n const script = tags[i]\n if(willBeUnblocked(script)) {\n backupScripts.blacklisted.push([script, 'application/javascript'])\n script.parentElement.removeChild(script)\n }\n }\n\n // Exclude 'whitelisted' scripts from the blacklist and append them to \n let indexOffset = 0;\n [...backupScripts.blacklisted].forEach(([script, type], index) => {\n if(willBeUnblocked(script)) {\n const scriptNode = document.createElement('script')\n for(let i = 0; i < script.attributes.length; i++) {\n let attribute = script.attributes[i]\n if(attribute.name !== 'src' && attribute.name !== 'type') {\n scriptNode.setAttribute(attribute.name, script.attributes[i].value)\n }\n }\n scriptNode.setAttribute('src', script.src)\n scriptNode.setAttribute('type', type || 'application/javascript')\n document.head.appendChild(scriptNode)\n backupScripts.blacklisted.splice(index - indexOffset, 1)\n indexOffset++\n }\n })\n\n // Disconnect the observer if the blacklist is empty for performance reasons\n if(patterns.blacklist && patterns.blacklist.length < 1) {\n observer.disconnect()\n }\n}"],"names":["TYPE_ATTRIBUTE","patterns","blacklist","window","YETT_BLACKLIST","whitelist","YETT_WHITELIST","backupScripts","blacklisted","isOnBlacklist","src","type","some","pattern","test","every","willBeUnblocked","script","getAttribute","entry","observer","MutationObserver","mutations","i","length","addedNodes","node","nodeType","tagName","push","addEventListener","beforeScriptExecuteListener","event","preventDefault","removeEventListener","parentElement","removeChild","observe","document","documentElement","childList","subtree","createElementBackup","createElement","originalDescriptors","Object","getOwnPropertyDescriptor","HTMLScriptElement","prototype","args","toLowerCase","bind","scriptElt","defineProperties","set","value","call","this","get","typeValue","setAttribute","name","error","console","warn","URL_REPLACER_REGEXP","RegExp","scriptUrlsOrRegexes","filter","urlOrRegexp","toString","map","permissiveRegexp","replace","p","Boolean","tags","querySelectorAll","indexOffset","forEach","index","scriptNode","attributes","attribute","head","appendChild","splice","disconnect"],"mappings":"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"}