Chrome扩展内容脚本:无类定义访问时能否欺骗JavaScript的instanceof?
解决Chrome扩展内容脚本调用带instanceof检查的页面函数问题
由于Chrome扩展的内容脚本与页面脚本运行在隔离的上下文中,无法直接访问页面闭包内的SomeClass,核心解决思路是通过注入到页面上下文的脚本来操作(注入脚本与页面脚本共享同一执行环境),以下是几种可行方案:
方案1:提取闭包内的SomeClass并暴露到全局
页面的accessibleFunction是箭头函数,其作用域链包含定义SomeClass的闭包。通过注入脚本遍历函数的作用域链,提取SomeClass并挂载到全局,让内容脚本可以直接实例化:
实现步骤
- 在内容脚本中注入页面脚本:
// 内容脚本代码 const injectScript = document.createElement('script'); injectScript.textContent = ` // 此代码运行在页面上下文 function extractSomeClass(targetFn) { let currentScope = targetFn; // 遍历函数作用域链查找SomeClass while (currentScope) { try { const scopeChain = currentScope[[Scopes]]; for (const scope of scopeChain) { if ('SomeClass' in scope) { return scope.SomeClass; } } currentScope = Object.getPrototypeOf(currentScope); } catch (e) { currentScope = null; } } return null; } // 将SomeClass暴露到全局 window.ExposedSomeClass = extractSomeClass(window.accessibleFunction); `; document.head.appendChild(injectScript); injectScript.remove();
- 内容脚本中使用暴露的类:
// 等待注入脚本完成(可通过自定义事件确保) setTimeout(() => { if (window.ExposedSomeClass) { const validInstance = new window.ExposedSomeClass(); window.accessibleFunction(validInstance); // 可通过instanceof检查 } }, 100);
方案2:直接在页面上下文创建实例并调用目标函数
如果不需要获取SomeClass本身,仅需触发目标行为,可直接在注入脚本中创建合法实例并调用accessibleFunction:
// 内容脚本代码 const injectScript = document.createElement('script'); injectScript.textContent = ` // 页面上下文代码 function extractSomeClass(targetFn) { let currentScope = targetFn; while (currentScope) { try { const scopeChain = currentScope[[Scopes]]; for (const scope of scopeChain) { if ('SomeClass' in scope) { return scope.SomeClass; } } currentScope = Object.getPrototypeOf(currentScope); } catch (e) { currentScope = null; } } return null; } // 创建合法实例并调用目标函数 const SomeClass = extractSomeClass(window.accessibleFunction); if (SomeClass) { const validInstance = new SomeClass(); window.accessibleFunction(validInstance); } `; document.head.appendChild(injectScript); injectScript.remove();
方案3:绕过instanceof检查(不推荐)
若无法提取SomeClass,可重写accessibleFunction修改判断逻辑,比如通过对象结构或原型特征替代instanceof:
// 内容脚本注入的页面代码 const originalFn = window.accessibleFunction; window.accessibleFunction = function(event) { // 原闭包内可直接访问SomeClass const isValid = event instanceof SomeClass || (event && event.constructor?.name === 'SomeClass'); if (isValid) { originalFn.call(this, event); } };
注意:此方案可能破坏页面原有逻辑,仅作为备选方案。
内容的提问来源于stack exchange,提问作者TechyTech
相关产品推荐
相关产品推荐

