一般拿到一个代码,先跑一遍main.js,建议在toolsFunc里把proxy关掉跑,这样可以生成尽量少的日志,日志里只有关键函数缺失的信息
首先报错Document_head_get函数缺失
1
| {tools|dispatch -> 环境缺失:Document_head_get ->错误:HTMLHeadElement is not defined
|
document.head会返回当前页面的head标签,head标签实例的__proto__是HTMLHeadElement,需要把这个给脱下来,脱环境脚本运行getEnvCode(HTMLHeadElement)
拿到函数报错,第一步先在浏览器中执行,看到底返回的什么东西,是返回的实例,还是返回的字符串等,不同的返回值有不同的补法
然后在envFuncs.js里实现Document_head_get,生成一个head标签,设置这个标签对象的原型
1 2 3 4 5
| sandBox.envFuncs.Document_head_get=function () { let _head={} Object.setPrototypeOf(_head,HTMLHeadElement.prototype) return _head }
|
然后补Navigator_javaEnabled和Navigator_languages_get两个方法的缺失,这两个方法一个返回布尔值,一个返回字符串,和上面返回head标签实例的不同,不需要额外再补对象环境
1 2 3 4 5 6
| sandBox.envFuncs.Navigator_javaEnabled=function () { return false } sandBox.envFuncs.Navigator_languages_get=function () { return ['zh-CN', 'en', 'en-GB', 'en-US'] }
|
继续处理报错
1
| {Document_getElementsByTagName|未实现Document_getElementsByTagName_base}
|
意思是缺失base标签,导致js代码再尝试获取base标签的时候获取不到,所以需要在userVar.js中添加标签,所有新增标签的操作都在userVar.js中实现
1 2 3
| !function () { let _base=document.createElement('base') }()
|
此时会报错未实现对应的Document_createElement_base,去envFuncs.js中实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| sandBox.envFuncs.Document_createElement=function (tagName,options) { let tag={}; switch (tagName) { case "div": Object.setPrototypeOf(tag,HTMLDivElement.prototype) tag=sandBox.proxy(tag,`Document_createElement_${tagName}_${sandBox.getID()}`) break; case "meta": Object.setPrototypeOf(tag,HTMLMetaElement.prototype) tag=sandBox.proxy(tag,`Document_createElement_${tagName}_${sandBox.getID()}`) break; case "head": Object.setPrototypeOf(tag,HTMLHeadElement.prototype) tag=sandBox.proxy(tag,`Document_createElement_${tagName}_${sandBox.getID()}`) break; case "input": Object.setPrototypeOf(tag,HTMLInputElement.prototype) tag=sandBox.proxy(tag,`Document_createElement_${tagName}_${sandBox.getID()}`) break; case "a": Object.setPrototypeOf(tag,HTMLAnchorElement.prototype) tag=sandBox.proxy(tag,`Document_createElement_${tagName}_${sandBox.getID()}`) break; case "i": Object.setPrototypeOf(tag,HTMLElement.prototype) tag=sandBox.proxy(tag,`Document_createElement_${tagName}_${sandBox.getID()}`) break; case "canvas": Object.setPrototypeOf(tag,HTMLCanvasElement.prototype) tag=sandBox.proxy(tag,`Document_createElement_${tagName}_${sandBox.getID()}`) break; case "script": Object.setPrototypeOf(tag,HTMLScriptElement.prototype) tag=sandBox.proxy(tag,`Document_createElement_${tagName}_${sandBox.getID()}`) break; case "base": Object.setPrototypeOf(tag,HTMLBaseElement.prototype) tag=sandBox.proxy(tag,`Document_createElement_${tagName}_${sandBox.getID()}`) break; default: console.log(`未实现Document_createElement_${tagName}`) break; } sandBox.tags.push(tag) return tag; }
|
然后在浏览器执行let b = document.createElement("base");b.__proto__,发现调用base标签的原型是HTMLBaseElement,需要去把HTMLBaseElement的环境再脱下来
继续处理报错,刚才创建了base标签,现在要完善Document_getElementsByTagName方法,来获取base标签
1
| {Document_getElementsByTagName|未实现Document_getElementsByTagName_base}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| sandBox.envFuncs.Document_getElementsByTagName=function (tagName){ let collections=[] switch (tagName) { case "meta": collections=sandBox.getCollections('[object HTMLMetaElement]') Object.setPrototypeOf(collections,HTMLCollection.prototype) collections=sandBox.proxy(collections,`Document_getElementsByTagName_${tagName}`) break; case "i": collections=sandBox.getCollections('[object HTMLElement]') Object.setPrototypeOf(collections,HTMLElement.prototype) collections=sandBox.proxy(collections,`Document_getElementsByTagName_${tagName}`) break; case "script": collections=sandBox.getCollections('[object HTMLScriptElement]') Object.setPrototypeOf(collections,HTMLScriptElement.prototype) collections=sandBox.proxy(collections,`Document_getElementsByTagName_${tagName}`) break; case "base": collections=sandBox.getCollections('[object HTMLBaseElement]') Object.setPrototypeOf(collections,HTMLBaseElement.prototype) collections=sandBox.proxy(collections,`Document_getElementsByTagName_${tagName}`) break; default: console.log(`{Document_getElementsByTagName|未实现Document_getElementsByTagName_${tagName}}`) break; } return collections }
|
继续处理报错
1
| {HTMLCanvasElement_getContext未实现:webgl2
|
首先要知道这个getContext是干啥的,在浏览器中创建一个canvas并执行getContext("webgl2")
1 2 3
| let canvas = document.createElement("canvas");canvas.getContext("webgl2")
WebGL2RenderingContext {canvas: canvas, drawingBufferWidth: 300, drawingBufferHeight: 150, drawingBufferColorSpace: 'srgb', unpackColorSpace: 'srgb', …}
|
然后需要脱WebGL2RenderingContext环境,浏览器运行getEnvCode(WebGL2RenderingContext),把环境丢到envs目录下
然后补HTMLCanvasElement_getContext方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| sandBox.envFuncs.HTMLCanvasElement_getContext=function (name) { let ctx={} switch (name){ case '2d': Object.setPrototypeOf(ctx,CanvasRenderingContext2D.prototype) ctx=sandBox.proxy(ctx,`HTMLCanvasElement_getContext_${name}`) break; case 'webgl' || 'experimental-webgl' : Object.setPrototypeOf(ctx,WebGLRenderingContext.prototype) ctx=sandBox.proxy(ctx,`HTMLCanvasElement_getContext_${name}`) break; case 'webgl2': Object.setPrototypeOf(ctx,WebGL2RenderingContext.prototype) ctx=sandBox.proxy(ctx,`HTMLCanvasElement_getContext_${name}`) break; default: console.log(`{HTMLCanvasElement_getContext | 未实现:${name}}`) break; } sandBox.setProtoAttribute.call(this,'context',ctx) return ctx }
|
然后补异步事件缺失
1 2 3 4 5
| {EventTarget_addEventListener | 异步事件:wheel} {EventTarget_addEventListener | 异步事件:mousemove} {EventTarget_addEventListener | 异步事件:touchmove} {EventTarget_addEventListener | 异步事件:click} {EventTarget_addEventListener | 异步事件:keydown}
|
在asyncCode.js中可以实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| let MouseEvents=[ { "clientX": 154, "clientY": 317, "type": "mousemove", "button": 0 }, ] for(let i=0;i<MouseEvents.length;i++){ let mouseEvent=MouseEvents[i] let type=mouseEvent['type'] let listeners=sandBox.asyncCode.eventListener[type] for(let j=0;j<listeners.length;j++){ let listen=listeners[j] listen['func'].call(listen['this'],mouseEvent) } }
|
注意这里的鼠标事件要只给mousemove的,给mousedown这种的话js代码识别不了,因为匹配事件的逻辑就是根据事件type去匹配对应的函数进行调用,如果找不到对应的类型直接报错了
有的异步事件可以完全不用管,不会影响结果生成