/** * gpu.js * http://gpu.rocks/ * * GPU Accelerated JavaScript * * @version 2.0.0-rc.14 * @date Mon May 20 2019 18:50:57 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License * * Copyright (c) 2019 gpu.js Team */(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 0) { recording.pop(); } } function insertVariable(name, value) { variables[name] = value; } function getEntity(value) { const name = entityNames[value]; if (name) { return contextName + '.' + name; } return value; } function setIndent(spaces) { indent = ' '.repeat(spaces); } function addVariable(value, source) { const variableName = `${contextName}Variable${contextVariables.length}`; recording.push(`${indent}const ${variableName} = ${source};`); contextVariables.push(value); return variableName; } function writePPM(width, height) { const sourceVariable = `${contextName}Variable${contextVariables.length}`; const imageVariable = `imageDatum${imageCount}`; recording.push(`${indent}let ${imageVariable} = ["P3\\n# ${readPixelsFile}.ppm\\n", ${width}, ' ', ${height}, "\\n255\\n"].join("");`); recording.push(`${indent}for (let i = 0; i < ${imageVariable}.length; i += 4) {`); recording.push(`${indent} ${imageVariable} += ${sourceVariable}[i] + ' ' + ${sourceVariable}[i + 1] + ' ' + ${sourceVariable}[i + 2] + ' ';`); recording.push(`${indent}}`); recording.push(`${indent}if (typeof require !== "undefined") {`); recording.push(`${indent} require('fs').writeFileSync('./${readPixelsFile}.ppm', ${imageVariable});`); recording.push(`${indent}}`); imageCount++; } function addComment(value) { recording.push(`${indent}// ${value}`); } function checkThrowError() { recording.push(`${indent}(() => { ${indent}const error = ${contextName}.getError(); ${indent}if (error !== ${contextName}.NONE) { ${indent} const names = Object.getOwnPropertyNames(gl); ${indent} for (let i = 0; i < names.length; i++) { ${indent} const name = names[i]; ${indent} if (${contextName}[name] === error) { ${indent} throw new Error('${contextName} threw ' + name); ${indent} } ${indent} } ${indent}} ${indent}})();`); } function methodCallToString(method, args) { return `${contextName}.${method}(${argumentsToString(args, { contextName, contextVariables, getEntity, addVariable, variables })})`; } function getVariableName(value) { if (variables) { for (const name in variables) { if (variables[name] === value) { return name; } } } return null; } } function glExtensionWiretap(extension, options) { const proxy = new Proxy(extension, { get: listen }); const extensionEntityNames = {}; const { contextName, contextVariables, getEntity, useTrackablePrimitives, recording, variables, indent, } = options; return proxy; function listen(obj, property) { if (typeof obj[property] === 'function') { return function() { switch (property) { case 'drawBuffersWEBGL': recording.push(`${indent}${contextName}.drawBuffersWEBGL([${argumentsToString(arguments[0], { contextName, contextVariables, getEntity: getExtensionEntity, addVariable, variables })}]);`); return extension.drawBuffersWEBGL(arguments[0]); } let result = extension[property].apply(extension, arguments); switch (typeof result) { case 'undefined': recording.push(`${indent}${methodCallToString(property, arguments)};`); return; case 'number': case 'boolean': if (useTrackablePrimitives && contextVariables.indexOf(trackablePrimitive(result)) === -1) { recording.push(`${indent}const ${contextName}Variable${contextVariables.length} = ${methodCallToString(property, arguments)};`); contextVariables.push(result = trackablePrimitive(result)); } else { recording.push(`${indent}const ${contextName}Variable${contextVariables.length} = ${methodCallToString(property, arguments)};`); contextVariables.push(result); } break; default: if (result === null) { recording.push(`${methodCallToString(property, arguments)};`); } else { recording.push(`${indent}const ${contextName}Variable${contextVariables.length} = ${methodCallToString(property, arguments)};`); } contextVariables.push(result); } return result; }; } extensionEntityNames[extension[property]] = property; return extension[property]; } function getExtensionEntity(value) { if (extensionEntityNames.hasOwnProperty(value)) { return `${contextName}.${extensionEntityNames[value]}`; } return getEntity(value); } function methodCallToString(method, args) { return `${contextName}.${method}(${argumentsToString(args, { contextName, contextVariables, getEntity: getExtensionEntity, addVariable, variables })})`; } function addVariable(value, source) { const variableName = `${contextName}Variable${contextVariables.length}`; contextVariables.push(value); recording.push(`${indent}const ${variableName} = ${source};`); return variableName; } } function argumentsToString(args, options) { const { variables } = options; return (Array.from(args).map((arg) => { const variableName = getVariableName(arg); if (variableName) { return variableName; } return argumentToString(arg, options); }).join(', ')); function getVariableName(value) { if (variables) { for (const name in variables) { if (variables[name] === value) { return name; } } } return null; } } 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': return getEntity(arg); case 'Boolean': return getEntity(arg); case 'Array': return addVariable(arg, `new ${arg.constructor.name}(${Array.from(arg).join(',')})`); case 'Float32Array': case 'Uint8Array': case 'Uint16Array': case 'Int32Array': return addVariable(arg, `new ${arg.constructor.name}(${JSON.stringify(Array.from(arg))})`); default: throw new Error('unrecognized argument'); } } function trackablePrimitive(value) { return new value.constructor(value); } if (typeof module !== 'undefined') { module.exports = { glWiretap, glExtensionWiretap }; } if (typeof window !== 'undefined') { glWiretap.glExtensionWiretap = glExtensionWiretap; window.glWiretap = glWiretap; } },{}],2:[function(require,module,exports){ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.acorn = {}))); }(this, (function (exports) { 'use strict'; var reservedWords = { 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", 5: "class enum extends super const export import", 6: "enum", strict: "implements interface let package private protected public static yield", strictBind: "eval arguments" }; var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; var keywords = { 5: ecma5AndLessKeywords, 6: ecma5AndLessKeywords + " const class extends export import super" }; var keywordRelationalOperator = /^in(stanceof)?$/; var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fef\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7b9\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,477,28,11,0,9,21,190,52,76,44,33,24,27,35,30,0,12,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,26,230,43,117,63,32,0,257,0,11,39,8,0,22,0,12,39,3,3,20,0,35,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,270,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,689,63,129,68,12,0,67,12,65,1,31,6129,15,754,9486,286,82,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,15,7472,3104,541]; var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,525,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,4,9,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9,280,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,19306,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239]; function isInAstralSet(code, set) { var pos = 0x10000; for (var i = 0; i < set.length; i += 2) { pos += set[i]; if (pos > code) { return false } pos += set[i + 1]; if (pos >= code) { return true } } } function isIdentifierStart(code, astral) { if (code < 65) { return code === 36 } if (code < 91) { return true } if (code < 97) { return code === 95 } if (code < 123) { return true } if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } if (astral === false) { return false } return isInAstralSet(code, astralIdentifierStartCodes) } function isIdentifierChar(code, astral) { if (code < 48) { return code === 36 } if (code < 58) { return true } if (code < 65) { return false } if (code < 91) { return true } if (code < 97) { return code === 95 } if (code < 123) { return true } if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } if (astral === false) { return false } return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) } var TokenType = function TokenType(label, conf) { if ( conf === void 0 ) conf = {}; this.label = label; this.keyword = conf.keyword; this.beforeExpr = !!conf.beforeExpr; this.startsExpr = !!conf.startsExpr; this.isLoop = !!conf.isLoop; this.isAssign = !!conf.isAssign; this.prefix = !!conf.prefix; this.postfix = !!conf.postfix; this.binop = conf.binop || null; this.updateContext = null; }; function binop(name, prec) { return new TokenType(name, {beforeExpr: true, binop: prec}) } var beforeExpr = {beforeExpr: true}; var startsExpr = {startsExpr: true}; var keywords$1 = {}; function kw(name, options) { if ( options === void 0 ) options = {}; options.keyword = name; return keywords$1[name] = new TokenType(name, options) } var types = { num: new TokenType("num", startsExpr), regexp: new TokenType("regexp", startsExpr), string: new TokenType("string", startsExpr), name: new TokenType("name", startsExpr), eof: new TokenType("eof"), bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), bracketR: new TokenType("]"), braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), braceR: new TokenType("}"), parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), parenR: new TokenType(")"), comma: new TokenType(",", beforeExpr), semi: new TokenType(";", beforeExpr), colon: new TokenType(":", beforeExpr), dot: new TokenType("."), question: new TokenType("?", beforeExpr), arrow: new TokenType("=>", beforeExpr), template: new TokenType("template"), invalidTemplate: new TokenType("invalidTemplate"), ellipsis: new TokenType("...", beforeExpr), backQuote: new TokenType("`", startsExpr), dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), eq: new TokenType("=", {beforeExpr: true, isAssign: true}), assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}), logicalOR: binop("||", 1), logicalAND: binop("&&", 2), bitwiseOR: binop("|", 3), bitwiseXOR: binop("^", 4), bitwiseAND: binop("&", 5), equality: binop("==/!=/===/!==", 6), relational: binop("/<=/>=", 7), bitShift: binop("<>/>>>", 8), plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), modulo: binop("%", 10), star: binop("*", 10), slash: binop("/", 10), starstar: new TokenType("**", {beforeExpr: true}), _break: kw("break"), _case: kw("case", beforeExpr), _catch: kw("catch"), _continue: kw("continue"), _debugger: kw("debugger"), _default: kw("default", beforeExpr), _do: kw("do", {isLoop: true, beforeExpr: true}), _else: kw("else", beforeExpr), _finally: kw("finally"), _for: kw("for", {isLoop: true}), _function: kw("function", startsExpr), _if: kw("if"), _return: kw("return", beforeExpr), _switch: kw("switch"), _throw: kw("throw", beforeExpr), _try: kw("try"), _var: kw("var"), _const: kw("const"), _while: kw("while", {isLoop: true}), _with: kw("with"), _new: kw("new", {beforeExpr: true, startsExpr: true}), _this: kw("this", startsExpr), _super: kw("super", startsExpr), _class: kw("class", startsExpr), _extends: kw("extends", beforeExpr), _export: kw("export"), _import: kw("import"), _null: kw("null", startsExpr), _true: kw("true", startsExpr), _false: kw("false", startsExpr), _in: kw("in", {beforeExpr: true, binop: 7}), _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) }; var lineBreak = /\r\n?|\n|\u2028|\u2029/; var lineBreakG = new RegExp(lineBreak.source, "g"); function isNewLine(code, ecma2019String) { return code === 10 || code === 13 || (!ecma2019String && (code === 0x2028 || code === 0x2029)) } var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; var ref = Object.prototype; var hasOwnProperty = ref.hasOwnProperty; var toString = ref.toString; function has(obj, propName) { return hasOwnProperty.call(obj, propName) } var isArray = Array.isArray || (function (obj) { return ( toString.call(obj) === "[object Array]" ); }); var Position = function Position(line, col) { this.line = line; this.column = col; }; Position.prototype.offset = function offset (n) { return new Position(this.line, this.column + n) }; var SourceLocation = function SourceLocation(p, start, end) { this.start = start; this.end = end; if (p.sourceFile !== null) { this.source = p.sourceFile; } }; function getLineInfo(input, offset) { for (var line = 1, cur = 0;;) { lineBreakG.lastIndex = cur; var match = lineBreakG.exec(input); if (match && match.index < offset) { ++line; cur = match.index + match[0].length; } else { return new Position(line, offset - cur) } } } var defaultOptions = { ecmaVersion: 7, sourceType: "script", onInsertedSemicolon: null, onTrailingComma: null, allowReserved: null, allowReturnOutsideFunction: false, allowImportExportEverywhere: false, allowAwaitOutsideFunction: false, allowHashBang: false, locations: false, onToken: null, onComment: null, ranges: false, program: null, sourceFile: null, directSourceFile: null, preserveParens: false, plugins: {} }; function getOptions(opts) { var options = {}; for (var opt in defaultOptions) { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; } if (options.ecmaVersion >= 2015) { options.ecmaVersion -= 2009; } if (options.allowReserved == null) { options.allowReserved = options.ecmaVersion < 5; } if (isArray(options.onToken)) { var tokens = options.onToken; options.onToken = function (token) { return tokens.push(token); }; } if (isArray(options.onComment)) { options.onComment = pushComment(options, options.onComment); } return options } function pushComment(options, array) { return function(block, text, start, end, startLoc, endLoc) { var comment = { type: block ? "Block" : "Line", value: text, start: start, end: end }; if (options.locations) { comment.loc = new SourceLocation(this, startLoc, endLoc); } if (options.ranges) { comment.range = [start, end]; } array.push(comment); } } var plugins = {}; function keywordRegexp(words) { return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") } var Parser = function Parser(options, input, startPos) { this.options = options = getOptions(options); this.sourceFile = options.sourceFile; this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]); var reserved = ""; if (!options.allowReserved) { for (var v = options.ecmaVersion;; v--) { if (reserved = reservedWords[v]) { break } } if (options.sourceType === "module") { reserved += " await"; } } this.reservedWords = keywordRegexp(reserved); var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; this.reservedWordsStrict = keywordRegexp(reservedStrict); this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind); this.input = String(input); this.containsEsc = false; this.loadPlugins(options.plugins); if (startPos) { this.pos = startPos; this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; } else { this.pos = this.lineStart = 0; this.curLine = 1; } this.type = types.eof; this.value = null; this.start = this.end = this.pos; this.startLoc = this.endLoc = this.curPosition(); this.lastTokEndLoc = this.lastTokStartLoc = null; this.lastTokStart = this.lastTokEnd = this.pos; this.context = this.initialContext(); this.exprAllowed = true; this.inModule = options.sourceType === "module"; this.strict = this.inModule || this.strictDirective(this.pos); this.potentialArrowAt = -1; this.inFunction = this.inGenerator = this.inAsync = false; this.yieldPos = this.awaitPos = 0; this.labels = []; if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") { this.skipLineComment(2); } this.scopeStack = []; this.enterFunctionScope(); this.regexpState = null; }; Parser.prototype.isKeyword = function isKeyword (word) { return this.keywords.test(word) }; Parser.prototype.isReservedWord = function isReservedWord (word) { return this.reservedWords.test(word) }; Parser.prototype.extend = function extend (name, f) { this[name] = f(this[name]); }; Parser.prototype.loadPlugins = function loadPlugins (pluginConfigs) { var this$1 = this; for (var name in pluginConfigs) { var plugin = plugins[name]; if (!plugin) { throw new Error("Plugin '" + name + "' not found") } plugin(this$1, pluginConfigs[name]); } }; Parser.prototype.parse = function parse () { var node = this.options.program || this.startNode(); this.nextToken(); return this.parseTopLevel(node) }; var pp = Parser.prototype; var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/; pp.strictDirective = function(start) { var this$1 = this; for (;;) { skipWhiteSpace.lastIndex = start; start += skipWhiteSpace.exec(this$1.input)[0].length; var match = literal.exec(this$1.input.slice(start)); if (!match) { return false } if ((match[1] || match[2]) === "use strict") { return true } start += match[0].length; } }; pp.eat = function(type) { if (this.type === type) { this.next(); return true } else { return false } }; pp.isContextual = function(name) { return this.type === types.name && this.value === name && !this.containsEsc }; pp.eatContextual = function(name) { if (!this.isContextual(name)) { return false } this.next(); return true }; pp.expectContextual = function(name) { if (!this.eatContextual(name)) { this.unexpected(); } }; pp.canInsertSemicolon = function() { return this.type === types.eof || this.type === types.braceR || lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }; pp.insertSemicolon = function() { if (this.canInsertSemicolon()) { if (this.options.onInsertedSemicolon) { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } return true } }; pp.semicolon = function() { if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); } }; pp.afterTrailingComma = function(tokType, notNext) { if (this.type === tokType) { if (this.options.onTrailingComma) { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } if (!notNext) { this.next(); } return true } }; pp.expect = function(type) { this.eat(type) || this.unexpected(); }; pp.unexpected = function(pos) { this.raise(pos != null ? pos : this.start, "Unexpected token"); }; function DestructuringErrors() { this.shorthandAssign = this.trailingComma = this.parenthesizedAssign = this.parenthesizedBind = this.doubleProto = -1; } pp.checkPatternErrors = function(refDestructuringErrors, isAssign) { if (!refDestructuringErrors) { return } if (refDestructuringErrors.trailingComma > -1) { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); } }; pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { if (!refDestructuringErrors) { return false } var shorthandAssign = refDestructuringErrors.shorthandAssign; var doubleProto = refDestructuringErrors.doubleProto; if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 } if (shorthandAssign >= 0) { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); } if (doubleProto >= 0) { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); } }; pp.checkYieldAwaitInDefaultParams = function() { if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) { this.raise(this.yieldPos, "Yield expression cannot be a default value"); } if (this.awaitPos) { this.raise(this.awaitPos, "Await expression cannot be a default value"); } }; pp.isSimpleAssignTarget = function(expr) { if (expr.type === "ParenthesizedExpression") { return this.isSimpleAssignTarget(expr.expression) } return expr.type === "Identifier" || expr.type === "MemberExpression" }; var pp$1 = Parser.prototype; pp$1.parseTopLevel = function(node) { var this$1 = this; var exports = {}; if (!node.body) { node.body = []; } while (this.type !== types.eof) { var stmt = this$1.parseStatement(true, true, exports); node.body.push(stmt); } this.adaptDirectivePrologue(node.body); this.next(); if (this.options.ecmaVersion >= 6) { node.sourceType = this.options.sourceType; } return this.finishNode(node, "Program") }; var loopLabel = {kind: "loop"}; var switchLabel = {kind: "switch"}; pp$1.isLet = function() { if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false } skipWhiteSpace.lastIndex = this.pos; var skip = skipWhiteSpace.exec(this.input); var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); if (nextCh === 91 || nextCh === 123) { return true } if (isIdentifierStart(nextCh, true)) { var pos = next + 1; while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; } var ident = this.input.slice(next, pos); if (!keywordRelationalOperator.test(ident)) { return true } } return false }; pp$1.isAsyncFunction = function() { if (this.options.ecmaVersion < 8 || !this.isContextual("async")) { return false } skipWhiteSpace.lastIndex = this.pos; var skip = skipWhiteSpace.exec(this.input); var next = this.pos + skip[0].length; return !lineBreak.test(this.input.slice(this.pos, next)) && this.input.slice(next, next + 8) === "function" && (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8))) }; pp$1.parseStatement = function(declaration, topLevel, exports) { var starttype = this.type, node = this.startNode(), kind; if (this.isLet()) { starttype = types._var; kind = "let"; } switch (starttype) { case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword) case types._debugger: return this.parseDebuggerStatement(node) case types._do: return this.parseDoStatement(node) case types._for: return this.parseForStatement(node) case types._function: if (!declaration && this.options.ecmaVersion >= 6) { this.unexpected(); } return this.parseFunctionStatement(node, false) case types._class: if (!declaration) { this.unexpected(); } return this.parseClass(node, true) case types._if: return this.parseIfStatement(node) case types._return: return this.parseReturnStatement(node) case types._switch: return this.parseSwitchStatement(node) case types._throw: return this.parseThrowStatement(node) case types._try: return this.parseTryStatement(node) case types._const: case types._var: kind = kind || this.value; if (!declaration && kind !== "var") { this.unexpected(); } return this.parseVarStatement(node, kind) case types._while: return this.parseWhileStatement(node) case types._with: return this.parseWithStatement(node) case types.braceL: return this.parseBlock() case types.semi: return this.parseEmptyStatement(node) case types._export: case types._import: if (!this.options.allowImportExportEverywhere) { if (!topLevel) { this.raise(this.start, "'import' and 'export' may only appear at the top level"); } if (!this.inModule) { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } } return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports) default: if (this.isAsyncFunction()) { if (!declaration) { this.unexpected(); } this.next(); return this.parseFunctionStatement(node, true) } var maybeName = this.value, expr = this.parseExpression(); if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon)) { return this.parseLabeledStatement(node, maybeName, expr) } else { return this.parseExpressionStatement(node, expr) } } }; pp$1.parseBreakContinueStatement = function(node, keyword) { var this$1 = this; var isBreak = keyword === "break"; this.next(); if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; } else if (this.type !== types.name) { this.unexpected(); } else { node.label = this.parseIdent(); this.semicolon(); } var i = 0; for (; i < this.labels.length; ++i) { var lab = this$1.labels[i]; if (node.label == null || lab.name === node.label.name) { if (lab.kind != null && (isBreak || lab.kind === "loop")) { break } if (node.label && isBreak) { break } } } if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); } return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") }; pp$1.parseDebuggerStatement = function(node) { this.next(); this.semicolon(); return this.finishNode(node, "DebuggerStatement") }; pp$1.parseDoStatement = function(node) { this.next(); this.labels.push(loopLabel); node.body = this.parseStatement(false); this.labels.pop(); this.expect(types._while); node.test = this.parseParenExpression(); if (this.options.ecmaVersion >= 6) { this.eat(types.semi); } else { this.semicolon(); } return this.finishNode(node, "DoWhileStatement") }; pp$1.parseForStatement = function(node) { this.next(); var awaitAt = (this.options.ecmaVersion >= 9 && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) && this.eatContextual("await")) ? this.lastTokStart : -1; this.labels.push(loopLabel); this.enterLexicalScope(); this.expect(types.parenL); if (this.type === types.semi) { if (awaitAt > -1) { this.unexpected(awaitAt); } return this.parseFor(node, null) } var isLet = this.isLet(); if (this.type === types._var || this.type === types._const || isLet) { var init$1 = this.startNode(), kind = isLet ? "let" : this.value; this.next(); this.parseVar(init$1, true, kind); this.finishNode(init$1, "VariableDeclaration"); if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1 && !(kind !== "var" && init$1.declarations[0].init)) { if (this.options.ecmaVersion >= 9) { if (this.type === types._in) { if (awaitAt > -1) { this.unexpected(awaitAt); } } else { node.await = awaitAt > -1; } } return this.parseForIn(node, init$1) } if (awaitAt > -1) { this.unexpected(awaitAt); } return this.parseFor(node, init$1) } var refDestructuringErrors = new DestructuringErrors; var init = this.parseExpression(true, refDestructuringErrors); if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { if (this.options.ecmaVersion >= 9) { if (this.type === types._in) { if (awaitAt > -1) { this.unexpected(awaitAt); } } else { node.await = awaitAt > -1; } } this.toAssignable(init, false, refDestructuringErrors); this.checkLVal(init); return this.parseForIn(node, init) } else { this.checkExpressionErrors(refDestructuringErrors, true); } if (awaitAt > -1) { this.unexpected(awaitAt); } return this.parseFor(node, init) }; pp$1.parseFunctionStatement = function(node, isAsync) { this.next(); return this.parseFunction(node, true, false, isAsync) }; pp$1.parseIfStatement = function(node) { this.next(); node.test = this.parseParenExpression(); node.consequent = this.parseStatement(!this.strict && this.type === types._function); node.alternate = this.eat(types._else) ? this.parseStatement(!this.strict && this.type === types._function) : null; return this.finishNode(node, "IfStatement") }; pp$1.parseReturnStatement = function(node) { if (!this.inFunction && !this.options.allowReturnOutsideFunction) { this.raise(this.start, "'return' outside of function"); } this.next(); if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; } else { node.argument = this.parseExpression(); this.semicolon(); } return this.finishNode(node, "ReturnStatement") }; pp$1.parseSwitchStatement = function(node) { var this$1 = this; this.next(); node.discriminant = this.parseParenExpression(); node.cases = []; this.expect(types.braceL); this.labels.push(switchLabel); this.enterLexicalScope(); var cur; for (var sawDefault = false; this.type !== types.braceR;) { if (this$1.type === types._case || this$1.type === types._default) { var isCase = this$1.type === types._case; if (cur) { this$1.finishNode(cur, "SwitchCase"); } node.cases.push(cur = this$1.startNode()); cur.consequent = []; this$1.next(); if (isCase) { cur.test = this$1.parseExpression(); } else { if (sawDefault) { this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses"); } sawDefault = true; cur.test = null; } this$1.expect(types.colon); } else { if (!cur) { this$1.unexpected(); } cur.consequent.push(this$1.parseStatement(true)); } } this.exitLexicalScope(); if (cur) { this.finishNode(cur, "SwitchCase"); } this.next(); this.labels.pop(); return this.finishNode(node, "SwitchStatement") }; pp$1.parseThrowStatement = function(node) { this.next(); if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) { this.raise(this.lastTokEnd, "Illegal newline after throw"); } node.argument = this.parseExpression(); this.semicolon(); return this.finishNode(node, "ThrowStatement") }; var empty = []; pp$1.parseTryStatement = function(node) { this.next(); node.block = this.parseBlock(); node.handler = null; if (this.type === types._catch) { var clause = this.startNode(); this.next(); if (this.eat(types.parenL)) { clause.param = this.parseBindingAtom(); this.enterLexicalScope(); this.checkLVal(clause.param, "let"); this.expect(types.parenR); } else { if (this.options.ecmaVersion < 10) { this.unexpected(); } clause.param = null; this.enterLexicalScope(); } clause.body = this.parseBlock(false); this.exitLexicalScope(); node.handler = this.finishNode(clause, "CatchClause"); } node.finalizer = this.eat(types._finally) ? this.parseBlock() : null; if (!node.handler && !node.finalizer) { this.raise(node.start, "Missing catch or finally clause"); } return this.finishNode(node, "TryStatement") }; pp$1.parseVarStatement = function(node, kind) { this.next(); this.parseVar(node, false, kind); this.semicolon(); return this.finishNode(node, "VariableDeclaration") }; pp$1.parseWhileStatement = function(node) { this.next(); node.test = this.parseParenExpression(); this.labels.push(loopLabel); node.body = this.parseStatement(false); this.labels.pop(); return this.finishNode(node, "WhileStatement") }; pp$1.parseWithStatement = function(node) { if (this.strict) { this.raise(this.start, "'with' in strict mode"); } this.next(); node.object = this.parseParenExpression(); node.body = this.parseStatement(false); return this.finishNode(node, "WithStatement") }; pp$1.parseEmptyStatement = function(node) { this.next(); return this.finishNode(node, "EmptyStatement") }; pp$1.parseLabeledStatement = function(node, maybeName, expr) { var this$1 = this; for (var i$1 = 0, list = this$1.labels; i$1 < list.length; i$1 += 1) { var label = list[i$1]; if (label.name === maybeName) { this$1.raise(expr.start, "Label '" + maybeName + "' is already declared"); } } var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null; for (var i = this.labels.length - 1; i >= 0; i--) { var label$1 = this$1.labels[i]; if (label$1.statementStart === node.start) { label$1.statementStart = this$1.start; label$1.kind = kind; } else { break } } this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); node.body = this.parseStatement(true); if (node.body.type === "ClassDeclaration" || node.body.type === "VariableDeclaration" && node.body.kind !== "var" || node.body.type === "FunctionDeclaration" && (this.strict || node.body.generator || node.body.async)) { this.raiseRecoverable(node.body.start, "Invalid labeled declaration"); } this.labels.pop(); node.label = expr; return this.finishNode(node, "LabeledStatement") }; pp$1.parseExpressionStatement = function(node, expr) { node.expression = expr; this.semicolon(); return this.finishNode(node, "ExpressionStatement") }; pp$1.parseBlock = function(createNewLexicalScope) { var this$1 = this; if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; var node = this.startNode(); node.body = []; this.expect(types.braceL); if (createNewLexicalScope) { this.enterLexicalScope(); } while (!this.eat(types.braceR)) { var stmt = this$1.parseStatement(true); node.body.push(stmt); } if (createNewLexicalScope) { this.exitLexicalScope(); } return this.finishNode(node, "BlockStatement") }; pp$1.parseFor = function(node, init) { node.init = init; this.expect(types.semi); node.test = this.type === types.semi ? null : this.parseExpression(); this.expect(types.semi); node.update = this.type === types.parenR ? null : this.parseExpression(); this.expect(types.parenR); this.exitLexicalScope(); node.body = this.parseStatement(false); this.labels.pop(); return this.finishNode(node, "ForStatement") }; pp$1.parseForIn = function(node, init) { var type = this.type === types._in ? "ForInStatement" : "ForOfStatement"; this.next(); if (type === "ForInStatement") { if (init.type === "AssignmentPattern" || (init.type === "VariableDeclaration" && init.declarations[0].init != null && (this.strict || init.declarations[0].id.type !== "Identifier"))) { this.raise(init.start, "Invalid assignment in for-in loop head"); } } node.left = init; node.right = type === "ForInStatement" ? this.parseExpression() : this.parseMaybeAssign(); this.expect(types.parenR); this.exitLexicalScope(); node.body = this.parseStatement(false); this.labels.pop(); return this.finishNode(node, type) }; pp$1.parseVar = function(node, isFor, kind) { var this$1 = this; node.declarations = []; node.kind = kind; for (;;) { var decl = this$1.startNode(); this$1.parseVarId(decl, kind); if (this$1.eat(types.eq)) { decl.init = this$1.parseMaybeAssign(isFor); } else if (kind === "const" && !(this$1.type === types._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) { this$1.unexpected(); } else if (decl.id.type !== "Identifier" && !(isFor && (this$1.type === types._in || this$1.isContextual("of")))) { this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value"); } else { decl.init = null; } node.declarations.push(this$1.finishNode(decl, "VariableDeclarator")); if (!this$1.eat(types.comma)) { break } } return node }; pp$1.parseVarId = function(decl, kind) { decl.id = this.parseBindingAtom(kind); this.checkLVal(decl.id, kind, false); }; pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { this.initFunction(node); if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) { node.generator = this.eat(types.star); } if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } if (isStatement) { node.id = isStatement === "nullableID" && this.type !== types.name ? null : this.parseIdent(); if (node.id) { this.checkLVal(node.id, this.inModule && !this.inFunction ? "let" : "var"); } } var oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; this.inGenerator = node.generator; this.inAsync = node.async; this.yieldPos = 0; this.awaitPos = 0; this.inFunction = true; this.enterFunctionScope(); if (!isStatement) { node.id = this.type === types.name ? this.parseIdent() : null; } this.parseFunctionParams(node); this.parseFunctionBody(node, allowExpressionBody); this.inGenerator = oldInGen; this.inAsync = oldInAsync; this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; this.inFunction = oldInFunc; return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") }; pp$1.parseFunctionParams = function(node) { this.expect(types.parenL); node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); this.checkYieldAwaitInDefaultParams(); }; pp$1.parseClass = function(node, isStatement) { var this$1 = this; this.next(); this.parseClassId(node, isStatement); this.parseClassSuper(node); var classBody = this.startNode(); var hadConstructor = false; classBody.body = []; this.expect(types.braceL); while (!this.eat(types.braceR)) { var member = this$1.parseClassMember(classBody); if (member && member.type === "MethodDefinition" && member.kind === "constructor") { if (hadConstructor) { this$1.raise(member.start, "Duplicate constructor in the same class"); } hadConstructor = true; } } node.body = this.finishNode(classBody, "ClassBody"); return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") }; pp$1.parseClassMember = function(classBody) { var this$1 = this; if (this.eat(types.semi)) { return null } var method = this.startNode(); var tryContextual = function (k, noLineBreak) { if ( noLineBreak === void 0 ) noLineBreak = false; var start = this$1.start, startLoc = this$1.startLoc; if (!this$1.eatContextual(k)) { return false } if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true } if (method.key) { this$1.unexpected(); } method.computed = false; method.key = this$1.startNodeAt(start, startLoc); method.key.name = k; this$1.finishNode(method.key, "Identifier"); return false }; method.kind = "method"; method.static = tryContextual("static"); var isGenerator = this.eat(types.star); var isAsync = false; if (!isGenerator) { if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) { isAsync = true; isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); } else if (tryContextual("get")) { method.kind = "get"; } else if (tryContextual("set")) { method.kind = "set"; } } if (!method.key) { this.parsePropertyName(method); } var key = method.key; if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" || key.type === "Literal" && key.value === "constructor")) { if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); } if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); } if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); } method.kind = "constructor"; } else if (method.static && key.type === "Identifier" && key.name === "prototype") { this.raise(key.start, "Classes may not have a static property named prototype"); } this.parseClassMethod(classBody, method, isGenerator, isAsync); if (method.kind === "get" && method.value.params.length !== 0) { this.raiseRecoverable(method.value.start, "getter should have no params"); } if (method.kind === "set" && method.value.params.length !== 1) { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); } if (method.kind === "set" && method.value.params[0].type === "RestElement") { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); } return method }; pp$1.parseClassMethod = function(classBody, method, isGenerator, isAsync) { method.value = this.parseMethod(isGenerator, isAsync); classBody.body.push(this.finishNode(method, "MethodDefinition")); }; pp$1.parseClassId = function(node, isStatement) { node.id = this.type === types.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null; }; pp$1.parseClassSuper = function(node) { node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null; }; pp$1.parseExport = function(node, exports) { var this$1 = this; this.next(); if (this.eat(types.star)) { this.expectContextual("from"); if (this.type !== types.string) { this.unexpected(); } node.source = this.parseExprAtom(); this.semicolon(); return this.finishNode(node, "ExportAllDeclaration") } if (this.eat(types._default)) { this.checkExport(exports, "default", this.lastTokStart); var isAsync; if (this.type === types._function || (isAsync = this.isAsyncFunction())) { var fNode = this.startNode(); this.next(); if (isAsync) { this.next(); } node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync); } else if (this.type === types._class) { var cNode = this.startNode(); node.declaration = this.parseClass(cNode, "nullableID"); } else { node.declaration = this.parseMaybeAssign(); this.semicolon(); } return this.finishNode(node, "ExportDefaultDeclaration") } if (this.shouldParseExportStatement()) { node.declaration = this.parseStatement(true); if (node.declaration.type === "VariableDeclaration") { this.checkVariableExport(exports, node.declaration.declarations); } else { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); } node.specifiers = []; node.source = null; } else { node.declaration = null; node.specifiers = this.parseExportSpecifiers(exports); if (this.eatContextual("from")) { if (this.type !== types.string) { this.unexpected(); } node.source = this.parseExprAtom(); } else { for (var i = 0, list = node.specifiers; i < list.length; i += 1) { var spec = list[i]; this$1.checkUnreserved(spec.local); } node.source = null; } this.semicolon(); } return this.finishNode(node, "ExportNamedDeclaration") }; pp$1.checkExport = function(exports, name, pos) { if (!exports) { return } if (has(exports, name)) { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } exports[name] = true; }; pp$1.checkPatternExport = function(exports, pat) { var this$1 = this; var type = pat.type; if (type === "Identifier") { this.checkExport(exports, pat.name, pat.start); } else if (type === "ObjectPattern") { for (var i = 0, list = pat.properties; i < list.length; i += 1) { var prop = list[i]; this$1.checkPatternExport(exports, prop); } } else if (type === "ArrayPattern") { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { var elt = list$1[i$1]; if (elt) { this$1.checkPatternExport(exports, elt); } } } else if (type === "Property") { this.checkPatternExport(exports, pat.value); } else if (type === "AssignmentPattern") { this.checkPatternExport(exports, pat.left); } else if (type === "RestElement") { this.checkPatternExport(exports, pat.argument); } else if (type === "ParenthesizedExpression") { this.checkPatternExport(exports, pat.expression); } }; pp$1.checkVariableExport = function(exports, decls) { var this$1 = this; if (!exports) { return } for (var i = 0, list = decls; i < list.length; i += 1) { var decl = list[i]; this$1.checkPatternExport(exports, decl.id); } }; pp$1.shouldParseExportStatement = function() { return this.type.keyword === "var" || this.type.keyword === "const" || this.type.keyword === "class" || this.type.keyword === "function" || this.isLet() || this.isAsyncFunction() }; pp$1.parseExportSpecifiers = function(exports) { var this$1 = this; var nodes = [], first = true; this.expect(types.braceL); while (!this.eat(types.braceR)) { if (!first) { this$1.expect(types.comma); if (this$1.afterTrailingComma(types.braceR)) { break } } else { first = false; } var node = this$1.startNode(); node.local = this$1.parseIdent(true); node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local; this$1.checkExport(exports, node.exported.name, node.exported.start); nodes.push(this$1.finishNode(node, "ExportSpecifier")); } return nodes }; pp$1.parseImport = function(node) { this.next(); if (this.type === types.string) { node.specifiers = empty; node.source = this.parseExprAtom(); } else { node.specifiers = this.parseImportSpecifiers(); this.expectContextual("from"); node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); } this.semicolon(); return this.finishNode(node, "ImportDeclaration") }; pp$1.parseImportSpecifiers = function() { var this$1 = this; var nodes = [], first = true; if (this.type === types.name) { var node = this.startNode(); node.local = this.parseIdent(); this.checkLVal(node.local, "let"); nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); if (!this.eat(types.comma)) { return nodes } } if (this.type === types.star) { var node$1 = this.startNode(); this.next(); this.expectContextual("as"); node$1.local = this.parseIdent(); this.checkLVal(node$1.local, "let"); nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")); return nodes } this.expect(types.braceL); while (!this.eat(types.braceR)) { if (!first) { this$1.expect(types.comma); if (this$1.afterTrailingComma(types.braceR)) { break } } else { first = false; } var node$2 = this$1.startNode(); node$2.imported = this$1.parseIdent(true); if (this$1.eatContextual("as")) { node$2.local = this$1.parseIdent(); } else { this$1.checkUnreserved(node$2.imported); node$2.local = node$2.imported; } this$1.checkLVal(node$2.local, "let"); nodes.push(this$1.finishNode(node$2, "ImportSpecifier")); } return nodes }; pp$1.adaptDirectivePrologue = function(statements) { for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { statements[i].directive = statements[i].expression.raw.slice(1, -1); } }; pp$1.isDirectiveCandidate = function(statement) { return ( statement.type === "ExpressionStatement" && statement.expression.type === "Literal" && typeof statement.expression.value === "string" && (this.input[statement.start] === "\"" || this.input[statement.start] === "'") ) }; var pp$2 = Parser.prototype; pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) { var this$1 = this; if (this.options.ecmaVersion >= 6 && node) { switch (node.type) { case "Identifier": if (this.inAsync && node.name === "await") { this.raise(node.start, "Can not use 'await' as identifier inside an async function"); } break case "ObjectPattern": case "ArrayPattern": case "RestElement": break case "ObjectExpression": node.type = "ObjectPattern"; if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } for (var i = 0, list = node.properties; i < list.length; i += 1) { var prop = list[i]; this$1.toAssignable(prop, isBinding); if ( prop.type === "RestElement" && (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern") ) { this$1.raise(prop.argument.start, "Unexpected token"); } } break case "Property": if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); } this.toAssignable(node.value, isBinding); break case "ArrayExpression": node.type = "ArrayPattern"; if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } this.toAssignableList(node.elements, isBinding); break case "SpreadElement": node.type = "RestElement"; this.toAssignable(node.argument, isBinding); if (node.argument.type === "AssignmentPattern") { this.raise(node.argument.start, "Rest elements cannot have a default value"); } break case "AssignmentExpression": if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); } node.type = "AssignmentPattern"; delete node.operator; this.toAssignable(node.left, isBinding); case "AssignmentPattern": break case "ParenthesizedExpression": this.toAssignable(node.expression, isBinding); break case "MemberExpression": if (!isBinding) { break } default: this.raise(node.start, "Assigning to rvalue"); } } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } return node }; pp$2.toAssignableList = function(exprList, isBinding) { var this$1 = this; var end = exprList.length; for (var i = 0; i < end; i++) { var elt = exprList[i]; if (elt) { this$1.toAssignable(elt, isBinding); } } if (end) { var last = exprList[end - 1]; if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") { this.unexpected(last.argument.start); } } return exprList }; pp$2.parseSpread = function(refDestructuringErrors) { var node = this.startNode(); this.next(); node.argument = this.parseMaybeAssign(false, refDestructuringErrors); return this.finishNode(node, "SpreadElement") }; pp$2.parseRestBinding = function() { var node = this.startNode(); this.next(); if (this.options.ecmaVersion === 6 && this.type !== types.name) { this.unexpected(); } node.argument = this.parseBindingAtom(); return this.finishNode(node, "RestElement") }; pp$2.parseBindingAtom = function() { if (this.options.ecmaVersion >= 6) { switch (this.type) { case types.bracketL: var node = this.startNode(); this.next(); node.elements = this.parseBindingList(types.bracketR, true, true); return this.finishNode(node, "ArrayPattern") case types.braceL: return this.parseObj(true) } } return this.parseIdent() }; pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) { var this$1 = this; var elts = [], first = true; while (!this.eat(close)) { if (first) { first = false; } else { this$1.expect(types.comma); } if (allowEmpty && this$1.type === types.comma) { elts.push(null); } else if (allowTrailingComma && this$1.afterTrailingComma(close)) { break } else if (this$1.type === types.ellipsis) { var rest = this$1.parseRestBinding(); this$1.parseBindingListItem(rest); elts.push(rest); if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } this$1.expect(close); break } else { var elem = this$1.parseMaybeDefault(this$1.start, this$1.startLoc); this$1.parseBindingListItem(elem); elts.push(elem); } } return elts }; pp$2.parseBindingListItem = function(param) { return param }; pp$2.parseMaybeDefault = function(startPos, startLoc, left) { left = left || this.parseBindingAtom(); if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left } var node = this.startNodeAt(startPos, startLoc); node.left = left; node.right = this.parseMaybeAssign(); return this.finishNode(node, "AssignmentPattern") }; pp$2.checkLVal = function(expr, bindingType, checkClashes) { var this$1 = this; switch (expr.type) { case "Identifier": if (this.strict && this.reservedWordsStrictBind.test(expr.name)) { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } if (checkClashes) { if (has(checkClashes, expr.name)) { this.raiseRecoverable(expr.start, "Argument name clash"); } checkClashes[expr.name] = true; } if (bindingType && bindingType !== "none") { if ( bindingType === "var" && !this.canDeclareVarName(expr.name) || bindingType !== "var" && !this.canDeclareLexicalName(expr.name) ) { this.raiseRecoverable(expr.start, ("Identifier '" + (expr.name) + "' has already been declared")); } if (bindingType === "var") { this.declareVarName(expr.name); } else { this.declareLexicalName(expr.name); } } break case "MemberExpression": if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); } break case "ObjectPattern": for (var i = 0, list = expr.properties; i < list.length; i += 1) { var prop = list[i]; this$1.checkLVal(prop, bindingType, checkClashes); } break case "Property": this.checkLVal(expr.value, bindingType, checkClashes); break case "ArrayPattern": for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { var elem = list$1[i$1]; if (elem) { this$1.checkLVal(elem, bindingType, checkClashes); } } break case "AssignmentPattern": this.checkLVal(expr.left, bindingType, checkClashes); break case "RestElement": this.checkLVal(expr.argument, bindingType, checkClashes); break case "ParenthesizedExpression": this.checkLVal(expr.expression, bindingType, checkClashes); break default: this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue"); } }; var pp$3 = Parser.prototype; pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) { if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement") { return } if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) { return } var key = prop.key; var name; switch (key.type) { case "Identifier": name = key.name; break case "Literal": name = String(key.value); break default: return } var kind = prop.kind; if (this.options.ecmaVersion >= 6) { if (name === "__proto__" && kind === "init") { if (propHash.proto) { if (refDestructuringErrors && refDestructuringErrors.doubleProto < 0) { refDestructuringErrors.doubleProto = key.start; } else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); } } propHash.proto = true; } return } name = "$" + name; var other = propHash[name]; if (other) { var redefinition; if (kind === "init") { redefinition = this.strict && other.init || other.get || other.set; } else { redefinition = other.init || other[kind]; } if (redefinition) { this.raiseRecoverable(key.start, "Redefinition of property"); } } else { other = propHash[name] = { init: false, get: false, set: false }; } other[kind] = true; }; pp$3.parseExpression = function(noIn, refDestructuringErrors) { var this$1 = this; var startPos = this.start, startLoc = this.startLoc; var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); if (this.type === types.comma) { var node = this.startNodeAt(startPos, startLoc); node.expressions = [expr]; while (this.eat(types.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn, refDestructuringErrors)); } return this.finishNode(node, "SequenceExpression") } return expr }; pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { if (this.inGenerator && this.isContextual("yield")) { return this.parseYield() } var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1; if (refDestructuringErrors) { oldParenAssign = refDestructuringErrors.parenthesizedAssign; oldTrailingComma = refDestructuringErrors.trailingComma; refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1; } else { refDestructuringErrors = new DestructuringErrors; ownDestructuringErrors = true; } var startPos = this.start, startLoc = this.startLoc; if (this.type === types.parenL || this.type === types.name) { this.potentialArrowAt = this.start; } var left = this.parseMaybeConditional(noIn, refDestructuringErrors); if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } if (this.type.isAssign) { var node = this.startNodeAt(startPos, startLoc); node.operator = this.value; node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left; if (!ownDestructuringErrors) { DestructuringErrors.call(refDestructuringErrors); } refDestructuringErrors.shorthandAssign = -1; this.checkLVal(left); this.next(); node.right = this.parseMaybeAssign(noIn); return this.finishNode(node, "AssignmentExpression") } else { if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } } if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } return left }; pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseExprOps(noIn, refDestructuringErrors); if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } if (this.eat(types.question)) { var node = this.startNodeAt(startPos, startLoc); node.test = expr; node.consequent = this.parseMaybeAssign(); this.expect(types.colon); node.alternate = this.parseMaybeAssign(noIn); return this.finishNode(node, "ConditionalExpression") } return expr }; pp$3.parseExprOps = function(noIn, refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseMaybeUnary(refDestructuringErrors, false); if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) }; pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) { var prec = this.type.binop; if (prec != null && (!noIn || this.type !== types._in)) { if (prec > minPrec) { var logical = this.type === types.logicalOR || this.type === types.logicalAND; var op = this.value; this.next(); var startPos = this.start, startLoc = this.startLoc; var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn); var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical); return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn) } } return left }; pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) { var node = this.startNodeAt(startPos, startLoc); node.left = left; node.operator = op; node.right = right; return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") }; pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) { var this$1 = this; var startPos = this.start, startLoc = this.startLoc, expr; if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) { expr = this.parseAwait(); sawUnary = true; } else if (this.type.prefix) { var node = this.startNode(), update = this.type === types.incDec; node.operator = this.value; node.prefix = true; this.next(); node.argument = this.parseMaybeUnary(null, true); this.checkExpressionErrors(refDestructuringErrors, true); if (update) { this.checkLVal(node.argument); } else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier") { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } else { sawUnary = true; } expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); } else { expr = this.parseExprSubscripts(refDestructuringErrors); if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } while (this.type.postfix && !this.canInsertSemicolon()) { var node$1 = this$1.startNodeAt(startPos, startLoc); node$1.operator = this$1.value; node$1.prefix = false; node$1.argument = expr; this$1.checkLVal(expr); this$1.next(); expr = this$1.finishNode(node$1, "UpdateExpression"); } } if (!sawUnary && this.eat(types.starstar)) { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) } else { return expr } }; pp$3.parseExprSubscripts = function(refDestructuringErrors) { var startPos = this.start, startLoc = this.startLoc; var expr = this.parseExprAtom(refDestructuringErrors); var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"; if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) { return expr } var result = this.parseSubscripts(expr, startPos, startLoc); if (refDestructuringErrors && result.type === "MemberExpression") { if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } } return result }; pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) { var this$1 = this; var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && this.lastTokEnd === base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async"; for (var computed = (void 0);;) { if ((computed = this$1.eat(types.bracketL)) || this$1.eat(types.dot)) { var node = this$1.startNodeAt(startPos, startLoc); node.object = base; node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true); node.computed = !!computed; if (computed) { this$1.expect(types.bracketR); } base = this$1.finishNode(node, "MemberExpression"); } else if (!noCalls && this$1.eat(types.parenL)) { var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos; this$1.yieldPos = 0; this$1.awaitPos = 0; var exprList = this$1.parseExprList(types.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors); if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(types.arrow)) { this$1.checkPatternErrors(refDestructuringErrors, false); this$1.checkYieldAwaitInDefaultParams(); this$1.yieldPos = oldYieldPos; this$1.awaitPos = oldAwaitPos; return this$1.parseArrowExpression(this$1.startNodeAt(startPos, startLoc), exprList, true) } this$1.checkExpressionErrors(refDestructuringErrors, true); this$1.yieldPos = oldYieldPos || this$1.yieldPos; this$1.awaitPos = oldAwaitPos || this$1.awaitPos; var node$1 = this$1.startNodeAt(startPos, startLoc); node$1.callee = base; node$1.arguments = exprList; base = this$1.finishNode(node$1, "CallExpression"); } else if (this$1.type === types.backQuote) { var node$2 = this$1.startNodeAt(startPos, startLoc); node$2.tag = base; node$2.quasi = this$1.parseTemplate({isTagged: true}); base = this$1.finishNode(node$2, "TaggedTemplateExpression"); } else { return base } } }; pp$3.parseExprAtom = function(refDestructuringErrors) { var node, canBeArrow = this.potentialArrowAt === this.start; switch (this.type) { case types._super: if (!this.inFunction) { this.raise(this.start, "'super' outside of function or class"); } node = this.startNode(); this.next(); if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL) { this.unexpected(); } return this.finishNode(node, "Super") case types._this: node = this.startNode(); this.next(); return this.finishNode(node, "ThisExpression") case types.name: var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc; var id = this.parseIdent(this.type !== types.name); if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function)) { return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true) } if (canBeArrow && !this.canInsertSemicolon()) { if (this.eat(types.arrow)) { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) } if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) { id = this.parseIdent(); if (this.canInsertSemicolon() || !this.eat(types.arrow)) { this.unexpected(); } return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true) } } return id case types.regexp: var value = this.value; node = this.parseLiteral(value.value); node.regex = {pattern: value.pattern, flags: value.flags}; return node case types.num: case types.string: return this.parseLiteral(this.value) case types._null: case types._true: case types._false: node = this.startNode(); node.value = this.type === types._null ? null : this.type === types._true; node.raw = this.type.keyword; this.next(); return this.finishNode(node, "Literal") case types.parenL: var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow); if (refDestructuringErrors) { if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) { refDestructuringErrors.parenthesizedAssign = start; } if (refDestructuringErrors.parenthesizedBind < 0) { refDestructuringErrors.parenthesizedBind = start; } } return expr case types.bracketL: node = this.startNode(); this.next(); node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors); return this.finishNode(node, "ArrayExpression") case types.braceL: return this.parseObj(false, refDestructuringErrors) case types._function: node = this.startNode(); this.next(); return this.parseFunction(node, false) case types._class: return this.parseClass(this.startNode(), false) case types._new: return this.parseNew() case types.backQuote: return this.parseTemplate() default: this.unexpected(); } }; pp$3.parseLiteral = function(value) { var node = this.startNode(); node.value = value; node.raw = this.input.slice(this.start, this.end); this.next(); return this.finishNode(node, "Literal") }; pp$3.parseParenExpression = function() { this.expect(types.parenL); var val = this.parseExpression(); this.expect(types.parenR); return val }; pp$3.parseParenAndDistinguishExpression = function(canBeArrow) { var this$1 = this; var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; if (this.options.ecmaVersion >= 6) { this.next(); var innerStartPos = this.start, innerStartLoc = this.startLoc; var exprList = [], first = true, lastIsComma = false; var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart; this.yieldPos = 0; this.awaitPos = 0; while (this.type !== types.parenR) { first ? first = false : this$1.expect(types.comma); if (allowTrailingComma && this$1.afterTrailingComma(types.parenR, true)) { lastIsComma = true; break } else if (this$1.type === types.ellipsis) { spreadStart = this$1.start; exprList.push(this$1.parseParenItem(this$1.parseRestBinding())); if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } break } else { exprList.push(this$1.parseMaybeAssign(false, refDestructuringErrors, this$1.parseParenItem)); } } var innerEndPos = this.start, innerEndLoc = this.startLoc; this.expect(types.parenR); if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) { this.checkPatternErrors(refDestructuringErrors, false); this.checkYieldAwaitInDefaultParams(); this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; return this.parseParenArrowList(startPos, startLoc, exprList) } if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } if (spreadStart) { this.unexpected(spreadStart); } this.checkExpressionErrors(refDestructuringErrors, true); this.yieldPos = oldYieldPos || this.yieldPos; this.awaitPos = oldAwaitPos || this.awaitPos; if (exprList.length > 1) { val = this.startNodeAt(innerStartPos, innerStartLoc); val.expressions = exprList; this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); } else { val = exprList[0]; } } else { val = this.parseParenExpression(); } if (this.options.preserveParens) { var par = this.startNodeAt(startPos, startLoc); par.expression = val; return this.finishNode(par, "ParenthesizedExpression") } else { return val } }; pp$3.parseParenItem = function(item) { return item }; pp$3.parseParenArrowList = function(startPos, startLoc, exprList) { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList) }; var empty$1 = []; pp$3.parseNew = function() { var node = this.startNode(); var meta = this.parseIdent(true); if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) { node.meta = meta; var containsEsc = this.containsEsc; node.property = this.parseIdent(true); if (node.property.name !== "target" || containsEsc) { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); } if (!this.inFunction) { this.raiseRecoverable(node.start, "new.target can only be used in functions"); } return this.finishNode(node, "MetaProperty") } var startPos = this.start, startLoc = this.startLoc; node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); } else { node.arguments = empty$1; } return this.finishNode(node, "NewExpression") }; pp$3.parseTemplateElement = function(ref) { var isTagged = ref.isTagged; var elem = this.startNode(); if (this.type === types.invalidTemplate) { if (!isTagged) { this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); } elem.value = { raw: this.value, cooked: null }; } else { elem.value = { raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), cooked: this.value }; } this.next(); elem.tail = this.type === types.backQuote; return this.finishNode(elem, "TemplateElement") }; pp$3.parseTemplate = function(ref) { var this$1 = this; if ( ref === void 0 ) ref = {}; var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false; var node = this.startNode(); this.next(); node.expressions = []; var curElt = this.parseTemplateElement({isTagged: isTagged}); node.quasis = [curElt]; while (!curElt.tail) { if (this$1.type === types.eof) { this$1.raise(this$1.pos, "Unterminated template literal"); } this$1.expect(types.dollarBraceL); node.expressions.push(this$1.parseExpression()); this$1.expect(types.braceR); node.quasis.push(curElt = this$1.parseTemplateElement({isTagged: isTagged})); } this.next(); return this.finishNode(node, "TemplateLiteral") }; pp$3.isAsyncProp = function(prop) { return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types.star)) && !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }; pp$3.parseObj = function(isPattern, refDestructuringErrors) { var this$1 = this; var node = this.startNode(), first = true, propHash = {}; node.properties = []; this.next(); while (!this.eat(types.braceR)) { if (!first) { this$1.expect(types.comma); if (this$1.afterTrailingComma(types.braceR)) { break } } else { first = false; } var prop = this$1.parseProperty(isPattern, refDestructuringErrors); if (!isPattern) { this$1.checkPropClash(prop, propHash, refDestructuringErrors); } node.properties.push(prop); } return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") }; pp$3.parseProperty = function(isPattern, refDestructuringErrors) { var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc; if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) { if (isPattern) { prop.argument = this.parseIdent(false); if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); } return this.finishNode(prop, "RestElement") } if (this.type === types.parenL && refDestructuringErrors) { if (refDestructuringErrors.parenthesizedAssign < 0) { refDestructuringErrors.parenthesizedAssign = this.start; } if (refDestructuringErrors.parenthesizedBind < 0) { refDestructuringErrors.parenthesizedBind = this.start; } } prop.argument = this.parseMaybeAssign(false, refDestructuringErrors); if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) { refDestructuringErrors.trailingComma = this.start; } return this.finishNode(prop, "SpreadElement") } if (this.options.ecmaVersion >= 6) { prop.method = false; prop.shorthand = false; if (isPattern || refDestructuringErrors) { startPos = this.start; startLoc = this.startLoc; } if (!isPattern) { isGenerator = this.eat(types.star); } } var containsEsc = this.containsEsc; this.parsePropertyName(prop); if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { isAsync = true; isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); this.parsePropertyName(prop, refDestructuringErrors); } else { isAsync = false; } this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc); return this.finishNode(prop, "Property") }; pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) { if ((isGenerator || isAsync) && this.type === types.colon) { this.unexpected(); } if (this.eat(types.colon)) { prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); prop.kind = "init"; } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) { if (isPattern) { this.unexpected(); } prop.kind = "init"; prop.method = true; prop.value = this.parseMethod(isGenerator, isAsync); } else if (!isPattern && !containsEsc && this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && (this.type !== types.comma && this.type !== types.braceR)) { if (isGenerator || isAsync) { this.unexpected(); } prop.kind = prop.key.name; this.parsePropertyName(prop); prop.value = this.parseMethod(false); var paramCount = prop.kind === "get" ? 0 : 1; if (prop.value.params.length !== paramCount) { var start = prop.value.start; if (prop.kind === "get") { this.raiseRecoverable(start, "getter should have no params"); } else { this.raiseRecoverable(start, "setter should have exactly one param"); } } else { if (prop.kind === "set" && prop.value.params[0].type === "RestElement") { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } } } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { this.checkUnreserved(prop.key); prop.kind = "init"; if (isPattern) { prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); } else if (this.type === types.eq && refDestructuringErrors) { if (refDestructuringErrors.shorthandAssign < 0) { refDestructuringErrors.shorthandAssign = this.start; } prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); } else { prop.value = prop.key; } prop.shorthand = true; } else { this.unexpected(); } }; pp$3.parsePropertyName = function(prop) { if (this.options.ecmaVersion >= 6) { if (this.eat(types.bracketL)) { prop.computed = true; prop.key = this.parseMaybeAssign(); this.expect(types.bracketR); return prop.key } else { prop.computed = false; } } return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(true) }; pp$3.initFunction = function(node) { node.id = null; if (this.options.ecmaVersion >= 6) { node.generator = false; node.expression = false; } if (this.options.ecmaVersion >= 8) { node.async = false; } }; pp$3.parseMethod = function(isGenerator, isAsync) { var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; this.initFunction(node); if (this.options.ecmaVersion >= 6) { node.generator = isGenerator; } if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } this.inGenerator = node.generator; this.inAsync = node.async; this.yieldPos = 0; this.awaitPos = 0; this.inFunction = true; this.enterFunctionScope(); this.expect(types.parenL); node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); this.checkYieldAwaitInDefaultParams(); this.parseFunctionBody(node, false); this.inGenerator = oldInGen; this.inAsync = oldInAsync; this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; this.inFunction = oldInFunc; return this.finishNode(node, "FunctionExpression") }; pp$3.parseArrowExpression = function(node, params, isAsync) { var oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction; this.enterFunctionScope(); this.initFunction(node); if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } this.inGenerator = false; this.inAsync = node.async; this.yieldPos = 0; this.awaitPos = 0; this.inFunction = true; node.params = this.toAssignableList(params, true); this.parseFunctionBody(node, true); this.inGenerator = oldInGen; this.inAsync = oldInAsync; this.yieldPos = oldYieldPos; this.awaitPos = oldAwaitPos; this.inFunction = oldInFunc; return this.finishNode(node, "ArrowFunctionExpression") }; pp$3.parseFunctionBody = function(node, isArrowFunction) { var isExpression = isArrowFunction && this.type !== types.braceL; var oldStrict = this.strict, useStrict = false; if (isExpression) { node.body = this.parseMaybeAssign(); node.expression = true; this.checkParams(node, false); } else { var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); if (!oldStrict || nonSimple) { useStrict = this.strictDirective(this.end); if (useStrict && nonSimple) { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } } var oldLabels = this.labels; this.labels = []; if (useStrict) { this.strict = true; } this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params)); node.body = this.parseBlock(false); node.expression = false; this.adaptDirectivePrologue(node.body.body); this.labels = oldLabels; } this.exitFunctionScope(); if (this.strict && node.id) { this.checkLVal(node.id, "none"); } this.strict = oldStrict; }; pp$3.isSimpleParamList = function(params) { for (var i = 0, list = params; i < list.length; i += 1) { var param = list[i]; if (param.type !== "Identifier") { return false } } return true }; pp$3.checkParams = function(node, allowDuplicates) { var this$1 = this; var nameHash = {}; for (var i = 0, list = node.params; i < list.length; i += 1) { var param = list[i]; this$1.checkLVal(param, "var", allowDuplicates ? null : nameHash); } }; pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { var this$1 = this; var elts = [], first = true; while (!this.eat(close)) { if (!first) { this$1.expect(types.comma); if (allowTrailingComma && this$1.afterTrailingComma(close)) { break } } else { first = false; } var elt = (void 0); if (allowEmpty && this$1.type === types.comma) { elt = null; } else if (this$1.type === types.ellipsis) { elt = this$1.parseSpread(refDestructuringErrors); if (refDestructuringErrors && this$1.type === types.comma && refDestructuringErrors.trailingComma < 0) { refDestructuringErrors.trailingComma = this$1.start; } } else { elt = this$1.parseMaybeAssign(false, refDestructuringErrors); } elts.push(elt); } return elts }; pp$3.checkUnreserved = function(ref) { var start = ref.start; var end = ref.end; var name = ref.name; if (this.inGenerator && name === "yield") { this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator"); } if (this.inAsync && name === "await") { this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function"); } if (this.isKeyword(name)) { this.raise(start, ("Unexpected keyword '" + name + "'")); } if (this.options.ecmaVersion < 6 && this.input.slice(start, end).indexOf("\\") !== -1) { return } var re = this.strict ? this.reservedWordsStrict : this.reservedWords; if (re.test(name)) { if (!this.inAsync && name === "await") { this.raiseRecoverable(start, "Can not use keyword 'await' outside an async function"); } this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); } }; pp$3.parseIdent = function(liberal, isBinding) { var node = this.startNode(); if (liberal && this.options.allowReserved === "never") { liberal = false; } if (this.type === types.name) { node.name = this.value; } else if (this.type.keyword) { node.name = this.type.keyword; if ((node.name === "class" || node.name === "function") && (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { this.context.pop(); } } else { this.unexpected(); } this.next(); this.finishNode(node, "Identifier"); if (!liberal) { this.checkUnreserved(node); } return node }; pp$3.parseYield = function() { if (!this.yieldPos) { this.yieldPos = this.start; } var node = this.startNode(); this.next(); if (this.type === types.semi || this.canInsertSemicolon() || (this.type !== types.star && !this.type.startsExpr)) { node.delegate = false; node.argument = null; } else { node.delegate = this.eat(types.star); node.argument = this.parseMaybeAssign(); } return this.finishNode(node, "YieldExpression") }; pp$3.parseAwait = function() { if (!this.awaitPos) { this.awaitPos = this.start; } var node = this.startNode(); this.next(); node.argument = this.parseMaybeUnary(null, true); return this.finishNode(node, "AwaitExpression") }; var pp$4 = Parser.prototype; pp$4.raise = function(pos, message) { var loc = getLineInfo(this.input, pos); message += " (" + loc.line + ":" + loc.column + ")"; var err = new SyntaxError(message); err.pos = pos; err.loc = loc; err.raisedAt = this.pos; throw err }; pp$4.raiseRecoverable = pp$4.raise; pp$4.curPosition = function() { if (this.options.locations) { return new Position(this.curLine, this.pos - this.lineStart) } }; var pp$5 = Parser.prototype; var assign = Object.assign || function(target) { var sources = [], len = arguments.length - 1; while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ]; for (var i = 0, list = sources; i < list.length; i += 1) { var source = list[i]; for (var key in source) { if (has(source, key)) { target[key] = source[key]; } } } return target }; pp$5.enterFunctionScope = function() { this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}}); }; pp$5.exitFunctionScope = function() { this.scopeStack.pop(); }; pp$5.enterLexicalScope = function() { var parentScope = this.scopeStack[this.scopeStack.length - 1]; var childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}}; this.scopeStack.push(childScope); assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical); }; pp$5.exitLexicalScope = function() { var childScope = this.scopeStack.pop(); var parentScope = this.scopeStack[this.scopeStack.length - 1]; assign(parentScope.childVar, childScope.var, childScope.childVar); }; pp$5.canDeclareVarName = function(name) { var currentScope = this.scopeStack[this.scopeStack.length - 1]; return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name) }; pp$5.canDeclareLexicalName = function(name) { var currentScope = this.scopeStack[this.scopeStack.length - 1]; return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name) }; pp$5.declareVarName = function(name) { this.scopeStack[this.scopeStack.length - 1].var[name] = true; }; pp$5.declareLexicalName = function(name) { this.scopeStack[this.scopeStack.length - 1].lexical[name] = true; }; var Node = function Node(parser, pos, loc) { this.type = ""; this.start = pos; this.end = 0; if (parser.options.locations) { this.loc = new SourceLocation(parser, loc); } if (parser.options.directSourceFile) { this.sourceFile = parser.options.directSourceFile; } if (parser.options.ranges) { this.range = [pos, 0]; } }; var pp$6 = Parser.prototype; pp$6.startNode = function() { return new Node(this, this.start, this.startLoc) }; pp$6.startNodeAt = function(pos, loc) { return new Node(this, pos, loc) }; function finishNodeAt(node, type, pos, loc) { node.type = type; node.end = pos; if (this.options.locations) { node.loc.end = loc; } if (this.options.ranges) { node.range[1] = pos; } return node } pp$6.finishNode = function(node, type) { return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) }; pp$6.finishNodeAt = function(node, type, pos, loc) { return finishNodeAt.call(this, node, type, pos, loc) }; var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { this.token = token; this.isExpr = !!isExpr; this.preserveSpace = !!preserveSpace; this.override = override; this.generator = !!generator; }; var types$1 = { b_stat: new TokContext("{", false), b_expr: new TokContext("{", true), b_tmpl: new TokContext("${", false), p_stat: new TokContext("(", false), p_expr: new TokContext("(", true), q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), f_stat: new TokContext("function", false), f_expr: new TokContext("function", true), f_expr_gen: new TokContext("function", true, false, null, true), f_gen: new TokContext("function", false, false, null, true) }; var pp$7 = Parser.prototype; pp$7.initialContext = function() { return [types$1.b_stat] }; pp$7.braceIsBlock = function(prevType) { var parent = this.curContext(); if (parent === types$1.f_expr || parent === types$1.f_stat) { return true } if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr)) { return !parent.isExpr } if (prevType === types._return || prevType === types.name && this.exprAllowed) { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType === types.arrow) { return true } if (prevType === types.braceL) { return parent === types$1.b_stat } if (prevType === types._var || prevType === types.name) { return false } return !this.exprAllowed }; pp$7.inGeneratorContext = function() { var this$1 = this; for (var i = this.context.length - 1; i >= 1; i--) { var context = this$1.context[i]; if (context.token === "function") { return context.generator } } return false }; pp$7.updateContext = function(prevType) { var update, type = this.type; if (type.keyword && prevType === types.dot) { this.exprAllowed = false; } else if (update = type.updateContext) { update.call(this, prevType); } else { this.exprAllowed = type.beforeExpr; } }; types.parenR.updateContext = types.braceR.updateContext = function() { if (this.context.length === 1) { this.exprAllowed = true; return } var out = this.context.pop(); if (out === types$1.b_stat && this.curContext().token === "function") { out = this.context.pop(); } this.exprAllowed = !out.isExpr; }; types.braceL.updateContext = function(prevType) { this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr); this.exprAllowed = true; }; types.dollarBraceL.updateContext = function() { this.context.push(types$1.b_tmpl); this.exprAllowed = true; }; types.parenL.updateContext = function(prevType) { var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; this.context.push(statementParens ? types$1.p_stat : types$1.p_expr); this.exprAllowed = true; }; types.incDec.updateContext = function() { }; types._function.updateContext = types._class.updateContext = function(prevType) { if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else && !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat)) { this.context.push(types$1.f_expr); } else { this.context.push(types$1.f_stat); } this.exprAllowed = false; }; types.backQuote.updateContext = function() { if (this.curContext() === types$1.q_tmpl) { this.context.pop(); } else { this.context.push(types$1.q_tmpl); } this.exprAllowed = false; }; types.star.updateContext = function(prevType) { if (prevType === types._function) { var index = this.context.length - 1; if (this.context[index] === types$1.f_expr) { this.context[index] = types$1.f_expr_gen; } else { this.context[index] = types$1.f_gen; } } this.exprAllowed = true; }; types.name.updateContext = function(prevType) { var allowed = false; if (this.options.ecmaVersion >= 6 && prevType !== types.dot) { if (this.value === "of" && !this.exprAllowed || this.value === "yield" && this.inGeneratorContext()) { allowed = true; } } this.exprAllowed = allowed; }; var data = { "$LONE": [ "ASCII", "ASCII_Hex_Digit", "AHex", "Alphabetic", "Alpha", "Any", "Assigned", "Bidi_Control", "Bidi_C", "Bidi_Mirrored", "Bidi_M", "Case_Ignorable", "CI", "Cased", "Changes_When_Casefolded", "CWCF", "Changes_When_Casemapped", "CWCM", "Changes_When_Lowercased", "CWL", "Changes_When_NFKC_Casefolded", "CWKCF", "Changes_When_Titlecased", "CWT", "Changes_When_Uppercased", "CWU", "Dash", "Default_Ignorable_Code_Point", "DI", "Deprecated", "Dep", "Diacritic", "Dia", "Emoji", "Emoji_Component", "Emoji_Modifier", "Emoji_Modifier_Base", "Emoji_Presentation", "Extender", "Ext", "Grapheme_Base", "Gr_Base", "Grapheme_Extend", "Gr_Ext", "Hex_Digit", "Hex", "IDS_Binary_Operator", "IDSB", "IDS_Trinary_Operator", "IDST", "ID_Continue", "IDC", "ID_Start", "IDS", "Ideographic", "Ideo", "Join_Control", "Join_C", "Logical_Order_Exception", "LOE", "Lowercase", "Lower", "Math", "Noncharacter_Code_Point", "NChar", "Pattern_Syntax", "Pat_Syn", "Pattern_White_Space", "Pat_WS", "Quotation_Mark", "QMark", "Radical", "Regional_Indicator", "RI", "Sentence_Terminal", "STerm", "Soft_Dotted", "SD", "Terminal_Punctuation", "Term", "Unified_Ideograph", "UIdeo", "Uppercase", "Upper", "Variation_Selector", "VS", "White_Space", "space", "XID_Continue", "XIDC", "XID_Start", "XIDS" ], "General_Category": [ "Cased_Letter", "LC", "Close_Punctuation", "Pe", "Connector_Punctuation", "Pc", "Control", "Cc", "cntrl", "Currency_Symbol", "Sc", "Dash_Punctuation", "Pd", "Decimal_Number", "Nd", "digit", "Enclosing_Mark", "Me", "Final_Punctuation", "Pf", "Format", "Cf", "Initial_Punctuation", "Pi", "Letter", "L", "Letter_Number", "Nl", "Line_Separator", "Zl", "Lowercase_Letter", "Ll", "Mark", "M", "Combining_Mark", "Math_Symbol", "Sm", "Modifier_Letter", "Lm", "Modifier_Symbol", "Sk", "Nonspacing_Mark", "Mn", "Number", "N", "Open_Punctuation", "Ps", "Other", "C", "Other_Letter", "Lo", "Other_Number", "No", "Other_Punctuation", "Po", "Other_Symbol", "So", "Paragraph_Separator", "Zp", "Private_Use", "Co", "Punctuation", "P", "punct", "Separator", "Z", "Space_Separator", "Zs", "Spacing_Mark", "Mc", "Surrogate", "Cs", "Symbol", "S", "Titlecase_Letter", "Lt", "Unassigned", "Cn", "Uppercase_Letter", "Lu" ], "Script": [ "Adlam", "Adlm", "Ahom", "Anatolian_Hieroglyphs", "Hluw", "Arabic", "Arab", "Armenian", "Armn", "Avestan", "Avst", "Balinese", "Bali", "Bamum", "Bamu", "Bassa_Vah", "Bass", "Batak", "Batk", "Bengali", "Beng", "Bhaiksuki", "Bhks", "Bopomofo", "Bopo", "Brahmi", "Brah", "Braille", "Brai", "Buginese", "Bugi", "Buhid", "Buhd", "Canadian_Aboriginal", "Cans", "Carian", "Cari", "Caucasian_Albanian", "Aghb", "Chakma", "Cakm", "Cham", "Cherokee", "Cher", "Common", "Zyyy", "Coptic", "Copt", "Qaac", "Cuneiform", "Xsux", "Cypriot", "Cprt", "Cyrillic", "Cyrl", "Deseret", "Dsrt", "Devanagari", "Deva", "Duployan", "Dupl", "Egyptian_Hieroglyphs", "Egyp", "Elbasan", "Elba", "Ethiopic", "Ethi", "Georgian", "Geor", "Glagolitic", "Glag", "Gothic", "Goth", "Grantha", "Gran", "Greek", "Grek", "Gujarati", "Gujr", "Gurmukhi", "Guru", "Han", "Hani", "Hangul", "Hang", "Hanunoo", "Hano", "Hatran", "Hatr", "Hebrew", "Hebr", "Hiragana", "Hira", "Imperial_Aramaic", "Armi", "Inherited", "Zinh", "Qaai", "Inscriptional_Pahlavi", "Phli", "Inscriptional_Parthian", "Prti", "Javanese", "Java", "Kaithi", "Kthi", "Kannada", "Knda", "Katakana", "Kana", "Kayah_Li", "Kali", "Kharoshthi", "Khar", "Khmer", "Khmr", "Khojki", "Khoj", "Khudawadi", "Sind", "Lao", "Laoo", "Latin", "Latn", "Lepcha", "Lepc", "Limbu", "Limb", "Linear_A", "Lina", "Linear_B", "Linb", "Lisu", "Lycian", "Lyci", "Lydian", "Lydi", "Mahajani", "Mahj", "Malayalam", "Mlym", "Mandaic", "Mand", "Manichaean", "Mani", "Marchen", "Marc", "Masaram_Gondi", "Gonm", "Meetei_Mayek", "Mtei", "Mende_Kikakui", "Mend", "Meroitic_Cursive", "Merc", "Meroitic_Hieroglyphs", "Mero", "Miao", "Plrd", "Modi", "Mongolian", "Mong", "Mro", "Mroo", "Multani", "Mult", "Myanmar", "Mymr", "Nabataean", "Nbat", "New_Tai_Lue", "Talu", "Newa", "Nko", "Nkoo", "Nushu", "Nshu", "Ogham", "Ogam", "Ol_Chiki", "Olck", "Old_Hungarian", "Hung", "Old_Italic", "Ital", "Old_North_Arabian", "Narb", "Old_Permic", "Perm", "Old_Persian", "Xpeo", "Old_South_Arabian", "Sarb", "Old_Turkic", "Orkh", "Oriya", "Orya", "Osage", "Osge", "Osmanya", "Osma", "Pahawh_Hmong", "Hmng", "Palmyrene", "Palm", "Pau_Cin_Hau", "Pauc", "Phags_Pa", "Phag", "Phoenician", "Phnx", "Psalter_Pahlavi", "Phlp", "Rejang", "Rjng", "Runic", "Runr", "Samaritan", "Samr", "Saurashtra", "Saur", "Sharada", "Shrd", "Shavian", "Shaw", "Siddham", "Sidd", "SignWriting", "Sgnw", "Sinhala", "Sinh", "Sora_Sompeng", "Sora", "Soyombo", "Soyo", "Sundanese", "Sund", "Syloti_Nagri", "Sylo", "Syriac", "Syrc", "Tagalog", "Tglg", "Tagbanwa", "Tagb", "Tai_Le", "Tale", "Tai_Tham", "Lana", "Tai_Viet", "Tavt", "Takri", "Takr", "Tamil", "Taml", "Tangut", "Tang", "Telugu", "Telu", "Thaana", "Thaa", "Thai", "Tibetan", "Tibt", "Tifinagh", "Tfng", "Tirhuta", "Tirh", "Ugaritic", "Ugar", "Vai", "Vaii", "Warang_Citi", "Wara", "Yi", "Yiii", "Zanabazar_Square", "Zanb" ] }; Array.prototype.push.apply(data.$LONE, data.General_Category); data.gc = data.General_Category; data.sc = data.Script_Extensions = data.scx = data.Script; var pp$9 = Parser.prototype; var RegExpValidationState = function RegExpValidationState(parser) { this.parser = parser; this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : ""); this.source = ""; this.flags = ""; this.start = 0; this.switchU = false; this.switchN = false; this.pos = 0; this.lastIntValue = 0; this.lastStringValue = ""; this.lastAssertionIsQuantifiable = false; this.numCapturingParens = 0; this.maxBackReference = 0; this.groupNames = []; this.backReferenceNames = []; }; RegExpValidationState.prototype.reset = function reset (start, pattern, flags) { var unicode = flags.indexOf("u") !== -1; this.start = start | 0; this.source = pattern + ""; this.flags = flags; this.switchU = unicode && this.parser.options.ecmaVersion >= 6; this.switchN = unicode && this.parser.options.ecmaVersion >= 9; }; RegExpValidationState.prototype.raise = function raise (message) { this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message)); }; RegExpValidationState.prototype.at = function at (i) { var s = this.source; var l = s.length; if (i >= l) { return -1 } var c = s.charCodeAt(i); if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { return c } return (c << 10) + s.charCodeAt(i + 1) - 0x35FDC00 }; RegExpValidationState.prototype.nextIndex = function nextIndex (i) { var s = this.source; var l = s.length; if (i >= l) { return l } var c = s.charCodeAt(i); if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { return i + 1 } return i + 2 }; RegExpValidationState.prototype.current = function current () { return this.at(this.pos) }; RegExpValidationState.prototype.lookahead = function lookahead () { return this.at(this.nextIndex(this.pos)) }; RegExpValidationState.prototype.advance = function advance () { this.pos = this.nextIndex(this.pos); }; RegExpValidationState.prototype.eat = function eat (ch) { if (this.current() === ch) { this.advance(); return true } return false }; function codePointToString$1(ch) { if (ch <= 0xFFFF) { return String.fromCharCode(ch) } ch -= 0x10000; return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00) } pp$9.validateRegExpFlags = function(state) { var this$1 = this; var validFlags = state.validFlags; var flags = state.flags; for (var i = 0; i < flags.length; i++) { var flag = flags.charAt(i); if (validFlags.indexOf(flag) === -1) { this$1.raise(state.start, "Invalid regular expression flag"); } if (flags.indexOf(flag, i + 1) > -1) { this$1.raise(state.start, "Duplicate regular expression flag"); } } }; pp$9.validateRegExpPattern = function(state) { this.regexp_pattern(state); if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) { state.switchN = true; this.regexp_pattern(state); } }; pp$9.regexp_pattern = function(state) { state.pos = 0; state.lastIntValue = 0; state.lastStringValue = ""; state.lastAssertionIsQuantifiable = false; state.numCapturingParens = 0; state.maxBackReference = 0; state.groupNames.length = 0; state.backReferenceNames.length = 0; this.regexp_disjunction(state); if (state.pos !== state.source.length) { if (state.eat(0x29 )) { state.raise("Unmatched ')'"); } if (state.eat(0x5D ) || state.eat(0x7D )) { state.raise("Lone quantifier brackets"); } } if (state.maxBackReference > state.numCapturingParens) { state.raise("Invalid escape"); } for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) { var name = list[i]; if (state.groupNames.indexOf(name) === -1) { state.raise("Invalid named capture referenced"); } } }; pp$9.regexp_disjunction = function(state) { var this$1 = this; this.regexp_alternative(state); while (state.eat(0x7C )) { this$1.regexp_alternative(state); } if (this.regexp_eatQuantifier(state, true)) { state.raise("Nothing to repeat"); } if (state.eat(0x7B )) { state.raise("Lone quantifier brackets"); } }; pp$9.regexp_alternative = function(state) { while (state.pos < state.source.length && this.regexp_eatTerm(state)) { } }; pp$9.regexp_eatTerm = function(state) { if (this.regexp_eatAssertion(state)) { if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) { if (state.switchU) { state.raise("Invalid quantifier"); } } return true } if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) { this.regexp_eatQuantifier(state); return true } return false }; pp$9.regexp_eatAssertion = function(state) { var start = state.pos; state.lastAssertionIsQuantifiable = false; if (state.eat(0x5E ) || state.eat(0x24 )) { return true } if (state.eat(0x5C )) { if (state.eat(0x42 ) || state.eat(0x62 )) { return true } state.pos = start; } if (state.eat(0x28 ) && state.eat(0x3F )) { var lookbehind = false; if (this.options.ecmaVersion >= 9) { lookbehind = state.eat(0x3C ); } if (state.eat(0x3D ) || state.eat(0x21 )) { this.regexp_disjunction(state); if (!state.eat(0x29 )) { state.raise("Unterminated group"); } state.lastAssertionIsQuantifiable = !lookbehind; return true } } state.pos = start; return false }; pp$9.regexp_eatQuantifier = function(state, noError) { if ( noError === void 0 ) noError = false; if (this.regexp_eatQuantifierPrefix(state, noError)) { state.eat(0x3F ); return true } return false }; pp$9.regexp_eatQuantifierPrefix = function(state, noError) { return ( state.eat(0x2A ) || state.eat(0x2B ) || state.eat(0x3F ) || this.regexp_eatBracedQuantifier(state, noError) ) }; pp$9.regexp_eatBracedQuantifier = function(state, noError) { var start = state.pos; if (state.eat(0x7B )) { var min = 0, max = -1; if (this.regexp_eatDecimalDigits(state)) { min = state.lastIntValue; if (state.eat(0x2C ) && this.regexp_eatDecimalDigits(state)) { max = state.lastIntValue; } if (state.eat(0x7D )) { if (max !== -1 && max < min && !noError) { state.raise("numbers out of order in {} quantifier"); } return true } } if (state.switchU && !noError) { state.raise("Incomplete quantifier"); } state.pos = start; } return false }; pp$9.regexp_eatAtom = function(state) { return ( this.regexp_eatPatternCharacters(state) || state.eat(0x2E ) || this.regexp_eatReverseSolidusAtomEscape(state) || this.regexp_eatCharacterClass(state) || this.regexp_eatUncapturingGroup(state) || this.regexp_eatCapturingGroup(state) ) }; pp$9.regexp_eatReverseSolidusAtomEscape = function(state) { var start = state.pos; if (state.eat(0x5C )) { if (this.regexp_eatAtomEscape(state)) { return true } state.pos = start; } return false }; pp$9.regexp_eatUncapturingGroup = function(state) { var start = state.pos; if (state.eat(0x28 )) { if (state.eat(0x3F ) && state.eat(0x3A )) { this.regexp_disjunction(state); if (state.eat(0x29 )) { return true } state.raise("Unterminated group"); } state.pos = start; } return false }; pp$9.regexp_eatCapturingGroup = function(state) { if (state.eat(0x28 )) { if (this.options.ecmaVersion >= 9) { this.regexp_groupSpecifier(state); } else if (state.current() === 0x3F ) { state.raise("Invalid group"); } this.regexp_disjunction(state); if (state.eat(0x29 )) { state.numCapturingParens += 1; return true } state.raise("Unterminated group"); } return false }; pp$9.regexp_eatExtendedAtom = function(state) { return ( state.eat(0x2E ) || this.regexp_eatReverseSolidusAtomEscape(state) || this.regexp_eatCharacterClass(state) || this.regexp_eatUncapturingGroup(state) || this.regexp_eatCapturingGroup(state) || this.regexp_eatInvalidBracedQuantifier(state) || this.regexp_eatExtendedPatternCharacter(state) ) }; pp$9.regexp_eatInvalidBracedQuantifier = function(state) { if (this.regexp_eatBracedQuantifier(state, true)) { state.raise("Nothing to repeat"); } return false }; pp$9.regexp_eatSyntaxCharacter = function(state) { var ch = state.current(); if (isSyntaxCharacter(ch)) { state.lastIntValue = ch; state.advance(); return true } return false }; function isSyntaxCharacter(ch) { return ( ch === 0x24 || ch >= 0x28 && ch <= 0x2B || ch === 0x2E || ch === 0x3F || ch >= 0x5B && ch <= 0x5E || ch >= 0x7B && ch <= 0x7D ) } pp$9.regexp_eatPatternCharacters = function(state) { var start = state.pos; var ch = 0; while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) { state.advance(); } return state.pos !== start }; pp$9.regexp_eatExtendedPatternCharacter = function(state) { var ch = state.current(); if ( ch !== -1 && ch !== 0x24 && !(ch >= 0x28 && ch <= 0x2B ) && ch !== 0x2E && ch !== 0x3F && ch !== 0x5B && ch !== 0x5E && ch !== 0x7C ) { state.advance(); return true } return false }; pp$9.regexp_groupSpecifier = function(state) { if (state.eat(0x3F )) { if (this.regexp_eatGroupName(state)) { if (state.groupNames.indexOf(state.lastStringValue) !== -1) { state.raise("Duplicate capture group name"); } state.groupNames.push(state.lastStringValue); return } state.raise("Invalid group"); } }; pp$9.regexp_eatGroupName = function(state) { state.lastStringValue = ""; if (state.eat(0x3C )) { if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E )) { return true } state.raise("Invalid capture group name"); } return false }; pp$9.regexp_eatRegExpIdentifierName = function(state) { state.lastStringValue = ""; if (this.regexp_eatRegExpIdentifierStart(state)) { state.lastStringValue += codePointToString$1(state.lastIntValue); while (this.regexp_eatRegExpIdentifierPart(state)) { state.lastStringValue += codePointToString$1(state.lastIntValue); } return true } return false }; pp$9.regexp_eatRegExpIdentifierStart = function(state) { var start = state.pos; var ch = state.current(); state.advance(); if (ch === 0x5C && this.regexp_eatRegExpUnicodeEscapeSequence(state)) { ch = state.lastIntValue; } if (isRegExpIdentifierStart(ch)) { state.lastIntValue = ch; return true } state.pos = start; return false }; function isRegExpIdentifierStart(ch) { return isIdentifierStart(ch, true) || ch === 0x24 || ch === 0x5F } pp$9.regexp_eatRegExpIdentifierPart = function(state) { var start = state.pos; var ch = state.current(); state.advance(); if (ch === 0x5C && this.regexp_eatRegExpUnicodeEscapeSequence(state)) { ch = state.lastIntValue; } if (isRegExpIdentifierPart(ch)) { state.lastIntValue = ch; return true } state.pos = start; return false }; function isRegExpIdentifierPart(ch) { return isIdentifierChar(ch, true) || ch === 0x24 || ch === 0x5F || ch === 0x200C || ch === 0x200D } pp$9.regexp_eatAtomEscape = function(state) { if ( this.regexp_eatBackReference(state) || this.regexp_eatCharacterClassEscape(state) || this.regexp_eatCharacterEscape(state) || (state.switchN && this.regexp_eatKGroupName(state)) ) { return true } if (state.switchU) { if (state.current() === 0x63 ) { state.raise("Invalid unicode escape"); } state.raise("Invalid escape"); } return false }; pp$9.regexp_eatBackReference = function(state) { var start = state.pos; if (this.regexp_eatDecimalEscape(state)) { var n = state.lastIntValue; if (state.switchU) { if (n > state.maxBackReference) { state.maxBackReference = n; } return true } if (n <= state.numCapturingParens) { return true } state.pos = start; } return false }; pp$9.regexp_eatKGroupName = function(state) { if (state.eat(0x6B )) { if (this.regexp_eatGroupName(state)) { state.backReferenceNames.push(state.lastStringValue); return true } state.raise("Invalid named reference"); } return false }; pp$9.regexp_eatCharacterEscape = function(state) { return ( this.regexp_eatControlEscape(state) || this.regexp_eatCControlLetter(state) || this.regexp_eatZero(state) || this.regexp_eatHexEscapeSequence(state) || this.regexp_eatRegExpUnicodeEscapeSequence(state) || (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) || this.regexp_eatIdentityEscape(state) ) }; pp$9.regexp_eatCControlLetter = function(state) { var start = state.pos; if (state.eat(0x63 )) { if (this.regexp_eatControlLetter(state)) { return true } state.pos = start; } return false }; pp$9.regexp_eatZero = function(state) { if (state.current() === 0x30 && !isDecimalDigit(state.lookahead())) { state.lastIntValue = 0; state.advance(); return true } return false }; pp$9.regexp_eatControlEscape = function(state) { var ch = state.current(); if (ch === 0x74 ) { state.lastIntValue = 0x09; state.advance(); return true } if (ch === 0x6E ) { state.lastIntValue = 0x0A; state.advance(); return true } if (ch === 0x76 ) { state.lastIntValue = 0x0B; state.advance(); return true } if (ch === 0x66 ) { state.lastIntValue = 0x0C; state.advance(); return true } if (ch === 0x72 ) { state.lastIntValue = 0x0D; state.advance(); return true } return false }; pp$9.regexp_eatControlLetter = function(state) { var ch = state.current(); if (isControlLetter(ch)) { state.lastIntValue = ch % 0x20; state.advance(); return true } return false }; function isControlLetter(ch) { return ( (ch >= 0x41 && ch <= 0x5A ) || (ch >= 0x61 && ch <= 0x7A ) ) } pp$9.regexp_eatRegExpUnicodeEscapeSequence = function(state) { var start = state.pos; if (state.eat(0x75 )) { if (this.regexp_eatFixedHexDigits(state, 4)) { var lead = state.lastIntValue; if (state.switchU && lead >= 0xD800 && lead <= 0xDBFF) { var leadSurrogateEnd = state.pos; if (state.eat(0x5C ) && state.eat(0x75 ) && this.regexp_eatFixedHexDigits(state, 4)) { var trail = state.lastIntValue; if (trail >= 0xDC00 && trail <= 0xDFFF) { state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000; return true } } state.pos = leadSurrogateEnd; state.lastIntValue = lead; } return true } if ( state.switchU && state.eat(0x7B ) && this.regexp_eatHexDigits(state) && state.eat(0x7D ) && isValidUnicode(state.lastIntValue) ) { return true } if (state.switchU) { state.raise("Invalid unicode escape"); } state.pos = start; } return false }; function isValidUnicode(ch) { return ch >= 0 && ch <= 0x10FFFF } pp$9.regexp_eatIdentityEscape = function(state) { if (state.switchU) { if (this.regexp_eatSyntaxCharacter(state)) { return true } if (state.eat(0x2F )) { state.lastIntValue = 0x2F; return true } return false } var ch = state.current(); if (ch !== 0x63 && (!state.switchN || ch !== 0x6B )) { state.lastIntValue = ch; state.advance(); return true } return false }; pp$9.regexp_eatDecimalEscape = function(state) { state.lastIntValue = 0; var ch = state.current(); if (ch >= 0x31 && ch <= 0x39 ) { do { state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 ); state.advance(); } while ((ch = state.current()) >= 0x30 && ch <= 0x39 ) return true } return false }; pp$9.regexp_eatCharacterClassEscape = function(state) { var ch = state.current(); if (isCharacterClassEscape(ch)) { state.lastIntValue = -1; state.advance(); return true } if ( state.switchU && this.options.ecmaVersion >= 9 && (ch === 0x50 || ch === 0x70 ) ) { state.lastIntValue = -1; state.advance(); if ( state.eat(0x7B ) && this.regexp_eatUnicodePropertyValueExpression(state) && state.eat(0x7D ) ) { return true } state.raise("Invalid property name"); } return false }; function isCharacterClassEscape(ch) { return ( ch === 0x64 || ch === 0x44 || ch === 0x73 || ch === 0x53 || ch === 0x77 || ch === 0x57 ) } pp$9.regexp_eatUnicodePropertyValueExpression = function(state) { var start = state.pos; if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D )) { var name = state.lastStringValue; if (this.regexp_eatUnicodePropertyValue(state)) { var value = state.lastStringValue; this.regexp_validateUnicodePropertyNameAndValue(state, name, value); return true } } state.pos = start; if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) { var nameOrValue = state.lastStringValue; this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue); return true } return false }; pp$9.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) { if (!data.hasOwnProperty(name) || data[name].indexOf(value) === -1) { state.raise("Invalid property name"); } }; pp$9.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) { if (data.$LONE.indexOf(nameOrValue) === -1) { state.raise("Invalid property name"); } }; pp$9.regexp_eatUnicodePropertyName = function(state) { var ch = 0; state.lastStringValue = ""; while (isUnicodePropertyNameCharacter(ch = state.current())) { state.lastStringValue += codePointToString$1(ch); state.advance(); } return state.lastStringValue !== "" }; function isUnicodePropertyNameCharacter(ch) { return isControlLetter(ch) || ch === 0x5F } pp$9.regexp_eatUnicodePropertyValue = function(state) { var ch = 0; state.lastStringValue = ""; while (isUnicodePropertyValueCharacter(ch = state.current())) { state.lastStringValue += codePointToString$1(ch); state.advance(); } return state.lastStringValue !== "" }; function isUnicodePropertyValueCharacter(ch) { return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch) } pp$9.regexp_eatLoneUnicodePropertyNameOrValue = function(state) { return this.regexp_eatUnicodePropertyValue(state) }; pp$9.regexp_eatCharacterClass = function(state) { if (state.eat(0x5B )) { state.eat(0x5E ); this.regexp_classRanges(state); if (state.eat(0x5D )) { return true } state.raise("Unterminated character class"); } return false }; pp$9.regexp_classRanges = function(state) { var this$1 = this; while (this.regexp_eatClassAtom(state)) { var left = state.lastIntValue; if (state.eat(0x2D ) && this$1.regexp_eatClassAtom(state)) { var right = state.lastIntValue; if (state.switchU && (left === -1 || right === -1)) { state.raise("Invalid character class"); } if (left !== -1 && right !== -1 && left > right) { state.raise("Range out of order in character class"); } } } }; pp$9.regexp_eatClassAtom = function(state) { var start = state.pos; if (state.eat(0x5C )) { if (this.regexp_eatClassEscape(state)) { return true } if (state.switchU) { var ch$1 = state.current(); if (ch$1 === 0x63 || isOctalDigit(ch$1)) { state.raise("Invalid class escape"); } state.raise("Invalid escape"); } state.pos = start; } var ch = state.current(); if (ch !== 0x5D ) { state.lastIntValue = ch; state.advance(); return true } return false }; pp$9.regexp_eatClassEscape = function(state) { var start = state.pos; if (state.eat(0x62 )) { state.lastIntValue = 0x08; return true } if (state.switchU && state.eat(0x2D )) { state.lastIntValue = 0x2D; return true } if (!state.switchU && state.eat(0x63 )) { if (this.regexp_eatClassControlLetter(state)) { return true } state.pos = start; } return ( this.regexp_eatCharacterClassEscape(state) || this.regexp_eatCharacterEscape(state) ) }; pp$9.regexp_eatClassControlLetter = function(state) { var ch = state.current(); if (isDecimalDigit(ch) || ch === 0x5F ) { state.lastIntValue = ch % 0x20; state.advance(); return true } return false }; pp$9.regexp_eatHexEscapeSequence = function(state) { var start = state.pos; if (state.eat(0x78 )) { if (this.regexp_eatFixedHexDigits(state, 2)) { return true } if (state.switchU) { state.raise("Invalid escape"); } state.pos = start; } return false }; pp$9.regexp_eatDecimalDigits = function(state) { var start = state.pos; var ch = 0; state.lastIntValue = 0; while (isDecimalDigit(ch = state.current())) { state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 ); state.advance(); } return state.pos !== start }; function isDecimalDigit(ch) { return ch >= 0x30 && ch <= 0x39 } pp$9.regexp_eatHexDigits = function(state) { var start = state.pos; var ch = 0; state.lastIntValue = 0; while (isHexDigit(ch = state.current())) { state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); state.advance(); } return state.pos !== start }; function isHexDigit(ch) { return ( (ch >= 0x30 && ch <= 0x39 ) || (ch >= 0x41 && ch <= 0x46 ) || (ch >= 0x61 && ch <= 0x66 ) ) } function hexToInt(ch) { if (ch >= 0x41 && ch <= 0x46 ) { return 10 + (ch - 0x41 ) } if (ch >= 0x61 && ch <= 0x66 ) { return 10 + (ch - 0x61 ) } return ch - 0x30 } pp$9.regexp_eatLegacyOctalEscapeSequence = function(state) { if (this.regexp_eatOctalDigit(state)) { var n1 = state.lastIntValue; if (this.regexp_eatOctalDigit(state)) { var n2 = state.lastIntValue; if (n1 <= 3 && this.regexp_eatOctalDigit(state)) { state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue; } else { state.lastIntValue = n1 * 8 + n2; } } else { state.lastIntValue = n1; } return true } return false }; pp$9.regexp_eatOctalDigit = function(state) { var ch = state.current(); if (isOctalDigit(ch)) { state.lastIntValue = ch - 0x30; state.advance(); return true } state.lastIntValue = 0; return false }; function isOctalDigit(ch) { return ch >= 0x30 && ch <= 0x37 } pp$9.regexp_eatFixedHexDigits = function(state, length) { var start = state.pos; state.lastIntValue = 0; for (var i = 0; i < length; ++i) { var ch = state.current(); if (!isHexDigit(ch)) { state.pos = start; return false } state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); state.advance(); } return true }; var Token = function Token(p) { this.type = p.type; this.value = p.value; this.start = p.start; this.end = p.end; if (p.options.locations) { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } if (p.options.ranges) { this.range = [p.start, p.end]; } }; var pp$8 = Parser.prototype; pp$8.next = function() { if (this.options.onToken) { this.options.onToken(new Token(this)); } this.lastTokEnd = this.end; this.lastTokStart = this.start; this.lastTokEndLoc = this.endLoc; this.lastTokStartLoc = this.startLoc; this.nextToken(); }; pp$8.getToken = function() { this.next(); return new Token(this) }; if (typeof Symbol !== "undefined") { pp$8[Symbol.iterator] = function() { var this$1 = this; return { next: function () { var token = this$1.getToken(); return { done: token.type === types.eof, value: token } } } }; } pp$8.curContext = function() { return this.context[this.context.length - 1] }; pp$8.nextToken = function() { var curContext = this.curContext(); if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } this.start = this.pos; if (this.options.locations) { this.startLoc = this.curPosition(); } if (this.pos >= this.input.length) { return this.finishToken(types.eof) } if (curContext.override) { return curContext.override(this) } else { this.readToken(this.fullCharCodeAtPos()); } }; pp$8.readToken = function(code) { if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 ) { return this.readWord() } return this.getTokenFromCode(code) }; pp$8.fullCharCodeAtPos = function() { var code = this.input.charCodeAt(this.pos); if (code <= 0xd7ff || code >= 0xe000) { return code } var next = this.input.charCodeAt(this.pos + 1); return (code << 10) + next - 0x35fdc00 }; pp$8.skipBlockComment = function() { var this$1 = this; var startLoc = this.options.onComment && this.curPosition(); var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } this.pos = end + 2; if (this.options.locations) { lineBreakG.lastIndex = start; var match; while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) { ++this$1.curLine; this$1.lineStart = match.index + match[0].length; } } if (this.options.onComment) { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, startLoc, this.curPosition()); } }; pp$8.skipLineComment = function(startSkip) { var this$1 = this; var start = this.pos; var startLoc = this.options.onComment && this.curPosition(); var ch = this.input.charCodeAt(this.pos += startSkip); while (this.pos < this.input.length && !isNewLine(ch)) { ch = this$1.input.charCodeAt(++this$1.pos); } if (this.options.onComment) { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, startLoc, this.curPosition()); } }; pp$8.skipSpace = function() { var this$1 = this; loop: while (this.pos < this.input.length) { var ch = this$1.input.charCodeAt(this$1.pos); switch (ch) { case 32: case 160: ++this$1.pos; break case 13: if (this$1.input.charCodeAt(this$1.pos + 1) === 10) { ++this$1.pos; } case 10: case 8232: case 8233: ++this$1.pos; if (this$1.options.locations) { ++this$1.curLine; this$1.lineStart = this$1.pos; } break case 47: switch (this$1.input.charCodeAt(this$1.pos + 1)) { case 42: this$1.skipBlockComment(); break case 47: this$1.skipLineComment(2); break default: break loop } break default: if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { ++this$1.pos; } else { break loop } } } }; pp$8.finishToken = function(type, val) { this.end = this.pos; if (this.options.locations) { this.endLoc = this.curPosition(); } var prevType = this.type; this.type = type; this.value = val; this.updateContext(prevType); }; pp$8.readToken_dot = function() { var next = this.input.charCodeAt(this.pos + 1); if (next >= 48 && next <= 57) { return this.readNumber(true) } var next2 = this.input.charCodeAt(this.pos + 2); if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { this.pos += 3; return this.finishToken(types.ellipsis) } else { ++this.pos; return this.finishToken(types.dot) } }; pp$8.readToken_slash = function() { var next = this.input.charCodeAt(this.pos + 1); if (this.exprAllowed) { ++this.pos; return this.readRegexp() } if (next === 61) { return this.finishOp(types.assign, 2) } return this.finishOp(types.slash, 1) }; pp$8.readToken_mult_modulo_exp = function(code) { var next = this.input.charCodeAt(this.pos + 1); var size = 1; var tokentype = code === 42 ? types.star : types.modulo; if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) { ++size; tokentype = types.starstar; next = this.input.charCodeAt(this.pos + 2); } if (next === 61) { return this.finishOp(types.assign, size + 1) } return this.finishOp(tokentype, size) }; pp$8.readToken_pipe_amp = function(code) { var next = this.input.charCodeAt(this.pos + 1); if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) } if (next === 61) { return this.finishOp(types.assign, 2) } return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1) }; pp$8.readToken_caret = function() { var next = this.input.charCodeAt(this.pos + 1); if (next === 61) { return this.finishOp(types.assign, 2) } return this.finishOp(types.bitwiseXOR, 1) }; pp$8.readToken_plus_min = function(code) { var next = this.input.charCodeAt(this.pos + 1); if (next === code) { if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 && (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { this.skipLineComment(3); this.skipSpace(); return this.nextToken() } return this.finishOp(types.incDec, 2) } if (next === 61) { return this.finishOp(types.assign, 2) } return this.finishOp(types.plusMin, 1) }; pp$8.readToken_lt_gt = function(code) { var next = this.input.charCodeAt(this.pos + 1); var size = 1; if (next === code) { size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) } return this.finishOp(types.bitShift, size) } if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && this.input.charCodeAt(this.pos + 3) === 45) { this.skipLineComment(4); this.skipSpace(); return this.nextToken() } if (next === 61) { size = 2; } return this.finishOp(types.relational, size) }; pp$8.readToken_eq_excl = function(code) { var next = this.input.charCodeAt(this.pos + 1); if (next === 61) { return this.finishOp(types.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) } if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { this.pos += 2; return this.finishToken(types.arrow) } return this.finishOp(code === 61 ? types.eq : types.prefix, 1) }; pp$8.getTokenFromCode = function(code) { switch (code) { case 46: return this.readToken_dot() case 40: ++this.pos; return this.finishToken(types.parenL) case 41: ++this.pos; return this.finishToken(types.parenR) case 59: ++this.pos; return this.finishToken(types.semi) case 44: ++this.pos; return this.finishToken(types.comma) case 91: ++this.pos; return this.finishToken(types.bracketL) case 93: ++this.pos; return this.finishToken(types.bracketR) case 123: ++this.pos; return this.finishToken(types.braceL) case 125: ++this.pos; return this.finishToken(types.braceR) case 58: ++this.pos; return this.finishToken(types.colon) case 63: ++this.pos; return this.finishToken(types.question) case 96: if (this.options.ecmaVersion < 6) { break } ++this.pos; return this.finishToken(types.backQuote) case 48: var next = this.input.charCodeAt(this.pos + 1); if (next === 120 || next === 88) { return this.readRadixNumber(16) } if (this.options.ecmaVersion >= 6) { if (next === 111 || next === 79) { return this.readRadixNumber(8) } if (next === 98 || next === 66) { return this.readRadixNumber(2) } } case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: return this.readNumber(false) case 34: case 39: return this.readString(code) case 47: return this.readToken_slash() case 37: case 42: return this.readToken_mult_modulo_exp(code) case 124: case 38: return this.readToken_pipe_amp(code) case 94: return this.readToken_caret() case 43: case 45: return this.readToken_plus_min(code) case 60: case 62: return this.readToken_lt_gt(code) case 61: case 33: return this.readToken_eq_excl(code) case 126: return this.finishOp(types.prefix, 1) } this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'"); }; pp$8.finishOp = function(type, size) { var str = this.input.slice(this.pos, this.pos + size); this.pos += size; return this.finishToken(type, str) }; pp$8.readRegexp = function() { var this$1 = this; var escaped, inClass, start = this.pos; for (;;) { if (this$1.pos >= this$1.input.length) { this$1.raise(start, "Unterminated regular expression"); } var ch = this$1.input.charAt(this$1.pos); if (lineBreak.test(ch)) { this$1.raise(start, "Unterminated regular expression"); } if (!escaped) { if (ch === "[") { inClass = true; } else if (ch === "]" && inClass) { inClass = false; } else if (ch === "/" && !inClass) { break } escaped = ch === "\\"; } else { escaped = false; } ++this$1.pos; } var pattern = this.input.slice(start, this.pos); ++this.pos; var flagsStart = this.pos; var flags = this.readWord1(); if (this.containsEsc) { this.unexpected(flagsStart); } var state = this.regexpState || (this.regexpState = new RegExpValidationState(this)); state.reset(start, pattern, flags); this.validateRegExpFlags(state); this.validateRegExpPattern(state); var value = null; try { value = new RegExp(pattern, flags); } catch (e) { } return this.finishToken(types.regexp, {pattern: pattern, flags: flags, value: value}) }; pp$8.readInt = function(radix, len) { var this$1 = this; var start = this.pos, total = 0; for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) { var code = this$1.input.charCodeAt(this$1.pos), val = (void 0); if (code >= 97) { val = code - 97 + 10; } else if (code >= 65) { val = code - 65 + 10; } else if (code >= 48 && code <= 57) { val = code - 48; } else { val = Infinity; } if (val >= radix) { break } ++this$1.pos; total = total * radix + val; } if (this.pos === start || len != null && this.pos - start !== len) { return null } return total }; pp$8.readRadixNumber = function(radix) { this.pos += 2; var val = this.readInt(radix); if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); } if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } return this.finishToken(types.num, val) }; pp$8.readNumber = function(startsWithDot) { var start = this.pos; if (!startsWithDot && this.readInt(10) === null) { this.raise(start, "Invalid number"); } var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48; if (octal && this.strict) { this.raise(start, "Invalid number"); } if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; } var next = this.input.charCodeAt(this.pos); if (next === 46 && !octal) { ++this.pos; this.readInt(10); next = this.input.charCodeAt(this.pos); } if ((next === 69 || next === 101) && !octal) { next = this.input.charCodeAt(++this.pos); if (next === 43 || next === 45) { ++this.pos; } if (this.readInt(10) === null) { this.raise(start, "Invalid number"); } } if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } var str = this.input.slice(start, this.pos); var val = octal ? parseInt(str, 8) : parseFloat(str); return this.finishToken(types.num, val) }; pp$8.readCodePoint = function() { var ch = this.input.charCodeAt(this.pos), code; if (ch === 123) { if (this.options.ecmaVersion < 6) { this.unexpected(); } var codePos = ++this.pos; code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos); ++this.pos; if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); } } else { code = this.readHexChar(4); } return code }; function codePointToString(code) { if (code <= 0xFFFF) { return String.fromCharCode(code) } code -= 0x10000; return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00) } pp$8.readString = function(quote) { var this$1 = this; var out = "", chunkStart = ++this.pos; for (;;) { if (this$1.pos >= this$1.input.length) { this$1.raise(this$1.start, "Unterminated string constant"); } var ch = this$1.input.charCodeAt(this$1.pos); if (ch === quote) { break } if (ch === 92) { out += this$1.input.slice(chunkStart, this$1.pos); out += this$1.readEscapedChar(false); chunkStart = this$1.pos; } else { if (isNewLine(ch, this$1.options.ecmaVersion >= 10)) { this$1.raise(this$1.start, "Unterminated string constant"); } ++this$1.pos; } } out += this.input.slice(chunkStart, this.pos++); return this.finishToken(types.string, out) }; var INVALID_TEMPLATE_ESCAPE_ERROR = {}; pp$8.tryReadTemplateToken = function() { this.inTemplateElement = true; try { this.readTmplToken(); } catch (err) { if (err === INVALID_TEMPLATE_ESCAPE_ERROR) { this.readInvalidTemplateToken(); } else { throw err } } this.inTemplateElement = false; }; pp$8.invalidStringToken = function(position, message) { if (this.inTemplateElement && this.options.ecmaVersion >= 9) { throw INVALID_TEMPLATE_ESCAPE_ERROR } else { this.raise(position, message); } }; pp$8.readTmplToken = function() { var this$1 = this; var out = "", chunkStart = this.pos; for (;;) { if (this$1.pos >= this$1.input.length) { this$1.raise(this$1.start, "Unterminated template"); } var ch = this$1.input.charCodeAt(this$1.pos); if (ch === 96 || ch === 36 && this$1.input.charCodeAt(this$1.pos + 1) === 123) { if (this$1.pos === this$1.start && (this$1.type === types.template || this$1.type === types.invalidTemplate)) { if (ch === 36) { this$1.pos += 2; return this$1.finishToken(types.dollarBraceL) } else { ++this$1.pos; return this$1.finishToken(types.backQuote) } } out += this$1.input.slice(chunkStart, this$1.pos); return this$1.finishToken(types.template, out) } if (ch === 92) { out += this$1.input.slice(chunkStart, this$1.pos); out += this$1.readEscapedChar(true); chunkStart = this$1.pos; } else if (isNewLine(ch)) { out += this$1.input.slice(chunkStart, this$1.pos); ++this$1.pos; switch (ch) { case 13: if (this$1.input.charCodeAt(this$1.pos) === 10) { ++this$1.pos; } case 10: out += "\n"; break default: out += String.fromCharCode(ch); break } if (this$1.options.locations) { ++this$1.curLine; this$1.lineStart = this$1.pos; } chunkStart = this$1.pos; } else { ++this$1.pos; } } }; pp$8.readInvalidTemplateToken = function() { var this$1 = this; for (; this.pos < this.input.length; this.pos++) { switch (this$1.input[this$1.pos]) { case "\\": ++this$1.pos; break case "$": if (this$1.input[this$1.pos + 1] !== "{") { break } case "`": return this$1.finishToken(types.invalidTemplate, this$1.input.slice(this$1.start, this$1.pos)) } } this.raise(this.start, "Unterminated template"); }; pp$8.readEscapedChar = function(inTemplate) { var ch = this.input.charCodeAt(++this.pos); ++this.pos; switch (ch) { case 110: return "\n" case 114: return "\r" case 120: return String.fromCharCode(this.readHexChar(2)) case 117: return codePointToString(this.readCodePoint()) case 116: return "\t" case 98: return "\b" case 118: return "\u000b" case 102: return "\f" case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } case 10: if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; } return "" default: if (ch >= 48 && ch <= 55) { var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0]; var octal = parseInt(octalStr, 8); if (octal > 255) { octalStr = octalStr.slice(0, -1); octal = parseInt(octalStr, 8); } this.pos += octalStr.length - 1; ch = this.input.charCodeAt(this.pos); if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) { this.invalidStringToken( this.pos - 1 - octalStr.length, inTemplate ? "Octal literal in template string" : "Octal literal in strict mode" ); } return String.fromCharCode(octal) } return String.fromCharCode(ch) } }; pp$8.readHexChar = function(len) { var codePos = this.pos; var n = this.readInt(16, len); if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); } return n }; pp$8.readWord1 = function() { var this$1 = this; this.containsEsc = false; var word = "", first = true, chunkStart = this.pos; var astral = this.options.ecmaVersion >= 6; while (this.pos < this.input.length) { var ch = this$1.fullCharCodeAtPos(); if (isIdentifierChar(ch, astral)) { this$1.pos += ch <= 0xffff ? 1 : 2; } else if (ch === 92) { this$1.containsEsc = true; word += this$1.input.slice(chunkStart, this$1.pos); var escStart = this$1.pos; if (this$1.input.charCodeAt(++this$1.pos) !== 117) { this$1.invalidStringToken(this$1.pos, "Expecting Unicode escape sequence \\uXXXX"); } ++this$1.pos; var esc = this$1.readCodePoint(); if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral)) { this$1.invalidStringToken(escStart, "Invalid Unicode escape"); } word += codePointToString(esc); chunkStart = this$1.pos; } else { break } first = false; } return word + this.input.slice(chunkStart, this.pos) }; pp$8.readWord = function() { var word = this.readWord1(); var type = types.name; if (this.keywords.test(word)) { if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword " + word); } type = keywords$1[word]; } return this.finishToken(type, word) }; var version = "5.7.3"; function parse(input, options) { return new Parser(options, input).parse() } function parseExpressionAt(input, pos, options) { var p = new Parser(options, input, pos); p.nextToken(); return p.parseExpression() } function tokenizer(input, options) { return new Parser(options, input) } function addLooseExports(parse, Parser$$1, plugins$$1) { exports.parse_dammit = parse; exports.LooseParser = Parser$$1; exports.pluginsLoose = plugins$$1; } exports.version = version; exports.parse = parse; exports.parseExpressionAt = parseExpressionAt; exports.tokenizer = tokenizer; exports.addLooseExports = addLooseExports; exports.Parser = Parser; exports.plugins = plugins; exports.defaultOptions = defaultOptions; exports.Position = Position; exports.SourceLocation = SourceLocation; exports.getLineInfo = getLineInfo; exports.Node = Node; exports.TokenType = TokenType; exports.tokTypes = types; exports.keywordTypes = keywords$1; exports.TokContext = TokContext; exports.tokContexts = types$1; exports.isIdentifierChar = isIdentifierChar; exports.isIdentifierStart = isIdentifierStart; exports.Token = Token; exports.isNewLine = isNewLine; exports.lineBreak = lineBreak; exports.lineBreakG = lineBreakG; exports.nonASCIIwhitespace = nonASCIIwhitespace; Object.defineProperty(exports, '__esModule', { value: true }); }))); },{}],3:[function(require,module,exports){ },{}],4:[function(require,module,exports){ 'use strict'; function mock1D() { const row = []; for (let x = 0; x < this.output.x; x++) { this.thread.x = x; this.thread.y = 0; this.thread.z = 0; row.push(this._fn.apply(this, arguments)); } return row; } function mock2D() { const matrix = []; for (let y = 0; y < this.output.y; y++) { const row = []; for (let x = 0; x < this.output.x; x++) { this.thread.x = x; this.thread.y = y; this.thread.z = 0; row.push(this._fn.apply(this, arguments)); } matrix.push(row); } return matrix; } function mock3D() { const cube = []; for (let z = 0; z < this.output.z; z++) { const matrix = []; for (let y = 0; y < this.output.y; y++) { const row = []; for (let x = 0; x < this.output.x; x++) { this.thread.x = x; this.thread.y = y; this.thread.z = z; row.push(this._fn.apply(this, arguments)); } matrix.push(row); } cube.push(matrix); } return cube; } module.exports = function gpuMock(fn, options) { let contextOutput = null; if (options.output.length) { if (options.output.length === 3) { contextOutput = { x: options.output[0], y: options.output[1], z: options.output[2] }; } else if (options.output.length === 2) { contextOutput = { x: options.output[0], y: options.output[1] }; } else { contextOutput = { x: options.output[0] }; } } else { contextOutput = options.output; } const context = { _fn: fn, constants: options.constants, output: contextOutput, thread: { x: 0, y: 0, z: 0 } }; if (contextOutput.z) { return mock3D.bind(context); } else if (contextOutput.y) { return mock2D.bind(context); } else { return mock1D.bind(context); } }; },{}],5:[function(require,module,exports){ const { utils } = require('./utils'); function alias(name, source) { const fnString = source.toString(); return new Function(`return function ${ name } (${ utils.getArgumentNamesFromString(fnString).join(', ') }) { ${ utils.getFunctionBodyFromString(fnString) } }`)(); } module.exports = { alias }; },{"./utils":70}],6:[function(require,module,exports){ const { FunctionNode } = require('../function-node'); class CPUFunctionNode extends FunctionNode { astFunctionExpression(ast, retArr) { if (!this.isRootKernel) { retArr.push('function'); retArr.push(' '); retArr.push(this.name); retArr.push('('); for (let i = 0; i < this.argumentNames.length; ++i) { const argumentName = this.argumentNames[i]; if (i > 0) { retArr.push(', '); } retArr.push('user_'); retArr.push(argumentName); } retArr.push(') {\n'); } for (let i = 0; i < ast.body.body.length; ++i) { this.astGeneric(ast.body.body[i], retArr); retArr.push('\n'); } if (!this.isRootKernel) { retArr.push('}\n'); } return retArr; } astReturnStatement(ast, retArr) { if (this.isRootKernel) { retArr.push(this.leadingReturnStatement); this.astGeneric(ast.argument, retArr); retArr.push(';\n'); retArr.push(this.followingReturnStatement); retArr.push('continue;\n'); } else if (this.isSubKernel) { retArr.push(`subKernelResult_${ this.name } = `); this.astGeneric(ast.argument, retArr); retArr.push(';'); retArr.push(`return subKernelResult_${ this.name };`); } else { retArr.push('return '); this.astGeneric(ast.argument, retArr); retArr.push(';'); } return retArr; } astLiteral(ast, retArr) { if (isNaN(ast.value)) { throw this.astErrorOutput( 'Non-numeric literal not supported : ' + ast.value, ast ); } retArr.push(ast.value); return retArr; } astBinaryExpression(ast, retArr) { retArr.push('('); this.astGeneric(ast.left, retArr); retArr.push(ast.operator); this.astGeneric(ast.right, retArr); retArr.push(')'); return retArr; } astIdentifierExpression(idtNode, retArr) { if (idtNode.type !== 'Identifier') { throw this.astErrorOutput( 'IdentifierExpression - not an Identifier', idtNode ); } switch (idtNode.name) { case 'Infinity': retArr.push('Infinity'); break; default: if (this.constants && this.constants.hasOwnProperty(idtNode.name)) { retArr.push('constants_' + idtNode.name); } else { const name = this.getKernelArgumentName(idtNode.name); if (name) { retArr.push('user_' + name); } else { retArr.push('user_' + idtNode.name); } } } return retArr; } astForStatement(forNode, retArr) { if (forNode.type !== 'ForStatement') { throw this.astErrorOutput('Invalid for statement', forNode); } const initArr = []; const testArr = []; const updateArr = []; const bodyArr = []; let isSafe = null; if (forNode.init) { this.pushState('in-for-loop-init'); this.astGeneric(forNode.init, initArr); for (let i = 0; i < initArr.length; i++) { if (initArr[i].includes && initArr[i].includes(',')) { isSafe = false; } } this.popState('in-for-loop-init'); } else { isSafe = false; } if (forNode.test) { this.astGeneric(forNode.test, testArr); } else { isSafe = false; } if (forNode.update) { this.astGeneric(forNode.update, updateArr); } else { isSafe = false; } if (forNode.body) { this.pushState('loop-body'); this.astGeneric(forNode.body, bodyArr); this.popState('loop-body'); } if (isSafe === null) { isSafe = this.isSafe(forNode.init) && this.isSafe(forNode.test); } if (isSafe) { retArr.push(`for (${initArr.join('')};${testArr.join('')};${updateArr.join('')}){\n`); retArr.push(bodyArr.join('')); retArr.push('}\n'); } else { const iVariableName = this.getInternalVariableName('safeI'); if (initArr.length > 0) { retArr.push(initArr.join(''), ';\n'); } retArr.push(`for (let ${iVariableName}=0;${iVariableName} 0) { retArr.push(`if (!${testArr.join('')}) break;\n`); } retArr.push(bodyArr.join('')); retArr.push(`\n${updateArr.join('')};`); retArr.push('}\n'); } return retArr; } astWhileStatement(whileNode, retArr) { if (whileNode.type !== 'WhileStatement') { throw this.astErrorOutput( 'Invalid while statement', whileNode ); } retArr.push('for (let i = 0; i < LOOP_MAX; i++) {'); retArr.push('if ('); this.astGeneric(whileNode.test, retArr); retArr.push(') {\n'); this.astGeneric(whileNode.body, retArr); retArr.push('} else {\n'); retArr.push('break;\n'); retArr.push('}\n'); retArr.push('}\n'); return retArr; } astDoWhileStatement(doWhileNode, retArr) { if (doWhileNode.type !== 'DoWhileStatement') { throw this.astErrorOutput( 'Invalid while statement', doWhileNode ); } retArr.push('for (let i = 0; i < LOOP_MAX; i++) {'); this.astGeneric(doWhileNode.body, retArr); retArr.push('if (!'); this.astGeneric(doWhileNode.test, retArr); retArr.push(') {\n'); retArr.push('break;\n'); retArr.push('}\n'); retArr.push('}\n'); return retArr; } astAssignmentExpression(assNode, retArr) { this.astGeneric(assNode.left, retArr); retArr.push(assNode.operator); this.astGeneric(assNode.right, retArr); return retArr; } astBlockStatement(bNode, retArr) { if (this.isState('loop-body')) { this.pushState('block-body'); for (let i = 0; i < bNode.body.length; i++) { this.astGeneric(bNode.body[i], retArr); } this.popState('block-body'); } else { retArr.push('{\n'); for (let i = 0; i < bNode.body.length; i++) { this.astGeneric(bNode.body[i], retArr); } retArr.push('}\n'); } return retArr; } astVariableDeclaration(varDecNode, retArr) { if (varDecNode.kind === 'var') { this.varWarn(); } retArr.push(`${varDecNode.kind} `); const firstDeclaration = varDecNode.declarations[0]; const type = this.getType(firstDeclaration.init); for (let i = 0; i < varDecNode.declarations.length; i++) { this.declarations[varDecNode.declarations[i].id.name] = { type: type === 'LiteralInteger' ? 'Number' : type, dependencies: { constants: [], arguments: [] }, isUnsafe: false }; if (i > 0) { retArr.push(','); } this.astGeneric(varDecNode.declarations[i], retArr); } if (!this.isState('in-for-loop-init')) { retArr.push(';'); } return retArr; } astIfStatement(ifNode, retArr) { retArr.push('if ('); this.astGeneric(ifNode.test, retArr); retArr.push(')'); if (ifNode.consequent.type === 'BlockStatement') { this.astGeneric(ifNode.consequent, retArr); } else { retArr.push(' {\n'); this.astGeneric(ifNode.consequent, retArr); retArr.push('\n}\n'); } if (ifNode.alternate) { retArr.push('else '); if (ifNode.alternate.type === 'BlockStatement') { this.astGeneric(ifNode.alternate, retArr); } else { retArr.push(' {\n'); this.astGeneric(ifNode.alternate, retArr); retArr.push('\n}\n'); } } return retArr; } astThisExpression(tNode, retArr) { retArr.push('_this'); return retArr; } astMemberExpression(mNode, retArr) { const { signature, type, property, xProperty, yProperty, zProperty, name, origin } = this.getMemberExpressionDetails(mNode); switch (signature) { case 'this.thread.value': retArr.push(`_this.thread.${ name }`); return retArr; case 'this.output.value': switch (name) { case 'x': retArr.push('outputX'); break; case 'y': retArr.push('outputY'); break; case 'z': retArr.push('outputZ'); break; default: throw this.astErrorOutput('Unexpected expression', mNode); } return retArr; case 'value': throw this.astErrorOutput('Unexpected expression', mNode); case 'value[]': case 'value[][]': case 'value[][][]': case 'value.value': if (origin === 'Math') { retArr.push(Math[name]); return retArr; } switch (property) { case 'r': retArr.push(`user_${ name }[0]`); return retArr; case 'g': retArr.push(`user_${ name }[1]`); return retArr; case 'b': retArr.push(`user_${ name }[2]`); return retArr; case 'a': retArr.push(`user_${ name }[3]`); return retArr; } break; case 'this.constants.value': case 'this.constants.value[]': case 'this.constants.value[][]': case 'this.constants.value[][][]': break; case 'fn()[]': this.astGeneric(mNode.object, retArr); retArr.push('['); this.astGeneric(mNode.property, retArr); retArr.push(']'); return retArr; default: throw this.astErrorOutput('Unexpected expression', mNode); } switch (type) { case 'Number': case 'Integer': case 'Float': case 'Boolean': retArr.push(`${ origin }_${ name}`); return retArr; } const synonymName = this.getKernelArgumentName(name); const markupName = `${origin}_${synonymName || name}`; switch (type) { case 'Array(2)': case 'Array(3)': case 'Array(4)': case 'HTMLImageArray': case 'ArrayTexture(1)': case 'ArrayTexture(2)': case 'ArrayTexture(3)': case 'ArrayTexture(4)': case 'HTMLImage': default: const isInput = this.isInput(synonymName || name); retArr.push(`${ markupName }`); if (zProperty && yProperty) { if (isInput) { const size = this.argumentSizes[this.argumentNames.indexOf(name)]; retArr.push('[('); this.astGeneric(zProperty, retArr); retArr.push(`*${ size[1] * size[0]})+(`); this.astGeneric(yProperty, retArr); retArr.push(`*${ size[0] })+`); this.astGeneric(xProperty, retArr); retArr.push(']'); } else { retArr.push('['); this.astGeneric(zProperty, retArr); retArr.push(']'); retArr.push('['); this.astGeneric(yProperty, retArr); retArr.push(']'); retArr.push('['); this.astGeneric(xProperty, retArr); retArr.push(']'); } } else if (yProperty) { if (isInput) { const size = this.argumentSizes[this.argumentNames.indexOf(name)]; retArr.push('[('); this.astGeneric(yProperty, retArr); retArr.push(`*${ size[0] })+`); this.astGeneric(xProperty, retArr); retArr.push(']'); } else { retArr.push('['); this.astGeneric(yProperty, retArr); retArr.push(']'); retArr.push('['); this.astGeneric(xProperty, retArr); retArr.push(']'); } } else { retArr.push('['); this.astGeneric(xProperty, retArr); retArr.push(']'); } } return retArr; } astCallExpression(ast, retArr) { if (ast.callee) { let funcName = this.astMemberExpressionUnroll(ast.callee); if (this.calledFunctions.indexOf(funcName) < 0) { this.calledFunctions.push(funcName); } if (!this.calledFunctionsArguments[funcName]) { this.calledFunctionsArguments[funcName] = []; } const functionArguments = []; this.calledFunctionsArguments[funcName].push(functionArguments); retArr.push(funcName); retArr.push('('); for (let i = 0; i < ast.arguments.length; ++i) { const argument = ast.arguments[i]; if (i > 0) { retArr.push(', '); } this.astGeneric(argument, retArr); const argumentType = this.getType(argument); if (argumentType) { functionArguments.push({ name: argument.name || null, type: argumentType }); } else { functionArguments.push(null); } } retArr.push(')'); return retArr; } throw this.astErrorOutput( 'Unknown CallExpression', ast ); } astArrayExpression(arrNode, retArr) { const arrLen = arrNode.elements.length; retArr.push('new Float32Array(['); for (let i = 0; i < arrLen; ++i) { if (i > 0) { retArr.push(', '); } const subNode = arrNode.elements[i]; this.astGeneric(subNode, retArr) } retArr.push('])'); return retArr; } astDebuggerStatement(arrNode, retArr) { retArr.push('debugger;'); return retArr; } } module.exports = { CPUFunctionNode }; },{"../function-node":10}],7:[function(require,module,exports){ const { utils } = require('../../utils'); const { kernelRunShortcut } = require('../../kernel-run-shortcut'); function removeFnNoise(fn) { if (/^function /.test(fn)) { fn = fn.substring(9); } return fn.replace(/[_]typeof/g, 'typeof'); } function removeNoise(str) { return str .replace(/^[A-Za-z]+/, 'function') .replace(/[_]typeof/g, 'typeof'); } function cpuKernelString(cpuKernel, name) { return `() => { ${ kernelRunShortcut.toString() }; const utils = { allPropertiesOf: ${ removeNoise(utils.allPropertiesOf.toString()) }, clone: ${ removeNoise(utils.clone.toString()) }, isArray: ${ removeNoise(utils.isArray.toString()) }, }; let Input = function() {}; class ${ name || 'Kernel' } { constructor() { this.canvas = null; this.context = null; this.built = false; this.program = null; this.argumentNames = ${ JSON.stringify(cpuKernel.argumentNames) }; this.argumentTypes = ${ JSON.stringify(cpuKernel.argumentTypes) }; this.argumentSizes = ${ JSON.stringify(cpuKernel.argumentSizes) }; this.output = ${ JSON.stringify(cpuKernel.output) }; this._kernelString = \`${ cpuKernel._kernelString }\`; this.output = ${ JSON.stringify(cpuKernel.output) }; this.run = function() { this.run = null; this.build(arguments); return this.run.apply(this, arguments); }.bind(this); this.thread = { x: 0, y: 0, z: 0 }; } setCanvas(canvas) { this.canvas = canvas; return this; } setContext(context) { this.context = context; return this; } setInput(Type) { Input = Type; } ${ removeFnNoise(cpuKernel.build.toString()) } setupArguments() {} ${ removeFnNoise(cpuKernel.setupConstants.toString()) } translateSource() {} pickRenderStrategy() {} run () { ${ cpuKernel.kernelString } } getKernelString() { return this._kernelString; } ${ removeFnNoise(cpuKernel.validateSettings.toString()) } ${ removeFnNoise(cpuKernel.checkOutput.toString()) } }; return kernelRunShortcut(new Kernel()); };`; } module.exports = { cpuKernelString }; },{"../../kernel-run-shortcut":67,"../../utils":70}],8:[function(require,module,exports){ const { Kernel } = require('../kernel'); const { FunctionBuilder } = require('../function-builder'); const { CPUFunctionNode } = require('./function-node'); const { utils } = require('../../utils'); const { cpuKernelString } = require('./kernel-string'); class CPUKernel extends Kernel { static getFeatures() { return this.features; } static get features() { return Object.freeze({ kernelMap: true, isIntegerDivisionAccurate: true }); } static get isSupported() { return true; } static isContextMatch(context) { return false; } static get mode() { return 'cpu'; } static nativeFunctionArguments() { return null; } static nativeFunctionReturnType() { return null; } static combineKernels(combinedKernel) { return combinedKernel; } constructor(source, settings) { super(source, settings); this.mergeSettings(source.settings || settings); this._imageData = null; this._colorData = null; this._kernelString = null; this.thread = { x: 0, y: 0, z: 0 }; this.translatedSources = null; } initCanvas() { if (typeof document !== 'undefined') { return document.createElement('canvas'); } else if (typeof OffscreenCanvas !== 'undefined') { return new OffscreenCanvas(0, 0); } } initContext() { if (!this.canvas) return null; return this.canvas.getContext('2d'); } initPlugins(settings) { return []; } validateSettings() { if (!this.output || this.output.length === 0) { if (arguments.length !== 1) { throw 'Auto dimensions only supported for kernels with only one input'; } const argType = utils.getVariableType(arguments[0], this.strictIntegers); if (argType === 'Array') { this.output = utils.getDimensions(argType); } else if (argType === 'NumberTexture' || argType === 'ArrayTexture(4)') { this.output = arguments[0].output; } else { throw 'Auto dimensions not supported for input type: ' + argType; } } if (this.graphical) { if (this.output.length !== 2) { throw new Error('Output must have 2 dimensions on graphical mode'); } } this.checkOutput(); } translateSource() { this.leadingReturnStatement = this.output.length > 1 ? 'resultX[x] = ' : 'result[x] = '; if (this.subKernels) { const followingReturnStatement = [] for (let i = 0; i < this.subKernels.length; i++) { const { name } = this.subKernels[i]; followingReturnStatement.push(this.output.length > 1 ? `resultX_${ name }[x] = subKernelResult_${ name };\n` : `result_${ name }[x] = subKernelResult_${ name };\n`); } this.followingReturnStatement = followingReturnStatement.join(''); } const functionBuilder = FunctionBuilder.fromKernel(this, CPUFunctionNode); this.translatedSources = functionBuilder.getPrototypes('kernel'); if (!this.graphical && !this.returnType) { this.returnType = functionBuilder.getKernelResultType(); } } build() { this.setupConstants(); this.setupArguments(arguments); this.validateSettings(); this.translateSource(); if (this.graphical) { const { canvas, output } = this; if (!canvas) { throw new Error('no canvas available for using graphical output'); } const width = output[0]; const height = output[1] || 1; canvas.width = width; canvas.height = height; this._imageData = this.context.createImageData(width, height); this._colorData = new Uint8ClampedArray(width * height * 4); } const kernelString = this.getKernelString(); this.kernelString = kernelString; if (this.debug) { console.log('Function output:'); console.log(kernelString); } try { this.run = new Function([], kernelString).bind(this)(); } catch (e) { console.error('An error occurred compiling the javascript: ', e); } } color(r, g, b, a) { if (typeof a === 'undefined') { a = 1; } r = Math.floor(r * 255); g = Math.floor(g * 255); b = Math.floor(b * 255); a = Math.floor(a * 255); const width = this.output[0]; const height = this.output[1]; const x = this.thread.x; const y = height - this.thread.y - 1; const index = x + y * width; this._colorData[index * 4 + 0] = r; this._colorData[index * 4 + 1] = g; this._colorData[index * 4 + 2] = b; this._colorData[index * 4 + 3] = a; } getKernelString() { if (this._kernelString !== null) return this._kernelString; let kernelThreadString = null; let { translatedSources } = this; if (translatedSources.length > 1) { translatedSources = translatedSources.filter(fn => { if (/^function/.test(fn)) return fn; kernelThreadString = fn; return false; }) } else { kernelThreadString = translatedSources.shift(); } const kernelString = this._kernelString = ` const LOOP_MAX = ${ this._getLoopMaxString() } const constants = this.constants; const _this = this; return (${ this.argumentNames.map(argumentName => 'user_' + argumentName).join(', ') }) => { ${ this._processConstants() } ${ this._processArguments() } ${ this.graphical ? this._graphicalKernelBody(kernelThreadString) : this._resultKernelBody(kernelThreadString) } ${ translatedSources.length > 0 ? translatedSources.join('\n') : '' } };`; return kernelString; } toString() { return cpuKernelString(this); } _getLoopMaxString() { return ( this.loopMaxIterations ? ` ${ parseInt(this.loopMaxIterations) };` : ' 1000;' ); } _processConstants() { if (!this.constants) return ''; const result = []; for (let p in this.constants) { const type = this.constantTypes[p]; switch (type) { case 'HTMLImage': result.push(` const constants_${p} = this._imageTo2DArray(this.constants.${p});\n`); break; case 'HTMLImageArray': result.push(` const constants_${p} = this._imageTo3DArray(this.constants.${p});\n`); break; case 'Input': result.push(` const constants_${p} = this.constants.${p}.value;\n`); break; default: result.push(` const constants_${p} = this.constants.${p};\n`); } } return result.join(''); } _processArguments() { const result = []; for (let i = 0; i < this.argumentTypes.length; i++) { switch (this.argumentTypes[i]) { case 'HTMLImage': result.push(` user_${this.argumentNames[i]} = this._imageTo2DArray(user_${this.argumentNames[i]});\n`); break; case 'HTMLImageArray': result.push(` user_${this.argumentNames[i]} = this._imageTo3DArray(user_${this.argumentNames[i]});\n`); break; case 'Input': result.push(` user_${this.argumentNames[i]} = user_${this.argumentNames[i]}.value;\n`); break; } } return result.join(''); } _imageTo2DArray(image) { const canvas = this.canvas; if (canvas.width < image.width) { canvas.width = image.width; } if (canvas.height < image.height) { canvas.height = image.height; } const ctx = this.context; ctx.drawImage(image, 0, 0, image.width, image.height); const pixelsData = ctx.getImageData(0, 0, image.width, image.height).data; const imageArray = new Array(image.height); let index = 0; for (let y = image.height - 1; y >= 0; y--) { const row = imageArray[y] = new Array(image.width); for (let x = 0; x < image.width; x++) { const pixel = new Float32Array(4); pixel[0] = pixelsData[index++] / 255; pixel[1] = pixelsData[index++] / 255; pixel[2] = pixelsData[index++] / 255; pixel[3] = pixelsData[index++] / 255; row[x] = pixel; } } return imageArray; } getPixels(flip) { const [width, height] = this.output; return flip ? utils.flipPixels(this._imageData.data, width, height) : this._imageData.data.slice(0); } _imageTo3DArray(images) { const imagesArray = new Array(images.length); for (let i = 0; i < images.length; i++) { imagesArray[i] = this._imageTo2DArray(images[i]); } return imagesArray; } _resultKernelBody(kernelString) { switch (this.output.length) { case 1: return this._resultKernel1DLoop(kernelString) + this._kernelOutput(); case 2: return this._resultKernel2DLoop(kernelString) + this._kernelOutput(); case 3: return this._resultKernel3DLoop(kernelString) + this._kernelOutput(); default: throw new Error('unsupported size kernel'); } } _graphicalKernelBody(kernelThreadString) { switch (this.output.length) { case 2: return this._graphicalKernel2DLoop(kernelThreadString) + this._graphicalOutput(); default: throw new Error('unsupported size kernel'); } } _graphicalOutput() { return ` this._imageData.data.set(this._colorData); this.context.putImageData(this._imageData, 0, 0); return;` } _getKernelResultTypeConstructorString() { switch (this.returnType) { case 'LiteralInteger': case 'Number': case 'Integer': case 'Float': return 'Float32Array'; case 'Array(2)': case 'Array(3)': case 'Array(4)': return 'Array'; default: if (this.graphical) { return 'Float32Array'; } throw new Error(`unhandled returnType ${ this.returnType }`); } } _resultKernel1DLoop(kernelString) { const { output } = this; const constructorString = this._getKernelResultTypeConstructorString(); return ` const outputX = _this.output[0]; const result = new ${constructorString}(outputX); ${ this._mapSubKernels(subKernel => `const result_${ subKernel.name } = new ${constructorString}(outputX);\n`).join(' ') } ${ this._mapSubKernels(subKernel => `let subKernelResult_${ subKernel.name };\n`).join(' ') } for (let x = 0; x < outputX; x++) { this.thread.x = x; this.thread.y = 0; this.thread.z = 0; ${ kernelString } }`; } _resultKernel2DLoop(kernelString) { const { output } = this; const constructorString = this._getKernelResultTypeConstructorString(); return ` const outputX = _this.output[0]; const outputY = _this.output[1]; const result = new Array(outputY); ${ this._mapSubKernels(subKernel => `const result_${ subKernel.name } = new Array(outputY);\n`).join(' ') } ${ this._mapSubKernels(subKernel => `let subKernelResult_${ subKernel.name };\n`).join(' ') } for (let y = 0; y < outputY; y++) { this.thread.z = 0; this.thread.y = y; const resultX = result[y] = new ${constructorString}(outputX); ${ this._mapSubKernels(subKernel => `const resultX_${ subKernel.name } = result_${subKernel.name}[y] = new ${constructorString}(outputX);\n`).join('') } for (let x = 0; x < outputX; x++) { this.thread.x = x; ${ kernelString } } }`; } _graphicalKernel2DLoop(kernelString) { const { output } = this; const constructorString = this._getKernelResultTypeConstructorString(); return ` const outputX = _this.output[0]; const outputY = _this.output[1]; ${ this._mapSubKernels(subKernel => `const result_${ subKernel.name } = new Array(outputY);\n`).join(' ') } ${ this._mapSubKernels(subKernel => `let subKernelResult_${ subKernel.name };\n`).join(' ') } for (let y = 0; y < outputY; y++) { this.thread.z = 0; this.thread.y = y; ${ this._mapSubKernels(subKernel => `const resultX_${ subKernel.name } = result_${subKernel.name}[y] = new ${constructorString}(outputX);\n`).join('') } for (let x = 0; x < outputX; x++) { this.thread.x = x; ${ kernelString } } }`; } _resultKernel3DLoop(kernelString) { const { output } = this; const constructorString = this._getKernelResultTypeConstructorString(); return ` const outputX = _this.output[0]; const outputY = _this.output[1]; const outputZ = _this.output[2]; const result = new Array(outputZ); ${ this._mapSubKernels(subKernel => `const result_${ subKernel.name } = new Array(outputZ);\n`).join(' ') } ${ this._mapSubKernels(subKernel => `let subKernelResult_${ subKernel.name };\n`).join(' ') } for (let z = 0; z < outputZ; z++) { this.thread.z = z; const resultY = result[z] = new Array(outputY); ${ this._mapSubKernels(subKernel => `const resultY_${ subKernel.name } = result_${subKernel.name}[z] = new Array(outputY);\n`).join(' ') } for (let y = 0; y < outputY; y++) { this.thread.y = y; const resultX = resultY[y] = new ${constructorString}(outputX); ${ this._mapSubKernels(subKernel => `const resultX_${ subKernel.name } = resultY_${subKernel.name}[y] = new ${constructorString}(outputX);\n`).join(' ') } for (let x = 0; x < outputX; x++) { this.thread.x = x; ${ kernelString } } } }`; } _kernelOutput() { if (!this.subKernels) { return '\n return result;'; } return `\n return { result: result, ${ this.subKernels.map(subKernel => `${ subKernel.property }: result_${ subKernel.name }`).join(',\n ') } };`; } _mapSubKernels(fn) { return this.subKernels === null ? [''] : this.subKernels.map(fn); } destroy(removeCanvasReference) { if (removeCanvasReference) { delete this.canvas; } } static destroyContext(context) {} toJSON() { const json = super.toJSON(); json.functionNodes = FunctionBuilder.fromKernel(this, CPUFunctionNode).toJSON(); return json; } setOutput(output) { super.setOutput(output); const [width, height] = this.output; if (this.graphical) { this._imageData = this.context.createImageData(width, height); this._colorData = new Uint8ClampedArray(width * height * 4); } } } module.exports = { CPUKernel }; },{"../../utils":70,"../function-builder":9,"../kernel":15,"./function-node":6,"./kernel-string":7}],9:[function(require,module,exports){ class FunctionBuilder { static fromKernel(kernel, FunctionNode, extraNodeOptions) { const { kernelArguments, argumentNames, argumentTypes, argumentSizes, argumentBitRatios, constants, constantTypes, constantBitRatios, debug, loopMaxIterations, nativeFunctions, output, optimizeFloatMemory, precision, plugins, source, subKernels, functions, leadingReturnStatement, followingReturnStatement, dynamicOutput, } = kernel; const lookupReturnType = (functionName, ast, requestingNode) => { return functionBuilder.lookupReturnType(functionName, ast, requestingNode); }; const lookupArgumentType = (argumentName, requestingNode) => { return functionBuilder.lookupArgumentType(argumentName, requestingNode); }; const lookupFunctionArgumentTypes = (functionName) => { return functionBuilder.lookupFunctionArgumentTypes(functionName); }; const lookupFunctionArgumentName = (functionName, argumentIndex) => { return functionBuilder.lookupFunctionArgumentName(functionName, argumentIndex); }; const lookupFunctionArgumentBitRatio = (functionName, argumentName) => { return functionBuilder.lookupFunctionArgumentBitRatio(functionName, argumentName); }; const triggerImplyArgumentType = (functionName, i, argumentType, requestingNode) => { functionBuilder.assignArgumentType(functionName, i, argumentType, requestingNode); }; const triggerTrackArgumentSynonym = (functionName, argumentName, calleeFunctionName, argumentIndex) => { functionBuilder.trackArgumentSynonym(functionName, argumentName, calleeFunctionName, argumentIndex); }; const lookupArgumentSynonym = (originFunctionName, functionName, argumentName) => { return functionBuilder.lookupArgumentSynonym(originFunctionName, functionName, argumentName); }; const onFunctionCall = (functionName, calleeFunctionName) => { functionBuilder.trackFunctionCall(functionName, calleeFunctionName); }; const onNestedFunction = (fnString, returnType) => { functionBuilder.addFunctionNode(new FunctionNode(fnString, Object.assign({}, nodeOptions, { returnType: returnType || 'Number', lookupReturnType, lookupArgumentType, lookupFunctionArgumentTypes, lookupFunctionArgumentName, lookupFunctionArgumentBitRatio, triggerImplyArgumentType, triggerTrackArgumentSynonym, lookupArgumentSynonym, onFunctionCall }))); }; const nodeOptions = Object.assign({ isRootKernel: false, onNestedFunction, lookupReturnType, lookupArgumentType, lookupFunctionArgumentTypes, lookupFunctionArgumentName, lookupFunctionArgumentBitRatio, triggerImplyArgumentType, triggerTrackArgumentSynonym, lookupArgumentSynonym, onFunctionCall, optimizeFloatMemory, precision, constants, constantTypes, constantBitRatios, debug, loopMaxIterations, output, plugins, dynamicOutput, }, extraNodeOptions || {}); const rootNodeOptions = Object.assign({}, nodeOptions, { isRootKernel: true, name: 'kernel', argumentNames, argumentTypes, argumentSizes, argumentBitRatios, leadingReturnStatement, followingReturnStatement, }); if (typeof source === 'object' && source.functionNodes) { return new FunctionBuilder().fromJSON(source.functionNodes, FunctionNode); } const rootNode = new FunctionNode(source, rootNodeOptions); let functionNodes = null; if (functions) { functionNodes = functions.map((fn) => new FunctionNode(fn.source, { returnType: fn.returnType, argumentTypes: fn.argumentTypes, output, plugins, constants, constantTypes, constantBitRatios, optimizeFloatMemory, precision, lookupReturnType, lookupArgumentType, lookupFunctionArgumentTypes, lookupFunctionArgumentName, lookupFunctionArgumentBitRatio, triggerImplyArgumentType, triggerTrackArgumentSynonym, lookupArgumentSynonym, onFunctionCall, })); } let subKernelNodes = null; if (subKernels) { subKernelNodes = subKernels.map((subKernel) => { const { name, source } = subKernel; return new FunctionNode(source, Object.assign({}, nodeOptions, { name, isSubKernel: true, isRootKernel: false, returnType: 'Number', })); }); } const functionBuilder = new FunctionBuilder({ kernel, rootNode, functionNodes, nativeFunctions, subKernelNodes }); return functionBuilder; } constructor(settings) { settings = settings || {}; this.kernel = settings.kernel; this.rootNode = settings.rootNode; this.functionNodes = settings.functionNodes || []; this.subKernelNodes = settings.subKernelNodes || []; this.nativeFunctions = settings.nativeFunctions || []; this.functionMap = {}; this.nativeFunctionNames = []; this.lookupChain = []; this.argumentChain = []; this.functionNodeDependencies = {}; if (this.rootNode) { this.functionMap['kernel'] = this.rootNode; } if (this.functionNodes) { for (let i = 0; i < this.functionNodes.length; i++) { this.functionMap[this.functionNodes[i].name] = this.functionNodes[i]; } } if (this.subKernelNodes) { for (let i = 0; i < this.subKernelNodes.length; i++) { this.functionMap[this.subKernelNodes[i].name] = this.subKernelNodes[i]; } } if (this.nativeFunctions) { for (let i = 0; i < this.nativeFunctions.length; i++) { const nativeFunction = this.nativeFunctions[i]; this.nativeFunctionNames.push(nativeFunction.name); } } } addFunctionNode(functionNode) { this.functionMap[functionNode.name] = functionNode; if (functionNode.isRootKernel) { this.rootNode = functionNode; } } traceFunctionCalls(functionName, retList) { functionName = functionName || 'kernel'; retList = retList || []; if (this.nativeFunctionNames.indexOf(functionName) > -1) { if (retList.indexOf(functionName) === -1) { retList.push(functionName); } return retList; } const functionNode = this.functionMap[functionName]; if (functionNode) { const functionIndex = retList.indexOf(functionName); if (functionIndex === -1) { retList.push(functionName); functionNode.toString(); for (let i = 0; i < functionNode.calledFunctions.length; ++i) { this.traceFunctionCalls(functionNode.calledFunctions[i], retList); } } else { const dependantFunctionName = retList.splice(functionIndex, 1)[0]; retList.push(dependantFunctionName); } } return retList; } getPrototypeString(functionName) { return this.getPrototypes(functionName).join('\n'); } getPrototypes(functionName) { if (this.rootNode) { this.rootNode.toString(); } if (functionName) { return this.getPrototypesFromFunctionNames(this.traceFunctionCalls(functionName, []).reverse()); } return this.getPrototypesFromFunctionNames(Object.keys(this.functionMap)); } getStringFromFunctionNames(functionList) { const ret = []; for (let i = 0; i < functionList.length; ++i) { const node = this.functionMap[functionList[i]]; if (node) { ret.push(this.functionMap[functionList[i]].toString()); } } return ret.join('\n'); } getPrototypesFromFunctionNames(functionList) { const ret = []; for (let i = 0; i < functionList.length; ++i) { const functionName = functionList[i]; const functionIndex = this.nativeFunctionNames.indexOf(functionName); if (functionIndex > -1) { ret.push(this.nativeFunctions[functionIndex].source); continue; } const node = this.functionMap[functionName]; if (node) { ret.push(node.toString()); } } return ret; } toJSON() { return this.traceFunctionCalls(this.rootNode.name).reverse().map(name => { const nativeIndex = this.nativeFunctions.indexOf(name); if (nativeIndex > -1) { return { name, source: this.nativeFunctions[nativeIndex].source }; } else if (this.functionMap[name]) { return this.functionMap[name].toJSON(); } else { throw new Error(`function ${ name } not found`); } }); } fromJSON(jsonFunctionNodes, FunctionNode) { this.functionMap = {}; for (let i = 0; i < jsonFunctionNodes.length; i++) { const jsonFunctionNode = jsonFunctionNodes[i]; this.functionMap[jsonFunctionNode.settings.name] = new FunctionNode(jsonFunctionNode.ast, jsonFunctionNode.settings); } return this; } getString(functionName) { if (functionName) { return this.getStringFromFunctionNames(this.traceFunctionCalls(functionName).reverse()); } return this.getStringFromFunctionNames(Object.keys(this.functionMap)); } lookupArgumentType(argumentName, requestingNode) { const index = requestingNode.argumentNames.indexOf(argumentName); if (index === -1) return null; if (this.lookupChain.length === 0) return null; let link = this.lookupChain[this.lookupChain.length - 1 - this.argumentChain.length]; if (!link) return null; const { ast, requestingNode: parentRequestingNode } = link; if (ast.arguments.length === 0) return null; const usedVariable = ast.arguments[index]; if (!usedVariable) return null; this.argumentChain.push(argumentName); const type = parentRequestingNode.getType(usedVariable); this.argumentChain.pop(); return type; } lookupReturnType(functionName, ast, requestingNode) { if (ast.type !== 'CallExpression') { throw new Error(`expected ast type of "CallExpression", but is ${ ast.type }`); } if (this._isNativeFunction(functionName)) { return this._lookupNativeFunctionReturnType(functionName); } else if (this._isFunction(functionName)) { const node = this._getFunction(functionName); if (node.returnType) { return node.returnType; } else { this.lookupChain.push({ name: requestingNode.name, ast, requestingNode }); const type = node.getType(node.getJsAST()); this.lookupChain.pop(); return node.returnType = type; } } return null; } _getFunction(functionName) { if (!this._isFunction(functionName)) { new Error(`Function ${functionName} not found`); } return this.functionMap[functionName]; } _isFunction(functionName) { return Boolean(this.functionMap[functionName]); } _getNativeFunction(functionName) { for (let i = 0; i < this.nativeFunctions.length; i++) { if (this.nativeFunctions[i].name === functionName) return this.nativeFunctions[i]; } return null; } _isNativeFunction(functionName) { return Boolean(this._getNativeFunction(functionName)); } _lookupNativeFunctionReturnType(functionName) { let nativeFunction = this._getNativeFunction(functionName); if (nativeFunction) { return nativeFunction.returnType; } throw new Error(`Native function ${ functionName } not found`); } lookupFunctionArgumentTypes(functionName) { if (this._isNativeFunction(functionName)) { return this._getNativeFunction(functionName).argumentTypes; } else if (this._isFunction(functionName)) { return this._getFunction(functionName).argumentTypes; } return null; } lookupFunctionArgumentName(functionName, argumentIndex) { return this._getFunction(functionName).argumentNames[argumentIndex]; } lookupFunctionArgumentBitRatio(functionName, argumentName) { if (!this._isFunction(functionName)) { throw new Error('function not found'); } if (this.rootNode.name === functionName) { const i = this.rootNode.argumentNames.indexOf(argumentName); if (i !== -1) { return this.rootNode.argumentBitRatios[i]; } else { throw new Error('argument bit ratio not found'); } } else { const node = this._getFunction(functionName); const argumentSynonym = node.argumentSynonym[node.synonymIndex]; if (!argumentSynonym) { throw new Error('argument synonym not found'); } return this.lookupFunctionArgumentBitRatio(argumentSynonym.functionName, argumentSynonym.argumentName); } } assignArgumentType(functionName, i, argumentType, requestingNode) { if (!this._isFunction(functionName)) return; this._getFunction(functionName).argumentTypes[i] = argumentType; } trackArgumentSynonym(functionName, argumentName, calleeFunctionName, argumentIndex) { if (!this._isFunction(calleeFunctionName)) return; const node = this._getFunction(calleeFunctionName); if (!node.argumentSynonym) { node.argumentSynonym = {}; } const calleeArgumentName = node.argumentNames[argumentIndex]; if (!node.argumentSynonym[calleeArgumentName]) { node.argumentSynonym[calleeArgumentName] = {}; } node.synonymIndex++; node.argumentSynonym[node.synonymIndex] = { functionName, argumentName, calleeArgumentName, calleeFunctionName, }; } lookupArgumentSynonym(originFunctionName, functionName, argumentName) { if (originFunctionName === functionName) return argumentName; if (!this._isFunction(functionName)) return null; const node = this._getFunction(functionName); const argumentSynonym = node.argumentSynonym[node.synonymUseIndex]; if (!argumentSynonym) return null; if (argumentSynonym.calleeArgumentName !== argumentName) return null; node.synonymUseIndex++; if (originFunctionName !== functionName) { return this.lookupArgumentSynonym(originFunctionName, argumentSynonym.functionName, argumentSynonym.argumentName); } return argumentSynonym.argumentName; } trackFunctionCall(functionName, calleeFunctionName) { if (!this.functionNodeDependencies[functionName]) { this.functionNodeDependencies[functionName] = new Set(); } this.functionNodeDependencies[functionName].add(calleeFunctionName); } getKernelResultType() { return this.rootNode.getType(this.rootNode.ast); } getReturnTypes() { const result = { [this.rootNode.name]: this.rootNode.getType(this.rootNode.ast), }; const list = this.traceFunctionCalls(this.rootNode.name); for (let i = 0; i < list.length; i++) { const functionName = list[i]; const functionNode = this.functionMap[functionName]; result[functionName] = functionNode.getType(functionNode.ast); } return result; } } module.exports = { FunctionBuilder }; },{}],10:[function(require,module,exports){ const { utils } = require('../utils'); const acorn = require('acorn'); class FunctionNode { constructor(source, settings) { if (!source) { throw new Error('source parameter is missing'); } settings = settings || {}; this.source = source; this.name = typeof source === 'string' ? settings.isRootKernel ? 'kernel' : (settings.name || utils.getFunctionNameFromString(source)) : null; this.calledFunctions = []; this.calledFunctionsArguments = {}; this.constants = {}; this.constantTypes = {}; this.constantBitRatios = {}; this.isRootKernel = false; this.isSubKernel = false; this.debug = null; this.declarations = {}; this.states = []; this.lookupReturnType = null; this.lookupArgumentType = null; this.lookupFunctionArgumentTypes = null; this.lookupFunctionArgumentBitRatio = null; this.triggerImplyArgumentType = null; this.triggerTrackArgumentSynonym = null; this.lookupArgumentSynonym = null; this.onNestedFunction = null; this.onFunctionCall = null; this.optimizeFloatMemory = null; this.precision = null; this.loopMaxIterations = null; this.argumentNames = (typeof this.source === 'string' ? utils.getArgumentNamesFromString(this.source) : null); this.argumentTypes = []; this.argumentSizes = []; this.argumentBitRatios = null; this.returnType = null; this.output = []; this.plugins = null; this.leadingReturnStatement = null; this.followingReturnStatement = null; this.dynamicOutput = null; if (settings) { for (const p in settings) { if (!settings.hasOwnProperty(p)) continue; if (!this.hasOwnProperty(p)) continue; this[p] = settings[p]; } } this.synonymIndex = -1; this.synonymUseIndex = 0; this.argumentSynonym = {}; this.literalTypes = {}; if (this.isRootKernel && !this.returnType) { this.returnType = 'Number'; } this.validate(); this._string = null; this._internalVariableNames = {}; } validate() { if (typeof this.source !== 'string') { throw new Error('this.source not a string'); } if (!utils.isFunctionString(this.source)) { throw new Error('this.source not a function string'); } if (!this.name) { throw new Error('this.name could not be set'); } if (this.argumentTypes.length > 0 && this.argumentTypes.length !== this.argumentNames.length) { throw new Error(`argumentTypes count of ${ this.argumentTypes.length } exceeds ${ this.argumentNames.length }`); } if (this.output.length < 1) { throw new Error('this.output is not big enough'); } } isIdentifierConstant(name) { if (!this.constants) return false; return this.constants.hasOwnProperty(name); } isInput(argumentName) { return this.argumentTypes[this.argumentNames.indexOf(argumentName)] === 'Input'; } pushState(state) { this.states.push(state); } popState(state) { if (this.state !== state) { throw new Error(`Cannot popState ${ state } when in ${ this.state }`); } this.states.pop(); } isState(state) { return this.state === state; } get state() { return this.states[this.states.length - 1]; } astMemberExpressionUnroll(ast) { if (ast.type === 'Identifier') { return ast.name; } else if (ast.type === 'ThisExpression') { return 'this'; } if (ast.type === 'MemberExpression') { if (ast.object && ast.property) { if (ast.object.hasOwnProperty('name') && ast.object.name[0] === '_') { return this.astMemberExpressionUnroll(ast.property); } return ( this.astMemberExpressionUnroll(ast.object) + '.' + this.astMemberExpressionUnroll(ast.property) ); } } if (ast.hasOwnProperty('expressions')) { const firstExpression = ast.expressions[0]; if (firstExpression.type === 'Literal' && firstExpression.value === 0 && ast.expressions.length === 2) { return this.astMemberExpressionUnroll(ast.expressions[1]); } } throw this.astErrorOutput('Unknown astMemberExpressionUnroll', ast); } getJsAST(inParser) { if (typeof this.source === 'object') { return this.ast = this.source; } if (this.ast) { return this.ast; } inParser = inParser || acorn; if (inParser === null) { throw 'Missing JS to AST parser'; } const ast = Object.freeze(inParser.parse(`const parser_${ this.name } = ${ this.source };`, { locations: true })); const functionAST = ast.body[0].declarations[0].init; if (!ast) { throw new Error('Failed to parse JS code'); } return this.ast = functionAST; } getVariableType(name) { let type = null; const argumentIndex = this.argumentNames.indexOf(name); if (argumentIndex === -1) { if (this.declarations[name]) { return this.declarations[name].type; } } else { const argumentType = this.argumentTypes[argumentIndex]; if (argumentType) { type = argumentType; } else if (this.lookupArgumentType) { type = this.argumentTypes[argumentIndex] = this.lookupArgumentType(name, this); } } if (!type) { } return type; } getConstantType(constantName) { if (this.constantTypes[constantName]) { const type = this.constantTypes[constantName]; if (type === 'Float') { return 'Number'; } else { return type; } } throw new Error(`Type for constant "${ constantName }" not declared`); } getKernelArgumentName(name) { if (!this.lookupArgumentSynonym) return null; const argumentIndex = this.argumentNames.indexOf(name); if (argumentIndex === -1) return null; return this.lookupArgumentSynonym('kernel', this.name, name); } toString() { if (this._string) return this._string; return this._string = this.astGeneric(this.getJsAST(), []).join('').trim(); } toJSON() { const settings = { source: this.source, name: this.name, constants: this.constants, constantTypes: this.constantTypes, isRootKernel: this.isRootKernel, isSubKernel: this.isSubKernel, debug: this.debug, output: this.output, loopMaxIterations: this.loopMaxIterations, argumentNames: this.argumentNames, argumentTypes: this.argumentTypes, argumentSizes: this.argumentSizes, returnType: this.returnType, leadingReturnStatement: this.leadingReturnStatement, followingReturnStatement: this.followingReturnStatement, }; return { ast: this.ast, settings }; } getType(ast) { if (Array.isArray(ast)) { return this.getType(ast[ast.length - 1]); } switch (ast.type) { case 'BlockStatement': return this.getType(ast.body); case 'ArrayExpression': return `Array(${ ast.elements.length })`; case 'Literal': const literalKey = `${ast.start},${ast.end}`; if (this.literalTypes[literalKey]) { return this.literalTypes[literalKey]; } if (Number.isInteger(ast.value)) { return 'LiteralInteger'; } else if (ast.value === true || ast.value === false) { return 'Boolean'; } else { return 'Number'; } case 'AssignmentExpression': return this.getType(ast.left); case 'CallExpression': if (this.isAstMathFunction(ast)) { return 'Number'; } if (!ast.callee || !ast.callee.name) { if (ast.callee.type === 'SequenceExpression' && ast.callee.expressions[ast.callee.expressions.length - 1].property.name) { return this.lookupReturnType(ast.callee.expressions[ast.callee.expressions.length - 1].property.name, ast, this); } throw this.astErrorOutput('Unknown call expression', ast); } if (ast.callee && ast.callee.name) { return this.lookupReturnType(ast.callee.name, ast, this); } throw this.astErrorOutput(`Unhandled getType Type "${ ast.type }"`, ast); case 'BinaryExpression': switch (ast.operator) { case '%': return 'Number'; case '>': case '<': return 'Boolean'; } const type = this.getType(ast.left); return typeLookupMap[type] || type; case 'UpdateExpression': return this.getType(ast.argument); case 'UnaryExpression': return this.getType(ast.argument); case 'VariableDeclaration': return this.getType(ast.declarations[0]); case 'VariableDeclarator': return this.getType(ast.id); case 'Identifier': if (this.isAstVariable(ast)) { const signature = this.getVariableSignature(ast); if (signature === 'value') { if (this.argumentNames.indexOf(ast.name) > -1) { return this.getVariableType(ast.name); } else if (this.declarations[ast.name]) { return this.declarations[ast.name].type; } } } if (ast.name === 'Infinity') { return 'Number'; } const origin = this.findIdentifierOrigin(ast); if (origin && origin.init) { return this.getType(origin.init); } return null; case 'ReturnStatement': return this.getType(ast.argument); case 'MemberExpression': if (this.isAstMathFunction(ast)) { switch (ast.property.name) { case 'ceil': return 'Integer'; case 'floor': return 'Integer'; case 'round': return 'Integer'; } return 'Number'; } if (this.isAstVariable(ast)) { const variableSignature = this.getVariableSignature(ast); switch (variableSignature) { case 'value[]': return typeLookupMap[this.getVariableType(ast.object.name)]; case 'value[][]': return typeLookupMap[this.getVariableType(ast.object.object.name)]; case 'value[][][]': return typeLookupMap[this.getVariableType(ast.object.object.object.name)]; case 'value[][][][]': return typeLookupMap[this.getVariableType(ast.object.object.object.object.name)]; case 'this.thread.value': return 'Integer'; case 'this.output.value': return this.dynamicOutput ? 'Integer' : 'LiteralInteger'; case 'this.constants.value': return this.getConstantType(ast.property.name); case 'this.constants.value[]': return typeLookupMap[this.getConstantType(ast.object.property.name)]; case 'this.constants.value[][]': return typeLookupMap[this.getConstantType(ast.object.object.property.name)]; case 'this.constants.value[][][]': return typeLookupMap[this.getConstantType(ast.object.object.object.property.name)]; case 'this.constants.value[][][][]': return typeLookupMap[this.getConstantType(ast.object.object.object.object.property.name)]; case 'fn()[]': return typeLookupMap[this.getType(ast.object)]; case 'fn()[][]': return typeLookupMap[this.getType(ast.object)]; case 'fn()[][][]': return typeLookupMap[this.getType(ast.object)]; case 'value.value': if (this.isAstMathVariable(ast)) { return 'Number'; } switch (ast.property.name) { case 'r': return typeLookupMap[this.getVariableType(ast.object.name)]; case 'g': return typeLookupMap[this.getVariableType(ast.object.name)]; case 'b': return typeLookupMap[this.getVariableType(ast.object.name)]; case 'a': return typeLookupMap[this.getVariableType(ast.object.name)]; } case '[][]': return 'Number'; } throw this.astErrorOutput('Unhandled getType MemberExpression', ast); } throw this.astErrorOutput('Unhandled getType MemberExpression', ast); case 'ConditionalExpression': return this.getType(ast.consequent); case 'FunctionDeclaration': case 'FunctionExpression': const lastReturn = this.findLastReturn(ast.body); if (lastReturn) { return this.getType(lastReturn); } return null; case 'IfStatement': return this.getType(ast.consequent); default: throw this.astErrorOutput(`Unhandled getType Type "${ ast.type }"`, ast); } } isAstMathVariable(ast) { const mathProperties = [ 'E', 'PI', 'SQRT2', 'SQRT1_2', 'LN2', 'LN10', 'LOG2E', 'LOG10E', ]; return ast.type === 'MemberExpression' && ast.object && ast.object.type === 'Identifier' && ast.object.name === 'Math' && ast.property && ast.property.type === 'Identifier' && mathProperties.indexOf(ast.property.name) > -1; } isAstMathFunction(ast) { const mathFunctions = [ 'abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'log2', 'max', 'min', 'pow', 'random', 'round', 'sign', 'sin', 'sqrt', 'tan', ]; return ast.type === 'CallExpression' && ast.callee && ast.callee.type === 'MemberExpression' && ast.callee.object && ast.callee.object.type === 'Identifier' && ast.callee.object.name === 'Math' && ast.callee.property && ast.callee.property.type === 'Identifier' && mathFunctions.indexOf(ast.callee.property.name) > -1; } isAstVariable(ast) { return ast.type === 'Identifier' || ast.type === 'MemberExpression'; } isSafe(ast) { return this.isSafeDependencies(this.getDependencies(ast)); } isSafeDependencies(dependencies) { return dependencies && dependencies.every ? dependencies.every(dependency => dependency.isSafe) : true; } getDependencies(ast, dependencies, isNotSafe) { if (!dependencies) { dependencies = []; } if (!ast) return null; if (Array.isArray(ast)) { for (let i = 0; i < ast.length; i++) { this.getDependencies(ast[i], dependencies, isNotSafe); } return dependencies; } switch (ast.type) { case 'Literal': dependencies.push({ origin: 'literal', value: ast.value, isSafe: isNotSafe === true ? false : ast.value > -Infinity && ast.value < Infinity && !isNaN(ast.value) }); break; case 'VariableDeclarator': return this.getDependencies(ast.init, dependencies, isNotSafe); case 'Identifier': if (this.declarations[ast.name]) { dependencies.push({ name: ast.name, origin: 'declaration', isSafe: isNotSafe ? false : this.isSafeDependencies(this.declarations[ast.name].dependencies), }); } else if (this.argumentNames.indexOf(ast.name) > -1) { dependencies.push({ name: ast.name, origin: 'argument', isSafe: false, }); } break; case 'FunctionDeclaration': return this.getDependencies(ast.body.body[ast.body.body.length - 1], dependencies, isNotSafe); case 'ReturnStatement': return this.getDependencies(ast.argument, dependencies); case 'BinaryExpression': isNotSafe = (ast.operator === '/' || ast.operator === '*'); this.getDependencies(ast.left, dependencies, isNotSafe); this.getDependencies(ast.right, dependencies, isNotSafe); return dependencies; case 'UnaryExpression': case 'UpdateExpression': return this.getDependencies(ast.argument, dependencies, isNotSafe); case 'VariableDeclaration': return this.getDependencies(ast.declarations, dependencies, isNotSafe); case 'ArrayExpression': dependencies.push({ origin: 'declaration', isSafe: true, }); return dependencies; case 'CallExpression': dependencies.push({ origin: 'function', isSafe: true, }); return dependencies; case 'MemberExpression': const details = this.getMemberExpressionDetails(ast); if (this.dynamicOutput && details.signature === 'this.output.value') { dependencies.push({ name: details.name, origin: 'output', isSafe: false, }); return dependencies; } if (details) { return details.type; } default: throw this.astErrorOutput(`Unhandled type ${ ast.type } in getAllVariables`, ast); } return dependencies; } getVariableSignature(ast) { if (!this.isAstVariable(ast)) { throw new Error(`ast of type "${ ast.type }" is not a variable signature`); } if (ast.type === 'Identifier') { return 'value'; } const signature = []; while (true) { if (!ast) break; if (ast.computed) { signature.push('[]'); } else if (ast.type === 'ThisExpression') { signature.unshift('this'); } else if (ast.property && ast.property.name) { if ( ast.property.name === 'x' || ast.property.name === 'y' || ast.property.name === 'z' ) { signature.unshift('.value'); } else if ( ast.property.name === 'constants' || ast.property.name === 'thread' || ast.property.name === 'output' ) { signature.unshift('.' + ast.property.name); } else { signature.unshift('.value'); } } else if (ast.name) { signature.unshift('value'); } else if (ast.callee && ast.callee.name) { signature.unshift('fn()'); } else if (ast.elements) { signature.unshift('[]'); } else { signature.unshift('unknown'); } ast = ast.object; } const signatureString = signature.join(''); const allowedExpressions = [ 'value', 'value[]', 'value[][]', 'value[][][]', 'value[][][][]', 'value.value', 'this.thread.value', 'this.output.value', 'this.constants.value', 'this.constants.value[]', 'this.constants.value[][]', 'this.constants.value[][][]', 'this.constants.value[][][][]', 'fn()[]', 'fn()[][]', 'fn()[][][]', '[][]', ]; if (allowedExpressions.indexOf(signatureString) > -1) { return signatureString; } return null; } build() { return this.toString().length > 0; } astGeneric(ast, retArr) { if (ast === null) { throw this.astErrorOutput('NULL ast', ast); } else { if (Array.isArray(ast)) { for (let i = 0; i < ast.length; i++) { this.astGeneric(ast[i], retArr); } return retArr; } switch (ast.type) { case 'FunctionDeclaration': return this.astFunctionDeclaration(ast, retArr); case 'FunctionExpression': return this.astFunctionExpression(ast, retArr); case 'ReturnStatement': return this.astReturnStatement(ast, retArr); case 'Literal': return this.astLiteral(ast, retArr); case 'BinaryExpression': return this.astBinaryExpression(ast, retArr); case 'Identifier': return this.astIdentifierExpression(ast, retArr); case 'AssignmentExpression': return this.astAssignmentExpression(ast, retArr); case 'ExpressionStatement': return this.astExpressionStatement(ast, retArr); case 'EmptyStatement': return this.astEmptyStatement(ast, retArr); case 'BlockStatement': return this.astBlockStatement(ast, retArr); case 'IfStatement': return this.astIfStatement(ast, retArr); case 'BreakStatement': return this.astBreakStatement(ast, retArr); case 'ContinueStatement': return this.astContinueStatement(ast, retArr); case 'ForStatement': return this.astForStatement(ast, retArr); case 'WhileStatement': return this.astWhileStatement(ast, retArr); case 'DoWhileStatement': return this.astDoWhileStatement(ast, retArr); case 'VariableDeclaration': return this.astVariableDeclaration(ast, retArr); case 'VariableDeclarator': return this.astVariableDeclarator(ast, retArr); case 'ThisExpression': return this.astThisExpression(ast, retArr); case 'SequenceExpression': return this.astSequenceExpression(ast, retArr); case 'UnaryExpression': return this.astUnaryExpression(ast, retArr); case 'UpdateExpression': return this.astUpdateExpression(ast, retArr); case 'LogicalExpression': return this.astLogicalExpression(ast, retArr); case 'MemberExpression': return this.astMemberExpression(ast, retArr); case 'CallExpression': return this.astCallExpression(ast, retArr); case 'ArrayExpression': return this.astArrayExpression(ast, retArr); case 'DebuggerStatement': return this.astDebuggerStatement(ast, retArr); case 'ConditionalExpression': return this.astConditionalExpression(ast, retArr); } throw this.astErrorOutput('Unknown ast type : ' + ast.type, ast); } } astErrorOutput(error, ast) { if (typeof this.source !== 'string') { return new Error(error); } const debugString = utils.getAstString(this.source, ast); const leadingSource = this.source.substr(ast.start); const splitLines = leadingSource.split(/\n/); const lineBefore = splitLines.length > 0 ? splitLines[splitLines.length - 1] : 0; return new Error(`${error} on line ${ splitLines.length }, position ${ lineBefore.length }:\n ${ debugString }`); } astDebuggerStatement(arrNode, retArr) { return retArr; } astConditionalExpression(ast, retArr) { if (ast.type !== 'ConditionalExpression') { throw this.astErrorOutput('Not a conditional expression', ast); } retArr.push('('); this.astGeneric(ast.test, retArr); retArr.push('?'); this.astGeneric(ast.consequent, retArr); retArr.push(':'); this.astGeneric(ast.alternate, retArr); retArr.push(')'); return retArr; } astFunctionDeclaration(ast, retArr) { if (this.onNestedFunction) { let returnType = this.getType(ast); if (returnType === 'LiteralInteger') { returnType = 'Number'; } this.onNestedFunction(utils.getAstString(this.source, ast), returnType); } return retArr; } astFunctionExpression(ast, retArr) { return retArr; } astReturnStatement(ast, retArr) { return retArr; } astLiteral(ast, retArr) { this.literalTypes[`${ast.start},${ast.end}`] = 'Number'; return retArr; } astBinaryExpression(ast, retArr) { return retArr; } astIdentifierExpression(ast, retArr) { return retArr; } astAssignmentExpression(ast, retArr) { return retArr; } astExpressionStatement(esNode, retArr) { this.astGeneric(esNode.expression, retArr); retArr.push(';'); return retArr; } astEmptyStatement(eNode, retArr) { return retArr; } astBlockStatement(ast, retArr) { return retArr; } astIfStatement(ast, retArr) { return retArr; } astBreakStatement(brNode, retArr) { retArr.push('break;'); return retArr; } astContinueStatement(crNode, retArr) { retArr.push('continue;\n'); return retArr; } astForStatement(ast, retArr) { return retArr; } astWhileStatement(ast, retArr) { return retArr; } astDoWhileStatement(ast, retArr) { return retArr; } astVariableDeclaration(varDecNode, retArr) { const declarations = varDecNode.declarations; if (!declarations || !declarations[0] || !declarations[0].init) { throw this.astErrorOutput('Unexpected expression', varDecNode); } const result = []; const firstDeclaration = declarations[0]; const init = firstDeclaration.init; let type = this.isState('in-for-loop-init') ? 'Integer' : this.getType(init); if (type === 'LiteralInteger') { type = 'Number'; } const markupType = typeMap[type]; if (!markupType) { throw this.astErrorOutput(`Markup type ${ markupType } not handled`, varDecNode); } let dependencies = this.getDependencies(firstDeclaration.init); this.declarations[firstDeclaration.id.name] = Object.freeze({ type, dependencies, isSafe: dependencies.every(dependency => dependency.isSafe) }); const initResult = [`${type} user_${firstDeclaration.id.name}=`]; this.astGeneric(init, initResult); result.push(initResult.join('')); for (let i = 1; i < declarations.length; i++) { const declaration = declarations[i]; dependencies = this.getDependencies(declaration); this.declarations[declaration.id.name] = Object.freeze({ type, dependencies, isSafe: false }); this.astGeneric(declaration, result); } retArr.push(retArr, result.join(',')); retArr.push(';'); return retArr; } astVariableDeclarator(iVarDecNode, retArr) { this.astGeneric(iVarDecNode.id, retArr); if (iVarDecNode.init !== null) { retArr.push('='); this.astGeneric(iVarDecNode.init, retArr); } return retArr; } astThisExpression(ast, retArr) { return retArr; } astSequenceExpression(sNode, retArr) { for (let i = 0; i < sNode.expressions.length; i++) { if (i > 0) { retArr.push(','); } this.astGeneric(sNode.expressions, retArr); } return retArr; } astUnaryExpression(uNode, retArr) { if (uNode.prefix) { retArr.push(uNode.operator); this.astGeneric(uNode.argument, retArr); } else { this.astGeneric(uNode.argument, retArr); retArr.push(uNode.operator); } return retArr; } astUpdateExpression(uNode, retArr) { if (uNode.prefix) { retArr.push(uNode.operator); this.astGeneric(uNode.argument, retArr); } else { this.astGeneric(uNode.argument, retArr); retArr.push(uNode.operator); } return retArr; } astLogicalExpression(logNode, retArr) { retArr.push('('); this.astGeneric(logNode.left, retArr); retArr.push(logNode.operator); this.astGeneric(logNode.right, retArr); retArr.push(')'); return retArr; } astMemberExpression(ast, retArr) { return retArr; } astCallExpression(ast, retArr) { return retArr; } astArrayExpression(ast, retArr) { return retArr; } getMemberExpressionDetails(ast) { if (ast.type !== 'MemberExpression') { throw this.astErrorOutput(`Expression ${ ast.type } not a MemberExpression`, ast); } let name = null; let type = null; const variableSignature = this.getVariableSignature(ast); switch (variableSignature) { case 'value': return null; case 'this.thread.value': case 'this.output.value': return { signature: variableSignature, type: 'Integer', name: ast.property.name }; case 'value[]': if (typeof ast.object.name !== 'string') { throw this.astErrorOutput('Unexpected expression', ast); } name = ast.object.name; return { name, origin: 'user', signature: variableSignature, type: this.getVariableType(name), xProperty: ast.property }; case 'value[][]': if (typeof ast.object.object.name !== 'string') { throw this.astErrorOutput('Unexpected expression', ast); } name = ast.object.object.name; return { name, origin: 'user', signature: variableSignature, type: this.getVariableType(name), yProperty: ast.object.property, xProperty: ast.property, }; case 'value[][][]': if (typeof ast.object.object.object.name !== 'string') { throw this.astErrorOutput('Unexpected expression', ast); } name = ast.object.object.object.name; return { name, origin: 'user', signature: variableSignature, type: this.getVariableType(name), zProperty: ast.object.object.property, yProperty: ast.object.property, xProperty: ast.property, }; case 'value[][][][]': if (typeof ast.object.object.object.object.name !== 'string') { throw this.astErrorOutput('Unexpected expression', ast); } name = ast.object.object.object.object.name; return { name, origin: 'user', signature: variableSignature, type: this.getVariableType(name), zProperty: ast.object.object.property, yProperty: ast.object.property, xProperty: ast.property, }; case 'value.value': if (typeof ast.property.name !== 'string') { throw this.astErrorOutput('Unexpected expression', ast); } if (this.isAstMathVariable(ast)) { name = ast.property.name; return { name, origin: 'Math', type: 'Number', signature: variableSignature, }; } switch (ast.property.name) { case 'r': case 'g': case 'b': case 'a': name = ast.object.name; return { name, property: ast.property.name, origin: 'user', signature: variableSignature, type: 'Number' }; default: throw this.astErrorOutput('Unexpected expression', ast); } case 'this.constants.value': if (typeof ast.property.name !== 'string') { throw this.astErrorOutput('Unexpected expression', ast); } name = ast.property.name; type = this.getConstantType(name); if (!type) { throw this.astErrorOutput('Constant has no type', ast); } return { name, type, origin: 'constants', signature: variableSignature, }; case 'this.constants.value[]': if (typeof ast.object.property.name !== 'string') { throw this.astErrorOutput('Unexpected expression', ast); } name = ast.object.property.name; type = this.getConstantType(name); if (!type) { throw this.astErrorOutput('Constant has no type', ast); } return { name, type, origin: 'constants', signature: variableSignature, xProperty: ast.property, }; case 'this.constants.value[][]': { if (typeof ast.object.object.property.name !== 'string') { throw this.astErrorOutput('Unexpected expression', ast); } name = ast.object.object.property.name; type = this.getConstantType(name); if (!type) { throw this.astErrorOutput('Constant has no type', ast); } return { name, type, origin: 'constants', signature: variableSignature, yProperty: ast.object.property, xProperty: ast.property, }; } case 'this.constants.value[][][]': { if (typeof ast.object.object.object.property.name !== 'string') { throw this.astErrorOutput('Unexpected expression', ast); } name = ast.object.object.object.property.name; type = this.getConstantType(name); if (!type) { throw this.astErrorOutput('Constant has no type', ast); } return { name, type, origin: 'constants', signature: variableSignature, zProperty: ast.object.object.property, yProperty: ast.object.property, xProperty: ast.property, }; } case 'fn()[]': case '[][]': return { signature: variableSignature, property: ast.property, }; default: throw this.astErrorOutput('Unexpected expression', ast); } } findIdentifierOrigin(astToFind) { const stack = [this.ast]; while (stack.length > 0) { const atNode = stack[0]; if (atNode.type === 'VariableDeclarator' && atNode.id && atNode.id.name && atNode.id.name === astToFind.name) { return atNode; } stack.shift(); if (atNode.argument) { stack.push(atNode.argument); } else if (atNode.body) { stack.push(atNode.body); } else if (atNode.declarations) { stack.push(atNode.declarations); } else if (Array.isArray(atNode)) { for (let i = 0; i < atNode.length; i++) { stack.push(atNode[i]); } } } return null; } findLastReturn(ast) { const stack = [ast || this.ast]; while (stack.length > 0) { const atNode = stack.pop(); if (atNode.type === 'ReturnStatement') { return atNode; } if (atNode.argument) { stack.push(atNode.argument); } else if (atNode.body) { stack.push(atNode.body); } else if (atNode.declarations) { stack.push(atNode.declarations); } else if (Array.isArray(atNode)) { for (let i = 0; i < atNode.length; i++) { stack.push(atNode[i]); } } else if (atNode.consequent) { stack.push(atNode.consequent); } } return null; } getInternalVariableName(name) { if (!this._internalVariableNames.hasOwnProperty(name)) { this._internalVariableNames[name] = 0; } this._internalVariableNames[name]++; if (this._internalVariableNames[name] === 1) { return name; } return name + this._internalVariableNames[name]; } varWarn() { console.warn('var declarations are deprecated, weird things happen when falling back to CPU because var scope differs in javascript than in most languages. Use const or let'); } } const typeLookupMap = { 'Array': 'Number', 'Array(2)': 'Number', 'Array(3)': 'Number', 'Array(4)': 'Number', 'Array2D': 'Number', 'Array3D': 'Number', 'Input': 'Number', 'HTMLImage': 'Array(4)', 'HTMLImageArray': 'Array(4)', 'NumberTexture': 'Number', 'MemoryOptimizedNumberTexture': 'Number', 'ArrayTexture(1)': 'Number', 'ArrayTexture(2)': 'Array(2)', 'ArrayTexture(3)': 'Array(3)', 'ArrayTexture(4)': 'Array(4)', }; module.exports = { FunctionNode }; },{"../utils":70,"acorn":2}],11:[function(require,module,exports){ const { glWiretap } = require('gl-wiretap'); const { utils } = require('../../utils'); const { Texture } = require('../../texture'); function toStringWithoutUtils(fn) { return fn.toString() .replace(/^function /, '') .replace(/utils[.]/g, '/*utils.*/'); } function glKernelString(Kernel, args, originKernel, setupContextString, destroyContextString) { const context = glWiretap(originKernel.context, { useTrackablePrimitives: true }); const { source, canvas, output, pipeline, graphical, loopMaxIterations, constants, optimizeFloatMemory, precision, fixIntegerDivisionAccuracy, functions, nativeFunctions, subKernels, immutable, } = originKernel; const kernel = new Kernel(source, { canvas, context, output, pipeline, graphical, loopMaxIterations, constants, optimizeFloatMemory, precision, fixIntegerDivisionAccuracy, functions, nativeFunctions, subKernels, immutable, }); let result = []; context.setIndent(2); kernel.build.apply(kernel, args); result.push(context.toString()); context.reset(); kernel.kernelArguments.forEach(kernelArgument => { context.insertVariable(`uploadValue_${kernelArgument.name}`, kernelArgument.uploadValue); }); result.push('/** start of injected functions **/'); result.push(`function ${toStringWithoutUtils(utils.flattenTo)}`); result.push(`function ${toStringWithoutUtils(utils.flatten2dArrayTo)}`); result.push(`function ${toStringWithoutUtils(utils.flatten3dArrayTo)}`); result.push(`function ${toStringWithoutUtils(utils.isArray)}`); if (kernel.renderOutput === kernel.renderTexture) { result.push(Texture.toString()); result.push( ` const renderOutput = function ${ toStringWithoutUtils(kernel.renderOutput.toString()) .replace(`this.outputTexture`, 'null') .replace('this.texSize', `new Int32Array(${JSON.stringify(Array.from(kernel.texSize))})`) .replace('this.threadDim', `new Int32Array(${JSON.stringify(Array.from(kernel.threadDim))})`) .replace('this.output', `new Int32Array(${JSON.stringify(this.output)})`) .replace('this.context', 'gl') .replace('this.gpu', 'null') .replace('this.getReturnTextureType()', `'${kernel.getReturnTextureType()}'`) };` ); } else { result.push( ` const renderOutput = function ${toStringWithoutUtils(kernel.renderOutput.toString()) .replace('() {', '(pixels) {') .replace(' const pixels = this.readFloatPixelsToFloat32Array();\n', '') .replace('this.readPackedPixelsToFloat32Array()', 'new Float32Array(pixels.buffer)') .replace('this.output;', JSON.stringify(kernel.output) + ';') };` ); } kernel.kernelArguments.forEach(kernelArgument => { kernelArgument.context = originKernel.context; }); result.push('/** end of injected functions **/'); result.push(` return function (${kernel.kernelArguments.map(kernelArgument => kernelArgument.name).join(', ')}) {`); context.setIndent(4); kernel.run.apply(kernel, args); if (kernel.renderKernels) { kernel.renderKernels(); } else if (kernel.renderOutput) { kernel.renderOutput(); } result.push('/** start setup uploads for kernel values **/'); kernel.kernelArguments.forEach(kernelArgument => { result.push(kernelArgument.getStringValueHandler()); }); result.push('/** end setup uploads for kernel values **/'); result.push(context.toString()); result.push(` ${destroyContextString ? '\n' + destroyContextString + ' ': ''}return renderOutput(${context.getReadPixelsVariableName});`); result.push(' };'); return `function kernel(context = null) { ${setupContextString ? setupContextString : ''}${result.join('\n')} }`; } module.exports = { glKernelString }; },{"../../texture":69,"../../utils":70,"gl-wiretap":1}],12:[function(require,module,exports){ const { Kernel } = require('../kernel'); const { Texture } = require('../../texture'); const { utils } = require('../../utils'); class GLKernel extends Kernel { static get mode() { return 'gpu'; } static getIsFloatRead() { const kernelString = `function kernelFunction() { return 1; }`; const kernel = new this(kernelString, { context: this.testContext, canvas: this.testCanvas, validate: false, output: [1], precision: 'single', returnType: 'Number' }); kernel.build(); kernel.run(); const result = kernel.renderOutput(); kernel.destroy(true); return result[0] === 1; } static getIsIntegerDivisionAccurate() { function kernelFunction(v1, v2) { return v1[this.thread.x] / v2[this.thread.x]; } const kernel = new this(kernelFunction.toString(), { context: this.testContext, canvas: this.testCanvas, validate: false, output: [2], returnType: 'Number', precision: 'unsigned', }); const args = [ [6, 6030401], [3, 3991] ]; kernel.build.apply(kernel, args); kernel.run.apply(kernel, args); const result = kernel.renderOutput(); kernel.destroy(true); return result[0] === 2 && result[1] === 1511; } static get testCanvas() { throw new Error(`"testCanvas" not defined on ${ this.name }`); } static get testContext() { throw new Error(`"testContext" not defined on ${ this.name }`); } static get features() { throw new Error(`"features" not defined on ${ this.name }`); } static setupFeatureChecks() { throw new Error(`"setupFeatureChecks" not defined on ${ this.name }`); } setFixIntegerDivisionAccuracy(fix) { this.fixIntegerDivisionAccuracy = fix; return this; } setPrecision(flag) { this.precision = flag; return this; } setFloatTextures(flag) { utils.warnDeprecated('method', 'setFloatTextures', 'setOptimizeFloatMemory'); this.floatTextures = flag; return this; } static nativeFunctionArguments(source) { const argumentTypes = []; const argumentNames = []; const states = []; const isStartingVariableName = /^[a-zA-Z_]/; const isVariableChar = /[a-zA-Z_0-9]/; let i = 0; let argumentName = null; let argumentType = null; while (i < source.length) { const char = source[i]; const nextChar = source[i + 1]; const state = states.length > 0 ? states[states.length - 1] : null; if (state === 'FUNCTION_ARGUMENTS' && char === '/' && nextChar === '*') { states.push('MULTI_LINE_COMMENT'); i += 2; continue; } else if (state === 'MULTI_LINE_COMMENT' && char === '*' && nextChar === '/') { states.pop(); i += 2; continue; } else if (state === 'FUNCTION_ARGUMENTS' && char === '/' && nextChar === '/') { states.push('COMMENT'); i += 2; continue; } else if (state === 'COMMENT' && char === '\n') { states.pop(); i++; continue; } else if (state === null && char === '(') { states.push('FUNCTION_ARGUMENTS'); i++; continue; } else if (state === 'FUNCTION_ARGUMENTS') { if (char === ')') { states.pop(); break; } if (char === 'f' && nextChar === 'l' && source[i + 2] === 'o' && source[i + 3] === 'a' && source[i + 4] === 't' && source[i + 5] === ' ') { states.push('DECLARE_VARIABLE'); argumentType = 'float'; argumentName = ''; i += 6; continue; } else if (char === 'i' && nextChar === 'n' && source[i + 2] === 't' && source[i + 3] === ' ') { states.push('DECLARE_VARIABLE'); argumentType = 'int'; argumentName = ''; i += 4; continue; } else if (char === 'v' && nextChar === 'e' && source[i + 2] === 'c' && source[i + 3] === '2' && source[i + 4] === ' ') { states.push('DECLARE_VARIABLE'); argumentType = 'vec2'; argumentName = ''; i += 5; continue; } else if (char === 'v' && nextChar === 'e' && source[i + 2] === 'c' && source[i + 3] === '3' && source[i + 4] === ' ') { states.push('DECLARE_VARIABLE'); argumentType = 'vec3'; argumentName = ''; i += 5; continue; } else if (char === 'v' && nextChar === 'e' && source[i + 2] === 'c' && source[i + 3] === '4' && source[i + 4] === ' ') { states.push('DECLARE_VARIABLE'); argumentType = 'vec4'; argumentName = ''; i += 5; continue; } } else if (state === 'DECLARE_VARIABLE') { if (argumentName === '') { if (char === ' ') { i++; continue; } if (!isStartingVariableName.test(char)) { throw new Error('variable name is not expected string'); } } argumentName += char; if (!isVariableChar.test(nextChar)) { states.pop(); argumentNames.push(argumentName); argumentTypes.push(typeMap[argumentType]); } } i++; } if (states.length > 0) { throw new Error('GLSL function was not parsable'); } return { argumentNames, argumentTypes, }; } static nativeFunctionReturnType(source) { return typeMap[source.match(/int|float|vec[2-4]/)[0]]; } static combineKernels(combinedKernel, lastKernel) { combinedKernel.apply(null, arguments); const { texSize, context, threadDim } = lastKernel.texSize; let result; if (lastKernel.precision === 'single') { const w = texSize[0]; const h = Math.ceil(texSize[1] / 4); result = new Float32Array(w * h * 4 * 4); context.readPixels(0, 0, w, h * 4, context.RGBA, context.FLOAT, result); } else { const bytes = new Uint8Array(texSize[0] * texSize[1] * 4); context.readPixels(0, 0, texSize[0], texSize[1], context.RGBA, context.UNSIGNED_BYTE, bytes); result = new Float32Array(bytes.buffer); } result = result.subarray(0, threadDim[0] * threadDim[1] * threadDim[2]); if (lastKernel.output.length === 1) { return result; } else if (lastKernel.output.length === 2) { return utils.splitArray(result, lastKernel.output[0]); } else if (lastKernel.output.length === 3) { const cube = utils.splitArray(result, lastKernel.output[0] * lastKernel.output[1]); return cube.map(function(x) { return utils.splitArray(x, lastKernel.output[0]); }); } } constructor(source, settings) { super(source, settings); this.renderOutput = null; this.renderRawOutput = null; this.texSize = null; this.fixIntegerDivisionAccuracy = null; this.translatedSource = null; this.renderStrategy = null; this.compiledFragmentShader = null; this.compiledVertexShader = null; } translateSource() { throw new Error(`"translateSource" not defined on ${this.constructor.name}`); } pickRenderStrategy(args) { if (this.graphical) return; if (this.precision === 'unsigned') { this.renderRawOutput = this.readPackedPixelsToUint8Array; switch (this.returnType) { case 'LiteralInteger': case 'Float': case 'Number': case 'Integer': if (this.pipeline) { this.renderStrategy = renderStrategy.PackedTexture; this.renderOutput = this.renderTexture; if (this.subKernels !== null) { this.renderKernels = this.renderKernelsToTextures; } return true; } else if (this.output[2] > 0) { this.renderStrategy = renderStrategy.PackedPixelTo3DFloat; this.renderOutput = this.render3DPackedFloat; } else if (this.output[1] > 0) { this.renderStrategy = renderStrategy.PackedPixelTo2DFloat; this.renderOutput = this.render2DPackedFloat; } else { this.renderStrategy = renderStrategy.PackedPixelToFloat; this.renderOutput = this.renderPackedFloat; } if (this.subKernels !== null) { this.renderKernels = this.renderKernelsToArrays; } return true; case 'Array(2)': case 'Array(3)': case 'Array(4)': this.onRequestFallback(args); return false; } } else if (this.precision === 'single') { this.renderRawOutput = this.readFloatPixelsToFloat32Array; if (this.pipeline) { this.renderStrategy = renderStrategy.FloatTexture; this.renderOutput = this.renderTexture; if (this.subKernels !== null) { this.renderKernels = this.renderKernelsToTextures; } return true; } switch (this.returnType) { case 'LiteralInteger': case 'Float': case 'Number': case 'Integer': if (this.output[2] > 0) { if (this.optimizeFloatMemory) { this.renderStrategy = renderStrategy.MemoryOptimizedFloatPixelToMemoryOptimized3DFloat; this.renderOutput = this.renderMemoryOptimized3DFloat; } else { this.renderStrategy = renderStrategy.FloatPixelTo3DFloat; this.renderOutput = this.render3DFloat; } } else if (this.output[1] > 0) { if (this.optimizeFloatMemory) { this.renderStrategy = renderStrategy.MemoryOptimizedFloatPixelToMemoryOptimized2DFloat; this.renderOutput = this.renderMemoryOptimized2DFloat; } else { this.renderStrategy = renderStrategy.FloatPixelTo2DFloat; this.renderOutput = this.render2DFloat; } } else { if (this.optimizeFloatMemory) { this.renderStrategy = renderStrategy.MemoryOptimizedFloatPixelToMemoryOptimizedFloat; this.renderOutput = this.renderMemoryOptimizedFloat; } else { this.renderStrategy = renderStrategy.FloatPixelToFloat; this.renderOutput = this.renderFloat; } } if (this.subKernels !== null) { this.renderKernels = this.renderKernelsToArrays; } return true; case 'Array(2)': if (this.output[2] > 0) { this.renderStrategy = renderStrategy.FloatPixelTo3DArray2; this.renderOutput = this.render3DArray2; } else if (this.output[1] > 0) { this.renderStrategy = renderStrategy.FloatPixelTo2DArray2; this.renderOutput = this.render2DArray2; } else { this.renderStrategy = renderStrategy.FloatPixelToArray2; this.renderOutput = this.renderArray2; } if (this.subKernels !== null) { this.renderKernels = this.renderKernelsToArrays; } return true; case 'Array(3)': if (this.output[2] > 0) { this.renderStrategy = renderStrategy.FloatPixelTo3DArray3; this.renderOutput = this.render3DArray3; } else if (this.output[1] > 0) { this.renderStrategy = renderStrategy.FloatPixelTo2DArray3; this.renderOutput = this.render2DArray3; } else { this.renderStrategy = renderStrategy.FloatPixelToArray3; this.renderOutput = this.renderArray3; } if (this.subKernels !== null) { this.renderKernels = this.renderKernelsToArrays; } return true; case 'Array(4)': if (this.output[2] > 0) { this.renderStrategy = renderStrategy.FloatPixelTo3DArray4; this.renderOutput = this.render3DArray4; } else if (this.output[1] > 0) { this.renderStrategy = renderStrategy.FloatPixelTo2DArray4; this.renderOutput = this.render2DArray4; } else { this.renderStrategy = renderStrategy.FloatPixelToArray4; this.renderOutput = this.renderArray4; } if (this.subKernels !== null) { this.renderKernels = this.renderKernelsToArrays; } return true; } } else { throw new Error(`unhandled precision of "${this.precision}"`); } throw new Error(`unhandled return type "${this.returnType}"`); } getKernelString() { throw new Error(`abstract method call`); } getMainResultTexture() { switch (this.returnType) { case 'LiteralInteger': case 'Float': case 'Integer': case 'Number': return this.getMainResultNumberTexture(); case 'Array(2)': return this.getMainResultArray2Texture(); case 'Array(3)': return this.getMainResultArray3Texture(); case 'Array(4)': return this.getMainResultArray4Texture(); default: throw new Error(`unhandled returnType type ${ this.returnType }`); } } getMainResultKernelNumberTexture() { throw new Error(`abstract method call`); } getMainResultSubKernelNumberTexture() { throw new Error(`abstract method call`); } getMainResultKernelArray2Texture() { throw new Error(`abstract method call`); } getMainResultSubKernelArray2Texture() { throw new Error(`abstract method call`); } getMainResultKernelArray3Texture() { throw new Error(`abstract method call`); } getMainResultSubKernelArray3Texture() { throw new Error(`abstract method call`); } getMainResultKernelArray4Texture() { throw new Error(`abstract method call`); } getMainResultSubKernelArray4Texture() { throw new Error(`abstract method call`); } getMainResultGraphical() { throw new Error(`abstract method call`); } getMainResultMemoryOptimizedFloats() { throw new Error(`abstract method call`); } getMainResultPackedPixels() { throw new Error(`abstract method call`); } getMainResultString() { if (this.graphical) { return this.getMainResultGraphical(); } else if (this.precision === 'single') { if (this.optimizeFloatMemory) { return this.getMainResultMemoryOptimizedFloats(); } return this.getMainResultTexture(); } else { return this.getMainResultPackedPixels(); } } getMainResultNumberTexture() { return utils.linesToString(this.getMainResultKernelNumberTexture()) + utils.linesToString(this.getMainResultSubKernelNumberTexture()); } getMainResultArray2Texture() { return utils.linesToString(this.getMainResultKernelArray2Texture()) + utils.linesToString(this.getMainResultSubKernelArray2Texture()); } getMainResultArray3Texture() { return utils.linesToString(this.getMainResultKernelArray3Texture()) + utils.linesToString(this.getMainResultSubKernelArray3Texture()); } getMainResultArray4Texture() { return utils.linesToString(this.getMainResultKernelArray4Texture()) + utils.linesToString(this.getMainResultSubKernelArray4Texture()); } getReturnTextureType() { if (this.graphical) { return 'ArrayTexture(4)'; } if (this.precision === 'single') { switch (this.returnType) { case 'Float': case 'Number': case 'Integer': if (this.optimizeFloatMemory) { return 'MemoryOptimizedNumberTexture'; } else { return 'ArrayTexture(1)'; } case 'Array(2)': return 'ArrayTexture(2)'; case 'Array(3)': return 'ArrayTexture(3)'; case 'Array(4)': return 'ArrayTexture(4)'; default: throw new Error(`unsupported returnType ${this.returnType}`); } } else { switch (this.returnType) { case 'Float': case 'Number': case 'Integer': return 'NumberTexture'; case 'Array(2)': case 'Array(3)': case 'Array(4)': default: throw new Error(`unsupported returnType ${ this.returnType }`); } } } renderTexture() { return new Texture({ texture: this.outputTexture, size: this.texSize, dimensions: this.threadDim, output: this.output, context: this.context, gpu: this.gpu, type: this.getReturnTextureType(), }); } readPackedPixelsToUint8Array() { if (this.precision !== 'unsigned') throw new Error('Requires this.precision to be "unsigned"'); const { texSize, context: gl } = this; const result = new Uint8Array(texSize[0] * texSize[1] * 4); gl.readPixels(0, 0, texSize[0], texSize[1], gl.RGBA, gl.UNSIGNED_BYTE, result); return result; } readPackedPixelsToFloat32Array() { return new Float32Array(this.readPackedPixelsToUint8Array().buffer); } readFloatPixelsToFloat32Array() { if (this.precision !== 'single') throw new Error('Requires this.precision to be "single"'); const { texSize, context: gl } = this; const w = texSize[0]; const h = texSize[1]; const result = new Float32Array(w * h * 4); gl.readPixels(0, 0, w, h, gl.RGBA, gl.FLOAT, result); return result; } readMemoryOptimizedFloatPixelsToFloat32Array() { if (this.precision !== 'single') throw new Error('Requires this.precision to be "single"'); const { texSize, context: gl } = this; const w = texSize[0]; const h = texSize[1]; const result = new Float32Array(w * h * 4); gl.readPixels(0, 0, w, h, gl.RGBA, gl.FLOAT, result); return result; } renderPackedFloat() { const [xMax] = this.output; return this.readPackedPixelsToFloat32Array().subarray(0, xMax); } render2DPackedFloat() { const pixels = this.readPackedPixelsToFloat32Array(); const [xMax, yMax] = this.output; const yResults = new Array(yMax); for (let y = 0; y < yMax; y++) { const xStart = y * xMax; const xEnd = xStart + xMax; yResults[y] = pixels.subarray(xStart, xEnd); } return yResults; } render3DPackedFloat() { const pixels = this.readPackedPixelsToFloat32Array(); const [xMax, yMax, zMax] = this.output; const zResults = new Array(zMax); for (let z = 0; z < zMax; z++) { const yResults = new Array(yMax); for (let y = 0; y < yMax; y++) { const xStart = (z * yMax * xMax) + y * xMax; const xEnd = xStart + xMax; yResults[y] = pixels.subarray(xStart, xEnd); } zResults[z] = yResults; } return zResults; } renderFloat() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax] = this.output; const xResults = new Float32Array(xMax); let i = 0; for (let x = 0; x < xMax; x++) { xResults[x] = pixels[i]; i += 4; } return xResults; } renderMemoryOptimizedFloat() { const pixels = this.readMemoryOptimizedFloatPixelsToFloat32Array(); const [xMax] = this.output; return pixels.subarray(0, xMax); } render2DFloat() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax, yMax] = this.output; const yResults = new Array(yMax); let i = 0; for (let y = 0; y < yMax; y++) { const xResults = new Float32Array(xMax); for (let x = 0; x < xMax; x++) { xResults[x] = pixels[i]; i += 4; } yResults[y] = xResults; } return yResults; } renderMemoryOptimized2DFloat() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax, yMax] = this.output; const yResults = new Array(yMax); for (let y = 0; y < yMax; y++) { const offset = y * xMax; yResults[y] = pixels.subarray(offset, offset + xMax); } return yResults; } render3DFloat() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax, yMax, zMax] = this.output; const zResults = new Array(zMax); let i = 0; for (let z = 0; z < zMax; z++) { const yResults = new Array(yMax); for (let y = 0; y < yMax; y++) { const xResults = new Float32Array(xMax); for (let x = 0; x < xMax; x++) { xResults[x] = pixels[i]; i += 4; } yResults[y] = xResults; } zResults[z] = yResults; } return zResults; } renderMemoryOptimized3DFloat() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax, yMax, zMax] = this.output; const zResults = new Array(zMax); for (let z = 0; z < zMax; z++) { const yResults = new Array(yMax); for (let y = 0; y < yMax; y++) { const offset = (z * yMax * xMax) + (y * xMax); yResults[y] = pixels.subarray(offset, offset + xMax); } zResults[z] = yResults; } return zResults; } renderArray2() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax] = this.output; const xResults = new Array(xMax); const xResultsMax = xMax * 4; let i = 0; for (let x = 0; x < xResultsMax; x += 4) { xResults[i++] = pixels.subarray(x, x + 2); } return xResults; } render2DArray2() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax, yMax] = this.output; const yResults = new Array(yMax); const XResultsMax = xMax * 4; for (let y = 0; y < yMax; y++) { const xResults = new Array(xMax); const offset = y * XResultsMax; let i = 0; for (let x = 0; x < XResultsMax; x += 4) { xResults[i++] = pixels.subarray(x + offset, x + offset + 2); } yResults[y] = xResults; } return yResults; } render3DArray2() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax, yMax, zMax] = this.output; const xResultsMax = xMax * 4; const zResults = new Array(zMax); for (let z = 0; z < zMax; z++) { const yResults = new Array(yMax); for (let y = 0; y < yMax; y++) { const xResults = new Array(xMax); const offset = (z * xResultsMax * yMax) + (y * xResultsMax); let i = 0; for (let x = 0; x < xResultsMax; x += 4) { xResults[i++] = pixels.subarray(x + offset, x + offset + 2); } yResults[y] = xResults; } zResults[z] = yResults; } return zResults; } renderArray3() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax] = this.output; const xResults = new Array(xMax); const xResultsMax = xMax * 4; let i = 0; for (let x = 0; x < xResultsMax; x += 4) { xResults[i++] = pixels.subarray(x, x + 3); } return xResults; } render2DArray3() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax, yMax] = this.output; const xResultsMax = xMax * 4; const yResults = new Array(yMax); for (let y = 0; y < yMax; y++) { const xResults = new Array(xMax); const offset = y * xResultsMax; let i = 0; for (let x = 0; x < xResultsMax; x += 4) { xResults[i++] = pixels.subarray(x + offset, x + offset + 3); } yResults[y] = xResults; } return yResults; } render3DArray3() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax, yMax, zMax] = this.output; const xResultsMax = xMax * 4; const zResults = new Array(zMax); for (let z = 0; z < zMax; z++) { const yResults = new Array(yMax); for (let y = 0; y < yMax; y++) { const xResults = new Array(xMax); const offset = (z * xResultsMax * yMax) + (y * xResultsMax); let i = 0; for (let x = 0; x < xResultsMax; x += 4) { xResults[i++] = pixels.subarray(x + offset, x + offset + 3); } yResults[y] = xResults; } zResults[z] = yResults; } return zResults; } renderArray4() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax] = this.output; const xResults = new Array(xMax); const xResultsMax = xMax * 4; let i = 0; for (let x = 0; x < xResultsMax; x += 4) { xResults[i++] = pixels.subarray(x, x + 4); } return xResults; } render2DArray4() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax, yMax] = this.output; const xResultsMax = xMax * 4; const yResults = new Array(yMax); for (let y = 0; y < yMax; y++) { const xResults = new Array(xMax); const offset = y * xResultsMax; let i = 0; for (let x = 0; x < xResultsMax; x += 4) { xResults[i++] = pixels.subarray(x + offset, x + offset + 4); } yResults[y] = xResults; } return yResults; } render3DArray4() { const pixels = this.readFloatPixelsToFloat32Array(); const [xMax, yMax, zMax] = this.output; const xResultsMax = xMax * 4; const zResults = new Array(zMax); for (let z = 0; z < zMax; z++) { const yResults = new Array(yMax); for (let y = 0; y < yMax; y++) { const xResults = new Array(xMax); const offset = (z * xResultsMax * yMax) + (y * xResultsMax); let i = 0; for (let x = 0; x < xResultsMax; x += 4) { xResults[i++] = pixels.subarray(x + offset, x + offset + 4); } yResults[y] = xResults; } zResults[z] = yResults; } return zResults; } getPixels(flip) { const { context: gl, output } = this; const [width, height] = output; const pixels = new Uint8Array(width * height * 4); gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels); return flip ? pixels : utils.flipPixels(pixels, width, height); } renderKernelsToArrays() { const result = { result: this.renderOutput(), }; const type = this.getReturnTextureType(); for (let i = 0; i < this.subKernels.length; i++) { result[this.subKernels[i].property] = new Texture({ texture: this.subKernelOutputTextures[i], size: this.texSize, dimensions: this.threadDim, output: this.output, context: this.context, gpu: this.gpu, type, }).toArray(); } return result; } renderKernelsToTextures() { const result = { result: this.renderOutput(), }; const type = this.getReturnTextureType(); for (let i = 0; i < this.subKernels.length; i++) { result[this.subKernels[i].property] = new Texture({ texture: this.subKernelOutputTextures[i], size: this.texSize, dimensions: this.threadDim, output: this.output, context: this.context, gpu: this.gpu, type, }); } return result; } setOutput(output) { super.setOutput(output); if (this.program) { this.threadDim = [this.output[0], this.output[1] || 1, this.output[2] || 1]; this.texSize = utils.dimToTexSize({ floatTextures: this.optimizeFloatMemory, floatOutput: this.precision === 'single', }, this.threadDim, true); const { context: gl } = this; gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); this.updateMaxTexSize(); this.framebuffer.width = this.texSize[0]; this.framebuffer.height = this.texSize[1]; this.context.viewport(0, 0, this.maxTexSize[0], this.maxTexSize[1]); this.canvas.width = this.maxTexSize[0]; this.canvas.height = this.maxTexSize[1]; this._setupOutputTexture(); if (this.subKernels && this.subKernels.length > 0) { this._setupSubOutputTextures(); } } return this; } } const renderStrategy = Object.freeze({ PackedPixelToUint8Array: Symbol('PackedPixelToUint8Array'), PackedPixelToFloat: Symbol('PackedPixelToFloat'), PackedPixelTo2DFloat: Symbol('PackedPixelTo2DFloat'), PackedPixelTo3DFloat: Symbol('PackedPixelTo3DFloat'), PackedTexture: Symbol('PackedTexture'), FloatPixelToFloat32Array: Symbol('FloatPixelToFloat32Array'), FloatPixelToFloat: Symbol('FloatPixelToFloat'), FloatPixelTo2DFloat: Symbol('FloatPixelTo2DFloat'), FloatPixelTo3DFloat: Symbol('FloatPixelTo3DFloat'), FloatPixelToArray2: Symbol('FloatPixelToArray2'), FloatPixelTo2DArray2: Symbol('FloatPixelTo2DArray2'), FloatPixelTo3DArray2: Symbol('FloatPixelTo3DArray2'), FloatPixelToArray3: Symbol('FloatPixelToArray3'), FloatPixelTo2DArray3: Symbol('FloatPixelTo2DArray3'), FloatPixelTo3DArray3: Symbol('FloatPixelTo3DArray3'), FloatPixelToArray4: Symbol('FloatPixelToArray4'), FloatPixelTo2DArray4: Symbol('FloatPixelTo2DArray4'), FloatPixelTo3DArray4: Symbol('FloatPixelTo3DArray4'), FloatTexture: Symbol('FloatTexture'), MemoryOptimizedFloatPixelToMemoryOptimizedFloat: Symbol('MemoryOptimizedFloatPixelToFloat'), MemoryOptimizedFloatPixelToMemoryOptimized2DFloat: Symbol('MemoryOptimizedFloatPixelTo2DFloat'), MemoryOptimizedFloatPixelToMemoryOptimized3DFloat: Symbol('MemoryOptimizedFloatPixelTo3DFloat'), }); const typeMap = { int: 'Integer', float: 'Number', vec2: 'Array(2)', vec3: 'Array(3)', vec4: 'Array(4)', }; module.exports = { GLKernel, renderStrategy }; },{"../../texture":69,"../../utils":70,"../kernel":15}],13:[function(require,module,exports){ const getContext = require('gl'); const { WebGLKernel } = require('../web-gl/kernel'); const { glKernelString } = require('../gl/kernel-string'); let isSupported = null; let testCanvas = null; let testContext = null; let testExtensions = null; let features = null; class HeadlessGLKernel extends WebGLKernel { static get isSupported() { if (isSupported !== null) return isSupported; this.setupFeatureChecks(); isSupported = testContext !== null; return isSupported; } static setupFeatureChecks() { testCanvas = null; testExtensions = null; if (typeof getContext !== 'function') return; try { testContext = getContext(2, 2, { preserveDrawingBuffer: true }); if (!testContext || !testContext.getExtension) return; testExtensions = { STACKGL_resize_drawingbuffer: testContext.getExtension('STACKGL_resize_drawingbuffer'), STACKGL_destroy_context: testContext.getExtension('STACKGL_destroy_context'), OES_texture_float: testContext.getExtension('OES_texture_float'), OES_texture_float_linear: testContext.getExtension('OES_texture_float_linear'), OES_element_index_uint: testContext.getExtension('OES_element_index_uint'), WEBGL_draw_buffers: testContext.getExtension('WEBGL_draw_buffers'), }; features = this.getFeatures(); } catch (e) {} } static isContextMatch(context) { try { return context.getParameter(context.RENDERER) === 'ANGLE'; } catch (e) { return false; } } static getFeatures() { const isDrawBuffers = this.getIsDrawBuffers(); return Object.freeze({ isFloatRead: this.getIsFloatRead(), isIntegerDivisionAccurate: this.getIsIntegerDivisionAccurate(), isTextureFloat: this.getIsTextureFloat(), isDrawBuffers, kernelMap: isDrawBuffers }); } static getIsTextureFloat() { return Boolean(testExtensions.OES_texture_float); } static getIsDrawBuffers() { return Boolean(testExtensions.WEBGL_draw_buffers); } static get testCanvas() { return testCanvas; } static get testContext() { return testContext; } static get features() { return features; } initCanvas() { return {}; } initContext() { const context = getContext(2, 2, { preserveDrawingBuffer: true }); return context; } initExtensions() { this.extensions = { STACKGL_resize_drawingbuffer: this.context.getExtension('STACKGL_resize_drawingbuffer'), STACKGL_destroy_context: this.context.getExtension('STACKGL_destroy_context'), OES_texture_float: this.context.getExtension('OES_texture_float'), OES_texture_float_linear: this.context.getExtension('OES_texture_float_linear'), OES_element_index_uint: this.context.getExtension('OES_element_index_uint'), WEBGL_draw_buffers: this.context.getExtension('WEBGL_draw_buffers'), }; } destroyExtensions() { this.extensions.STACKGL_resize_drawingbuffer = null; this.extensions.STACKGL_destroy_context = null; this.extensions.OES_texture_float = null; this.extensions.OES_texture_float_linear = null; this.extensions.OES_element_index_uint = null; this.extensions.WEBGL_draw_buffers = null; } static destroyContext(context) { const extension = context.getExtension('STACKGL_destroy_context'); if (extension && extension.destroy) { extension.destroy(); } } toString() { const setupContextString = `const gl = context || require('gl')(1, 1);\n`; const destroyContextString = `if (!context) { gl.getExtension('STACKGL_destroy_context').destroy(); }\n`; return glKernelString(this.constructor, arguments, this, setupContextString, destroyContextString); } setOutput(output) { super.setOutput(output); if (this.graphical) { const { context: gl } = this; const [width, height] = this.output; (this.extensions.STACKGL_resize_drawingbuffer || gl.getExtension('STACKGL_resize_drawingbuffer')).resize(width, height); } } } module.exports = { HeadlessGLKernel }; },{"../gl/kernel-string":11,"../web-gl/kernel":37,"gl":3}],14:[function(require,module,exports){ const { utils } = require('../utils'); class KernelValue { constructor(value, settings) { const { name, kernel, context, onRequestContextHandle, onUpdateValueMismatch, origin, strictIntegers, } = settings; if (!name) { throw new Error('name not set'); } if (!origin) { throw new Error('origin not set'); } if (origin !== 'user' && origin !== 'constants') { throw new Error(`origin must be "user" or "constants" value is "${ origin }"`); } if (!onRequestContextHandle) { throw new Error('onRequestContextHandle is not set'); } this.name = name; this.origin = origin; this.id = `${this.origin}_${name}`; this.kernel = kernel; this.strictIntegers = strictIntegers; this.type = utils.getVariableType(value, strictIntegers); this.size = value.size || null; this.index = null; this.context = context; this.contextHandle = null; this.onRequestContextHandle = onRequestContextHandle; this.onUpdateValueMismatch = onUpdateValueMismatch; } getSource() { throw new Error(`"getSource" not defined on ${ this.constructor.name }`); } updateValue(value) { throw new Error(`"updateValue" not defined on ${ this.constructor.name }`); } } module.exports = { KernelValue }; },{"../utils":70}],15:[function(require,module,exports){ const { utils } = require('../utils'); const { Input } = require('../input'); class Kernel { static get isSupported() { throw new Error(`"isSupported" not implemented on ${ this.name }`); } static isContextMatch(context) { throw new Error(`"isContextMatch" not implemented on ${ this.name }`); } static getFeatures() { throw new Error(`"getFeatures" not implemented on ${ this.name }`); } static destroyContext(context) { throw new Error(`"destroyContext" called on ${ this.name }`); } static nativeFunctionArguments() { throw new Error(`"nativeFunctionArguments" called on ${ this.name }`); } static nativeFunctionReturnType() { throw new Error(`"nativeFunctionReturnType" called on ${ this.name }`); } static combineKernels() { throw new Error(`"combineKernels" called on ${ this.name }`); } constructor(source, settings) { if (typeof source !== 'object') { if (typeof source !== 'string') { throw new Error('source not a string'); } if (!utils.isFunctionString(source)) { throw new Error('source not a function string'); } } this.onRequestFallback = null; this.argumentNames = typeof source === 'string' ? utils.getArgumentNamesFromString(source) : null; this.argumentTypes = null; this.argumentSizes = null; this.argumentBitRatios = null; this.kernelArguments = null; this.kernelConstants = null; this.source = source; this.output = null; this.debug = false; this.graphical = false; this.loopMaxIterations = 0; this.constants = null; this.constantTypes = null; this.constantBitRatios = null; this.dynamicArguments = false; this.dynamicOutput = true; this.canvas = null; this.context = null; this.gpu = null; this.functions = null; this.nativeFunctions = null; this.subKernels = null; this.validate = true; this.immutable = false; this.pipeline = false; this.precision = null; this.plugins = null; this.returnType = null; this.leadingReturnStatement = null; this.followingReturnStatement = null; this.optimizeFloatMemory = null; this.strictIntegers = false; } mergeSettings(settings) { for (let p in settings) { if (!settings.hasOwnProperty(p) || !this.hasOwnProperty(p)) continue; switch (p) { case 'output': if (!Array.isArray(settings.output)) { this.setOutput(settings.output); continue; } break; case 'functions': if (typeof settings.functions[0] === 'function') { this.functions = settings.functions.map(source => utils.functionToIFunction(source)); continue; } break; case 'graphical': if (settings[p] && !settings.hasOwnProperty('precision')) { this.precision = 'unsigned'; } this[p] = settings[p]; continue; } this[p] = settings[p]; } if (!this.canvas) this.canvas = this.initCanvas(); if (!this.context) this.context = this.initContext(); if (!this.plugins) this.plugins = this.initPlugins(settings); } build() { throw new Error(`"build" not defined on ${ this.constructor.name }`); } run() { throw new Error(`"run" not defined on ${ this.constructor.name }`) } initCanvas() { throw new Error(`"initCanvas" not defined on ${ this.constructor.name }`); } initContext() { throw new Error(`"initContext" not defined on ${ this.constructor.name }`); } initPlugins(settings) { throw new Error(`"initPlugins" not defined on ${ this.constructor.name }`); } setupArguments(args) { if (!this.argumentTypes) { this.kernelArguments = []; this.argumentTypes = []; for (let i = 0; i < args.length; i++) { const argType = utils.getVariableType(args[i], this.strictIntegers); this.argumentTypes.push(argType === 'Integer' ? 'Number' : argType); } } this.argumentSizes = new Array(args.length); this.argumentBitRatios = new Int32Array(args.length); for (let i = 0; i < args.length; i++) { const arg = args[i]; this.argumentSizes[i] = arg.constructor === Input ? arg.size : null; this.argumentBitRatios[i] = this.getBitRatio(arg); } if (this.argumentNames.length !== args.length) { throw new Error(`arguments are miss-aligned`); } } setupConstants() { this.kernelConstants = []; this.constantTypes = {}; this.constantBitRatios = {}; if (this.constants) { for (let p in this.constants) { this.constantTypes[p] = utils.getVariableType(this.constants[p], this.strictIntegers); this.constantBitRatios[p] = this.getBitRatio(this.constants[p]); } } } setOptimizeFloatMemory(flag) { this.optimizeFloatMemory = flag; return this; } setOutput(output) { if (output.hasOwnProperty('x')) { if (output.hasOwnProperty('y')) { if (output.hasOwnProperty('z')) { this.output = [output.x, output.y, output.z]; } else { this.output = [output.x, output.y]; } } else { this.output = [output.x]; } } else { this.output = output; } return this; } setDebug(flag) { this.debug = flag; return this; } setGraphical(flag) { this.graphical = flag; this.precision = 'unsigned'; return this; } setLoopMaxIterations(max) { this.loopMaxIterations = max; return this; } setConstants(constants) { this.constants = constants; return this; } setFunctions(functions) { if (typeof functions[0] === 'function') { this.functions = functions.map(source => utils.functionToIFunction(source)); } else { this.functions = functions; } return this; } setPipeline(flag) { this.pipeline = flag; return this; } setPrecision(flag) { this.precision = flag; return this; } setOutputToTexture(flag) { utils.warnDeprecated('method', 'setOutputToTexture', 'setPipeline'); this.pipeline = flag; return this; } setImmutable(flag) { this.immutable = flag; return this; } setCanvas(canvas) { this.canvas = canvas; return this; } setStrictIntegers(flag) { this.strictIntegers = flag; return this; } setDynamicOutput(flag) { this.dynamicOutput = flag; return this; } setHardcodeConstants(flag) { utils.warnDeprecated('method', 'setHardcodeConstants'); this.setDynamicOutput(flag); this.setDynamicArguments(flag); return this; } setDynamicArguments(flag) { this.dynamicArguments = flag; return this; } getCanvas() { utils.warnDeprecated('method', 'getCanvas'); return this.canvas; } getWebGl() { utils.warnDeprecated('method', 'getWebGl'); return this.context; } setContext(context) { this.context = context; return this; } setArgumentTypes(argumentTypes) { this.argumentTypes = argumentTypes; return this; } requestFallback(args) { if (!this.onRequestFallback) { throw new Error(`"onRequestFallback" not defined on ${ this.constructor.name }`); } return this.onRequestFallback(args); } validateSettings() { throw new Error(`"validateSettings" not defined on ${ this.constructor.name }`); } addSubKernel(subKernel) { if (this.subKernels === null) { this.subKernels = []; } if (!subKernel.source) throw new Error('subKernel missing "source" property'); if (!subKernel.property && isNaN(subKernel.property)) throw new Error('subKernel missing "property" property'); if (!subKernel.name) throw new Error('subKernel missing "name" property'); this.subKernels.push(subKernel); return this; } destroy(removeCanvasReferences) { throw new Error(`"destroy" called on ${ this.constructor.name }`); } getBitRatio(value) { if (this.precision === 'single') { return 4; } else if (Array.isArray(value[0])) { return this.getBitRatio(value[0]); } else if (value.constructor === Input) { return this.getBitRatio(value.value); } switch (value.constructor) { case Uint8Array: case Int8Array: return 1; case Uint16Array: case Int16Array: return 2; case Float32Array: case Int32Array: default: return 4; } } getPixels() { throw new Error(`"getPixels" called on ${ this.constructor.name }`); } checkOutput() { if (!this.output || !utils.isArray(this.output)) throw new Error('kernel.output not an array'); if (this.output.length < 1) throw new Error('kernel.output is empty, needs at least 1 value'); for (let i = 0; i < this.output.length; i++) { if (isNaN(this.output[i]) || this.output[i] < 1) { throw new Error(`${ this.constructor.name }.output[${ i }] incorrectly defined as \`${ this.output[i] }\`, needs to be numeric, and greater than 0`); } } } toJSON() { const settings = { output: this.output, threadDim: this.threadDim, pipeline: this.pipeline, argumentNames: this.argumentNames, argumentsTypes: this.argumentTypes, constants: this.constants, pluginNames: this.plugins ? this.plugins.map(plugin => plugin.name) : null, returnType: this.returnType, }; return { settings }; } } module.exports = { Kernel }; },{"../input":66,"../utils":70}],16:[function(require,module,exports){ const fragmentShader = `__HEADER__; precision highp float; precision highp int; precision highp sampler2D; const int LOOP_MAX = __LOOP_MAX__; __PLUGINS__; __CONSTANTS__; varying vec2 vTexCoord; vec4 round(vec4 x) { return floor(x + 0.5); } float round(float x) { return floor(x + 0.5); } vec2 integerMod(vec2 x, float y) { vec2 res = floor(mod(x, y)); return res * step(1.0 - floor(y), -res); } vec3 integerMod(vec3 x, float y) { vec3 res = floor(mod(x, y)); return res * step(1.0 - floor(y), -res); } vec4 integerMod(vec4 x, vec4 y) { vec4 res = floor(mod(x, y)); return res * step(1.0 - floor(y), -res); } float integerMod(float x, float y) { float res = floor(mod(x, y)); return res * (res > floor(y) - 1.0 ? 0.0 : 1.0); } int integerMod(int x, int y) { return x - (y * int(x / y)); } __DIVIDE_WITH_INTEGER_CHECK__; // Here be dragons! // DO NOT OPTIMIZE THIS CODE // YOU WILL BREAK SOMETHING ON SOMEBODY\'S MACHINE // LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME const vec2 MAGIC_VEC = vec2(1.0, -256.0); const vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0); const vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536 float decode32(vec4 texel) { __DECODE32_ENDIANNESS__; texel *= 255.0; vec2 gte128; gte128.x = texel.b >= 128.0 ? 1.0 : 0.0; gte128.y = texel.a >= 128.0 ? 1.0 : 0.0; float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC); float res = exp2(round(exponent)); texel.b = texel.b - 128.0 * gte128.x; res = dot(texel, SCALE_FACTOR) * exp2(round(exponent-23.0)) + res; res *= gte128.y * -2.0 + 1.0; return res; } float decode16(vec4 texel, int index) { int channel = integerMod(index, 2); if (channel == 0) return texel.r * 255.0 + texel.g * 65280.0; if (channel == 1) return texel.b * 255.0 + texel.a * 65280.0; return 0.0; } float decode8(vec4 texel, int index) { int channel = integerMod(index, 4); if (channel == 0) return texel.r * 255.0; if (channel == 1) return texel.g * 255.0; if (channel == 2) return texel.b * 255.0; if (channel == 3) return texel.a * 255.0; return 0.0; } vec4 encode32(float f) { float F = abs(f); float sign = f < 0.0 ? 1.0 : 0.0; float exponent = floor(log2(F)); float mantissa = (exp2(-exponent) * F); // exponent += floor(log2(mantissa)); vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV; texel.rg = integerMod(texel.rg, 256.0); texel.b = integerMod(texel.b, 128.0); texel.a = exponent*0.5 + 63.5; texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0; texel = floor(texel); texel *= 0.003921569; // 1/255 __ENCODE32_ENDIANNESS__; return texel; } // Dragons end here int index; ivec3 threadId; ivec3 indexTo3D(int idx, ivec3 texDim) { int z = int(idx / (texDim.x * texDim.y)); idx -= z * int(texDim.x * texDim.y); int y = int(idx / texDim.x); int x = int(integerMod(idx, texDim.x)); return ivec3(x, y, z); } float get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { ivec3 xyz = ivec3(x, y, z); int index = xyz.x + texDim.x * (xyz.y + texDim.y * xyz.z); int w = texSize.x; vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; vec4 texel = texture2D(tex, st / vec2(texSize)); return decode32(texel); } float get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { ivec3 xyz = ivec3(x, y, z); int index = xyz.x + texDim.x * (xyz.y + texDim.y * xyz.z); int w = texSize.x * 2; vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; vec4 texel = texture2D(tex, st / vec2(texSize.x * 2, texSize.y)); return decode16(texel, index); } float get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { ivec3 xyz = ivec3(x, y, z); int index = xyz.x + texDim.x * (xyz.y + texDim.y * xyz.z); int w = texSize.x * 4; vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; vec4 texel = texture2D(tex, st / vec2(texSize.x * 4, texSize.y)); return decode8(texel, index); } float getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { ivec3 xyz = ivec3(x, y, z); int index = xyz.x + texDim.x * (xyz.y + texDim.y * xyz.z); int channel = integerMod(index, 4); index = index / 4; int w = texSize.x; vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; vec4 texel = texture2D(tex, st / vec2(texSize)); if (channel == 0) return texel.r; if (channel == 1) return texel.g; if (channel == 2) return texel.b; if (channel == 3) return texel.a; return 0.0; } vec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { ivec3 xyz = ivec3(x, y, z); int index = xyz.x + texDim.x * (xyz.y + texDim.y * xyz.z); int w = texSize.x; vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; return texture2D(tex, st / vec2(texSize)); } float getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { vec4 result = getImage2D(tex, texSize, texDim, z, y, x); return result[0]; } vec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { vec4 result = getImage2D(tex, texSize, texDim, z, y, x); return vec2(result[0], result[1]); } vec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { vec4 result = getImage2D(tex, texSize, texDim, z, y, x); return vec3(result[0], result[1], result[2]); } vec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { return getImage2D(tex, texSize, texDim, z, y, x); } vec4 actualColor; void color(float r, float g, float b, float a) { actualColor = vec4(r,g,b,a); } void color(float r, float g, float b) { color(r,g,b,1.0); } void color(sampler2D image) { actualColor = texture2D(image, vTexCoord); } __MAIN_CONSTANTS__; __MAIN_ARGUMENTS__; __KERNEL__; void main(void) { index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x; __MAIN_RESULT__; }`; module.exports = { fragmentShader }; },{}],17:[function(require,module,exports){ const { FunctionNode } = require('../function-node'); const jsMathPrefix = 'Math.'; const localPrefix = 'this.'; class WebGLFunctionNode extends FunctionNode { constructor(source, settings) { super(source, settings); this.fixIntegerDivisionAccuracy = null; if (settings && settings.hasOwnProperty('fixIntegerDivisionAccuracy')) { this.fixIntegerDivisionAccuracy = settings.fixIntegerDivisionAccuracy; } } astFunctionExpression(ast, retArr) { if (this.isRootKernel) { retArr.push('void'); } else { if (!this.returnType) { const lastReturn = this.findLastReturn(); if (lastReturn) { this.returnType = this.getType(ast.body); if (this.returnType === 'LiteralInteger') { this.returnType = 'Number'; } } } const { returnType } = this; if (!returnType) { retArr.push('void'); } else { const type = typeMap[returnType]; if (!type) { throw new Error(`unknown type ${returnType}`); } retArr.push(type); } } retArr.push(' '); retArr.push(this.name); retArr.push('('); if (!this.isRootKernel) { for (let i = 0; i < this.argumentNames.length; ++i) { const argumentName = this.argumentNames[i]; if (i > 0) { retArr.push(', '); } let argumentType = this.getVariableType(argumentName); if (!argumentType || argumentType === 'LiteralInteger') { argumentType = 'Number'; } const type = typeMap[argumentType]; if (!type) { throw this.astErrorOutput('Unexpected expression', ast); } retArr.push(type); retArr.push(' '); retArr.push('user_'); retArr.push(argumentName); } } retArr.push(') {\n'); for (let i = 0; i < ast.body.body.length; ++i) { this.astGeneric(ast.body.body[i], retArr); retArr.push('\n'); } retArr.push('}\n'); return retArr; } astReturnStatement(ast, retArr) { if (!ast.argument) throw this.astErrorOutput('Unexpected return statement', ast); const type = this.getType(ast.argument); const result = []; if (!this.returnType) { if (this.isRootKernel) { this.returnType = 'Number'; } else { this.returnType = type; } } switch (this.returnType) { case 'LiteralInteger': case 'Number': case 'Float': switch (type) { case 'Integer': result.push('float('); this.astGeneric(ast.argument, result); result.push(')'); break; case 'LiteralInteger': this.pushState('casting-to-float'); this.astGeneric(ast.argument, result); this.popState('casting-to-float'); if (this.getType(ast) === 'Integer') { result.unshift('float('); result.push(')'); } break; default: this.astGeneric(ast.argument, result); } break; case 'Integer': switch (type) { case 'Float': case 'Number': this.pushState('casting-to-integer'); result.push('int('); this.astGeneric(ast.argument, result); result.push(')'); this.popState('casting-to-integer'); break; case 'LiteralInteger': this.pushState('casting-to-integer'); this.astGeneric(ast.argument, result); this.popState('casting-to-integer'); break; default: this.astGeneric(ast.argument, result); } break; case 'Array(4)': case 'Array(3)': case 'Array(2)': case 'Input': this.astGeneric(ast.argument, result); break; default: throw this.astErrorOutput(`unhandled return type ${this.returnType}`, ast); } if (this.isRootKernel) { retArr.push(`kernelResult = ${ result.join('') };`); retArr.push('return;'); } else if (this.isSubKernel) { retArr.push(`subKernelResult_${ this.name } = ${ result.join('') };`); retArr.push(`return subKernelResult_${ this.name };`); } else { retArr.push(`return ${ result.join('') };`); } return retArr; } astLiteral(ast, retArr) { if (isNaN(ast.value)) { throw this.astErrorOutput( 'Non-numeric literal not supported : ' + ast.value, ast ); } if (Number.isInteger(ast.value)) { if (this.isState('in-for-loop-init') || this.isState('casting-to-integer')) { this.literalTypes[`${ast.start},${ast.end}`] = 'Integer'; retArr.push(`${ast.value}`); } else if (this.isState('casting-to-float')) { this.literalTypes[`${ast.start},${ast.end}`] = 'Number'; retArr.push(`${ast.value}.0`); } else { this.literalTypes[`${ast.start},${ast.end}`] = 'Number'; retArr.push(`${ast.value}.0`); } } else if (this.isState('casting-to-integer')) { this.literalTypes[`${ast.start},${ast.end}`] = 'Integer'; retArr.push(parseInt(ast.raw)); } else { this.literalTypes[`${ast.start},${ast.end}`] = 'Number'; retArr.push(`${ast.value}`); } return retArr; } astBinaryExpression(ast, retArr) { if (ast.operator === '%') { retArr.push('mod('); const leftType = this.getType(ast.left); if (leftType === 'Integer') { retArr.push('float('); this.astGeneric(ast.left, retArr); retArr.push(')'); } else if (leftType === 'LiteralInteger') { this.pushState('casting-to-float'); this.astGeneric(ast.left, retArr); this.popState('casting-to-float'); } else { this.astGeneric(ast.left, retArr); } retArr.push(','); const rightType = this.getType(ast.right); if (rightType === 'Integer') { retArr.push('float('); this.astGeneric(ast.right, retArr); retArr.push(')'); } else if (rightType === 'LiteralInteger') { this.pushState('casting-to-float'); this.astGeneric(ast.right, retArr); this.popState('casting-to-float'); } else { this.astGeneric(ast.right, retArr); } retArr.push(')'); return retArr; } if (ast.operator === '**') { retArr.push('pow('); const leftType = this.getType(ast.left); if (leftType === 'Integer') { retArr.push('float('); this.astGeneric(ast.left, retArr); retArr.push(')'); } else if (leftType === 'LiteralInteger') { this.pushState('casting-to-float'); this.astGeneric(ast.left, retArr); this.popState('casting-to-float'); } else { this.astGeneric(ast.left, retArr); } retArr.push(','); const rightType = this.getType(ast.right); if (rightType === 'Integer') { retArr.push('float('); this.astGeneric(ast.right, retArr); retArr.push(')'); } else if (rightType === 'LiteralInteger') { this.pushState('casting-to-float'); this.astGeneric(ast.right, retArr); this.popState('casting-to-float'); } else { this.astGeneric(ast.right, retArr); } retArr.push(')'); return retArr; } retArr.push('('); if (this.fixIntegerDivisionAccuracy && ast.operator === '/') { retArr.push('div_with_int_check('); switch (this.getType(ast.left)) { case 'Integer': retArr.push('float('); this.pushState('casting-to-float'); this.astGeneric(ast.left, retArr); this.popState('casting-to-float'); retArr.push(')'); break; case 'LiteralInteger': this.pushState('casting-to-float'); this.astGeneric(ast.left, retArr); this.popState('casting-to-float'); break; default: this.astGeneric(ast.left, retArr); } retArr.push(', '); switch (this.getType(ast.right)) { case 'Integer': retArr.push('float('); this.pushState('casting-to-float'); this.astGeneric(ast.right, retArr); this.popState('casting-to-float'); retArr.push(')'); break; case 'LiteralInteger': this.pushState('casting-to-float'); this.astGeneric(ast.right, retArr); this.popState('casting-to-float'); break; default: this.astGeneric(ast.right, retArr); } retArr.push(')'); } else { const leftType = this.getType(ast.left) || 'Number'; const rightType = this.getType(ast.right) || 'Number'; if (!leftType || !rightType) { throw this.astErrorOutput(`Unhandled binary expression`, ast); } const key = leftType + ' & ' + rightType; switch (key) { case 'Integer & Integer': this.astGeneric(ast.left, retArr); retArr.push(operatorMap[ast.operator] || ast.operator); this.astGeneric(ast.right, retArr); break; case 'Number & Float': case 'Float & Number': case 'Float & Float': case 'Number & Number': this.astGeneric(ast.left, retArr); retArr.push(operatorMap[ast.operator] || ast.operator); this.astGeneric(ast.right, retArr); break; case 'LiteralInteger & LiteralInteger': this.pushState('casting-to-float'); this.astGeneric(ast.left, retArr); retArr.push(operatorMap[ast.operator] || ast.operator); this.astGeneric(ast.right, retArr); this.popState('casting-to-float'); break; case 'Integer & Float': case 'Integer & Number': if (ast.operator === '>' || ast.operator === '<' && ast.right.type === 'Literal') { if (!Number.isInteger(ast.right.value)) { this.pushState('casting-to-float'); retArr.push('float('); this.astGeneric(ast.left, retArr); retArr.push(')'); this.popState('casting-to-float'); retArr.push(operatorMap[ast.operator] || ast.operator); this.astGeneric(ast.right, retArr); break; } } this.astGeneric(ast.left, retArr); retArr.push(operatorMap[ast.operator] || ast.operator); this.pushState('casting-to-integer'); if (ast.right.type === 'Literal') { const literalResult = []; this.astGeneric(ast.right, literalResult); const literalType = this.getType(ast.right); if (literalType === 'Integer') { retArr.push(literalResult.join('')); } else { throw this.astErrorOutput(`Unhandled binary expression with literal`, ast); } } else { retArr.push('int('); this.astGeneric(ast.right, retArr); retArr.push(')'); } this.popState('casting-to-integer'); break; case 'Integer & LiteralInteger': this.astGeneric(ast.left, retArr); retArr.push(operatorMap[ast.operator] || ast.operator); this.pushState('casting-to-integer'); this.astGeneric(ast.right, retArr); this.popState('casting-to-integer'); break; case 'Number & Integer': this.astGeneric(ast.left, retArr); retArr.push(operatorMap[ast.operator] || ast.operator); this.pushState('casting-to-float'); retArr.push('float('); this.astGeneric(ast.right, retArr); retArr.push(')'); this.popState('casting-to-float'); break; case 'Float & LiteralInteger': case 'Number & LiteralInteger': if (this.isState('in-for-loop-test')) { retArr.push('int('); this.astGeneric(ast.left, retArr); retArr.push(')'); retArr.push(operatorMap[ast.operator] || ast.operator); this.pushState('casting-to-integer'); this.astGeneric(ast.right, retArr); this.popState('casting-to-integer'); } else { this.astGeneric(ast.left, retArr); retArr.push(operatorMap[ast.operator] || ast.operator); this.pushState('casting-to-float'); this.astGeneric(ast.right, retArr); this.popState('casting-to-float'); } break; case 'LiteralInteger & Float': case 'LiteralInteger & Number': if (this.isState('in-for-loop-test') || this.isState('in-for-loop-init') || this.isState('casting-to-integer')) { this.pushState('casting-to-integer'); this.astGeneric(ast.left, retArr); retArr.push(operatorMap[ast.operator] || ast.operator); retArr.push('int('); this.astGeneric(ast.right, retArr); retArr.push(')'); this.popState('casting-to-integer'); } else { this.astGeneric(ast.left, retArr); retArr.push(operatorMap[ast.operator] || ast.operator); this.pushState('casting-to-float'); this.astGeneric(ast.right, retArr); this.popState('casting-to-float'); } break; case 'LiteralInteger & Integer': this.pushState('casting-to-integer'); this.astGeneric(ast.left, retArr); this.popState('casting-to-integer'); retArr.push(operatorMap[ast.operator] || ast.operator); this.astGeneric(ast.right, retArr); break; case 'Boolean & Boolean': this.astGeneric(ast.left, retArr); retArr.push(operatorMap[ast.operator] || ast.operator); this.astGeneric(ast.right, retArr); break; case 'Float & Integer': this.astGeneric(ast.left, retArr); retArr.push(operatorMap[ast.operator] || ast.operator); this.pushState('casting-to-integer'); retArr.push('float('); this.astGeneric(ast.right, retArr); retArr.push(')'); this.popState('casting-to-integer'); break; default: throw this.astErrorOutput(`Unhandled binary expression between ${key}`, ast); } } retArr.push(')'); return retArr; } astIdentifierExpression(idtNode, retArr) { if (idtNode.type !== 'Identifier') { throw this.astErrorOutput('IdentifierExpression - not an Identifier', idtNode); } const type = this.getType(idtNode); if (idtNode.name === 'Infinity') { retArr.push('3.402823466e+38'); } else if (type === 'Boolean') { if (this.argumentNames.indexOf(idtNode.name) > -1) { retArr.push(`bool(user_${idtNode.name})`); } else { retArr.push(`user_${idtNode.name}`); } } else { const userArgumentName = this.getKernelArgumentName(idtNode.name); if (userArgumentName) { retArr.push(`user_${userArgumentName}`); } else { retArr.push(`user_${idtNode.name}`); } } return retArr; } astForStatement(forNode, retArr) { if (forNode.type !== 'ForStatement') { throw this.astErrorOutput('Invalid for statement', forNode); } const initArr = []; const testArr = []; const updateArr = []; const bodyArr = []; let isSafe = null; if (forNode.init) { this.pushState('in-for-loop-init'); this.astGeneric(forNode.init, initArr); for (let i = 0; i < initArr.length; i++) { if (initArr[i].includes && initArr[i].includes(',')) { isSafe = false; } } this.popState('in-for-loop-init'); } else { isSafe = false; } if (forNode.test) { this.pushState('in-for-loop-test'); this.astGeneric(forNode.test, testArr); this.popState('in-for-loop-test'); } else { isSafe = false; } if (forNode.update) { this.astGeneric(forNode.update, updateArr); } else { isSafe = false; } if (forNode.body) { this.pushState('loop-body'); this.astGeneric(forNode.body, bodyArr); this.popState('loop-body'); } if (isSafe === null) { isSafe = this.isSafe(forNode.init) && this.isSafe(forNode.test); } if (isSafe) { retArr.push(`for (${initArr.join('')};${testArr.join('')};${updateArr.join('')}){\n`); retArr.push(bodyArr.join('')); retArr.push('}\n'); } else { const iVariableName = this.getInternalVariableName('safeI'); if (initArr.length > 0) { retArr.push(initArr.join(''), ';\n'); } retArr.push(`for (int ${iVariableName}=0;${iVariableName} 0) { retArr.push(`if (!${testArr.join('')}) break;\n`); } retArr.push(bodyArr.join('')); retArr.push(`\n${updateArr.join('')};`); retArr.push('}\n'); } return retArr; } astWhileStatement(whileNode, retArr) { if (whileNode.type !== 'WhileStatement') { throw this.astErrorOutput('Invalid while statement', whileNode); } const iVariableName = this.getInternalVariableName('safeI'); retArr.push(`for (int ${iVariableName}=0;${iVariableName} 0) { for (let i = 0; i < this.plugins.length; i++) { const plugin = this.plugins[i]; if (plugin.functionMatch === 'Math.random()' && plugin.functionReplace) { retArr.push(plugin.functionReplace); return retArr; } } } if (this.onFunctionCall) { this.onFunctionCall(this.name, functionName); } retArr.push(functionName); retArr.push('('); if (isMathFunction) { for (let i = 0; i < ast.arguments.length; ++i) { const argument = ast.arguments[i]; const argumentType = this.getType(argument); if (i > 0) { retArr.push(', '); } switch (argumentType) { case 'Integer': this.pushState('casting-to-float'); retArr.push('float('); this.astGeneric(argument, retArr); retArr.push(')'); this.popState('casting-to-float'); break; default: this.astGeneric(argument, retArr); break; } } } else { const targetTypes = this.lookupFunctionArgumentTypes(functionName) || []; for (let i = 0; i < ast.arguments.length; ++i) { const argument = ast.arguments[i]; let targetType = targetTypes[i]; if (i > 0) { retArr.push(', '); } const argumentType = this.getType(argument); if (!targetType) { this.triggerImplyArgumentType(functionName, i, argumentType, this); targetType = argumentType; } switch (argumentType) { case 'Number': case 'Float': if (targetType === 'Integer') { retArr.push('int('); this.astGeneric(argument, retArr); retArr.push(')'); continue; } else if (targetType === 'Number' || targetType === 'Float') { this.astGeneric(argument, retArr); continue; } else if (targetType === 'LiteralInteger') { this.pushState('casting-to-float'); this.astGeneric(argument, retArr); this.popState('casting-to-float'); continue; } break; case 'Integer': if (targetType === 'Number' || targetType === 'Float') { retArr.push('float('); this.astGeneric(argument, retArr); retArr.push(')'); continue; } else if (targetType === 'Integer') { this.astGeneric(argument, retArr); continue; } break; case 'LiteralInteger': if (targetType === 'Integer') { this.pushState('casting-to-integer'); this.astGeneric(argument, retArr); this.popState('casting-to-integer'); continue; } else if (targetType === 'Number' || targetType === 'Float') { this.pushState('casting-to-float'); this.astGeneric(argument, retArr); this.popState('casting-to-float'); continue; } else if (targetType === 'LiteralInteger') { this.astGeneric(argument, retArr); continue; } break; case 'Array(2)': case 'Array(3)': case 'Array(4)': if (targetType === argumentType) { this.astGeneric(argument, retArr); continue; } break; case 'Array': case 'Input': if (targetType === argumentType) { this.triggerTrackArgumentSynonym(this.name, argument.name, functionName, i); this.astGeneric(argument, retArr); continue; } break; } throw this.astErrorOutput(`Unhandled argument combination of ${ argumentType } and ${ targetType }`, ast); } } retArr.push(')'); return retArr; } astArrayExpression(arrNode, retArr) { const arrLen = arrNode.elements.length; retArr.push('vec' + arrLen + '('); for (let i = 0; i < arrLen; ++i) { if (i > 0) { retArr.push(', '); } const subNode = arrNode.elements[i]; this.astGeneric(subNode, retArr) } retArr.push(')'); return retArr; } memberExpressionXYZ(x, y, z, retArr) { if (z) { retArr.push(this.memberExpressionPropertyMarkup(z), ', '); } else { retArr.push('0, '); } if (y) { retArr.push(this.memberExpressionPropertyMarkup(y), ', '); } else { retArr.push('0, '); } retArr.push(this.memberExpressionPropertyMarkup(x)); return retArr; } memberExpressionPropertyMarkup(property) { if (!property) { throw new Error('Property not set'); } const type = this.getType(property); const result = []; switch (type) { case 'Number': case 'Float': this.pushState('casting-to-integer'); result.push('int('); this.astGeneric(property, result); result.push(')'); this.popState('casting-to-integer'); break; case 'LiteralInteger': this.pushState('casting-to-integer'); this.astGeneric(property, result); this.popState('casting-to-integer'); break; default: this.astGeneric(property, result); } return result.join(''); } } const typeMap = { 'Array': 'sampler2D', 'Array(2)': 'vec2', 'Array(3)': 'vec3', 'Array(4)': 'vec4', 'Array2D': 'sampler2D', 'Array3D': 'sampler2D', 'Boolean': 'bool', 'Float': 'float', 'Input': 'sampler2D', 'Integer': 'int', 'Number': 'float', 'LiteralInteger': 'float', 'NumberTexture': 'sampler2D', 'MemoryOptimizedNumberTexture': 'sampler2D', 'ArrayTexture(1)': 'sampler2D', 'ArrayTexture(2)': 'sampler2D', 'ArrayTexture(3)': 'sampler2D', 'ArrayTexture(4)': 'sampler2D', }; const operatorMap = { '===': '==', '!==': '!=' }; module.exports = { WebGLFunctionNode }; },{"../function-node":10}],18:[function(require,module,exports){ const { WebGLKernelValueBoolean } = require('./kernel-value/boolean'); const { WebGLKernelValueFloat } = require('./kernel-value/float'); const { WebGLKernelValueInteger } = require('./kernel-value/integer'); const { WebGLKernelValueHTMLImage } = require('./kernel-value/html-image'); const { WebGLKernelValueDynamicHTMLImage } = require('./kernel-value/dynamic-html-image'); const { WebGLKernelValueSingleInput } = require('./kernel-value/single-input'); const { WebGLKernelValueDynamicSingleInput } = require('./kernel-value/dynamic-single-input'); const { WebGLKernelValueUnsignedInput } = require('./kernel-value/unsigned-input'); const { WebGLKernelValueDynamicUnsignedInput } = require('./kernel-value/dynamic-unsigned-input'); const { WebGLKernelValueMemoryOptimizedNumberTexture } = require('./kernel-value/memory-optimized-number-texture'); const { WebGLKernelValueDynamicMemoryOptimizedNumberTexture } = require('./kernel-value/dynamic-memory-optimized-number-texture'); const { WebGLKernelValueNumberTexture } = require('./kernel-value/number-texture'); const { WebGLKernelValueDynamicNumberTexture } = require('./kernel-value/dynamic-number-texture'); const { WebGLKernelValueSingleArray } = require('./kernel-value/single-array'); const { WebGLKernelValueDynamicSingleArray } = require('./kernel-value/dynamic-single-array'); const { WebGLKernelValueUnsignedArray } = require('./kernel-value/unsigned-array'); const { WebGLKernelValueDynamicUnsignedArray } = require('./kernel-value/dynamic-unsigned-array'); const kernelValueMaps = { unsigned: { dynamic: { 'Boolean': WebGLKernelValueBoolean, 'Interger': WebGLKernelValueInteger, 'Float': WebGLKernelValueFloat, 'Array': WebGLKernelValueDynamicUnsignedArray, 'Input': WebGLKernelValueDynamicUnsignedInput, 'NumberTexture': WebGLKernelValueDynamicNumberTexture, 'ArrayTexture(1)': WebGLKernelValueDynamicNumberTexture, 'ArrayTexture(2)': WebGLKernelValueDynamicNumberTexture, 'ArrayTexture(3)': WebGLKernelValueDynamicNumberTexture, 'ArrayTexture(4)': WebGLKernelValueDynamicNumberTexture, 'MemoryOptimizedNumberTexture': WebGLKernelValueDynamicMemoryOptimizedNumberTexture, 'HTMLImage': WebGLKernelValueDynamicHTMLImage, 'HTMLImageArray': false, }, static: { 'Boolean': WebGLKernelValueBoolean, 'Interger': WebGLKernelValueInteger, 'Float': WebGLKernelValueFloat, 'Integer': WebGLKernelValueInteger, 'Array': WebGLKernelValueUnsignedArray, 'Input': WebGLKernelValueUnsignedInput, 'NumberTexture': WebGLKernelValueNumberTexture, 'ArrayTexture(1)': WebGLKernelValueNumberTexture, 'ArrayTexture(2)': WebGLKernelValueNumberTexture, 'ArrayTexture(3)': WebGLKernelValueNumberTexture, 'ArrayTexture(4)': WebGLKernelValueNumberTexture, 'MemoryOptimizedNumberTexture': WebGLKernelValueDynamicMemoryOptimizedNumberTexture, 'HTMLImage': WebGLKernelValueHTMLImage, 'HTMLImageArray': false, } }, single: { dynamic: { 'Boolean': WebGLKernelValueBoolean, 'Interger': WebGLKernelValueInteger, 'Float': WebGLKernelValueFloat, 'Array': WebGLKernelValueDynamicSingleArray, 'Input': WebGLKernelValueDynamicSingleInput, 'NumberTexture': WebGLKernelValueDynamicNumberTexture, 'ArrayTexture(1)': WebGLKernelValueDynamicNumberTexture, 'ArrayTexture(2)': WebGLKernelValueDynamicNumberTexture, 'ArrayTexture(3)': WebGLKernelValueDynamicNumberTexture, 'ArrayTexture(4)': WebGLKernelValueDynamicNumberTexture, 'MemoryOptimizedNumberTexture': WebGLKernelValueDynamicMemoryOptimizedNumberTexture, 'HTMLImage': WebGLKernelValueDynamicHTMLImage, 'HTMLImageArray': false, }, static: { 'Boolean': WebGLKernelValueBoolean, 'Interger': WebGLKernelValueInteger, 'Float': WebGLKernelValueFloat, 'Integer': WebGLKernelValueInteger, 'Array': WebGLKernelValueSingleArray, 'Input': WebGLKernelValueSingleInput, 'NumberTexture': WebGLKernelValueNumberTexture, 'ArrayTexture(1)': WebGLKernelValueNumberTexture, 'ArrayTexture(2)': WebGLKernelValueNumberTexture, 'ArrayTexture(3)': WebGLKernelValueNumberTexture, 'ArrayTexture(4)': WebGLKernelValueNumberTexture, 'MemoryOptimizedNumberTexture': WebGLKernelValueMemoryOptimizedNumberTexture, 'HTMLImage': WebGLKernelValueHTMLImage, 'HTMLImageArray': false, } }, }; function lookupKernelValueType(type, dynamic, precision) { if (!type) { throw new Error('type missing'); } if (!dynamic) { throw new Error('dynamic missing'); } if (!precision) { throw new Error('precision missing'); } const types = kernelValueMaps[precision][dynamic]; if (types[type] === false) { return null; } else if (types[type] === undefined) { throw new Error(`Could not find a KernelValue for ${ type }`); } return types[type]; } module.exports = { lookupKernelValueType }; },{"./kernel-value/boolean":19,"./kernel-value/dynamic-html-image":20,"./kernel-value/dynamic-memory-optimized-number-texture":21,"./kernel-value/dynamic-number-texture":22,"./kernel-value/dynamic-single-array":23,"./kernel-value/dynamic-single-input":24,"./kernel-value/dynamic-unsigned-array":25,"./kernel-value/dynamic-unsigned-input":26,"./kernel-value/float":27,"./kernel-value/html-image":28,"./kernel-value/integer":30,"./kernel-value/memory-optimized-number-texture":31,"./kernel-value/number-texture":32,"./kernel-value/single-array":33,"./kernel-value/single-input":34,"./kernel-value/unsigned-array":35,"./kernel-value/unsigned-input":36}],19:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValue } = require('./index'); class WebGLKernelValueBoolean extends WebGLKernelValue { constructor(value, settings) { super(value, settings); this.uploadValue = value; } getSource(value) { if (this.origin === 'constants') { return `const bool ${this.id} = ${value};\n`; } return `uniform bool ${this.id};\n`; } getStringValueHandler() { return `const uploadValue_${this.name} = ${this.name};\n`; } updateValue(value) { if (this.origin === 'constants') return; this.kernel.setUniform1i(this.id, this.uploadValue = value); } } module.exports = { WebGLKernelValueBoolean }; },{"../../../utils":70,"./index":29}],20:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueHTMLImage } = require('./html-image'); class WebGLKernelValueDynamicInput extends WebGLKernelValueHTMLImage { getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `uniform ivec2 ${this.sizeId}`, `uniform ivec3 ${this.dimensionsId}`, ]); } updateValue(value) { const { width, height } = value; this.dimensions = [width, height, 1]; this.textureSize = [width, height]; this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); this.kernel.setUniform2iv(this.sizeId, this.textureSize); super.updateValue(value); } } module.exports = { WebGLKernelValueDynamicInput }; },{"../../../utils":70,"./html-image":28}],21:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueMemoryOptimizedNumberTexture } = require('./memory-optimized-number-texture'); class WebGLKernelValueDynamicMemoryOptimizedNumberTexture extends WebGLKernelValueMemoryOptimizedNumberTexture { getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `uniform ivec2 ${this.sizeId}`, `uniform ivec3 ${this.dimensionsId}`, ]); } updateValue(inputTexture) { this.dimensions = inputTexture.dimensions; this.textureSize = inputTexture.size; this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); this.kernel.setUniform2iv(this.sizeId, this.textureSize); super.updateValue(inputTexture); } } module.exports = { WebGLKernelValueDynamicMemoryOptimizedNumberTexture }; },{"../../../utils":70,"./memory-optimized-number-texture":31}],22:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueNumberTexture } = require('./number-texture'); class WebGLKernelValueDynamicNumberTexture extends WebGLKernelValueNumberTexture { getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `uniform ivec2 ${this.sizeId}`, `uniform ivec3 ${this.dimensionsId}`, ]); } updateValue(value) { this.dimensions = inputTexture.dimensions; this.textureSize = inputTexture.size; this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); this.kernel.setUniform2iv(this.sizeId, this.textureSize); super.updateValue(value); } } module.exports = { WebGLKernelValueDynamicNumberTexture }; },{"../../../utils":70,"./number-texture":32}],23:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueSingleArray } = require('./single-array'); class WebGLKernelValueDynamicSingleArray extends WebGLKernelValueSingleArray { getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `uniform ivec2 ${this.sizeId}`, `uniform ivec3 ${this.dimensionsId}`, ]); } updateValue(value) { this.dimensions = utils.getDimensions(value, true); this.textureSize = utils.getMemoryOptimizedFloatTextureSize(this.dimensions, this.bitRatio); this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * this.bitRatio; this.uploadValue = new Float32Array(this.uploadArrayLength); this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); this.kernel.setUniform2iv(this.sizeId, this.textureSize); super.updateValue(value); } } module.exports = { WebGLKernelValueDynamicSingleArray }; },{"../../../utils":70,"./single-array":33}],24:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueSingleInput } = require('./single-input'); class WebGLKernelValueDynamicSingleInput extends WebGLKernelValueSingleInput { getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `uniform ivec2 ${this.sizeId}`, `uniform ivec3 ${this.dimensionsId}`, ]); } updateValue(value) { this.dimensions = value.size; this.textureSize = utils.getMemoryOptimizedFloatTextureSize(this.dimensions, this.bitRatio); this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * (4 / this.bitRatio); this.uploadValue = new Float32Array(this.uploadArrayLength); this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); this.kernel.setUniform2iv(this.sizeId, this.textureSize); super.updateValue(value); } } module.exports = { WebGLKernelValueDynamicSingleInput }; },{"../../../utils":70,"./single-input":34}],25:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueUnsignedArray } = require('./unsigned-array'); class WebGLKernelValueDynamicUnsignedArray extends WebGLKernelValueUnsignedArray { getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `uniform ivec2 ${this.sizeId}`, `uniform ivec3 ${this.dimensionsId}`, ]); } updateValue(value) { this.dimensions = utils.getDimensions(value, true); this.textureSize = utils.getMemoryOptimizedPackedTextureSize(this.dimensions, this.bitRatio); this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * (4 / this.bitRatio); const Type = this.getTransferArrayType(value); this.preUploadValue = new Type(this.uploadArrayLength); this.uploadValue = new Uint8Array(this.preUploadValue.buffer); this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); this.kernel.setUniform2iv(this.sizeId, this.textureSize); super.updateValue(value); } } module.exports = { WebGLKernelValueDynamicUnsignedArray }; },{"../../../utils":70,"./unsigned-array":35}],26:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueUnsignedInput } = require('./unsigned-input'); class WebGLKernelValueDynamicUnsignedInput extends WebGLKernelValueUnsignedInput { getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `uniform ivec2 ${this.sizeId}`, `uniform ivec3 ${this.dimensionsId}`, ]); } updateValue(value) { this.dimensions = value.size; this.textureSize = utils.getMemoryOptimizedPackedTextureSize(this.dimensions, this.bitRatio); this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * (4 / this.bitRatio); const Type = this.getTransferArrayType(value.value); this.preUploadValue = new Type(this.uploadArrayLength); this.uploadValue = new Uint8Array(this.preUploadValue.buffer); this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); this.kernel.setUniform2iv(this.sizeId, this.textureSize); super.updateValue(value); } } module.exports = { WebGLKernelValueDynamicUnsignedInput }; },{"../../../utils":70,"./unsigned-input":36}],27:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValue } = require('./index'); class WebGLKernelValueFloat extends WebGLKernelValue { constructor(value, settings) { super(value, settings); this.uploadValue = value; } getSource(value) { if (this.origin === 'constants') { if (Number.isInteger(value)) { return `const float ${this.id} = ${value}.0;\n`; } return `const float ${this.id} = ${value};\n`; } return `uniform float ${this.id};\n`; } updateValue(value) { if (this.origin === 'constants') return; this.kernel.setUniform1f(this.id, this.uploadValue = value); } } module.exports = { WebGLKernelValueFloat }; },{"../../../utils":70,"./index":29}],28:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValue } = require('./index'); class WebGLKernelValueHTMLImage extends WebGLKernelValue { constructor(value, settings) { super(value, settings); const { width, height } = value; this.dimensions = [width, height, 1]; this.requestTexture(); this.textureSize = [width, height]; this.uploadValue = value; } getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } updateValue(inputImage) { const { context: gl } = this; gl.activeTexture(this.contextHandle); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.uploadValue = inputImage); this.kernel.setUniform1i(this.id, this.index); } } module.exports = { WebGLKernelValueHTMLImage }; },{"../../../utils":70,"./index":29}],29:[function(require,module,exports){ const { utils } = require('../../../utils'); const { Input } = require('../../../input'); const { KernelValue } = require('../../kernel-Value'); class WebGLKernelValue extends KernelValue { constructor(value, settings) { super(value, settings); this.dimensionsId = null; this.sizeId = null; this.initialValueConstructor = value.constructor; this.onRequestTexture = settings.onRequestTexture; this.onRequestIndex = settings.onRequestIndex; this.uploadValue = null; this.textureSize = null; this.bitRatio = null; } requestTexture() { this.texture = this.onRequestTexture(); this.setupTexture(); } setupTexture() { this.contextHandle = this.onRequestContextHandle(); this.index = this.onRequestIndex(); this.dimensionsId = this.id + 'Dim'; this.sizeId = this.id + 'Size'; } getTransferArrayType(value) { if (Array.isArray(value[0])) { return this.getTransferArrayType(value[0]); } if (value.constructor === Array) { return Float32Array; } return value.constructor; } formatArrayTransfer(value, length, Type) { if (utils.isArray(value[0]) || this.optimizeFloatMemory) { const valuesFlat = new Float32Array(length); utils.flattenTo(value, valuesFlat); return valuesFlat; } else { switch (value.constructor) { case Uint8Array: case Int8Array: case Uint16Array: case Int16Array: case Float32Array: case Int32Array: { const valuesFlat = new(Type || value.constructor)(length); utils.flattenTo(value, valuesFlat); return valuesFlat; } default: { const valuesFlat = new Float32Array(length); utils.flattenTo(value, valuesFlat); return valuesFlat; } } } } getBitRatio(value) { if (Array.isArray(value[0])) { return this.getBitRatio(value[0]); } else if (value.constructor === Input) { return this.getBitRatio(value.value); } switch (value.constructor) { case Uint8Array: case Int8Array: return 1; case Uint16Array: case Int16Array: return 2; case Float32Array: case Int32Array: default: return 4; } } getStringValueHandler() { throw new Error(`"getStringValueHandler" not implemented on ${this.constructor.name}`); } } module.exports = { WebGLKernelValue }; },{"../../../input":66,"../../../utils":70,"../../kernel-Value":14}],30:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValue } = require('./index'); class WebGLKernelValueInteger extends WebGLKernelValue { constructor(value, settings) { super(value, settings); this.uploadValue = value; } getSource(value) { if (this.origin === 'constants') { return `const int ${this.id} = ${ parseInt(value) };\n`; } return `uniform int ${this.id};\n`; } updateValue(value) { if (this.origin === 'constants') return; this.kernel.setUniform1i(this.id, this.uploadValue = value); } } module.exports = { WebGLKernelValueInteger }; },{"../../../utils":70,"./index":29}],31:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValue } = require('./index'); class WebGLKernelValueMemoryOptimizedNumberTexture extends WebGLKernelValue { constructor(value, settings) { super(value, settings); this.setupTexture(); this.dimensions = value.dimensions; this.textureSize = value.size; this.uploadValue = value.texture; } getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } updateValue(inputTexture) { if (inputTexture.constructor !== this.initialValueConstructor) { this.onUpdateValueMismatch(); return; } if (inputTexture.context !== this.context) { throw new Error(`Value ${this.name} (${this.type }) must be from same context`); } const { context: gl } = this; gl.activeTexture(this.contextHandle); gl.bindTexture(gl.TEXTURE_2D, this.uploadValue = inputTexture.texture); this.kernel.setUniform1i(this.id, this.index); } } module.exports = { WebGLKernelValueMemoryOptimizedNumberTexture }; },{"../../../utils":70,"./index":29}],32:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValue } = require('./index'); class WebGLKernelValueNumberTexture extends WebGLKernelValue { constructor(value, settings) { super(value, settings); this.setupTexture(); const { size: textureSize, dimensions } = value; this.bitRatio = this.getBitRatio(value); this.dimensions = dimensions; this.textureSize = textureSize; this.uploadValue = value.texture; } getStringValueHandler() { return `const uploadValue_${this.name} = ${this.name};\n`; } getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } updateValue(inputTexture) { if (inputTexture.constructor !== this.initialValueConstructor) { this.onUpdateValueMismatch(); return; } if (inputTexture.context !== this.context) { throw new Error(`Value ${this.name} (${this.type}) must be from same context`); } const { context: gl } = this; gl.activeTexture(this.contextHandle); gl.bindTexture(gl.TEXTURE_2D, this.uploadValue = inputTexture.texture); this.kernel.setUniform1i(this.id, this.index); } } module.exports = { WebGLKernelValueNumberTexture }; },{"../../../utils":70,"./index":29}],33:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValue } = require('./index'); class WebGLKernelValueSingleArray extends WebGLKernelValue { constructor(value, settings) { super(value, settings); this.requestTexture(); this.bitRatio = 4; this.dimensions = utils.getDimensions(value, true); this.textureSize = utils.getMemoryOptimizedFloatTextureSize(this.dimensions, this.bitRatio); this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * this.bitRatio; this.uploadValue = new Float32Array(this.uploadArrayLength); } getStringValueHandler() { return utils.linesToString([ `const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`, `flattenTo(${this.name}, uploadValue_${this.name})`, ]); } getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } updateValue(value) { if (value.constructor !== this.initialValueConstructor) { this.onUpdateValueMismatch(); return; } const { context: gl } = this; utils.flattenTo(value, this.uploadValue); gl.activeTexture(this.contextHandle); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); this.kernel.setUniform1i(this.id, this.index); } } module.exports = { WebGLKernelValueSingleArray }; },{"../../../utils":70,"./index":29}],34:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValue } = require('./index'); class WebGLKernelValueSingleInput extends WebGLKernelValue { constructor(value, settings) { super(value, settings); this.requestTexture(); this.bitRatio = 4; this.dimensions = value.size; this.textureSize = utils.getMemoryOptimizedFloatTextureSize(this.dimensions, this.bitRatio); this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * this.bitRatio; this.uploadValue = new Float32Array(this.uploadArrayLength); } getStringValueHandler() { return utils.linesToString([ `const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`, `flattenTo(${this.name}.value, uploadValue_${this.name})`, ]); } getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } updateValue(input) { if (input.constructor !== this.initialValueConstructor) { this.onUpdateValueMismatch(); return; } const { context: gl } = this; utils.flattenTo(input.value, this.uploadValue); gl.activeTexture(this.contextHandle); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); this.kernel.setUniform1i(this.id, this.index); } } module.exports = { WebGLKernelValueSingleInput }; },{"../../../utils":70,"./index":29}],35:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValue } = require('./index'); class WebGLKernelValueUnsignedArray extends WebGLKernelValue { constructor(value, settings) { super(value, settings); this.requestTexture(); this.bitRatio = this.getBitRatio(value); this.dimensions = utils.getDimensions(value, true); this.textureSize = utils.getMemoryOptimizedPackedTextureSize(this.dimensions, this.bitRatio); this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * (4 / this.bitRatio); this.TranserArrayType = this.getTransferArrayType(value); this.preUploadValue = new this.TranserArrayType(this.uploadArrayLength); this.uploadValue = new Uint8Array(this.preUploadValue.buffer); } getStringValueHandler() { return utils.linesToString([ `const preUploadValue_${this.name} = new ${this.TranserArrayType.name}(${this.uploadArrayLength})`, `const uploadValue_${this.name} = new Uint8Array(preUploadValue_${this.name}.buffer)`, `flattenTo(${this.name}, preUploadValue_${this.name})`, ]); } getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } updateValue(value) { if (value.constructor !== this.initialValueConstructor) { this.onUpdateValueMismatch(); return; } const { context: gl } = this; utils.flattenTo(value, this.preUploadValue); gl.activeTexture(this.contextHandle); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, this.uploadValue); this.kernel.setUniform1i(this.id, this.index); } } module.exports = { WebGLKernelValueUnsignedArray }; },{"../../../utils":70,"./index":29}],36:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValue } = require('./index'); class WebGLKernelValueUnsignedInput extends WebGLKernelValue { constructor(value, settings) { super(value, settings); this.requestTexture(); this.bitRatio = this.getBitRatio(value); this.dimensions = value.size; this.textureSize = utils.getMemoryOptimizedPackedTextureSize(this.dimensions, this.bitRatio); this.uploadArrayLength = this.textureSize[0] * this.textureSize[1] * (4 / this.bitRatio); this.TranserArrayType = this.getTransferArrayType(value.value); this.preUploadValue = new this.TranserArrayType(this.uploadArrayLength); this.uploadValue = new Uint8Array(this.preUploadValue.buffer); } getStringValueHandler() { return utils.linesToString([ `const preUploadValue_${this.name} = new ${this.TranserArrayType.name}(${this.uploadArrayLength})`, `const uploadValue_${this.name} = new Uint8Array(preUploadValue_${this.name}.buffer)`, `flattenTo(${this.name}.value, preUploadValue_${this.name})`, ]); } getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } updateValue(input) { if (input.constructor !== this.initialValueConstructor) { this.onUpdateValueMismatch(); return; } const { context: gl } = this; utils.flattenTo(input.value, this.preUploadValue); gl.activeTexture(this.contextHandle); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, this.uploadValue); this.kernel.setUniform1i(this.id, this.index); } } module.exports = { WebGLKernelValueUnsignedInput }; },{"../../../utils":70,"./index":29}],37:[function(require,module,exports){ const { GLKernel } = require('../gl/kernel'); const { FunctionBuilder } = require('../function-builder'); const { WebGLFunctionNode } = require('./function-node'); const { utils } = require('../../utils'); const { Texture } = require('../../texture'); const triangleNoise = require('../../plugins/triangle-noise'); const { fragmentShader } = require('./fragment-shader'); const { vertexShader } = require('./vertex-shader'); const { glKernelString } = require('../gl/kernel-string'); const { lookupKernelValueType } = require('./kernel-value-maps'); let isSupported = null; let testCanvas = null; let testContext = null; let testExtensions = null; let features = null; const plugins = [triangleNoise]; const canvases = []; const maxTexSizes = {}; class WebGLKernel extends GLKernel { static get isSupported() { if (isSupported !== null) { return isSupported; } this.setupFeatureChecks(); isSupported = this.isContextMatch(testContext); return isSupported; } static setupFeatureChecks() { if (typeof document !== 'undefined') { testCanvas = document.createElement('canvas'); } else if (typeof OffscreenCanvas !== 'undefined') { testCanvas = new OffscreenCanvas(0, 0); } if (!testCanvas) return; testContext = testCanvas.getContext('webgl') || testCanvas.getContext('experimental-webgl'); if (!testContext || !testContext.getExtension) return; testExtensions = { OES_texture_float: testContext.getExtension('OES_texture_float'), OES_texture_float_linear: testContext.getExtension('OES_texture_float_linear'), OES_element_index_uint: testContext.getExtension('OES_element_index_uint'), WEBGL_draw_buffers: testContext.getExtension('WEBGL_draw_buffers'), }; features = this.getFeatures(); } static isContextMatch(context) { if (typeof WebGLRenderingContext !== 'undefined') { return context instanceof WebGLRenderingContext; } return false; } static getFeatures() { const isDrawBuffers = this.getIsDrawBuffers(); return Object.freeze({ isFloatRead: this.getIsFloatRead(), isIntegerDivisionAccurate: this.getIsIntegerDivisionAccurate(), isTextureFloat: this.getIsTextureFloat(), isDrawBuffers, kernelMap: isDrawBuffers, channelCount: this.getChannelCount(), }); } static getIsTextureFloat() { return Boolean(testExtensions.OES_texture_float); } static getIsDrawBuffers() { return Boolean(testExtensions.WEBGL_draw_buffers); } static getChannelCount() { return testExtensions.WEBGL_draw_buffers ? testExtensions.WEBGL_draw_buffers.MAX_DRAW_BUFFERS_WEBGL : 1; } static lookupKernelValueType(type, dynamic, precision) { return lookupKernelValueType(type, dynamic, precision); } static get testCanvas() { return testCanvas; } static get testContext() { return testContext; } static get features() { return features; } static get fragmentShader() { return fragmentShader; } static get vertexShader() { return vertexShader; } constructor(source, settings) { super(source, settings); this.program = null; this.pipeline = settings.pipeline; this.endianness = utils.systemEndianness(); this.extensions = {}; this.subKernelOutputTextures = null; this.kernelArguments = null; this.argumentTextureCount = 0; this.constantTextureCount = 0; this.compiledFragmentShader = null; this.compiledVertexShader = null; this.fragShader = null; this.vertShader = null; this.drawBuffersMap = null; this.outputTexture = null; this.maxTexSize = null; this.switchingKernels = false; this.onRequestSwitchKernel = null; this.mergeSettings(source.settings || settings); this.threadDim = null; this.framebuffer = null; this.buffer = null; this.textureCache = {}; this.programUniformLocationCache = {}; this.uniform1fCache = {}; this.uniform1iCache = {}; this.uniform2fCache = {}; this.uniform2fvCache = {}; this.uniform2ivCache = {}; this.uniform3fvCache = {}; this.uniform3ivCache = {}; } initCanvas() { if (typeof document !== 'undefined') { const canvas = document.createElement('canvas'); canvas.width = 2; canvas.height = 2; return canvas; } else if (typeof OffscreenCanvas !== 'undefined') { return new OffscreenCanvas(0, 0); } } initContext() { const settings = { alpha: false, depth: false, antialias: false }; return this.canvas.getContext('webgl', settings) || this.canvas.getContext('experimental-webgl', settings); } initPlugins(settings) { const pluginsToUse = []; const { source } = this; if (typeof source === 'string') { for (let i = 0; i < plugins.length; i++) { const plugin = plugins[i]; if (source.match(plugin.functionMatch)) { pluginsToUse.push(plugin); } } } else if (typeof source === 'object') { if (settings.pluginNames) { for (let i = 0; i < plugins.length; i++) { const plugin = plugins[i]; const usePlugin = settings.pluginNames.some(pluginName => pluginName === plugin.name); if (usePlugin) { pluginsToUse.push(plugin); } } } } return pluginsToUse; } initExtensions() { this.extensions = { OES_texture_float: this.context.getExtension('OES_texture_float'), OES_texture_float_linear: this.context.getExtension('OES_texture_float_linear'), OES_element_index_uint: this.context.getExtension('OES_element_index_uint'), WEBGL_draw_buffers: this.context.getExtension('WEBGL_draw_buffers'), WEBGL_color_buffer_float: this.context.getExtension('WEBGL_color_buffer_float'), }; } validateSettings() { if (!this.validate) { this.texSize = utils.dimToTexSize({ floatTextures: this.optimizeFloatMemory, floatOutput: this.precision === 'single', }, this.output, true); return; } const { features } = this.constructor; if (this.optimizeFloatMemory === true && !features.isTextureFloat) { throw new Error('Float textures are not supported'); } else if (this.precision === 'single' && !features.isFloatRead) { throw new Error('Single precision not supported'); } else if (!this.graphical && this.precision === null && features.isTextureFloat) { this.precision = features.isFloatRead ? 'single' : 'unsigned'; } if (this.subKernels && this.subKernels.length > 0 && !this.extensions.WEBGL_draw_buffers) { throw new Error('could not instantiate draw buffers extension'); } if (this.fixIntegerDivisionAccuracy === null) { this.fixIntegerDivisionAccuracy = !features.isIntegerDivisionAccurate; } else if (this.fixIntegerDivisionAccuracy && features.isIntegerDivisionAccurate) { this.fixIntegerDivisionAccuracy = false; } this.checkOutput(); if (!this.output || this.output.length === 0) { if (arguments.length !== 1) { throw new Error('Auto output only supported for kernels with only one input'); } const argType = utils.getVariableType(arguments[0], this.strictIntegers); if (argType === 'Array') { this.output = utils.getDimensions(argType); } else if (argType === 'NumberTexture' || argType === 'ArrayTexture(4)') { this.output = arguments[0].output; } else { throw new Error('Auto output not supported for input type: ' + argType); } } if (this.graphical) { if (this.output.length !== 2) { throw new Error('Output must have 2 dimensions on graphical mode'); } if (this.precision === 'precision') { this.precision = 'unsigned'; console.warn('Cannot use graphical mode and single precision at the same time'); } this.texSize = utils.clone(this.output); return; } else if (this.precision === null && features.isTextureFloat) { this.precision = 'single'; } this.texSize = utils.dimToTexSize({ floatTextures: this.floatTextures, floatOutput: this.precision === 'single' }, this.output, true); } updateMaxTexSize() { const { texSize, canvas } = this; if (this.maxTexSize === null) { let canvasIndex = canvases.indexOf(canvas); if (canvasIndex === -1) { canvasIndex = canvases.length; canvases.push(canvas); maxTexSizes[canvasIndex] = [texSize[0], texSize[1]]; } this.maxTexSize = maxTexSizes[canvasIndex]; } if (this.maxTexSize[0] < texSize[0]) { this.maxTexSize[0] = texSize[0]; } if (this.maxTexSize[1] < texSize[1]) { this.maxTexSize[1] = texSize[1]; } } _oldtranslateSource() { const functionBuilder = FunctionBuilder.fromKernel(this, WebGLFunctionNode, { fixIntegerDivisionAccuracy: this.fixIntegerDivisionAccuracy }); const translatedSource = functionBuilder.getPrototypeString('kernel'); if (!this.returnType) { this.returnType = functionBuilder.getKernelResultType(); } let requiredChannels = 0; const returnTypes = functionBuilder.getReturnTypes(); for (let i = 0; i < returnTypes.length; i++) { switch (returnTypes[i]) { case 'Float': case 'Number': case 'Integer': requiredChannels++; break; case 'Array(2)': requiredChannels += 2; break; case 'Array(3)': requiredChannels += 3; break; case 'Array(4)': requiredChannels += 4; break; } } if (features && requiredChannels > features.channelCount) { throw new Error('Too many channels!'); } return this.translatedSource = translatedSource; } setupArguments(args) { this.kernelArguments = []; this.argumentTextureCount = 0; this.argumentTypes = []; this.argumentSizes = []; this.argumentBitRatios = []; if (!this.precision) { } if (args.length < this.argumentNames.length) { throw new Error('not enough arguments for kernel'); } else if (args.length > this.argumentNames.length) { throw new Error('too many arguments for kernel'); } const { context: gl } = this; let textureIndexes = 0; for (let index = 0; index < args.length; index++) { const value = args[index]; const name = this.argumentNames[index]; const type = utils.getVariableType(value, this.strictIntegers); this.argumentTypes.push(type); const KernelValue = this.constructor.lookupKernelValueType(type, this.dynamicArguments ? 'dynamic' : 'static', this.precision); if (KernelValue === null) { throw new Error('unsupported argument'); continue; } const kernelArgument = new KernelValue(value, { name, origin: 'user', context: gl, kernel: this, strictIntegers: this.strictIntegers, onRequestTexture: () => { return this.context.createTexture(); }, onRequestIndex: () => { return textureIndexes++; }, onUpdateValueMismatch: () => { this.switchingKernels = true; }, onRequestContextHandle: () => { return gl.TEXTURE0 + this.constantTextureCount + this.argumentTextureCount++; } }); this.kernelArguments.push(kernelArgument); this.argumentSizes.push(kernelArgument.textureSize); this.argumentBitRatios[index] = kernelArgument.bitRatio; } } setupConstants() { const { context: gl } = this; this.kernelConstants = []; this.constantTypes = {}; this.constantBitRatios = {}; let textureIndexes = 0; for (const name in this.constants) { const value = this.constants[name]; const type = utils.getVariableType(value, this.strictIntegers); this.constantTypes[name] = type; const KernelValue = this.constructor.lookupKernelValueType(type, 'static', this.precision); if (KernelValue === null) { throw new Error(`unsupported constant ${ type }`); continue; } const kernelValue = new KernelValue(value, { name, origin: 'constants', context: this.context, kernel: this, strictIntegers: this.strictIntegers, onRequestTexture: () => { return this.context.createTexture(); }, onRequestIndex: () => { return textureIndexes++; }, onRequestContextHandle: () => { return gl.TEXTURE0 + this.constantTextureCount++; } }); this.constantBitRatios[name] = kernelValue.bitRatio; this.kernelConstants.push(kernelValue); } } build() { this.initExtensions(); this.validateSettings(); this.setupConstants(); this.setupArguments(arguments); this.updateMaxTexSize(); this.translateSource(); this.pickRenderStrategy(); const { texSize, context: gl, canvas } = this; gl.enable(gl.SCISSOR_TEST); if (this.pipeline && this.precision === 'single') { gl.viewport(0, 0, this.maxTexSize[0], this.maxTexSize[1]); canvas.width = this.maxTexSize[0]; canvas.height = this.maxTexSize[1]; } else { gl.viewport(0, 0, this.maxTexSize[0], this.maxTexSize[1]); canvas.width = this.maxTexSize[0]; canvas.height = this.maxTexSize[1]; } const threadDim = this.threadDim = Array.from(this.output); while (threadDim.length < 3) { threadDim.push(1); } const compiledVertexShader = this.getVertexShader(arguments); const vertShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertShader, compiledVertexShader); gl.compileShader(vertShader); this.vertShader = vertShader; const compiledFragmentShader = this.getFragmentShader(arguments); const fragShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragShader, compiledFragmentShader); gl.compileShader(fragShader); this.fragShader = fragShader; if (this.debug) { console.log('GLSL Shader Output:'); console.log(compiledFragmentShader); } if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)) { throw new Error('Error compiling vertex shader: ' + gl.getShaderInfoLog(vertShader)); } if (!gl.getShaderParameter(fragShader, gl.COMPILE_STATUS)) { throw new Error('Error compiling fragment shader: ' + gl.getShaderInfoLog(fragShader)); } const program = this.program = gl.createProgram(); gl.attachShader(program, vertShader); gl.attachShader(program, fragShader); gl.linkProgram(program); this.framebuffer = gl.createFramebuffer(); this.framebuffer.width = texSize[0]; this.framebuffer.height = texSize[1]; const vertices = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1 ]); const texCoords = new Float32Array([ 0, 0, 1, 0, 0, 1, 1, 1 ]); const texCoordOffset = vertices.byteLength; let buffer = this.buffer; if (!buffer) { buffer = this.buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData(gl.ARRAY_BUFFER, vertices.byteLength + texCoords.byteLength, gl.STATIC_DRAW); } else { gl.bindBuffer(gl.ARRAY_BUFFER, buffer); } gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertices); gl.bufferSubData(gl.ARRAY_BUFFER, texCoordOffset, texCoords); const aPosLoc = gl.getAttribLocation(this.program, 'aPos'); gl.enableVertexAttribArray(aPosLoc); gl.vertexAttribPointer(aPosLoc, 2, gl.FLOAT, false, 0, 0); const aTexCoordLoc = gl.getAttribLocation(this.program, 'aTexCoord'); gl.enableVertexAttribArray(aTexCoordLoc); gl.vertexAttribPointer(aTexCoordLoc, 2, gl.FLOAT, false, 0, texCoordOffset); gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); let i = 0; gl.useProgram(this.program); for (let p in this.constants) { this.kernelConstants[i++].updateValue(this.constants[p]); } if (!this.immutable) { this._setupOutputTexture(); if ( this.subKernels !== null && this.subKernels.length > 0 ) { this._setupSubOutputTextures(); } } } translateSource() { const functionBuilder = FunctionBuilder.fromKernel(this, WebGLFunctionNode, { fixIntegerDivisionAccuracy: this.fixIntegerDivisionAccuracy }); this.translatedSource = functionBuilder.getPrototypeString('kernel'); if (!this.graphical && !this.returnType) { this.returnType = functionBuilder.getKernelResultType(); } } run() { const { kernelArguments } = this; const texSize = this.texSize; const gl = this.context; gl.useProgram(this.program); gl.scissor(0, 0, texSize[0], texSize[1]); if (this.dynamicOutput) { this.setUniform3iv('uOutputDim', this.threadDim); this.setUniform2iv('uTexSize', texSize); } this.setUniform2f('ratio', texSize[0] / this.maxTexSize[0], texSize[1] / this.maxTexSize[1]); for (let i = 0; i < kernelArguments.length; i++) { if (this.switchingKernels) return; kernelArguments[i].updateValue(arguments[i]); } if (this.plugins) { for (let i = 0; i < this.plugins.length; i++) { const plugin = this.plugins[i]; if (plugin.onBeforeRun) { plugin.onBeforeRun(this); } } } if (this.graphical) { if (this.pipeline) { gl.bindRenderbuffer(gl.RENDERBUFFER, null); gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); if (!this.outputTexture || this.immutable) { this._setupOutputTexture(); } gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); return new Texture({ texture: this.outputTexture, size: texSize, dimensions: this.threadDim, output: this.output, context: this.context, gpu: this.gpu, type: this.getReturnTextureType(), }); } gl.bindRenderbuffer(gl.RENDERBUFFER, null); gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); return; } gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); if (this.immutable) { this._setupOutputTexture(); } if (this.subKernels !== null) { if (this.immutable) { this._setupSubOutputTextures(); } this.extensions.WEBGL_draw_buffers.drawBuffersWEBGL(this.drawBuffersMap); } gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); } getOutputTexture() { return this.outputTexture; } _setupOutputTexture() { const gl = this.context; const texSize = this.texSize; const texture = this.outputTexture = this.context.createTexture(); gl.activeTexture(gl.TEXTURE0 + this.constantTextureCount + this.argumentTextureCount); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); if (this.precision === 'single') { if (this.pipeline) { switch (this.returnType) { case 'Number': case 'Float': case 'Integer': if (this.optimizeFloatMemory) { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); } else { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); } break; case 'Array(2)': gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); break; case 'Array(3)': gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); break; case 'Array(4)': gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); break; default: if (!this.graphical) { throw new Error('Unhandled return type'); } } } else { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); } } else { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, null); } gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); } _setupSubOutputTextures() { const gl = this.context; const texSize = this.texSize; this.drawBuffersMap = [gl.COLOR_ATTACHMENT0]; this.subKernelOutputTextures = []; for (let i = 0; i < this.subKernels.length; i++) { const texture = this.context.createTexture(); this.subKernelOutputTextures.push(texture); this.drawBuffersMap.push(gl.COLOR_ATTACHMENT0 + i + 1); gl.activeTexture(gl.TEXTURE0 + this.constantTextureCount + this.argumentTextureCount + i); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); if (this.precision === 'single') { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); } else { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, null); } gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i + 1, gl.TEXTURE_2D, texture, 0); } } getArgumentTexture(name) { return this.getTextureCache(`ARGUMENT_${name}`); } getTextureCache(name) { if (this.textureCache.hasOwnProperty(name)) { return this.textureCache[name]; } return this.textureCache[name] = this.context.createTexture(); } detachTextureCache(name) { delete this.textureCache[name]; } setUniform1f(name, value) { if (this.uniform1fCache.hasOwnProperty(name)) { const cache = this.uniform1fCache[name]; if (value === cache) { return; } } this.uniform1fCache[name] = value; const loc = this.getUniformLocation(name); this.context.uniform1f(loc, value); } setUniform1i(name, value) { if (this.uniform1iCache.hasOwnProperty(name)) { const cache = this.uniform1iCache[name]; if (value === cache) { return; } } this.uniform1iCache[name] = value; const loc = this.getUniformLocation(name); this.context.uniform1i(loc, value); } setUniform2f(name, value1, value2) { if (this.uniform2fCache.hasOwnProperty(name)) { const cache = this.uniform2fCache[name]; if ( value1 === cache[0] && value2 === cache[1] ) { return; } } this.uniform2fCache[name] = [value1, value2]; const loc = this.getUniformLocation(name); this.context.uniform2f(loc, value1, value2); } setUniform2fv(name, value) { if (this.uniform2fvCache.hasOwnProperty(name)) { const cache = this.uniform2fvCache[name]; if ( value[0] === cache[0] && value[1] === cache[1] ) { return; } } this.uniform2fvCache[name] = value; const loc = this.getUniformLocation(name); this.context.uniform2fv(loc, value); } setUniform2iv(name, value) { if (this.uniform2ivCache.hasOwnProperty(name)) { const cache = this.uniform2ivCache[name]; if ( value[0] === cache[0] && value[1] === cache[1] ) { return; } } this.uniform2ivCache[name] = value; const loc = this.getUniformLocation(name); this.context.uniform2iv(loc, value); } setUniform3fv(name, value) { if (this.uniform3fvCache.hasOwnProperty(name)) { const cache = this.uniform3fvCache[name]; if ( value[0] === cache[0] && value[1] === cache[1] && value[2] === cache[2] ) { return; } } this.uniform3fvCache[name] = value; const loc = this.getUniformLocation(name); this.context.uniform3fv(loc, value); } setUniform3iv(name, value) { if (this.uniform3ivCache.hasOwnProperty(name)) { const cache = this.uniform3ivCache[name]; if ( value[0] === cache[0] && value[1] === cache[1] && value[2] === cache[2] ) { return; } } this.uniform3ivCache[name] = value; const loc = this.getUniformLocation(name); this.context.uniform3iv(loc, value); } getUniformLocation(name) { if (this.programUniformLocationCache.hasOwnProperty(name)) { return this.programUniformLocationCache[name]; } return this.programUniformLocationCache[name] = this.context.getUniformLocation(this.program, name); } _getFragShaderArtifactMap(args) { return { HEADER: this._getHeaderString(), LOOP_MAX: this._getLoopMaxString(), PLUGINS: this._getPluginsString(), CONSTANTS: this._getConstantsString(), DECODE32_ENDIANNESS: this._getDecode32EndiannessString(), ENCODE32_ENDIANNESS: this._getEncode32EndiannessString(), DIVIDE_WITH_INTEGER_CHECK: this._getDivideWithIntegerCheckString(), MAIN_CONSTANTS: this._getMainConstantsString(), MAIN_ARGUMENTS: this._getMainArgumentsString(args), KERNEL: this.getKernelString(), MAIN_RESULT: this.getMainResultString() }; } _getHeaderString() { return ( this.subKernels !== null ? '#extension GL_EXT_draw_buffers : require\n' : '' ); } _getLoopMaxString() { return ( this.loopMaxIterations ? ` ${parseInt(this.loopMaxIterations)};\n` : ' 1000;\n' ); } _getPluginsString() { if (!this.plugins) return '\n'; return this.plugins.map(plugin => plugin.source && this.source.match(plugin.functionMatch) ? plugin.source : '').join('\n'); } _getConstantsString() { const result = []; const { threadDim, texSize } = this; if (this.dynamicOutput) { result.push( 'uniform ivec3 uOutputDim', 'uniform ivec2 uTexSize' ); } else { result.push( `ivec3 uOutputDim = ivec3(${threadDim[0]}, ${threadDim[1]}, ${threadDim[2]})`, `ivec2 uTexSize = ivec2(${texSize[0]}, ${texSize[1]})` ); } return utils.linesToString(result); } _getTextureCoordinate() { const subKernels = this.subKernels; if (subKernels === null || subKernels.length < 1) { return 'varying vec2 vTexCoord;\n'; } else { return 'out vec2 vTexCoord;\n'; } } _getDecode32EndiannessString() { return ( this.endianness === 'LE' ? '' : ' texel.rgba = texel.abgr;\n' ); } _getEncode32EndiannessString() { return ( this.endianness === 'LE' ? '' : ' texel.rgba = texel.abgr;\n' ); } _getDivideWithIntegerCheckString() { return this.fixIntegerDivisionAccuracy ? `float div_with_int_check(float x, float y) { if (floor(x) == x && floor(y) == y && integerMod(x, y) == 0.0) { return float(int(x)/int(y)); } return x / y; }` : ''; } _getMainArgumentsString(args) { const results = []; const { argumentNames } = this; for (let i = 0; i < argumentNames.length; i++) { results.push(this.kernelArguments[i].getSource(args[i])); } return results.join(''); } _getMainConstantsString() { const result = []; const { constants } = this; if (constants) { let i = 0; for (const name in constants) { result.push(this.kernelConstants[i++].getSource(this.constants[name])); } } return result.join(''); } getKernelString() { let kernelResultDeclaration; switch (this.returnType) { case 'Array(2)': kernelResultDeclaration = 'vec2 kernelResult'; break; case 'Array(3)': kernelResultDeclaration = 'vec3 kernelResult'; break; case 'Array(4)': kernelResultDeclaration = 'vec4 kernelResult'; break; case 'LiteralInteger': case 'Float': case 'Number': case 'Integer': kernelResultDeclaration = 'float kernelResult'; break; default: if (this.graphical) { kernelResultDeclaration = 'float kernelResult'; } else { throw new Error(`unrecognized output type "${ this.returnType }"`); } } const result = []; const subKernels = this.subKernels; if (subKernels !== null) { result.push( kernelResultDeclaration ); for (let i = 0; i < subKernels.length; i++) { result.push( `float subKernelResult_${ subKernels[i].name } = 0.0` ); } } else { result.push( kernelResultDeclaration ); } return utils.linesToString(result) + this.translatedSource; } getMainResultGraphical() { return utils.linesToString([ ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ' gl_FragColor = actualColor', ]); } getMainResultPackedPixels() { switch (this.returnType) { case 'LiteralInteger': case 'Number': case 'Integer': case 'Float': return utils.linesToString(this.getMainResultKernelPackedPixels()) + utils.linesToString(this.getMainResultSubKernelPackedPixels()); default: throw new Error(`packed output only usable with Numbers, "${this.returnType}" specified`); } } getMainResultKernelPackedPixels() { return [ ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ' gl_FragData[0] = encode32(kernelResult)' ]; } getMainResultSubKernelPackedPixels() { const result = []; if (!this.subKernels) return result; for (let i = 0; i < this.subKernels.length; i++) { result.push( ` gl_FragData[${i + 1}] = encode32(subKernelResult_${this.subKernels[i].name})` ); } return result; } getMainResultMemoryOptimizedFloats() { const result = [ ' index *= 4', ]; switch (this.returnType) { case 'Number': case 'Integer': case 'Float': const channels = ['r', 'g', 'b', 'a']; for (let i = 0; i < channels.length; i++) { const channel = channels[i]; this.getMainResultKernelMemoryOptimizedFloats(result, channel); this.getMainResultSubKernelMemoryOptimizedFloats(result, channel); if (i + 1 < channels.length) { result.push(' index += 1'); } } break; default: throw new Error(`optimized output only usable with Numbers, ${this.returnType} specified`); } return utils.linesToString(result); } getMainResultKernelMemoryOptimizedFloats(result, channel) { result.push( ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ` gl_FragData[0].${channel} = kernelResult`, ); } getMainResultSubKernelMemoryOptimizedFloats(result, channel) { if (!this.subKernels) return result; for (let i = 0; i < this.subKernels.length; i++) { result.push( ` gl_FragData[${i + 1}].${channel} = subKernelResult_${this.subKernels[i].name}`, ); } } getMainResultKernelNumberTexture() { return [ ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ' gl_FragData[0][0] = kernelResult', ]; } getMainResultSubKernelNumberTexture() { const result = []; if (!this.subKernels) return result; for (let i = 0; i < this.subKernels.length; ++i) { result.push( ` gl_FragData[${i + 1}][0] = subKernelResult_${this.subKernels[i].name}`, ); } return result; } getMainResultKernelArray2Texture() { return [ ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ' gl_FragData[0][0] = kernelResult[0]', ' gl_FragData[0][1] = kernelResult[1]', ]; } getMainResultSubKernelArray2Texture() { const result = []; if (!this.subKernels) return result; for (let i = 0; i < this.subKernels.length; ++i) { result.push( ` gl_FragData[${i + 1}][0] = subKernelResult_${this.subKernels[i].name}[0]`, ` gl_FragData[${i + 1}][1] = subKernelResult_${this.subKernels[i].name}[1]`, ); } return result; } getMainResultKernelArray3Texture() { return [ ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ' gl_FragData[0][0] = kernelResult[0]', ' gl_FragData[0][1] = kernelResult[1]', ' gl_FragData[0][2] = kernelResult[2]', ]; } getMainResultSubKernelArray3Texture() { const result = []; if (!this.subKernels) return result; for (let i = 0; i < this.subKernels.length; ++i) { result.push( ` gl_FragData[${i + 1}][0] = subKernelResult_${this.subKernels[i].name}[0]`, ` gl_FragData[${i + 1}][1] = subKernelResult_${this.subKernels[i].name}[1]`, ` gl_FragData[${i + 1}][2] = subKernelResult_${this.subKernels[i].name}[2]`, ); } return result; } getMainResultKernelArray4Texture() { return [ ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ' gl_FragData[0] = kernelResult', ]; } getMainResultSubKernelArray4Texture() { const result = []; if (!this.subKernels) return result; for (let i = 0; i < this.subKernels.length; ++i) { result.push( ` gl_FragData[${i + 1}] = subKernelResult_${this.subKernels[i].name}`, ); } return result; } replaceArtifacts(src, map) { return src.replace(/[ ]*__([A-Z]+[0-9]*([_]?[A-Z])*)__;\n/g, (match, artifact) => { if (map.hasOwnProperty(artifact)) { return map[artifact]; } throw `unhandled artifact ${artifact}`; }); } getFragmentShader(args) { if (this.compiledFragmentShader !== null) { return this.compiledFragmentShader; } return this.compiledFragmentShader = this.replaceArtifacts(this.constructor.fragmentShader, this._getFragShaderArtifactMap(args)); } getVertexShader(args) { if (this.compiledVertexShader !== null) { return this.compiledVertexShader; } return this.compiledVertexShader = this.constructor.vertexShader; } toString() { const setupContextString = utils.linesToString([ `const gl = context`, ]); return glKernelString(this.constructor, arguments, this, setupContextString); } destroy(removeCanvasReferences) { if (this.outputTexture) { this.context.deleteTexture(this.outputTexture); } if (this.buffer) { this.context.deleteBuffer(this.buffer); } if (this.framebuffer) { this.context.deleteFramebuffer(this.framebuffer); } if (this.vertShader) { this.context.deleteShader(this.vertShader); } if (this.fragShader) { this.context.deleteShader(this.fragShader); } if (this.program) { this.context.deleteProgram(this.program); } const keys = Object.keys(this.textureCache); for (let i = 0; i < keys.length; i++) { const name = keys[i]; this.context.deleteTexture(this.textureCache[name]); } if (this.subKernelOutputTextures) { for (let i = 0; i < this.subKernelOutputTextures.length; i++) { this.context.deleteTexture(this.subKernelOutputTextures[i]); } } if (removeCanvasReferences) { const idx = canvases.indexOf(this.canvas); if (idx >= 0) { canvases[idx] = null; maxTexSizes[idx] = null; } } this.destroyExtensions(); delete this.context; delete this.canvas; } destroyExtensions() { this.extensions.OES_texture_float = null; this.extensions.OES_texture_float_linear = null; this.extensions.OES_element_index_uint = null; this.extensions.WEBGL_draw_buffers = null; } static destroyContext(context) { const extension = context.getExtension('WEBGL_lose_context'); if (extension) { extension.loseContext(); } } toJSON() { const json = super.toJSON(); json.functionNodes = FunctionBuilder.fromKernel(this, WebGLFunctionNode).toJSON(); return json; } } module.exports = { WebGLKernel }; },{"../../plugins/triangle-noise":68,"../../texture":69,"../../utils":70,"../function-builder":9,"../gl/kernel":12,"../gl/kernel-string":11,"./fragment-shader":16,"./function-node":17,"./kernel-value-maps":18,"./vertex-shader":38}],38:[function(require,module,exports){ const vertexShader = `precision highp float; precision highp int; precision highp sampler2D; attribute vec2 aPos; attribute vec2 aTexCoord; varying vec2 vTexCoord; uniform vec2 ratio; void main(void) { gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1); vTexCoord = aTexCoord; }`; module.exports = { vertexShader }; },{}],39:[function(require,module,exports){ const fragmentShader = `#version 300 es __HEADER__; precision highp float; precision highp int; precision highp sampler2D; const int LOOP_MAX = __LOOP_MAX__; __PLUGINS__; __CONSTANTS__; in vec2 vTexCoord; vec2 integerMod(vec2 x, float y) { vec2 res = floor(mod(x, y)); return res * step(1.0 - floor(y), -res); } vec3 integerMod(vec3 x, float y) { vec3 res = floor(mod(x, y)); return res * step(1.0 - floor(y), -res); } vec4 integerMod(vec4 x, vec4 y) { vec4 res = floor(mod(x, y)); return res * step(1.0 - floor(y), -res); } float integerMod(float x, float y) { float res = floor(mod(x, y)); return res * (res > floor(y) - 1.0 ? 0.0 : 1.0); } int integerMod(int x, int y) { return x - (y * int(x/y)); } __DIVIDE_WITH_INTEGER_CHECK__; // Here be dragons! // DO NOT OPTIMIZE THIS CODE // YOU WILL BREAK SOMETHING ON SOMEBODY\'S MACHINE // LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME const vec2 MAGIC_VEC = vec2(1.0, -256.0); const vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0); const vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536 float decode32(vec4 texel) { __DECODE32_ENDIANNESS__; texel *= 255.0; vec2 gte128; gte128.x = texel.b >= 128.0 ? 1.0 : 0.0; gte128.y = texel.a >= 128.0 ? 1.0 : 0.0; float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC); float res = exp2(round(exponent)); texel.b = texel.b - 128.0 * gte128.x; res = dot(texel, SCALE_FACTOR) * exp2(round(exponent-23.0)) + res; res *= gte128.y * -2.0 + 1.0; return res; } float decode16(vec4 texel, int index) { int channel = integerMod(index, 2); return texel[channel*2] * 255.0 + texel[channel*2 + 1] * 65280.0; } float decode8(vec4 texel, int index) { int channel = integerMod(index, 4); return texel[channel] * 255.0; } vec4 encode32(float f) { float F = abs(f); float sign = f < 0.0 ? 1.0 : 0.0; float exponent = floor(log2(F)); float mantissa = (exp2(-exponent) * F); // exponent += floor(log2(mantissa)); vec4 texel = vec4(F * exp2(23.0 - exponent)) * SCALE_FACTOR_INV; texel.rg = integerMod(texel.rg, 256.0); texel.b = integerMod(texel.b, 128.0); texel.a = exponent * 0.5 + 63.5; texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0; texel = floor(texel); texel *= 0.003921569; // 1/255 __ENCODE32_ENDIANNESS__; return texel; } // Dragons end here int index; ivec3 threadId; ivec3 indexTo3D(int idx, ivec3 texDim) { int z = int(idx / (texDim.x * texDim.y)); idx -= z * int(texDim.x * texDim.y); int y = int(idx / texDim.x); int x = int(integerMod(idx, texDim.x)); return ivec3(x, y, z); } float get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { ivec3 xyz = ivec3(x, y, z); int index = xyz.x + texDim.x * (xyz.y + texDim.y * xyz.z); int w = texSize.x; vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; vec4 texel = texture(tex, st / vec2(texSize)); return decode32(texel); } float get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { ivec3 xyz = ivec3(x, y, z); int index = xyz.x + (texDim.x * (xyz.y + (texDim.y * xyz.z))); int w = texSize.x * 2; vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; vec4 texel = texture(tex, st / vec2(texSize.x * 2, texSize.y)); return decode16(texel, index); } float get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { ivec3 xyz = ivec3(x, y, z); int index = xyz.x + (texDim.x * (xyz.y + (texDim.y * xyz.z))); int w = texSize.x * 4; vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; vec4 texel = texture(tex, st / vec2(texSize.x * 4, texSize.y)); return decode8(texel, index); } float getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { ivec3 xyz = ivec3(x, y, z); int index = xyz.x + (texDim.x * (xyz.y + (texDim.y * xyz.z))); int channel = integerMod(index, 4); index = index / 4; int w = texSize.x; vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; index = index / 4; vec4 texel = texture(tex, st / vec2(texSize)); return texel[channel]; } vec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { ivec3 xyz = ivec3(x, y, z); int index = xyz.x + texDim.x * (xyz.y + texDim.y * xyz.z); int w = texSize.x; vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; return texture(tex, st / vec2(texSize)); } vec4 getImage3D(sampler2DArray tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { ivec3 xyz = ivec3(x, y, z); int index = xyz.x + texDim.x * (xyz.y + texDim.y * xyz.z); int w = texSize.x; vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5; return texture(tex, vec3(st / vec2(texSize), z)); } float getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { vec4 result = getImage2D(tex, texSize, texDim, z, y, x); return result[0]; } vec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { vec4 result = getImage2D(tex, texSize, texDim, z, y, x); return vec2(result[0], result[1]); } vec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { vec4 result = getImage2D(tex, texSize, texDim, z, y, x); return vec3(result[0], result[1], result[2]); } vec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) { return getImage2D(tex, texSize, texDim, z, y, x); } vec4 actualColor; void color(float r, float g, float b, float a) { actualColor = vec4(r,g,b,a); } void color(float r, float g, float b) { color(r,g,b,1.0); } __MAIN_CONSTANTS__; __MAIN_ARGUMENTS__; __KERNEL__; void main(void) { index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x; __MAIN_RESULT__; }`; module.exports = { fragmentShader }; },{}],40:[function(require,module,exports){ const { WebGLFunctionNode } = require('../web-gl/function-node'); class WebGL2FunctionNode extends WebGLFunctionNode { astIdentifierExpression(idtNode, retArr) { if (idtNode.type !== 'Identifier') { throw this.astErrorOutput( 'IdentifierExpression - not an Identifier', idtNode ); } const type = this.getType(idtNode); if (idtNode.name === 'Infinity') { retArr.push('intBitsToFloat(2139095039)'); } else if (type === 'Boolean') { if (this.argumentNames.indexOf(idtNode.name) > -1) { retArr.push(`bool(user_${idtNode.name})`); } else { retArr.push(`user_${idtNode.name}`); } } else { const userArgumentName = this.getKernelArgumentName(idtNode.name); if (userArgumentName) { retArr.push(`user_${userArgumentName}`); } else { retArr.push(`user_${idtNode.name}`); } } return retArr; } } module.exports = { WebGL2FunctionNode }; },{"../web-gl/function-node":17}],41:[function(require,module,exports){ const { WebGL2KernelValueBoolean } = require('./kernel-value/boolean'); const { WebGL2KernelValueFloat } = require('./kernel-value/float'); const { WebGL2KernelValueInteger } = require('./kernel-value/integer'); const { WebGL2KernelValueHTMLImage } = require('./kernel-value/html-image'); const { WebGL2KernelValueDynamicHTMLImage } = require('./kernel-value/dynamic-html-image'); const { WebGL2KernelValueHtmlImageArray } = require('./kernel-value/html-image-array'); const { WebGL2KernelValueDynamicHtmlImageArray } = require('./kernel-value/dynamic-html-image-array'); const { WebGL2KernelValueSingleInput } = require('./kernel-value/single-input'); const { WebGL2KernelValueDynamicSingleInput } = require('./kernel-value/dynamic-single-input'); const { WebGL2KernelValueUnsignedInput } = require('./kernel-value/unsigned-input'); const { WebGL2KernelValueDynamicUnsignedInput } = require('./kernel-value/dynamic-unsigned-input'); const { WebGL2KernelValueMemoryOptimizedNumberTexture } = require('./kernel-value/memory-optimized-number-texture'); const { WebGL2KernelValueDynamicMemoryOptimizedNumberTexture } = require('./kernel-value/dynamic-memory-optimized-number-texture'); const { WebGL2KernelValueNumberTexture } = require('./kernel-value/number-texture'); const { WebGL2KernelValueDynamicNumberTexture } = require('./kernel-value/dynamic-number-texture'); const { WebGL2KernelValueSingleArray } = require('./kernel-value/single-array'); const { WebGL2KernelValueDynamicSingleArray } = require('./kernel-value/dynamic-single-array'); const { WebGL2KernelValueUnsignedArray } = require('./kernel-value/unsigned-array'); const { WebGL2KernelValueDynamicUnsignedArray } = require('./kernel-value/dynamic-unsigned-array'); const kernelValueMaps = { unsigned: { dynamic: { 'Boolean': WebGL2KernelValueBoolean, 'Interger': WebGL2KernelValueInteger, 'Float': WebGL2KernelValueFloat, 'Array': WebGL2KernelValueDynamicUnsignedArray, 'Input': WebGL2KernelValueDynamicUnsignedInput, 'NumberTexture': WebGL2KernelValueDynamicNumberTexture, 'ArrayTexture(1)': WebGL2KernelValueDynamicNumberTexture, 'ArrayTexture(2)': WebGL2KernelValueDynamicNumberTexture, 'ArrayTexture(3)': WebGL2KernelValueDynamicNumberTexture, 'ArrayTexture(4)': WebGL2KernelValueDynamicNumberTexture, 'MemoryOptimizedNumberTexture': WebGL2KernelValueDynamicMemoryOptimizedNumberTexture, 'HTMLImage': WebGL2KernelValueDynamicHTMLImage, 'HTMLImageArray': WebGL2KernelValueDynamicHtmlImageArray, }, static: { 'Boolean': WebGL2KernelValueBoolean, 'Interger': WebGL2KernelValueInteger, 'Float': WebGL2KernelValueFloat, 'Integer': WebGL2KernelValueInteger, 'Array': WebGL2KernelValueUnsignedArray, 'Input': WebGL2KernelValueUnsignedInput, 'NumberTexture': WebGL2KernelValueNumberTexture, 'ArrayTexture(1)': WebGL2KernelValueNumberTexture, 'ArrayTexture(2)': WebGL2KernelValueNumberTexture, 'ArrayTexture(3)': WebGL2KernelValueNumberTexture, 'ArrayTexture(4)': WebGL2KernelValueNumberTexture, 'MemoryOptimizedNumberTexture': WebGL2KernelValueDynamicMemoryOptimizedNumberTexture, 'HTMLImage': WebGL2KernelValueHTMLImage, 'HTMLImageArray': WebGL2KernelValueHtmlImageArray, } }, single: { dynamic: { 'Boolean': WebGL2KernelValueBoolean, 'Interger': WebGL2KernelValueInteger, 'Float': WebGL2KernelValueFloat, 'Array': WebGL2KernelValueDynamicSingleArray, 'Input': WebGL2KernelValueDynamicSingleInput, 'NumberTexture': WebGL2KernelValueDynamicNumberTexture, 'ArrayTexture(1)': WebGL2KernelValueDynamicNumberTexture, 'ArrayTexture(2)': WebGL2KernelValueDynamicNumberTexture, 'ArrayTexture(3)': WebGL2KernelValueDynamicNumberTexture, 'ArrayTexture(4)': WebGL2KernelValueDynamicNumberTexture, 'MemoryOptimizedNumberTexture': WebGL2KernelValueDynamicMemoryOptimizedNumberTexture, 'HTMLImage': WebGL2KernelValueDynamicHTMLImage, 'HTMLImageArray': WebGL2KernelValueDynamicHtmlImageArray, }, static: { 'Boolean': WebGL2KernelValueBoolean, 'Interger': WebGL2KernelValueInteger, 'Float': WebGL2KernelValueFloat, 'Integer': WebGL2KernelValueInteger, 'Array': WebGL2KernelValueSingleArray, 'Input': WebGL2KernelValueSingleInput, 'NumberTexture': WebGL2KernelValueNumberTexture, 'ArrayTexture(1)': WebGL2KernelValueNumberTexture, 'ArrayTexture(2)': WebGL2KernelValueNumberTexture, 'ArrayTexture(3)': WebGL2KernelValueNumberTexture, 'ArrayTexture(4)': WebGL2KernelValueNumberTexture, 'MemoryOptimizedNumberTexture': WebGL2KernelValueMemoryOptimizedNumberTexture, 'HTMLImage': WebGL2KernelValueHTMLImage, 'HTMLImageArray': WebGL2KernelValueHtmlImageArray, } }, }; function lookupKernelValueType(type, dynamic, precision) { if (!type) { throw new Error('type missing'); } if (!dynamic) { throw new Error('dynamic missing'); } if (!precision) { throw new Error('precision missing'); } const types = kernelValueMaps[precision][dynamic]; if (types[type] === false) { return null; } else if (types[type] === undefined) { throw new Error(`Could not find a KernelValue for ${ type }`); } return types[type]; } module.exports = { lookupKernelValueType }; },{"./kernel-value/boolean":42,"./kernel-value/dynamic-html-image":44,"./kernel-value/dynamic-html-image-array":43,"./kernel-value/dynamic-memory-optimized-number-texture":45,"./kernel-value/dynamic-number-texture":46,"./kernel-value/dynamic-single-array":47,"./kernel-value/dynamic-single-input":48,"./kernel-value/dynamic-unsigned-array":49,"./kernel-value/dynamic-unsigned-input":50,"./kernel-value/float":51,"./kernel-value/html-image":53,"./kernel-value/html-image-array":52,"./kernel-value/integer":54,"./kernel-value/memory-optimized-number-texture":55,"./kernel-value/number-texture":56,"./kernel-value/single-array":57,"./kernel-value/single-input":58,"./kernel-value/unsigned-array":59,"./kernel-value/unsigned-input":60}],42:[function(require,module,exports){ const { WebGLKernelValueBoolean } = require('../../web-gl/kernel-value/boolean'); class WebGL2KernelValueBoolean extends WebGLKernelValueBoolean {} module.exports = { WebGL2KernelValueBoolean }; },{"../../web-gl/kernel-value/boolean":19}],43:[function(require,module,exports){ const { WebGL2KernelValueHtmlImageArray } = require('./html-image-array'); class WebGL2KernelValueDynamicHtmlImageArray extends WebGL2KernelValueHtmlImageArray { getSource() { return utils.linesToString([ `uniform highp sampler2DArray ${this.id}`, `uniform highp ivec2 ${this.sizeId}`, `uniform highp ivec3 ${this.dimensionsId}`, ]); } updateValue(images) { this.dimensions = [images[0].width, images[0].height, images.length]; this.textureSize = [images[0].width, images[0].height]; this.kernel.setUniform3iv(this.dimensionsId, this.dimensions); this.kernel.setUniform2iv(this.sizeId, this.textureSize); super.updateValue(images); } } module.exports = { WebGL2KernelValueDynamicHtmlImageArray }; },{"./html-image-array":52}],44:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueDynamicInput } = require('../../web-gl/kernel-value/dynamic-html-image'); class WebGL2KernelValueDynamicInput extends WebGLKernelValueDynamicInput { getSource() { return utils.linesToString([ `uniform highp sampler2D ${this.id}`, `uniform highp ivec2 ${this.sizeId}`, `uniform highp ivec3 ${this.dimensionsId}`, ]); } } module.exports = { WebGL2KernelValueDynamicInput }; },{"../../../utils":70,"../../web-gl/kernel-value/dynamic-html-image":20}],45:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueDynamicMemoryOptimizedNumberTexture } = require('../../web-gl/kernel-value/dynamic-memory-optimized-number-texture'); class WebGL2KernelValueDynamicMemoryOptimizedNumberTexture extends WebGLKernelValueDynamicMemoryOptimizedNumberTexture { getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `uniform ivec2 ${this.sizeId}`, `uniform ivec3 ${this.dimensionsId}`, ]); } } module.exports = { WebGL2KernelValueDynamicMemoryOptimizedNumberTexture }; },{"../../../utils":70,"../../web-gl/kernel-value/dynamic-memory-optimized-number-texture":21}],46:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueDynamicNumberTexture } = require('../../web-gl/kernel-value/dynamic-number-texture'); class WebGL2KernelValueDynamicNumberTexture extends WebGLKernelValueDynamicNumberTexture { getSource() { return utils.linesToString([ `uniform highp sampler2D ${this.id}`, `uniform highp ivec2 ${this.sizeId}`, `uniform highp ivec3 ${this.dimensionsId}`, ]); } } module.exports = { WebGL2KernelValueDynamicNumberTexture }; },{"../../../utils":70,"../../web-gl/kernel-value/dynamic-number-texture":22}],47:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueDynamicSingleArray } = require('../../web-gl/kernel-value/dynamic-single-array'); class WebGL2KernelValueDynamicSingleArray extends WebGLKernelValueDynamicSingleArray { getSource() { return utils.linesToString([ `uniform highp sampler2D ${this.id}`, `uniform highp ivec2 ${this.sizeId}`, `uniform highp ivec3 ${this.dimensionsId}`, ]); } } module.exports = { WebGL2KernelValueDynamicSingleArray }; },{"../../../utils":70,"../../web-gl/kernel-value/dynamic-single-array":23}],48:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueDynamicSingleInput } = require('../../web-gl/kernel-value/dynamic-single-input'); class WebGL2KernelValueDynamicSingleInput extends WebGLKernelValueDynamicSingleInput { getSource() { return utils.linesToString([ `uniform highp sampler2D ${this.id}`, `uniform highp ivec2 ${this.sizeId}`, `uniform highp ivec3 ${this.dimensionsId}`, ]); } } module.exports = { WebGL2KernelValueDynamicSingleInput }; },{"../../../utils":70,"../../web-gl/kernel-value/dynamic-single-input":24}],49:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueDynamicUnsignedArray } = require('../../web-gl/kernel-value/dynamic-unsigned-array'); class WebGL2KernelValueDynamicUnsignedArray extends WebGLKernelValueDynamicUnsignedArray { getSource() { return utils.linesToString([ `uniform highp sampler2D ${this.id}`, `uniform highp ivec2 ${this.sizeId}`, `uniform highp ivec3 ${this.dimensionsId}`, ]); } } module.exports = { WebGL2KernelValueDynamicUnsignedArray }; },{"../../../utils":70,"../../web-gl/kernel-value/dynamic-unsigned-array":25}],50:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueDynamicUnsignedInput } = require('../../web-gl/kernel-value/dynamic-unsigned-input'); class WebGL2KernelValueDynamicUnsignedInput extends WebGLKernelValueDynamicUnsignedInput { getSource() { return utils.linesToString([ `uniform highp sampler2D ${this.id}`, `uniform highp ivec2 ${this.sizeId}`, `uniform highp ivec3 ${this.dimensionsId}`, ]); } } module.exports = { WebGL2KernelValueDynamicUnsignedInput }; },{"../../../utils":70,"../../web-gl/kernel-value/dynamic-unsigned-input":26}],51:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueFloat } = require('../../web-gl/kernel-value/float'); class WebGL2KernelValueFloat extends WebGLKernelValueFloat {} module.exports = { WebGL2KernelValueFloat }; },{"../../../utils":70,"../../web-gl/kernel-value/float":27}],52:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValue } = require('../../web-gl/kernel-value/index'); class WebGL2KernelValueHtmlImageArray extends WebGLKernelValue { constructor(value, settings) { super(value, settings); this.requestTexture(); this.dimensions = [value[0].width, value[0].height, value.length]; this.textureSize = [value[0].width, value[0].height]; } getSource() { return utils.linesToString([ `uniform highp sampler2DArray ${this.id}`, `highp ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `highp ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } updateValue(images) { const { context: gl } = this; gl.activeTexture(this.contextHandle); gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.texture); gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); gl.texImage3D( gl.TEXTURE_2D_ARRAY, 0, gl.RGBA, images[0].width, images[0].height, images.length, 0, gl.RGBA, gl.UNSIGNED_BYTE, null ); for (let i = 0; i < images.length; i++) { const xOffset = 0; const yOffset = 0; const imageDepth = 1; gl.texSubImage3D( gl.TEXTURE_2D_ARRAY, 0, xOffset, yOffset, i, images[i].width, images[i].height, imageDepth, gl.RGBA, gl.UNSIGNED_BYTE, this.uploadValue = images[i] ); } this.kernel.setUniform1i(this.id, this.index); } } module.exports = { WebGL2KernelValueHtmlImageArray }; },{"../../../utils":70,"../../web-gl/kernel-value/index":29}],53:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueHTMLImage } = require('../../web-gl/kernel-value/html-image'); class WebGL2KernelValueHTMLImage extends WebGLKernelValueHTMLImage { getSource() { return utils.linesToString([ `uniform highp sampler2D ${this.id}`, `highp ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `highp ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } } module.exports = { WebGL2KernelValueHTMLImage }; },{"../../../utils":70,"../../web-gl/kernel-value/html-image":28}],54:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueInteger } = require('../../web-gl/kernel-value/integer'); class WebGL2KernelValueInteger extends WebGLKernelValueInteger { getSource(value) { if (this.origin === 'constants') { return `const highp int ${this.id} = ${ parseInt(value) };\n`; } return `uniform highp int ${this.id};\n`; } updateValue(value) { if (this.origin === 'constants') return; this.kernel.setUniform1i(this.id, this.uploadValue = value); } } module.exports = { WebGL2KernelValueInteger }; },{"../../../utils":70,"../../web-gl/kernel-value/integer":30}],55:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueMemoryOptimizedNumberTexture } = require('../../web-gl/kernel-value/memory-optimized-number-texture'); class WebGL2KernelValueMemoryOptimizedNumberTexture extends WebGLKernelValueMemoryOptimizedNumberTexture { getSource() { return utils.linesToString([ `uniform sampler2D ${this.id}`, `highp ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `highp ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } } module.exports = { WebGL2KernelValueMemoryOptimizedNumberTexture }; },{"../../../utils":70,"../../web-gl/kernel-value/memory-optimized-number-texture":31}],56:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueNumberTexture } = require('../../web-gl/kernel-value/number-texture'); class WebGL2KernelValueNumberTexture extends WebGLKernelValueNumberTexture { getSource() { return utils.linesToString([ `uniform highp sampler2D ${this.id}`, `highp ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `highp ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } } module.exports = { WebGL2KernelValueNumberTexture }; },{"../../../utils":70,"../../web-gl/kernel-value/number-texture":32}],57:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueSingleArray } = require('../../web-gl/kernel-value/single-array'); class WebGL2KernelValueSingleArray extends WebGLKernelValueSingleArray { getSource() { return utils.linesToString([ `uniform highp sampler2D ${this.id}`, `highp ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `highp ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } updateValue(value) { if (value.constructor !== this.initialValueConstructor) { this.onUpdateValueMismatch(); return; } const { context: gl } = this; utils.flattenTo(value, this.uploadValue); gl.activeTexture(this.contextHandle); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); this.kernel.setUniform1i(this.id, this.index); } } module.exports = { WebGL2KernelValueSingleArray }; },{"../../../utils":70,"../../web-gl/kernel-value/single-array":33}],58:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueSingleInput } = require('../../web-gl/kernel-value/single-input'); class WebGL2KernelValueSingleInput extends WebGLKernelValueSingleInput { getSource() { return utils.linesToString([ `uniform highp sampler2D ${this.id}`, `highp ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `highp ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } updateValue(input) { const { context: gl } = this; utils.flattenTo(input.value, this.uploadValue); gl.activeTexture(this.contextHandle); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, this.textureSize[0], this.textureSize[1], 0, gl.RGBA, gl.FLOAT, this.uploadValue); this.kernel.setUniform1i(this.id, this.index); } } module.exports = { WebGL2KernelValueSingleInput }; },{"../../../utils":70,"../../web-gl/kernel-value/single-input":34}],59:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueUnsignedArray } = require('../../web-gl/kernel-value/unsigned-array'); class WebGL2KernelValueUnsignedArray extends WebGLKernelValueUnsignedArray { getSource() { return utils.linesToString([ `uniform highp sampler2D ${this.id}`, `highp ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `highp ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } } module.exports = { WebGL2KernelValueUnsignedArray }; },{"../../../utils":70,"../../web-gl/kernel-value/unsigned-array":35}],60:[function(require,module,exports){ const { utils } = require('../../../utils'); const { WebGLKernelValueUnsignedInput } = require('../../web-gl/kernel-value/unsigned-input'); class WebGL2KernelValueUnsignedInput extends WebGLKernelValueUnsignedInput { getSource() { return utils.linesToString([ `uniform highp sampler2D ${this.id}`, `highp ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`, `highp ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`, ]); } } module.exports = { WebGL2KernelValueUnsignedInput }; },{"../../../utils":70,"../../web-gl/kernel-value/unsigned-input":36}],61:[function(require,module,exports){ const { WebGLKernel } = require('../web-gl/kernel'); const { WebGL2FunctionNode } = require('./function-node'); const { FunctionBuilder } = require('../function-builder'); const { utils } = require('../../utils'); const { Texture } = require('../../texture'); const { fragmentShader } = require('./fragment-shader'); const { vertexShader } = require('./vertex-shader'); const { lookupKernelValueType } = require('./kernel-value-maps'); let isSupported = null; let testCanvas = null; let testContext = null; let testExtensions = null; let features = null; class WebGL2Kernel extends WebGLKernel { static get isSupported() { if (isSupported !== null) { return isSupported; } this.setupFeatureChecks(); isSupported = this.isContextMatch(testContext); return isSupported; } static setupFeatureChecks() { if (typeof document !== 'undefined') { testCanvas = document.createElement('canvas'); } else if (typeof OffscreenCanvas !== 'undefined') { testCanvas = new OffscreenCanvas(0, 0); } if (!testCanvas) return; testContext = testCanvas.getContext('webgl2'); if (!testContext || !testContext.getExtension) return; testExtensions = { EXT_color_buffer_float: testContext.getExtension('EXT_color_buffer_float'), OES_texture_float_linear: testContext.getExtension('OES_texture_float_linear'), }; features = this.getFeatures(); } static isContextMatch(context) { if (typeof WebGL2RenderingContext !== 'undefined') { return context instanceof WebGL2RenderingContext; } return false; } static getFeatures() { return Object.freeze({ isFloatRead: this.getIsFloatRead(), isIntegerDivisionAccurate: this.getIsIntegerDivisionAccurate(), kernelMap: true, isTextureFloat: true, }); } static getIsTextureFloat() { return true; } static getIsIntegerDivisionAccurate() { return super.getIsIntegerDivisionAccurate(); } static lookupKernelValueType(type, dynamic, precision) { return lookupKernelValueType(type, dynamic, precision); } static get testCanvas() { return testCanvas; } static get testContext() { return testContext; } static get features() { return features; } static get fragmentShader() { return fragmentShader; } static get vertexShader() { return vertexShader; } initContext() { const settings = { alpha: false, depth: false, antialias: false }; const context = this.canvas.getContext('webgl2', settings); return context; } initExtensions() { this.extensions = { EXT_color_buffer_float: this.context.getExtension('EXT_color_buffer_float'), OES_texture_float_linear: this.context.getExtension('OES_texture_float_linear'), }; } validateSettings() { if (!this.validate) { this.texSize = utils.dimToTexSize({ floatTextures: this.optimizeFloatMemory, floatOutput: this.precision === 'single', }, this.output, true); return; } const features = this.constructor.features; if (this.precision === 'single' && !features.isFloatRead) { throw new Error('Float texture outputs are not supported'); } else if (!this.graphical && this.precision === null) { this.precision = features.isFloatRead ? 'single' : 'unsigned'; } if (this.fixIntegerDivisionAccuracy === null) { this.fixIntegerDivisionAccuracy = !features.isIntegerDivisionAccurate; } else if (this.fixIntegerDivisionAccuracy && features.isIntegerDivisionAccurate) { this.fixIntegerDivisionAccuracy = false; } this.checkOutput(); if (!this.output || this.output.length === 0) { if (arguments.length !== 1) { throw new Error('Auto output only supported for kernels with only one input'); } const argType = utils.getVariableType(arguments[0], this.strictIntegers); switch (argType) { case 'Array': this.output = utils.getDimensions(argType); break; case 'NumberTexture': case 'MemoryOptimizedNumberTexture': case 'ArrayTexture(1)': case 'ArrayTexture(2)': case 'ArrayTexture(3)': case 'ArrayTexture(4)': this.output = arguments[0].output; break; default: throw new Error('Auto output not supported for input type: ' + argType); } } if (this.graphical) { if (this.output.length !== 2) { throw new Error('Output must have 2 dimensions on graphical mode'); } if (this.precision === 'single') { console.warn('Cannot use graphical mode and single precision at the same time'); this.precision = 'unsigned'; } this.texSize = utils.clone(this.output); return; } else if (!this.graphical && this.precision === null && features.isTextureFloat) { this.precision = 'single'; } this.texSize = utils.dimToTexSize({ floatTextures: !this.optimizeFloatMemory, floatOutput: this.precision === 'single', }, this.output, true); if (this.precision === 'single') { this.context.getExtension('EXT_color_buffer_float'); } } translateSource() { const functionBuilder = FunctionBuilder.fromKernel(this, WebGL2FunctionNode, { fixIntegerDivisionAccuracy: this.fixIntegerDivisionAccuracy }); this.translatedSource = functionBuilder.getPrototypeString('kernel'); if (!this.graphical && !this.returnType) { this.returnType = functionBuilder.getKernelResultType(); } } run() { const { kernelArguments, texSize } = this; const gl = this.context; gl.useProgram(this.program); gl.scissor(0, 0, texSize[0], texSize[1]); if (this.dynamicOutput) { this.setUniform3iv('uOutputDim', new Int32Array(this.threadDim)); this.setUniform2iv('uTexSize', texSize); } this.setUniform2f('ratio', texSize[0] / this.maxTexSize[0], texSize[1] / this.maxTexSize[1]); for (let i = 0; i < kernelArguments.length; i++) { if (this.switchingKernels) return; kernelArguments[i].updateValue(arguments[i]); } if (this.plugins) { for (let i = 0; i < this.plugins.length; i++) { const plugin = this.plugins[i]; if (plugin.onBeforeRun) { plugin.onBeforeRun(this); } } } if (this.graphical) { if (this.pipeline) { gl.bindRenderbuffer(gl.RENDERBUFFER, null); gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); if (!this.outputTexture || this.immutable) { this._setupOutputTexture(); } gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); return new Texture({ texture: this.outputTexture, size: texSize, dimensions: this.threadDim, output: this.output, context: this.context, gpu: this.gpu, type: this.getReturnTextureType(), }); } gl.bindRenderbuffer(gl.RENDERBUFFER, null); gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); return; } gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); if (this.immutable) { this._setupOutputTexture(); } if (this.subKernels !== null) { if (this.immutable) { this._setupSubOutputTextures(); } gl.drawBuffers(this.drawBuffersMap); } gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); } drawBuffers() { this.context.drawBuffers(this.drawBuffersMap); } getOutputTexture() { return this.outputTexture; } _setupOutputTexture() { const { texSize } = this; const gl = this.context; const texture = this.outputTexture = gl.createTexture(); gl.activeTexture(gl.TEXTURE0 + this.constantTextureCount + this.argumentTextureCount); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); if (this.precision === 'single') { if (this.pipeline) { switch (this.returnType) { case 'Number': case 'Float': case 'Integer': if (this.optimizeFloatMemory) { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); } else { gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, texSize[0], texSize[1], 0, gl.RED, gl.FLOAT, null); } break; case 'Array(2)': gl.texImage2D(gl.TEXTURE_2D, 0, gl.RG32F, texSize[0], texSize[1], 0, gl.RG, gl.FLOAT, null); break; case 'Array(3)': gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB32F, texSize[0], texSize[1], 0, gl.RGB, gl.FLOAT, null); break; case 'Array(4)': gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); break; default: throw new Error('Unhandled return type'); } } else { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); } } else { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, null); } gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); } _setupSubOutputTextures() { const { texSize } = this; const gl = this.context; this.drawBuffersMap = [gl.COLOR_ATTACHMENT0]; this.subKernelOutputTextures = []; for (let i = 0; i < this.subKernels.length; i++) { const texture = this.context.createTexture(); this.subKernelOutputTextures.push(texture); this.drawBuffersMap.push(gl.COLOR_ATTACHMENT0 + i + 1); gl.activeTexture(gl.TEXTURE0 + this.constantTextureCount + this.argumentTextureCount + i); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); if (this.precision === 'single') { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); } else { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, null); } gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i + 1, gl.TEXTURE_2D, texture, 0); } } _getHeaderString() { return ''; } _getTextureCoordinate() { const subKernels = this.subKernels; if (subKernels === null || subKernels.length < 1) { return 'in highp vec2 vTexCoord;\n'; } else { return 'out highp vec2 vTexCoord;\n'; } } _getMainArgumentsString(args) { const result = []; const argumentNames = this.argumentNames; for (let i = 0; i < argumentNames.length; i++) { result.push(this.kernelArguments[i].getSource(args[i])); } return result.join(''); } getKernelString() { let kernelResultDeclaration; switch (this.returnType) { case 'Array(2)': kernelResultDeclaration = 'vec2 kernelResult'; break; case 'Array(3)': kernelResultDeclaration = 'vec3 kernelResult'; break; case 'Array(4)': kernelResultDeclaration = 'vec4 kernelResult'; break; case 'LiteralInteger': case 'Float': case 'Number': case 'Integer': kernelResultDeclaration = 'float kernelResult'; break; default: if (this.graphical) { kernelResultDeclaration = 'float kernelResult'; } else { throw new Error(`unrecognized output type "${ this.returnType }"`); } } const result = []; const subKernels = this.subKernels; if (subKernels !== null) { result.push( kernelResultDeclaration, 'layout(location = 0) out vec4 data0' ); for (let i = 0; i < subKernels.length; i++) { result.push( `float subKernelResult_${ subKernels[i].name } = 0.0`, `layout(location = ${ i + 1 }) out vec4 data${ i + 1 }` ); } } else { result.push( 'out vec4 data0', kernelResultDeclaration ); } return utils.linesToString(result) + this.translatedSource; } getMainResultGraphical() { return utils.linesToString([ ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ' data0 = actualColor', ]); } getMainResultPackedPixels() { switch (this.returnType) { case 'LiteralInteger': case 'Number': case 'Integer': case 'Float': return utils.linesToString(this.getMainResultKernelPackedPixels()) + utils.linesToString(this.getMainResultSubKernelPackedPixels()); default: throw new Error(`packed output only usable with Numbers, "${this.returnType}" specified`); } } getMainResultKernelPackedPixels() { return [ ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ' data0 = encode32(kernelResult)' ]; } getMainResultSubKernelPackedPixels() { const result = []; if (!this.subKernels) return result; for (let i = 0; i < this.subKernels.length; i++) { result.push( ` data${i + 1} = encode32(subKernelResult_${this.subKernels[i].name})` ); } return result; } getMainResultMemoryOptimizedFloats() { const result = [ ' index *= 4', ]; switch (this.returnType) { case 'Number': case 'Integer': case 'Float': const channels = ['r', 'g', 'b', 'a']; for (let i = 0; i < channels.length; i++) { const channel = channels[i]; this.getMainResultKernelMemoryOptimizedFloats(result, channel); this.getMainResultSubKernelMemoryOptimizedFloats(result, channel); if (i + 1 < channels.length) { result.push(' index += 1'); } } break; default: throw new Error(`optimized output only usable with Numbers, ${this.returnType} specified`); } return utils.linesToString(result); } getMainResultKernelMemoryOptimizedFloats(result, channel) { result.push( ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ` data0.${channel} = kernelResult`, ); } getMainResultSubKernelMemoryOptimizedFloats(result, channel) { if (!this.subKernels) return result; for (let i = 0; i < this.subKernels.length; i++) { result.push( ` data${i + 1}.${channel} = subKernelResult_${this.subKernels[i].name}`, ); } } getMainResultKernelNumberTexture() { return [ ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ' data0[0] = kernelResult', ]; } getMainResultSubKernelNumberTexture() { const result = []; if (!this.subKernels) return result; for (let i = 0; i < this.subKernels.length; ++i) { result.push( ` data${i + 1}[0] = subKernelResult_${this.subKernels[i].name}`, ); } return result; } getMainResultKernelArray2Texture() { return [ ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ' data0[0] = kernelResult[0]', ' data0[1] = kernelResult[1]', ]; } getMainResultSubKernelArray2Texture() { const result = []; if (!this.subKernels) return result; for (let i = 0; i < this.subKernels.length; ++i) { result.push( ` data${i + 1}[0] = subKernelResult_${this.subKernels[i].name}[0]`, ` data${i + 1}[1] = subKernelResult_${this.subKernels[i].name}[1]`, ); } return result; } getMainResultKernelArray3Texture() { return [ ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ' data0[0] = kernelResult[0]', ' data0[1] = kernelResult[1]', ' data0[2] = kernelResult[2]', ]; } getMainResultSubKernelArray3Texture() { const result = []; if (!this.subKernels) return result; for (let i = 0; i < this.subKernels.length; ++i) { result.push( ` data${i + 1}[0] = subKernelResult_${this.subKernels[i].name}[0]`, ` data${i + 1}[1] = subKernelResult_${this.subKernels[i].name}[1]`, ` data${i + 1}[2] = subKernelResult_${this.subKernels[i].name}[2]`, ); } return result; } getMainResultKernelArray4Texture() { return [ ' threadId = indexTo3D(index, uOutputDim)', ' kernel()', ' data0 = kernelResult', ]; } getMainResultSubKernelArray4Texture() { const result = []; if (!this.subKernels) return result; for (let i = 0; i < this.subKernels.length; ++i) { result.push( ` data${i + 1} = subKernelResult_${this.subKernels[i].name}`, ); } return result; } getFragmentShader(args) { if (this.compiledFragmentShader !== null) { return this.compiledFragmentShader; } return this.compiledFragmentShader = this.replaceArtifacts(this.constructor.fragmentShader, this._getFragShaderArtifactMap(args)); } getVertexShader(args) { if (this.compiledVertexShader !== null) { return this.compiledVertexShader; } return this.compiledVertexShader = this.constructor.vertexShader; } destroyExtensions() { this.extensions.EXT_color_buffer_float = null; this.extensions.OES_texture_float_linear = null; } toJSON() { const json = super.toJSON(); json.functionNodes = FunctionBuilder.fromKernel(this, WebGL2FunctionNode).toJSON(); return json; } } module.exports = { WebGL2Kernel }; },{"../../texture":69,"../../utils":70,"../function-builder":9,"../web-gl/kernel":37,"./fragment-shader":39,"./function-node":40,"./kernel-value-maps":41,"./vertex-shader":62}],62:[function(require,module,exports){ const vertexShader = `#version 300 es precision highp float; precision highp int; precision highp sampler2D; in vec2 aPos; in vec2 aTexCoord; out vec2 vTexCoord; uniform vec2 ratio; void main(void) { gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1); vTexCoord = aTexCoord; }`; module.exports = { vertexShader }; },{}],63:[function(require,module,exports){ const lib = require('./index'); const GPU = lib.GPU; for (const p in lib) { if (!lib.hasOwnProperty(p)) continue; if (p === 'GPU') continue; GPU[p] = lib[p]; } if (typeof module !== 'undefined') { module.exports = GPU; } if (typeof window !== 'undefined') { window.GPU = GPU; } if (typeof self !== 'undefined') { self.GPU = GPU; } },{"./index":65}],64:[function(require,module,exports){ const gpuMock = require('gpu-mock.js'); const { utils } = require('./utils'); const { CPUKernel } = require('./backend/cpu/kernel'); const { HeadlessGLKernel } = require('./backend/headless-gl/kernel'); const { WebGL2Kernel } = require('./backend/web-gl2/kernel'); const { WebGLKernel } = require('./backend/web-gl/kernel'); const { kernelRunShortcut } = require('./kernel-run-shortcut'); const kernelOrder = [HeadlessGLKernel, WebGL2Kernel, WebGLKernel]; const kernelTypes = ['gpu', 'cpu']; const internalKernels = { 'headlessgl': HeadlessGLKernel, 'webgl2': WebGL2Kernel, 'webgl': WebGLKernel, }; let validate = true; class GPU { static disableValidation() { validate = false; } static enableValidation() { validate = true; } static get isGPUSupported() { return kernelOrder.some(Kernel => Kernel.isSupported); } static get isKernelMapSupported() { return kernelOrder.some(Kernel => Kernel.isSupported && Kernel.features.kernelMap); } static get isOffscreenCanvasSupported() { return (typeof Worker !== 'undefined' && typeof OffscreenCanvas !== 'undefined') || typeof importScripts !== 'undefined'; } static get isWebGLSupported() { return WebGLKernel.isSupported; } static get isWebGL2Supported() { return WebGL2Kernel.isSupported; } static get isHeadlessGLSupported() { return HeadlessGLKernel.isSupported; } static get isCanvasSupported() { return typeof HTMLCanvasElement !== 'undefined'; } static get isGPUHTMLImageArraySupported() { return WebGL2Kernel.isSupported; } static get isSinglePrecisionSupported() { return kernelOrder.some(Kernel => Kernel.isSupported && Kernel.features.isFloatRead && Kernel.features.isTextureFloat); } constructor(settings) { settings = settings || {}; this.canvas = settings.canvas || null; this.context = settings.context || null; this.mode = settings.mode; if (this.mode === 'dev') return; this.Kernel = null; this.kernels = []; this.functions = []; this.nativeFunctions = []; this.chooseKernel(); if (settings.functions) { for (let i = 0; i < settings.functions.length; i++) { this.addFunction(settings.functions[i]); } } if (settings.nativeFunctions) { for (const p in settings.nativeFunctions) { this.addNativeFunction(p, settings.nativeFunctions[p]); } } } chooseKernel() { if (this.Kernel) return; let Kernel = null; if (this.context) { for (let i = 0; i < kernelOrder.length; i++) { const ExternalKernel = kernelOrder[i]; if (ExternalKernel.isContextMatch(this.context)) { if (!ExternalKernel.isSupported) { throw new Error(`Kernel type ${ExternalKernel.name} not supported`); } Kernel = ExternalKernel; break; } } if (Kernel === null) { throw new Error('unknown Context'); } } else if (this.mode) { if (this.mode in internalKernels) { if (!validate || internalKernels[this.mode].isSupported) { Kernel = internalKernels[this.mode]; } } else if (this.mode === 'gpu') { for (let i = 0; i < kernelOrder.length; i++) { if (kernelOrder[i].isSupported) { Kernel = kernelOrder[i]; break; } } } else if (this.mode === 'cpu') { Kernel = CPUKernel; } if (!Kernel) { throw new Error(`A requested mode of "${this.mode}" and is not supported`); } } else { for (let i = 0; i < kernelOrder.length; i++) { if (kernelOrder[i].isSupported) { Kernel = kernelOrder[i]; break; } } if (!Kernel) { Kernel = CPUKernel; } } if (!this.mode) { this.mode = Kernel.mode; } this.Kernel = Kernel; } createKernel(source, settings) { if (typeof source === 'undefined') { throw new Error('Missing source parameter'); } if (typeof source !== 'object' && !utils.isFunction(source) && typeof source !== 'string') { throw new Error('source parameter not a function'); } if (this.mode === 'dev') { return gpuMock(source, upgradeDeprecatedCreateKernelSettings(settings)); } source = typeof source === 'function' ? source.toString() : source; const switchableKernels = {}; const mergedSettings = Object.assign({ context: this.context, canvas: this.canvas, functions: this.functions, nativeFunctions: this.nativeFunctions, gpu: this, validate, onRequestFallback: (args) => { const fallbackKernel = new CPUKernel(source, mergedSettings); return fallbackKernel.run.apply(fallbackKernel, args); }, onRequestSwitchKernel: (args, kernel) => { const signatureArray = []; for (let i = 0; i < args.length; i++) { signatureArray.push(utils.getVariableType(args[i])); } const signature = signatureArray.join(','); const existingKernel = switchableKernels[signature]; if (existingKernel) { existingKernel.run.apply(existingKernel, args); if (existingKernel.renderKernels) { return existingKernel.renderKernels(); } else { return existingKernel.renderOutput(); } } const newKernel = switchableKernels[signature] = new this.Kernel(source, { graphical: kernel.graphical, constants: kernel.constants, context: kernel.context, canvas: kernel.canvas, output: kernel.output, precision: kernel.precision, pipeline: kernel.pipeline, immutable: kernel.immutable, optimizeFloatMemory: kernel.optimizeFloatMemory, fixIntegerDivisionAccuracy: kernel.fixIntegerDivisionAccuracy, functions: kernel.functions, nativeFunctions: kernel.nativeFunctions, subKernels: kernel.subKernels, strictIntegers: kernel.strictIntegers, debug: kernel.debug, gpu: this, validate, }); newKernel.build.apply(newKernel, args); newKernel.run.apply(newKernel, args); if (newKernel.renderKernels) { return newKernel.renderKernels(); } else { return newKernel.renderOutput(); } } }, upgradeDeprecatedCreateKernelSettings(settings) || {}); const kernel = kernelRunShortcut(new this.Kernel(source, mergedSettings)); if (!this.canvas) { this.canvas = kernel.canvas; } if (!this.context) { this.context = kernel.context; } this.kernels.push(kernel); return kernel; } createKernelMap() { let fn; let settings; if (typeof arguments[arguments.length - 2] === 'function') { fn = arguments[arguments.length - 2]; settings = arguments[arguments.length - 1]; } else { fn = arguments[arguments.length - 1]; } if (!this.Kernel.isSupported || !this.Kernel.features.kernelMap) { if (this.mode && kernelTypes.indexOf(this.mode) < 0) { throw new Error(`kernelMap not supported on ${this.Kernel.name}`); } } const kernel = this.createKernel(fn, upgradeDeprecatedCreateKernelSettings(settings)); if (Array.isArray(arguments[0])) { const functions = arguments[0]; for (let i = 0; i < functions.length; i++) { const source = functions[i].toString(); const name = utils.getFunctionNameFromString(source); kernel.addSubKernel({ name, source, property: i, }); } } else { const functions = arguments[0]; for (let p in functions) { if (!functions.hasOwnProperty(p)) continue; const source = functions[p].toString(); const name = utils.getFunctionNameFromString(source); kernel.addSubKernel({ name: name || p, source, property: p, }); } } return kernel; } combineKernels() { const firstKernel = arguments[0]; const combinedKernel = arguments[arguments.length - 1]; if (firstKernel.kernel.constructor.mode === 'cpu') return combinedKernel; const canvas = arguments[0].canvas; const context = arguments[0].context; const max = arguments.length - 1; for (let i = 0; i < max; i++) { arguments[i] .setCanvas(canvas) .setContext(context) .setPipeline(true); } return function() { const texture = combinedKernel.apply(this, arguments); if (texture.toArray) { return texture.toArray(); } return texture; }; } addFunction(source, settings) { this.functions.push(utils.functionToIFunction(source, settings)); return this; } addNativeFunction(name, source, settings) { if (this.kernels.length > 0) { throw new Error('Cannot call "addNativeFunction" after "createKernels" has been called.'); } settings = settings || {}; const { argumentTypes, argumentNames } = this.Kernel.nativeFunctionArguments(source) || {}; this.nativeFunctions.push({ name, source, settings, argumentTypes, argumentNames, returnType: settings.returnType || this.Kernel.nativeFunctionReturnType(source), }); return this; } destroy() { setTimeout(() => { for (let i = 0; i < this.kernels.length; i++) { this.kernels[i].destroy(true); } this.kernels[0].kernel.constructor.destroyContext(this.context); }, 0); } } function upgradeDeprecatedCreateKernelSettings(settings) { if (!settings) { return; } const upgradedSettings = Object.assign({}, settings); if (settings.hasOwnProperty('floatOutput')) { utils.warnDeprecated('setting', 'floatOutput', 'precision'); upgradedSettings.precision = settings.floatOutput ? 'single' : 'unsigned'; } if (settings.hasOwnProperty('outputToTexture')) { utils.warnDeprecated('setting', 'outputToTexture', 'pipeline'); upgradedSettings.pipeline = Boolean(settings.outputToTexture); } if (settings.hasOwnProperty('outputImmutable')) { utils.warnDeprecated('setting', 'outputImmutable', 'immutable'); upgradedSettings.immutable = Boolean(settings.outputImmutable); } if (settings.hasOwnProperty('floatTextures')) { utils.warnDeprecated('setting', 'floatTextures', 'optimizeFloatMemory'); upgradedSettings.optimizeFloatMemory = Boolean(settings.floatTextures); } return upgradedSettings; } module.exports = { GPU, kernelOrder, kernelTypes }; },{"./backend/cpu/kernel":8,"./backend/headless-gl/kernel":13,"./backend/web-gl/kernel":37,"./backend/web-gl2/kernel":61,"./kernel-run-shortcut":67,"./utils":70,"gpu-mock.js":4}],65:[function(require,module,exports){ const { GPU } = require('./gpu'); const { alias } = require('./alias'); const { utils } = require('./utils'); const { Input, input } = require('./input'); const { Texture } = require('./texture'); const { FunctionBuilder } = require('./backend/function-builder'); const { FunctionNode } = require('./backend/function-node'); const { CPUFunctionNode } = require('./backend/cpu/function-node'); const { CPUKernel } = require('./backend/cpu/kernel'); const { HeadlessGLKernel } = require('./backend/headless-gl/kernel'); const { WebGLFunctionNode } = require('./backend/web-gl/function-node'); const { WebGLKernel } = require('./backend/web-gl/kernel'); const { WebGL2FunctionNode } = require('./backend/web-gl2/function-node'); const { WebGL2Kernel } = require('./backend/web-gl2/kernel'); const { GLKernel } = require('./backend/gl/kernel'); const { Kernel } = require('./backend/kernel'); module.exports = { alias, CPUFunctionNode, CPUKernel, GPU, FunctionBuilder, FunctionNode, HeadlessGLKernel, Input, input, Texture, utils, WebGL2FunctionNode, WebGL2Kernel, WebGLFunctionNode, WebGLKernel, GLKernel, Kernel, }; },{"./alias":5,"./backend/cpu/function-node":6,"./backend/cpu/kernel":8,"./backend/function-builder":9,"./backend/function-node":10,"./backend/gl/kernel":12,"./backend/headless-gl/kernel":13,"./backend/kernel":15,"./backend/web-gl/function-node":17,"./backend/web-gl/kernel":37,"./backend/web-gl2/function-node":40,"./backend/web-gl2/kernel":61,"./gpu":64,"./input":66,"./texture":69,"./utils":70}],66:[function(require,module,exports){ class Input { constructor(value, size) { this.value = value; this.size = new Int32Array(3); if (Array.isArray(size)) { for (let i = 0; i < this.size.length; i++) { this.size[i] = size[i] || 1; } } else { if (size.z) { this.size = new Int32Array([size.x, size.y, size.z]); } else if (size.y) { this.size = new Int32Array([size.x, size.y, 1]); } else { this.size = new Int32Array([size.x, 1, 1]); } } const [h, w, d] = this.size; if (this.value.length !== (h * w * d)) { throw new Error(`Input size ${this.value.length} does not match ${w} * ${h} * ${d} = ${(h * w * d)}`); } } } function input(value, size) { return new Input(value, size); } module.exports = { Input, input }; },{}],67:[function(require,module,exports){ const { utils } = require('./utils'); function kernelRunShortcut(kernel) { let run = function() { kernel.build.apply(kernel, arguments); if (kernel.renderKernels) { run = function() { kernel.run.apply(kernel, arguments); kernel.run.apply(kernel, arguments); if (kernel.switchingKernels) { kernel.switchingKernels = false; return kernel.onRequestSwitchKernel(arguments, kernel); } return kernel.renderKernels(); }; kernel.run.apply(kernel, arguments); return kernel.renderKernels(); } else if (kernel.renderOutput) { run = function() { kernel.run.apply(kernel, arguments); if (kernel.switchingKernels) { kernel.switchingKernels = false; return kernel.onRequestSwitchKernel(arguments, kernel); } return kernel.renderOutput(); }; kernel.run.apply(kernel, arguments); return kernel.renderOutput(); } else { run = function() { return kernel.run.apply(kernel, arguments); }; return kernel.run.apply(kernel, arguments); } }; const shortcut = function() { return run.apply(kernel, arguments); }; shortcut.exec = function() { return new Promise((accept, reject) => { try { accept(run.apply(this, arguments)); } catch (e) { reject(e); } }); }; utils .allPropertiesOf(kernel) .forEach((key) => { if (key[0] === '_' && key[1] === '_') return; if (typeof kernel[key] === 'function') { if (key.substring(0, 3) === 'add' || key.substring(0, 3) === 'set') { shortcut[key] = function() { kernel[key].apply(kernel, arguments); return shortcut; }; } else if (key === 'requestFallback') { const requestFallback = kernel[key].bind(kernel); shortcut[key] = () => { kernel = requestFallback(); }; } else { shortcut[key] = kernel[key].bind(kernel); } } else { shortcut.__defineGetter__(key, () => { return kernel[key]; }); shortcut.__defineSetter__(key, (value) => { kernel[key] = value; }); } }); shortcut.kernel = kernel; return shortcut; } module.exports = { kernelRunShortcut }; },{"./utils":70}],68:[function(require,module,exports){ const source = ` uniform highp float triangle_noise_seed; highp float triangle_noise_shift = 0.000001; //https://www.shadertoy.com/view/4t2SDh //note: uniformly distributed, normalized rand, [0;1[ float nrand( vec2 n ) { return fract(sin(dot(n.xy, vec2(12.9898, 78.233)))* 43758.5453); } //note: remaps v to [0;1] in interval [a;b] float remap( float a, float b, float v ) { return clamp( (v-a) / (b-a), 0.0, 1.0 ); } float n4rand( vec2 n ) { float t = fract( triangle_noise_seed + triangle_noise_shift ); float nrnd0 = nrand( n + 0.07*t ); float nrnd1 = nrand( n + 0.11*t ); float nrnd2 = nrand( n + 0.13*t ); float nrnd3 = nrand( n + 0.17*t ); float result = (nrnd0+nrnd1+nrnd2+nrnd3) / 4.0; triangle_noise_shift = result + 0.000001; return result; }`; const name = 'triangle-noise-noise'; const functionMatch = 'Math.random()'; const functionReplace = 'n4rand(vTexCoord)'; const functionReturnType = 'Number'; const onBeforeRun = (kernel) => { kernel.setUniform1f('triangle_noise_seed', Math.random()); }; module.exports = { name, onBeforeRun, functionMatch, functionReplace, functionReturnType, source }; },{}],69:[function(require,module,exports){ class Texture { constructor(settings) { const { texture, size, dimensions, output, context, gpu, type = 'NumberTexture', } = settings; if (!output) throw new Error('settings property "output" required.'); if (!context) throw new Error('settings property "context" required.'); this.texture = texture; this.size = size; this.dimensions = dimensions; this.output = output; this.context = context; this.gpu = gpu; this.kernel = null; this.type = type; } toArray(gpu) { let { kernel } = this; if (kernel) return kernel(this); gpu = gpu || this.gpu; if (!gpu) throw new Error('settings property "gpu" or argument required.'); kernel = gpu.createKernel(function(x) { return x[this.thread.z][this.thread.y][this.thread.x]; }, { output: this.output, precision: this.getPrecision(), optimizeFloatMemory: this.type === 'MemoryOptimizedNumberTexture', }); this.kernel = kernel; return kernel(this); } getPrecision() { switch (this.type) { case 'NumberTexture': return 'unsigned'; case 'MemoryOptimizedNumberTexture': case 'ArrayTexture(1)': case 'ArrayTexture(2)': case 'ArrayTexture(3)': case 'ArrayTexture(4)': return 'single'; default: throw new Error('Unknown texture type'); } } delete() { return this.context.deleteTexture(this.texture); } } module.exports = { Texture }; },{}],70:[function(require,module,exports){ const { Input } = require('./input'); const { Texture } = require('./texture'); const FUNCTION_NAME = /function ([^(]*)/; const STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; const ARGUMENT_NAMES = /([^\s,]+)/g; const utils = { systemEndianness() { return _systemEndianness; }, getSystemEndianness() { const b = new ArrayBuffer(4); const a = new Uint32Array(b); const c = new Uint8Array(b); a[0] = 0xdeadbeef; if (c[0] === 0xef) return 'LE'; if (c[0] === 0xde) return 'BE'; throw new Error('unknown endianness'); }, isFunction(funcObj) { return typeof(funcObj) === 'function'; }, isFunctionString(fn) { if (typeof fn === 'string') { return (fn .slice(0, 'function'.length) .toLowerCase() === 'function'); } return false; }, getFunctionNameFromString(funcStr) { return FUNCTION_NAME.exec(funcStr)[1].trim(); }, getFunctionBodyFromString(funcStr) { return funcStr.substring(funcStr.indexOf('{') + 1, funcStr.lastIndexOf('}')); }, getArgumentNamesFromString(fn) { const fnStr = fn.replace(STRIP_COMMENTS, ''); let result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARGUMENT_NAMES); if (result === null) { result = []; } return result; }, clone(obj) { if (obj === null || typeof obj !== 'object' || obj.hasOwnProperty('isActiveClone')) return obj; const temp = obj.constructor(); for (let key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { obj.isActiveClone = null; temp[key] = utils.clone(obj[key]); delete obj.isActiveClone; } } return temp; }, isArray(array) { return !isNaN(array.length); }, getVariableType(value, strictIntegers) { if (utils.isArray(value)) { if (value[0].nodeName === 'IMG') { return 'HTMLImageArray'; } return 'Array'; } switch (value.constructor) { case Boolean: return 'Boolean'; case Number: if (strictIntegers && Number.isInteger(value)) { return 'Integer'; } return 'Float'; case Texture: return value.type; case Input: return 'Input'; } if (value.nodeName === 'IMG') { return 'HTMLImage'; } else { return 'Unknown'; } }, dimToTexSize(opt, dimensions, output) { let [w, h, d] = dimensions; let texelCount = (w || 1) * (h || 1) * (d || 1); if (opt.floatTextures && (!output || opt.precision === 'single')) { w = texelCount = Math.ceil(texelCount / 4); } if (h > 1 && w * h === texelCount) { return new Int32Array([w, h]); } return utils.closestSquareDimensions(texelCount); }, closestSquareDimensions(length) { const sqrt = Math.sqrt(length); let high = Math.ceil(sqrt); let low = Math.floor(sqrt); while (high * low < length) { high--; low = Math.ceil(length / high); } return new Int32Array([low, Math.ceil(length / low)]); }, getMemoryOptimizedFloatTextureSize(dimensions, bitRatio) { const [w, h, d] = dimensions; const totalArea = utils.roundTo((w || 1) * (h || 1) * (d || 1), 4); const texelCount = totalArea / bitRatio; return utils.closestSquareDimensions(texelCount); }, getMemoryOptimizedPackedTextureSize(dimensions, bitRatio) { const [w, h, d] = dimensions; const totalArea = utils.roundTo((w || 1) * (h || 1) * (d || 1), 4); const texelCount = totalArea / (4 / bitRatio); return utils.closestSquareDimensions(texelCount); }, roundTo(n, d) { return Math.floor((n + d - 1) / d) * d; }, getDimensions(x, pad) { let ret; if (utils.isArray(x)) { const dim = []; let temp = x; while (utils.isArray(temp)) { dim.push(temp.length); temp = temp[0]; } ret = dim.reverse(); } else if (x instanceof Texture) { ret = x.output; } else if (x instanceof Input) { ret = x.size; } else { throw new Error(`Unknown dimensions of ${x}`); } if (pad) { ret = Array.from(ret); while (ret.length < 3) { ret.push(1); } } return new Int32Array(ret); }, flatten2dArrayTo(array, target) { let offset = 0; for (let y = 0; y < array.length; y++) { target.set(array[y], offset); offset += array[y].length; } }, flatten3dArrayTo(array, target) { let offset = 0; for (let z = 0; z < array.length; z++) { for (let y = 0; y < array[z].length; y++) { target.set(array[z][y], offset); offset += array[z][y].length; } } }, flattenTo(array, target) { if (utils.isArray(array[0])) { if (utils.isArray(array[0][0])) { utils.flatten3dArrayTo(array, target); } else { utils.flatten2dArrayTo(array, target); } } else { target.set(array); } }, splitArray(array, part) { const result = []; for (let i = 0; i < array.length; i += part) { result.push(new array.constructor(array.buffer, i * 4 + array.byteOffset, part)); } return result; }, getAstString(source, ast) { const lines = Array.isArray(source) ? source : source.split(/\r?\n/g); const start = ast.loc.start; const end = ast.loc.end; const result = []; result.push(lines[start.line - 1].slice(start.column)); for (let i = start.line; i < end.line - 1; i++) { result.push(lines[i]); } result.push(lines[end.line - 1].slice(0, end.column)); return result.join('\n'); }, allPropertiesOf(obj) { const props = []; do { props.push.apply(props, Object.getOwnPropertyNames(obj)); } while (obj = Object.getPrototypeOf(obj)); return props; }, linesToString(lines) { if (lines.length > 0) { return lines.join(';\n') + ';\n'; } else { return '\n'; } }, warnDeprecated(type, oldName, newName) { if (newName) { console.warn(`You are using a deprecated ${ type } "${ oldName }". It has been replaced with "${ newName }". Fixing, but please upgrade as it will soon be removed.`); } else { console.warn(`You are using a deprecated ${ type } "${ oldName }". It has been removed. Fixing, but please upgrade as it will soon be removed.`); } }, functionToIFunction(source, settings) { settings = settings || {}; if (typeof source !== 'string' && typeof source !== 'function') throw new Error('source not a string or function'); const sourceString = typeof source === 'string' ? source : source.toString(); let argumentTypes = []; if (Array.isArray(settings.argumentTypes)) { argumentTypes = settings.argumentTypes; } else if (typeof settings.argumentTypes === 'object') { argumentTypes = utils.getArgumentNamesFromString(sourceString) .map(name => settings.argumentTypes[name]) || []; } else { argumentTypes = settings.argumentTypes || []; } return { source: sourceString, argumentTypes, returnType: settings.returnType || null, }; }, flipPixels: (pixels, width, height) => { const halfHeight = height / 2 | 0; const bytesPerRow = width * 4; const temp = new Uint8Array(width * 4); const result = pixels.slice(0); for (let y = 0; y < halfHeight; ++y) { const topOffset = y * bytesPerRow; const bottomOffset = (height - y - 1) * bytesPerRow; temp.set(result.subarray(topOffset, topOffset + bytesPerRow)); result.copyWithin(topOffset, bottomOffset, bottomOffset + bytesPerRow); result.set(temp, bottomOffset); } return result; } }; const _systemEndianness = utils.getSystemEndianness(); module.exports = { utils }; },{"./input":66,"./texture":69}]},{},[63]);