gl-wiretap
Advanced tools
Comparing version 0.1.1 to 0.2.0
@@ -8,9 +8,11 @@ export interface IGLWiretapOptions { | ||
throwGetProgramParameter?: Boolean; | ||
useTrackableNumbers?: Boolean; | ||
} | ||
export interface IGLExtensionWiretapOptions { | ||
gl: GLWiretapProxy; | ||
contextName: string; | ||
contextVariables: any[]; | ||
getEntity: (value: number) => string | number; | ||
useTrackableNumbers?: Boolean; | ||
recording: string[]; | ||
variableName: string; | ||
variables: any; | ||
} | ||
@@ -17,0 +19,0 @@ |
465
index.js
/** | ||
* | ||
* @param {WebGLRenderingContext} gl | ||
* @param {{ | ||
* contextName: String, | ||
* readPixelsFile: String, | ||
* recording: String[], | ||
* throwGetError: Boolean, | ||
* throwGetShaderParameter: Boolean, | ||
* throwGetProgramParameter: Boolean, | ||
* }} options? | ||
* @param {IGLWiretapOptions} options? | ||
* @returns {WebGLRenderingContext} | ||
*/ | ||
function glWiretap(gl, options) { | ||
options = options || {}; | ||
const recording = options.recording || []; | ||
const readPixelsFile = options.readPixelsFile; | ||
const throwGetError = options.throwGetError; | ||
const throwGetShaderParameter = options.throwGetShaderParameter; | ||
const throwGetProgramParameter = options.throwGetProgramParameter; | ||
const contextName = options.contextName || 'gl'; | ||
function glWiretap(gl, options = {}) { | ||
const { | ||
contextName = 'gl', | ||
throwGetError, | ||
useTrackableNumbers, | ||
readPixelsFile, | ||
recording = [], | ||
} = options; | ||
const proxy = new Proxy(gl, { get: listen }); | ||
const variables = { | ||
programs: [], | ||
vertexShaders: [], | ||
fragmentShaders: [], | ||
pixels: [], | ||
bufferOutputs: [], | ||
buffers: [], | ||
imageData: [], | ||
attributeLocations: [], | ||
uniformLocations: [], | ||
textures: [], | ||
framebuffers: [], | ||
extensions: [], | ||
}; | ||
const glEntityNames = Object.getOwnPropertyNames(gl).reduce((obj, name) => { | ||
obj[gl[name]] = name; | ||
return obj; | ||
}, {}); | ||
const contextVariables = []; | ||
const entityNames = {}; | ||
let imageCount = 0; | ||
return proxy; | ||
@@ -51,241 +29,52 @@ function listen(obj, property) { | ||
if (throwGetError) { | ||
recording.push(`if (${contextName}.getError() !== ${contextName}.NONE) throw new Error("error");`); | ||
recording.push(`if (${contextName}.getError() !== ${contextName}.NONE) throw new Error('error');`); | ||
} else { | ||
recording.push(`${contextName}.getError();`); // flush out errors | ||
} | ||
break; | ||
case 'createProgram': | ||
recording.push(`const program${variables.programs.length} = ${contextName}.createProgram();`); | ||
const program = gl.createProgram(); | ||
variables.programs.push(program); | ||
return program; | ||
case 'createShader': | ||
if (arguments[0] === gl.VERTEX_SHADER) { | ||
recording.push(`const vertexShader${variables.vertexShaders.length} = ${contextName}.createShader(${contextName}.VERTEX_SHADER);`); | ||
const vertexShader = gl.createShader(gl.VERTEX_SHADER); | ||
variables.vertexShaders.push(vertexShader); | ||
return vertexShader; | ||
} else if (arguments[0] === gl.FRAGMENT_SHADER) { | ||
recording.push(`const fragmentShader${variables.fragmentShaders.length} = ${contextName}.createShader(${contextName}.FRAGMENT_SHADER);`); | ||
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); | ||
variables.fragmentShaders.push(fragmentShader); | ||
return fragmentShader | ||
} else { | ||
throw new Error('unrecognized shader type'); | ||
} | ||
case 'createTexture': | ||
recording.push(`const texture${variables.textures.length} = ${contextName}.createTexture();`); | ||
const texture = gl.createTexture(); | ||
variables.textures.push(texture); | ||
return texture; | ||
case 'createFramebuffer': | ||
recording.push(`const framebuffer${variables.framebuffers.length} = ${contextName}.createFramebuffer();`); | ||
const framebuffer = gl.createFramebuffer(); | ||
variables.framebuffers.push(framebuffer); | ||
return framebuffer; | ||
return gl.getError(); | ||
case 'getExtension': | ||
recording.push(`const extension${variables.extensions.length} = ${contextName}.getExtension("${arguments[0]}");`); | ||
const variableName = `${contextName}Variables${contextVariables.length}`; | ||
recording.push(`const ${variableName} = ${contextName}.getExtension('${arguments[0]}');`); | ||
const extension = glExtensionWiretap(gl.getExtension(arguments[0]), { | ||
gl, | ||
getEntity, | ||
useTrackableNumbers, | ||
recording, | ||
variableName: `extension${variables.extensions.length}`, | ||
variables, | ||
contextName: variableName, | ||
contextVariables, | ||
}); | ||
variables.extensions.push(extension); | ||
contextVariables.push(extension); | ||
return extension; | ||
case 'shaderSource': | ||
if (variables.vertexShaders.indexOf(arguments[0]) > -1) { | ||
recording.push(contextName + '.shaderSource(vertexShader' + variables.vertexShaders.indexOf(arguments[0]) + ', `' + arguments[1] + '`);'); | ||
} else if (variables.fragmentShaders.indexOf(arguments[0]) > -1) { | ||
recording.push(contextName + '.shaderSource(fragmentShader' + variables.fragmentShaders.indexOf(arguments[0]) + ', `' + arguments[1] + '`);'); | ||
case 'readPixels': | ||
const i = contextVariables.indexOf(arguments[6]); | ||
let targetVariableName; | ||
if (i === -1) { | ||
targetVariableName = `${contextName}Variable${contextVariables.length}`; | ||
recording.push(`const ${targetVariableName} = new ${arguments[6].constructor.name}(${arguments[6].length});`); | ||
contextVariables.push(arguments[6]); | ||
} else { | ||
throw new Error('unrecognized shader type'); | ||
targetVariableName = `${contextName}Variable${i}`; | ||
} | ||
break; | ||
case 'compileShader': | ||
if (variables.vertexShaders.indexOf(arguments[0]) > -1) { | ||
recording.push(`${contextName}.compileShader(vertexShader${variables.vertexShaders.indexOf(arguments[0])});`); | ||
} else if (variables.fragmentShaders.indexOf(arguments[0]) > -1) { | ||
recording.push(`${contextName}.compileShader(fragmentShader${variables.fragmentShaders.indexOf(arguments[0])});`); | ||
} else { | ||
throw new Error('unrecognized shader type'); | ||
} | ||
break; | ||
case 'getShaderParameter': | ||
if (throwGetShaderParameter) { | ||
if (variables.vertexShaders.indexOf(arguments[0]) > -1) { | ||
recording.push(`if (!${contextName}.getShaderParameter(vertexShader${variables.vertexShaders.indexOf(arguments[0])}, ${contextName}.COMPILE_STATUS)) throw new Error("shader did not compile");`); | ||
} else if (variables.fragmentShaders.indexOf(arguments[0]) > -1) { | ||
recording.push(`if (!${contextName}.getShaderParameter(fragmentShader${variables.fragmentShaders.indexOf(arguments[0])}, ${contextName}.COMPILE_STATUS)) throw new Error("shader did not compile");`); | ||
} else { | ||
throw new Error('unrecognized shader type'); | ||
} | ||
} | ||
break; | ||
case 'attachShader': | ||
if (variables.vertexShaders.indexOf(arguments[1]) > -1) { | ||
recording.push(`${contextName}.attachShader(program${variables.programs.indexOf(arguments[0])}, vertexShader${variables.vertexShaders.indexOf(arguments[1])});`); | ||
} else if (variables.fragmentShaders.indexOf(arguments[1]) > -1) { | ||
recording.push(`${contextName}.attachShader(program${variables.programs.indexOf(arguments[0])}, fragmentShader${variables.fragmentShaders.indexOf(arguments[1])});`); | ||
} else if (arguments[1] === null) { | ||
recording.push(`${contextName}.attachShader(program${variables.programs.indexOf(arguments[0])}, null);`); | ||
} else { | ||
throw new Error('unrecognized shader type'); | ||
} | ||
break; | ||
case 'bindAttribLocation': | ||
recording.push(contextName + '.bindAttribLocation(program' + variables.programs.indexOf(arguments[0]) + ', ' + arguments[1] + ', `' + arguments[2] + '`);'); | ||
break; | ||
case 'linkProgram': | ||
recording.push(contextName + `.linkProgram(program${variables.programs.indexOf(arguments[0])});`); | ||
break; | ||
case 'getProgramParameter': | ||
if (throwGetProgramParameter) { | ||
recording.push(`if (!${contextName}.getProgramParameter(program${variables.programs.indexOf(arguments[0])}, ${contextName}.LINK_STATUS)) throw new Error(${contextName}.getProgramInfoLog(program${variables.programs.indexOf(arguments[0])}));`); | ||
} | ||
break; | ||
case 'useProgram': | ||
recording.push(`${contextName}.useProgram(program${variables.programs.indexOf(arguments[0])});`); | ||
break; | ||
case 'createBuffer': | ||
recording.push(`const buffer${variables.buffers.length} = ${contextName}.createBuffer();`); | ||
const buffer = gl.createBuffer(); | ||
variables.buffers.push(buffer); | ||
return buffer; | ||
case 'bindBuffer': | ||
if (arguments[0] === gl.ARRAY_BUFFER) { | ||
recording.push(`${contextName}.bindBuffer(${contextName}.ARRAY_BUFFER, buffer${variables.buffers.indexOf(arguments[1])});`); | ||
} else if (arguments[0] === gl.ELEMENT_ARRAY_BUFFER) { | ||
recording.push(`${contextName}.bindBuffer(${contextName}.ARRAY_BUFFER, buffer${variables.buffers.indexOf(arguments[1])});`); | ||
} else { | ||
throw new Error('unrecognized buffer type'); | ||
} | ||
break; | ||
case 'bufferData': | ||
if (arguments[0] === gl.ARRAY_BUFFER) { | ||
recording.push(`const bufferOutput${variables.bufferOutputs.length} = new Float32Array([${Array.from(arguments[1]).join(',')}]);`); | ||
recording.push(`${contextName}.bufferData(${contextName}.ARRAY_BUFFER, bufferOutput${variables.bufferOutputs.length}, ${arguments[2]});`); | ||
variables.bufferOutputs.push(arguments[1]); | ||
} else if (arguments[0] === gl.ELEMENT_ARRAY_BUFFER) { | ||
recording.push(`const bufferOutput${variables.bufferOutputs.length} = new Uint16Array([${Array.from(arguments[1]).join(',')}]);`); | ||
recording.push(`${contextName}.bufferData(${contextName}.ELEMENT_ARRAY_BUFFER, bufferOutput${variables.bufferOutputs.length}, ${arguments[2]});`); | ||
variables.bufferOutputs.push(arguments[1]); | ||
} else { | ||
throw new Error('unrecognized buffer type'); | ||
} | ||
break; | ||
case 'readPixels': | ||
recording.push(`const pixels${variables.pixels.length} = new Uint8Array(${arguments[2] * arguments[3] * 4});`); | ||
recording.push(`${contextName}.readPixels(${arguments[0]}, ${arguments[1]}, ${arguments[2]}, ${arguments[3]}, ${arguments[4]}, ${arguments[5]}, pixels${variables.pixels.length});`); | ||
recording.push(`${contextName}.readPixels(${arguments[0]}, ${arguments[1]}, ${arguments[2]}, ${arguments[3]}, ${getEntity(arguments[4])}, ${getEntity(arguments[5])}, ${targetVariableName});`); | ||
if (readPixelsFile) { | ||
writePPM(arguments[2], arguments[3]); | ||
} | ||
variables.pixels.push(null); | ||
break; | ||
case 'deleteProgram': | ||
if (arguments[0] === null) { | ||
recording.push(`${contextName}.deleteProgram(null);`); | ||
} else { | ||
recording.push(`${contextName}.deleteProgram(program${variables.programs.indexOf(arguments[0])});`); | ||
} | ||
break; | ||
case 'getAttribLocation': | ||
recording.push('const attributeLocation' + variables.attributeLocations.length + ' = ' + contextName + '.getAttribLocation(program' + variables.programs.indexOf(arguments[0]) + ', `' + arguments[1] + '`;'); | ||
const attributeLocation = gl.getAttribLocation(arguments[0], arguments[1]); | ||
variables.attributeLocations.push(attributeLocation); | ||
return attributeLocation; | ||
case 'getUniformLocation': | ||
recording.push(`const uniformLocation${variables.uniformLocations.length} = ${contextName}.getUniformLocation(program${variables.programs.indexOf(arguments[0])}, '${arguments[1]}');`); | ||
const uniformLocation = gl.getUniformLocation(arguments[0], arguments[1]); | ||
variables.uniformLocations.push(uniformLocation); | ||
return uniformLocation; | ||
case 'vertexAttribPointer': | ||
if (variables.attributeLocations.indexOf(arguments[0]) > -1) { | ||
recording.push(`${contextName}.vertexAttribPointer(attributeLocation${variables.attributeLocations.indexOf(arguments[0])}, ${arguments[1]}, ${arguments[2]}, ${arguments[3]}, ${arguments[4]}, ${arguments[5]});`); | ||
} else { | ||
recording.push(`${contextName}.vertexAttribPointer(${arguments[0]}, ${arguments[1]}, ${arguments[2]}, ${arguments[3]}, ${arguments[4]}, ${arguments[5]});`); | ||
} | ||
break; | ||
case 'enableVertexAttribArray': | ||
if (variables.attributeLocations.indexOf(arguments[0]) > -1) { | ||
recording.push(`${contextName}.enableVertexAttribArray(attributeLocation${variables.attributeLocations.indexOf(arguments[0])});`); | ||
} else { | ||
recording.push(`${contextName}.enableVertexAttribArray(${arguments[0]});`); | ||
} | ||
break; | ||
case 'getShaderInfoLog': | ||
if (variables.vertexShaders.indexOf(arguments[0]) > -1) { | ||
recording.push(`${contextName}.getShaderInfoLog(vertexShader${variables.vertexShaders.indexOf(arguments[0])});`); | ||
} else if (variables.fragmentShaders.indexOf(arguments[0]) > -1) { | ||
recording.push(`${contextName}.getShaderInfoLog(fragmentShader${variables.fragmentShaders.indexOf(arguments[0])});`); | ||
} else { | ||
throw new Error('unrecognized shader type'); | ||
} | ||
break; | ||
case 'deleteShader': | ||
if (variables.vertexShaders.indexOf(arguments[0]) > -1) { | ||
recording.push(`${contextName}.deleteShader(vertexShader${variables.vertexShaders.indexOf(arguments[0])});`); | ||
} else if (variables.fragmentShaders.indexOf(arguments[0]) > -1) { | ||
recording.push(`${contextName}.deleteShader(fragmentShader${variables.fragmentShaders.indexOf(arguments[0])});`); | ||
} else { | ||
throw new Error('unrecognized shader type'); | ||
} | ||
break; | ||
case 'getProgramInfoLog': | ||
recording.push(`${contextName}.getProgramInfoLog(program${variables.programs.indexOf(arguments[0])});`); | ||
break; | ||
case 'bindTexture': | ||
recording.push(`${contextName}.bindTexture(${arguments[0]}, texture${variables.textures.indexOf(arguments[1])});`); | ||
break; | ||
case 'bindFramebuffer': | ||
if (arguments[1] === null) { | ||
recording.push(`${contextName}.bindFramebuffer(${getGLEntity(arguments[0])}, null);`); | ||
} else { | ||
recording.push(`${contextName}.bindFramebuffer(${getGLEntity(arguments[0])}, framebuffer${variables.framebuffers.indexOf(arguments[1])});`); | ||
} | ||
break; | ||
case 'framebufferTexture2D': | ||
recording.push(`${contextName}.framebufferTexture2D(${arguments[0]}, ${arguments[1]}, ${arguments[2]}, texture${variables.textures.indexOf(arguments[3])}, ${arguments[4]});`); | ||
break; | ||
case 'deleteFramebuffer': | ||
recording.push(`${contextName}.deleteFramebuffer(framebuffer${variables.framebuffers.indexOf(arguments[0])});`); | ||
break; | ||
case 'deleteTexture': | ||
recording.push(`${contextName}.deleteTexture(texture${variables.textures.indexOf(arguments[0])});`); | ||
break; | ||
case 'uniform1fv': | ||
case 'uniform1iv': | ||
case 'uniform2fv': | ||
case 'uniform2iv': | ||
case 'uniform3fv': | ||
case 'uniform3iv': | ||
case 'uniform4fv': | ||
case 'uniform4iv': | ||
recording.push(`${contextName}.${property}(uniformLocation${variables.uniformLocations.indexOf(arguments[0])}, ${JSON.stringify(Array.from(arguments[1]))});`); | ||
break; | ||
case 'uniform1f': | ||
case 'uniform1i': | ||
recording.push(`${contextName}.${property}(uniformLocation${variables.uniformLocations.indexOf(arguments[0])}, ${arguments[1]});`); | ||
break; | ||
case 'uniform2f': | ||
case 'uniform2i': | ||
recording.push(`${contextName}.${property}(uniformLocation${variables.uniformLocations.indexOf(arguments[0])}, ${arguments[1]}, ${arguments[2]});`); | ||
break; | ||
case 'uniform3f': | ||
case 'uniform3i': | ||
recording.push(`${contextName}.${property}(uniformLocation${variables.uniformLocations.indexOf(arguments[0])}, ${arguments[1]}, ${arguments[2]}, ${arguments[3]});`); | ||
break; | ||
case 'uniform4f': | ||
case 'uniform4i': | ||
recording.push(`${contextName}.${property}(uniformLocation${variables.uniformLocations.indexOf(arguments[0])}, ${arguments[1]}, ${arguments[2]}, ${arguments[3]}, ${arguments[4]});`); | ||
break; | ||
case 'getParameter': | ||
recording.push(`${contextName}.getParameter(${getGLEntity(arguments[0])});`); | ||
break; | ||
default: | ||
recording.push(`${contextName}.${property}(${argumentsToString(arguments)});`); | ||
return gl.readPixels.apply(gl, arguments); | ||
case 'drawBuffers': | ||
recording.push(`${contextName}.drawBuffers([${argumentsToString(arguments[0], { contextName, contextVariables, getEntity, addVariable } )}]);`); | ||
return gl.drawBuffers(arguments[0]); | ||
} | ||
return gl[property].apply(gl, arguments); | ||
let result = gl[property].apply(gl, arguments); | ||
if (typeof result !== 'undefined' && contextVariables.indexOf(result) === -1) { | ||
if (typeof result === 'number' && useTrackableNumbers) { | ||
contextVariables.push(result = trackableNumber(result)); | ||
} | ||
recording.push(`const ${contextName}Variable${contextVariables.length} = ${methodCallToString(property, arguments)};`); | ||
contextVariables.push(result); | ||
} else { | ||
recording.push(`${methodCallToString(property, arguments)};`); | ||
} | ||
return result; | ||
} | ||
} | ||
entityNames[gl[property]] = property; | ||
return gl[property]; | ||
@@ -296,29 +85,23 @@ } | ||
} | ||
function getGLEntity(number) { | ||
const name = glEntityNames[number]; | ||
if (!name) { | ||
for (let extensionIndex = 0; extensionIndex < variables.extensions.length; extensionIndex++) { | ||
const extension = variables.extensions[extensionIndex]; | ||
const extensionEntityNames = Object.getOwnPropertyNames(variables.extensions[extensionIndex]); | ||
for (let extensionEntityNamesIndex = 0; extensionEntityNamesIndex < extensionEntityNames.length; extensionEntityNamesIndex++) { | ||
const extensionEntityName = extensionEntityNames[extensionEntityNamesIndex]; | ||
if (extension[extensionEntityName] === number) { | ||
return 'extension' + extensionIndex + '.' + extensionEntityName; | ||
} | ||
} | ||
} | ||
console.warn('GL entity not found'); | ||
return number; | ||
function getEntity(value) { | ||
const name = entityNames[value]; | ||
if (name) { | ||
return contextName + '.' + name; | ||
} | ||
return contextName + '.' + name; | ||
return value; | ||
} | ||
function addVariable(value) { | ||
contextVariables.push(value); | ||
} | ||
function writePPM(width, height) { | ||
recording.push(`let imageDatum${variables.imageData.length} = ["P3\\n# ${contextName}.ppm\\n", ${width}, " ", ${height}, "\\n255\\n"].join("");`); | ||
recording.push(`for (let i = 0; i < pixels${variables.pixels.length}.length; i += 4) {`); | ||
recording.push(` imageDatum${variables.imageData.length} += pixels${variables.pixels.length}[i] + " " + pixels${variables.pixels.length}[i + 1] + " " + pixels${variables.pixels.length}[i + 2] + " ";`); | ||
const sourceVariable = `${contextName}Variable${contextVariables.length}`; | ||
const imageVariable = `imageDatum${imageCount}`; | ||
recording.push(`let ${imageVariable} = ["P3\\n# ${readPixelsFile}.ppm\\n", ${width}, ' ', ${height}, "\\n255\\n"].join("");`); | ||
recording.push(`for (let i = 0; i < ${imageVariable}.length; i += 4) {`); | ||
recording.push(` ${imageVariable} += ${sourceVariable}[i] + ' ' + ${sourceVariable}[i + 1] + ' ' + ${sourceVariable}[i + 2] + ' ';`); | ||
recording.push('}'); | ||
recording.push('if (typeof require !== "undefined") {'); | ||
recording.push(` require("fs").writeFileSync("./${readPixelsFile}.ppm", imageDatum${variables.imageData.length});`); | ||
recording.push(` require('fs').writeFileSync('./${readPixelsFile}.ppm', ${imageVariable});`); | ||
recording.push('}'); | ||
variables.imageData.push(null); | ||
imageCount++; | ||
} | ||
@@ -342,2 +125,5 @@ function addComment(value) { | ||
} | ||
function methodCallToString(method, args) { | ||
return `${contextName}.${method}(${argumentsToString(args, { contextName, contextVariables, getEntity, addVariable })})`; | ||
} | ||
} | ||
@@ -348,3 +134,3 @@ | ||
* @param extension | ||
* @param {{recording: String, variableName: String}} options | ||
* @param {IGLExtensionWiretapOptions} options | ||
* @returns {*} | ||
@@ -354,6 +140,10 @@ */ | ||
const proxy = new Proxy(extension, { get: listen }); | ||
const gl = options.gl; | ||
const recording = options.recording; | ||
const variableName = options.variableName; | ||
const variables = options.variables; | ||
const extensionEntityNames = {}; | ||
const { | ||
contextName, | ||
contextVariables, | ||
getEntity, | ||
useTrackableNumbers, | ||
recording | ||
} = options; | ||
return proxy; | ||
@@ -365,40 +155,93 @@ function listen(obj, property) { | ||
case 'drawBuffersWEBGL': | ||
extension.drawBuffersWEBGL(arguments[0]); | ||
recording.push(`${variableName}.drawBuffersWEBGL([${Array.from(arguments).join(', ')}]);`); | ||
return; | ||
case 'getTranslatedShaderSource': | ||
if (variables.vertexShaders.indexOf(arguments[0]) > -1) { | ||
recording.push(`${variableName}.getTranslatedShaderSource(vertexShader${variables.vertexShaders.indexOf(arguments[0])})`); | ||
} else if (variables.fragmentShaders.indexOf(arguments[0]) > -1) { | ||
recording.push(`${variableName}.getTranslatedShaderSource(fragmentShader${variables.fragmentShaders.indexOf(arguments[0])})`); | ||
} else { | ||
throw new Error('Cannot find shader'); | ||
} | ||
return extension.getTranslatedShaderSource(arguments[0]); | ||
recording.push(`${contextName}.drawBuffersWEBGL([${argumentsToString(arguments[0], { contextName, contextVariables, getEntity: getExtensionEntity, addVariable })}]);`); | ||
return extension.drawBuffersWEBGL(arguments[0]); | ||
} | ||
recording.push(`${variableName}.${property}(${argumentsToString(arguments)});`); | ||
let result = extension[property].apply(extension, arguments); | ||
if (typeof result !== 'undefined' && contextVariables.indexOf(result) === -1) { | ||
if (useTrackableNumbers && typeof result === 'number') { | ||
contextVariables.push(result = trackableNumber(result)); | ||
} | ||
recording.push(`const ${contextName}Variable${contextVariables.length} = ${methodCallToString(property, arguments)};`); | ||
contextVariables.push(result); | ||
} else { | ||
recording.push(`${methodCallToString(property, arguments)};`); | ||
} | ||
return result; | ||
}; | ||
} | ||
extensionEntityNames[extension[property]] = property; | ||
return extension[property]; | ||
} | ||
function getExtensionEntity(value) { | ||
return extensionEntityNames[value] || getEntity(value); | ||
} | ||
function methodCallToString(method, args) { | ||
return `${contextName}.${method}(${argumentsToString(args, { contextName, contextVariables, getEntity: getExtensionEntity, addVariable })})`; | ||
} | ||
function addVariable(value, source) { | ||
const variableName = `${contextName}Variable${contextVariables.length}`; | ||
recording.push(`const ${variableName} = ${source};`); | ||
contextVariables.push(value); | ||
return variableName; | ||
} | ||
} | ||
function argumentsToString(args) { | ||
return (Array.from(args).map(function (arg) { | ||
switch (typeof arg) { | ||
case 'string': | ||
return '`' + arg + '`'; | ||
case 'number': | ||
return arg; | ||
case 'boolean': | ||
return arg ? 'true' : 'false'; | ||
default: | ||
if (arg === null) { | ||
return 'null'; | ||
} | ||
throw new Error('unrecognized argument'); | ||
} | ||
function argumentsToString(args, options) { | ||
return (Array.from(args).map((arg) => { | ||
return argumentToString(arg, options); | ||
}).join(', ')) | ||
} | ||
function argumentToString(arg, options) { | ||
const { contextName, contextVariables, getEntity, addVariable } = options; | ||
if (typeof arg === 'undefined') { | ||
return 'undefined'; | ||
} | ||
if (arg === null) { | ||
return 'null'; | ||
} | ||
const i = contextVariables.indexOf(arg); | ||
if (i > -1) { | ||
return `${contextName}Variable${i}`; | ||
} | ||
switch (arg.constructor.name) { | ||
case 'String': | ||
const hasLines = /\n/.test(arg); | ||
const hasSingleQuotes = /'/.test(arg); | ||
const hasDoubleQuotes = /"/.test(arg); | ||
if (hasLines) { | ||
return '`' + arg + '`'; | ||
} else if (hasSingleQuotes && !hasDoubleQuotes) { | ||
return '"' + arg + '"'; | ||
} else if (!hasSingleQuotes && hasDoubleQuotes) { | ||
return "'" + arg + "'"; | ||
} else { | ||
return '\'' + arg + '\''; | ||
} | ||
case 'Number': | ||
const name = getEntity(arg); | ||
return name || arg; | ||
case 'Boolean': | ||
return arg ? 'true' : 'false'; | ||
case 'Array': | ||
return JSON.stringify(Array.from(arg)); | ||
case 'Float32Array': | ||
case 'Uint8Array': | ||
case 'Uint16Array': | ||
case 'Int32Array': | ||
return addVariable(arg, `new ${arg.constructor.name}(${JSON.stringify(Array.from(arg))})`); | ||
default: | ||
debugger; | ||
throw new Error('unrecognized argument'); | ||
} | ||
} | ||
function trackableNumber(number) { | ||
// wrapped in object, so track-able | ||
return new Number(number); | ||
} | ||
if (typeof module !== 'undefined') { | ||
@@ -405,0 +248,0 @@ module.exports = { glWiretap, glExtensionWiretap }; |
{ | ||
"name": "gl-wiretap", | ||
"version": "0.1.1", | ||
"version": "0.2.0", | ||
"description": "A gl debugger that listens and replays gl (WebGL, WebGL2, and HeadlessGL) gpu commands", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
14119
262
1