mirror of
https://github.com/mattdesl/glsl-lut.git
synced 2026-01-18 14:08:28 +00:00
10621 lines
291 KiB
JavaScript
10621 lines
291 KiB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
|
var canvas = document.body.appendChild(document.createElement('canvas'))
|
|
var triangle = require('a-big-triangle')
|
|
var createContext = require('gl-context')
|
|
var createTex2d = require('gl-texture2d')
|
|
|
|
var createShell = require('gl-now')
|
|
|
|
canvas.width = 512
|
|
canvas.height = 512
|
|
document.body.style.margin = "0";
|
|
|
|
var gl = createContext(canvas, render)
|
|
var baboonTex = getTex2D("baboon.png")
|
|
var lookupTex1 = getTex2D("lookup_selective_color.png");
|
|
var lookupTex2 = getTex2D("lookup_miss_etikate.png");
|
|
var lookupTex = lookupTex1;
|
|
|
|
//could also use ndarray get-pixels
|
|
var lookupImage = new Image();
|
|
|
|
var shader = require('gl-shader')(gl,
|
|
"precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 position;\nvarying vec2 vUv;\n\nvoid main() {\n vUv = (position + vec2(1.0)) / 2.0;\n vUv.y = 1.0 - vUv.y;\n gl_Position = vec4(position, 1.0, 1.0);\n}",
|
|
"precision mediump float;\n#define GLSLIFY 1\n\nuniform sampler2D uTexture;\nuniform sampler2D uLookup;\nuniform float stop;\nvarying vec2 vUv;\n\nvec4 lookup_1_0(in vec4 textureColor, in sampler2D lookupTable) {\n #ifndef LUT_NO_CLAMP\n textureColor = clamp(textureColor, 0.0, 1.0);\n #endif\n\n mediump float blueColor = textureColor.b * 63.0;\n\n mediump vec2 quad1;\n quad1.y = floor(floor(blueColor) / 8.0);\n quad1.x = floor(blueColor) - (quad1.y * 8.0);\n\n mediump vec2 quad2;\n quad2.y = floor(ceil(blueColor) / 8.0);\n quad2.x = ceil(blueColor) - (quad2.y * 8.0);\n\n highp vec2 texPos1;\n texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);\n\n #ifdef LUT_FLIP_Y\n texPos1.y = 1.0-texPos1.y;\n #endif\n\n highp vec2 texPos2;\n texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);\n texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);\n\n #ifdef LUT_FLIP_Y\n texPos2.y = 1.0-texPos2.y;\n #endif\n\n lowp vec4 newColor1 = texture2D(lookupTable, texPos1);\n lowp vec4 newColor2 = texture2D(lookupTable, texPos2);\n\n lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));\n return newColor;\n}\n\n\n\nvoid main() {\n\tvec4 color = texture2D(uTexture, vUv);\n\n\tif (vUv.x > stop)\n\t\tgl_FragColor = lookup_1_0(color, uLookup);\n\telse \n\t\tgl_FragColor = color;\n}\n"
|
|
)
|
|
|
|
//handle mouse move
|
|
var mouseX = 0;
|
|
window.addEventListener("mousemove", function(ev) {
|
|
mouseX = Math.max(0, Math.min(1, ev.pageX/canvas.width));
|
|
});
|
|
|
|
canvas.addEventListener("mousedown", function(ev) {
|
|
ev.preventDefault();
|
|
lookupTex = lookupTex===lookupTex1 ? lookupTex2 : lookupTex1;
|
|
})
|
|
|
|
function render() {
|
|
if (!lookupTex.texture || !baboonTex.texture)
|
|
return;
|
|
shader.bind()
|
|
shader.uniforms.stop = mouseX;
|
|
shader.uniforms.uTexture = baboonTex.texture.bind(0)
|
|
shader.uniforms.uLookup = lookupTex.texture.bind(1);
|
|
triangle(gl)
|
|
}
|
|
|
|
//add some info text
|
|
document.body.appendChild(info());
|
|
|
|
function getTex2D(path) {
|
|
var obj = {
|
|
image: new Image(),
|
|
texture: null
|
|
};
|
|
obj.image.onload = function() {
|
|
obj.texture = createTex2d(gl, obj.image)
|
|
obj.texture.minFilter = obj.texture.magFilter = gl.LINEAR;
|
|
};
|
|
obj.image.src = path;
|
|
return obj;
|
|
}
|
|
|
|
function info() {
|
|
var lbl = document.createElement("div")
|
|
lbl.style.font = "14px 'Helvetica', 'Arial', sans-serif";
|
|
lbl.style.margin = "10px";
|
|
lbl.innerHTML = "move your mouse to see the color transform<br>click to swap lookup tables";
|
|
return lbl;
|
|
}
|
|
|
|
},{"a-big-triangle":2,"gl-context":20,"gl-now":22,"gl-shader":23,"gl-texture2d":33}],2:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
var createBuffer = require("gl-buffer")
|
|
var createVAO = require("gl-vao")
|
|
|
|
function createABigTriangle(gl) {
|
|
if(gl.__BIG_TRIANGLE) {
|
|
gl.__BIG_TRIANGLE.bind()
|
|
gl.drawArrays(gl.TRIANGLES, 0, 3)
|
|
gl.__BIG_TRIANGLE.unbind()
|
|
return
|
|
}
|
|
var buf = createBuffer(gl, new Float32Array([-1, -1, -1, 4, 4, -1]))
|
|
var vao = createVAO(gl, null, [
|
|
{ buffer: buf,
|
|
type: gl.FLOAT,
|
|
size: 2,
|
|
offset: 0,
|
|
stride: 0,
|
|
normalized: false
|
|
}
|
|
])
|
|
gl.__BIG_TRIANGLE = vao
|
|
vao.bind()
|
|
gl.drawArrays(gl.TRIANGLES, 0, 3)
|
|
vao.unbind()
|
|
}
|
|
|
|
module.exports = createABigTriangle
|
|
},{"gl-buffer":17,"gl-vao":38}],3:[function(require,module,exports){
|
|
var padLeft = require('pad-left')
|
|
|
|
module.exports = addLineNumbers
|
|
function addLineNumbers (string, start, delim) {
|
|
start = typeof start === 'number' ? start : 1
|
|
delim = delim || ': '
|
|
|
|
var lines = string.split(/\r?\n/)
|
|
var totalDigits = String(lines.length + start - 1).length
|
|
return lines.map(function (line, i) {
|
|
var c = i + start
|
|
var digits = String(c).length
|
|
var prefix = padLeft(c, totalDigits - digits)
|
|
return prefix + delim + line
|
|
}).join('\n')
|
|
}
|
|
|
|
},{"pad-left":56}],4:[function(require,module,exports){
|
|
module.exports = function _atob(str) {
|
|
return atob(str)
|
|
}
|
|
|
|
},{}],5:[function(require,module,exports){
|
|
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
|
|
;(function (exports) {
|
|
'use strict';
|
|
|
|
var Arr = (typeof Uint8Array !== 'undefined')
|
|
? Uint8Array
|
|
: Array
|
|
|
|
var PLUS = '+'.charCodeAt(0)
|
|
var SLASH = '/'.charCodeAt(0)
|
|
var NUMBER = '0'.charCodeAt(0)
|
|
var LOWER = 'a'.charCodeAt(0)
|
|
var UPPER = 'A'.charCodeAt(0)
|
|
var PLUS_URL_SAFE = '-'.charCodeAt(0)
|
|
var SLASH_URL_SAFE = '_'.charCodeAt(0)
|
|
|
|
function decode (elt) {
|
|
var code = elt.charCodeAt(0)
|
|
if (code === PLUS ||
|
|
code === PLUS_URL_SAFE)
|
|
return 62 // '+'
|
|
if (code === SLASH ||
|
|
code === SLASH_URL_SAFE)
|
|
return 63 // '/'
|
|
if (code < NUMBER)
|
|
return -1 //no match
|
|
if (code < NUMBER + 10)
|
|
return code - NUMBER + 26 + 26
|
|
if (code < UPPER + 26)
|
|
return code - UPPER
|
|
if (code < LOWER + 26)
|
|
return code - LOWER + 26
|
|
}
|
|
|
|
function b64ToByteArray (b64) {
|
|
var i, j, l, tmp, placeHolders, arr
|
|
|
|
if (b64.length % 4 > 0) {
|
|
throw new Error('Invalid string. Length must be a multiple of 4')
|
|
}
|
|
|
|
// the number of equal signs (place holders)
|
|
// if there are two placeholders, than the two characters before it
|
|
// represent one byte
|
|
// if there is only one, then the three characters before it represent 2 bytes
|
|
// this is just a cheap hack to not do indexOf twice
|
|
var len = b64.length
|
|
placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
|
|
|
|
// base64 is 4/3 + up to two characters of the original data
|
|
arr = new Arr(b64.length * 3 / 4 - placeHolders)
|
|
|
|
// if there are placeholders, only get up to the last complete 4 chars
|
|
l = placeHolders > 0 ? b64.length - 4 : b64.length
|
|
|
|
var L = 0
|
|
|
|
function push (v) {
|
|
arr[L++] = v
|
|
}
|
|
|
|
for (i = 0, j = 0; i < l; i += 4, j += 3) {
|
|
tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
|
|
push((tmp & 0xFF0000) >> 16)
|
|
push((tmp & 0xFF00) >> 8)
|
|
push(tmp & 0xFF)
|
|
}
|
|
|
|
if (placeHolders === 2) {
|
|
tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
|
|
push(tmp & 0xFF)
|
|
} else if (placeHolders === 1) {
|
|
tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
|
|
push((tmp >> 8) & 0xFF)
|
|
push(tmp & 0xFF)
|
|
}
|
|
|
|
return arr
|
|
}
|
|
|
|
function uint8ToBase64 (uint8) {
|
|
var i,
|
|
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
|
|
output = "",
|
|
temp, length
|
|
|
|
function encode (num) {
|
|
return lookup.charAt(num)
|
|
}
|
|
|
|
function tripletToBase64 (num) {
|
|
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
|
|
}
|
|
|
|
// go through the array every three bytes, we'll deal with trailing stuff later
|
|
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
|
|
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
|
|
output += tripletToBase64(temp)
|
|
}
|
|
|
|
// pad the end with zeros, but make sure to not forget the extra bytes
|
|
switch (extraBytes) {
|
|
case 1:
|
|
temp = uint8[uint8.length - 1]
|
|
output += encode(temp >> 2)
|
|
output += encode((temp << 4) & 0x3F)
|
|
output += '=='
|
|
break
|
|
case 2:
|
|
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
|
|
output += encode(temp >> 10)
|
|
output += encode((temp >> 4) & 0x3F)
|
|
output += encode((temp << 2) & 0x3F)
|
|
output += '='
|
|
break
|
|
}
|
|
|
|
return output
|
|
}
|
|
|
|
exports.toByteArray = b64ToByteArray
|
|
exports.fromByteArray = uint8ToBase64
|
|
}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
|
|
|
|
},{}],6:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
function compileSearch(funcName, predicate, reversed, extraArgs, useNdarray, earlyOut) {
|
|
var code = [
|
|
"function ", funcName, "(a,l,h,", extraArgs.join(","), "){",
|
|
earlyOut ? "" : "var i=", (reversed ? "l-1" : "h+1"),
|
|
";while(l<=h){\
|
|
var m=(l+h)>>>1,x=a", useNdarray ? ".get(m)" : "[m]"]
|
|
if(earlyOut) {
|
|
if(predicate.indexOf("c") < 0) {
|
|
code.push(";if(x===y){return m}else if(x<=y){")
|
|
} else {
|
|
code.push(";var p=c(x,y);if(p===0){return m}else if(p<=0){")
|
|
}
|
|
} else {
|
|
code.push(";if(", predicate, "){i=m;")
|
|
}
|
|
if(reversed) {
|
|
code.push("l=m+1}else{h=m-1}")
|
|
} else {
|
|
code.push("h=m-1}else{l=m+1}")
|
|
}
|
|
code.push("}")
|
|
if(earlyOut) {
|
|
code.push("return -1};")
|
|
} else {
|
|
code.push("return i};")
|
|
}
|
|
return code.join("")
|
|
}
|
|
|
|
function compileBoundsSearch(predicate, reversed, suffix, earlyOut) {
|
|
var result = new Function([
|
|
compileSearch("A", "x" + predicate + "y", reversed, ["y"], false, earlyOut),
|
|
compileSearch("B", "x" + predicate + "y", reversed, ["y"], true, earlyOut),
|
|
compileSearch("P", "c(x,y)" + predicate + "0", reversed, ["y", "c"], false, earlyOut),
|
|
compileSearch("Q", "c(x,y)" + predicate + "0", reversed, ["y", "c"], true, earlyOut),
|
|
"function dispatchBsearch", suffix, "(a,y,c,l,h){\
|
|
if(a.shape){\
|
|
if(typeof(c)==='function'){\
|
|
return Q(a,(l===undefined)?0:l|0,(h===undefined)?a.shape[0]-1:h|0,y,c)\
|
|
}else{\
|
|
return B(a,(c===undefined)?0:c|0,(l===undefined)?a.shape[0]-1:l|0,y)\
|
|
}}else{\
|
|
if(typeof(c)==='function'){\
|
|
return P(a,(l===undefined)?0:l|0,(h===undefined)?a.length-1:h|0,y,c)\
|
|
}else{\
|
|
return A(a,(c===undefined)?0:c|0,(l===undefined)?a.length-1:l|0,y)\
|
|
}}}\
|
|
return dispatchBsearch", suffix].join(""))
|
|
return result()
|
|
}
|
|
|
|
module.exports = {
|
|
ge: compileBoundsSearch(">=", false, "GE"),
|
|
gt: compileBoundsSearch(">", false, "GT"),
|
|
lt: compileBoundsSearch("<", true, "LT"),
|
|
le: compileBoundsSearch("<=", true, "LE"),
|
|
eq: compileBoundsSearch("-", true, "EQ", true)
|
|
}
|
|
|
|
},{}],7:[function(require,module,exports){
|
|
/**
|
|
* Bit twiddling hacks for JavaScript.
|
|
*
|
|
* Author: Mikola Lysenko
|
|
*
|
|
* Ported from Stanford bit twiddling hack library:
|
|
* http://graphics.stanford.edu/~seander/bithacks.html
|
|
*/
|
|
|
|
"use strict"; "use restrict";
|
|
|
|
//Number of bits in an integer
|
|
var INT_BITS = 32;
|
|
|
|
//Constants
|
|
exports.INT_BITS = INT_BITS;
|
|
exports.INT_MAX = 0x7fffffff;
|
|
exports.INT_MIN = -1<<(INT_BITS-1);
|
|
|
|
//Returns -1, 0, +1 depending on sign of x
|
|
exports.sign = function(v) {
|
|
return (v > 0) - (v < 0);
|
|
}
|
|
|
|
//Computes absolute value of integer
|
|
exports.abs = function(v) {
|
|
var mask = v >> (INT_BITS-1);
|
|
return (v ^ mask) - mask;
|
|
}
|
|
|
|
//Computes minimum of integers x and y
|
|
exports.min = function(x, y) {
|
|
return y ^ ((x ^ y) & -(x < y));
|
|
}
|
|
|
|
//Computes maximum of integers x and y
|
|
exports.max = function(x, y) {
|
|
return x ^ ((x ^ y) & -(x < y));
|
|
}
|
|
|
|
//Checks if a number is a power of two
|
|
exports.isPow2 = function(v) {
|
|
return !(v & (v-1)) && (!!v);
|
|
}
|
|
|
|
//Computes log base 2 of v
|
|
exports.log2 = function(v) {
|
|
var r, shift;
|
|
r = (v > 0xFFFF) << 4; v >>>= r;
|
|
shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift;
|
|
shift = (v > 0xF ) << 2; v >>>= shift; r |= shift;
|
|
shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift;
|
|
return r | (v >> 1);
|
|
}
|
|
|
|
//Computes log base 10 of v
|
|
exports.log10 = function(v) {
|
|
return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 :
|
|
(v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 :
|
|
(v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0;
|
|
}
|
|
|
|
//Counts number of bits
|
|
exports.popCount = function(v) {
|
|
v = v - ((v >>> 1) & 0x55555555);
|
|
v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);
|
|
return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
|
|
}
|
|
|
|
//Counts number of trailing zeros
|
|
function countTrailingZeros(v) {
|
|
var c = 32;
|
|
v &= -v;
|
|
if (v) c--;
|
|
if (v & 0x0000FFFF) c -= 16;
|
|
if (v & 0x00FF00FF) c -= 8;
|
|
if (v & 0x0F0F0F0F) c -= 4;
|
|
if (v & 0x33333333) c -= 2;
|
|
if (v & 0x55555555) c -= 1;
|
|
return c;
|
|
}
|
|
exports.countTrailingZeros = countTrailingZeros;
|
|
|
|
//Rounds to next power of 2
|
|
exports.nextPow2 = function(v) {
|
|
v += v === 0;
|
|
--v;
|
|
v |= v >>> 1;
|
|
v |= v >>> 2;
|
|
v |= v >>> 4;
|
|
v |= v >>> 8;
|
|
v |= v >>> 16;
|
|
return v + 1;
|
|
}
|
|
|
|
//Rounds down to previous power of 2
|
|
exports.prevPow2 = function(v) {
|
|
v |= v >>> 1;
|
|
v |= v >>> 2;
|
|
v |= v >>> 4;
|
|
v |= v >>> 8;
|
|
v |= v >>> 16;
|
|
return v - (v>>>1);
|
|
}
|
|
|
|
//Computes parity of word
|
|
exports.parity = function(v) {
|
|
v ^= v >>> 16;
|
|
v ^= v >>> 8;
|
|
v ^= v >>> 4;
|
|
v &= 0xf;
|
|
return (0x6996 >>> v) & 1;
|
|
}
|
|
|
|
var REVERSE_TABLE = new Array(256);
|
|
|
|
(function(tab) {
|
|
for(var i=0; i<256; ++i) {
|
|
var v = i, r = i, s = 7;
|
|
for (v >>>= 1; v; v >>>= 1) {
|
|
r <<= 1;
|
|
r |= v & 1;
|
|
--s;
|
|
}
|
|
tab[i] = (r << s) & 0xff;
|
|
}
|
|
})(REVERSE_TABLE);
|
|
|
|
//Reverse bits in a 32 bit word
|
|
exports.reverse = function(v) {
|
|
return (REVERSE_TABLE[ v & 0xff] << 24) |
|
|
(REVERSE_TABLE[(v >>> 8) & 0xff] << 16) |
|
|
(REVERSE_TABLE[(v >>> 16) & 0xff] << 8) |
|
|
REVERSE_TABLE[(v >>> 24) & 0xff];
|
|
}
|
|
|
|
//Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes
|
|
exports.interleave2 = function(x, y) {
|
|
x &= 0xFFFF;
|
|
x = (x | (x << 8)) & 0x00FF00FF;
|
|
x = (x | (x << 4)) & 0x0F0F0F0F;
|
|
x = (x | (x << 2)) & 0x33333333;
|
|
x = (x | (x << 1)) & 0x55555555;
|
|
|
|
y &= 0xFFFF;
|
|
y = (y | (y << 8)) & 0x00FF00FF;
|
|
y = (y | (y << 4)) & 0x0F0F0F0F;
|
|
y = (y | (y << 2)) & 0x33333333;
|
|
y = (y | (y << 1)) & 0x55555555;
|
|
|
|
return x | (y << 1);
|
|
}
|
|
|
|
//Extracts the nth interleaved component
|
|
exports.deinterleave2 = function(v, n) {
|
|
v = (v >>> n) & 0x55555555;
|
|
v = (v | (v >>> 1)) & 0x33333333;
|
|
v = (v | (v >>> 2)) & 0x0F0F0F0F;
|
|
v = (v | (v >>> 4)) & 0x00FF00FF;
|
|
v = (v | (v >>> 16)) & 0x000FFFF;
|
|
return (v << 16) >> 16;
|
|
}
|
|
|
|
|
|
//Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes
|
|
exports.interleave3 = function(x, y, z) {
|
|
x &= 0x3FF;
|
|
x = (x | (x<<16)) & 4278190335;
|
|
x = (x | (x<<8)) & 251719695;
|
|
x = (x | (x<<4)) & 3272356035;
|
|
x = (x | (x<<2)) & 1227133513;
|
|
|
|
y &= 0x3FF;
|
|
y = (y | (y<<16)) & 4278190335;
|
|
y = (y | (y<<8)) & 251719695;
|
|
y = (y | (y<<4)) & 3272356035;
|
|
y = (y | (y<<2)) & 1227133513;
|
|
x |= (y << 1);
|
|
|
|
z &= 0x3FF;
|
|
z = (z | (z<<16)) & 4278190335;
|
|
z = (z | (z<<8)) & 251719695;
|
|
z = (z | (z<<4)) & 3272356035;
|
|
z = (z | (z<<2)) & 1227133513;
|
|
|
|
return x | (z << 2);
|
|
}
|
|
|
|
//Extracts nth interleaved component of a 3-tuple
|
|
exports.deinterleave3 = function(v, n) {
|
|
v = (v >>> n) & 1227133513;
|
|
v = (v | (v>>>2)) & 3272356035;
|
|
v = (v | (v>>>4)) & 251719695;
|
|
v = (v | (v>>>8)) & 4278190335;
|
|
v = (v | (v>>>16)) & 0x3FF;
|
|
return (v<<22)>>22;
|
|
}
|
|
|
|
//Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page)
|
|
exports.nextCombination = function(v) {
|
|
var t = v | (v - 1);
|
|
return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1));
|
|
}
|
|
|
|
|
|
},{}],8:[function(require,module,exports){
|
|
(function (global){
|
|
/*!
|
|
* The buffer module from node.js, for the browser.
|
|
*
|
|
* @author Feross Aboukhadijeh <http://feross.org>
|
|
* @license MIT
|
|
*/
|
|
/* eslint-disable no-proto */
|
|
|
|
'use strict'
|
|
|
|
var base64 = require('base64-js')
|
|
var ieee754 = require('ieee754')
|
|
var isArray = require('isarray')
|
|
|
|
exports.Buffer = Buffer
|
|
exports.SlowBuffer = SlowBuffer
|
|
exports.INSPECT_MAX_BYTES = 50
|
|
Buffer.poolSize = 8192 // not used by this implementation
|
|
|
|
var rootParent = {}
|
|
|
|
/**
|
|
* If `Buffer.TYPED_ARRAY_SUPPORT`:
|
|
* === true Use Uint8Array implementation (fastest)
|
|
* === false Use Object implementation (most compatible, even IE6)
|
|
*
|
|
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
|
|
* Opera 11.6+, iOS 4.2+.
|
|
*
|
|
* Due to various browser bugs, sometimes the Object implementation will be used even
|
|
* when the browser supports typed arrays.
|
|
*
|
|
* Note:
|
|
*
|
|
* - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
|
|
* See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
|
|
*
|
|
* - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property
|
|
* on objects.
|
|
*
|
|
* - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
|
|
*
|
|
* - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
|
|
* incorrect length in some situations.
|
|
|
|
* We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
|
|
* get the Object implementation, which is slower but behaves correctly.
|
|
*/
|
|
Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
|
|
? global.TYPED_ARRAY_SUPPORT
|
|
: typedArraySupport()
|
|
|
|
function typedArraySupport () {
|
|
function Bar () {}
|
|
try {
|
|
var arr = new Uint8Array(1)
|
|
arr.foo = function () { return 42 }
|
|
arr.constructor = Bar
|
|
return arr.foo() === 42 && // typed array instances can be augmented
|
|
arr.constructor === Bar && // constructor can be set
|
|
typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
|
|
arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
|
|
} catch (e) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
function kMaxLength () {
|
|
return Buffer.TYPED_ARRAY_SUPPORT
|
|
? 0x7fffffff
|
|
: 0x3fffffff
|
|
}
|
|
|
|
/**
|
|
* Class: Buffer
|
|
* =============
|
|
*
|
|
* The Buffer constructor returns instances of `Uint8Array` that are augmented
|
|
* with function properties for all the node `Buffer` API functions. We use
|
|
* `Uint8Array` so that square bracket notation works as expected -- it returns
|
|
* a single octet.
|
|
*
|
|
* By augmenting the instances, we can avoid modifying the `Uint8Array`
|
|
* prototype.
|
|
*/
|
|
function Buffer (arg) {
|
|
if (!(this instanceof Buffer)) {
|
|
// Avoid going through an ArgumentsAdaptorTrampoline in the common case.
|
|
if (arguments.length > 1) return new Buffer(arg, arguments[1])
|
|
return new Buffer(arg)
|
|
}
|
|
|
|
if (!Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this.length = 0
|
|
this.parent = undefined
|
|
}
|
|
|
|
// Common case.
|
|
if (typeof arg === 'number') {
|
|
return fromNumber(this, arg)
|
|
}
|
|
|
|
// Slightly less common case.
|
|
if (typeof arg === 'string') {
|
|
return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
|
|
}
|
|
|
|
// Unusual.
|
|
return fromObject(this, arg)
|
|
}
|
|
|
|
function fromNumber (that, length) {
|
|
that = allocate(that, length < 0 ? 0 : checked(length) | 0)
|
|
if (!Buffer.TYPED_ARRAY_SUPPORT) {
|
|
for (var i = 0; i < length; i++) {
|
|
that[i] = 0
|
|
}
|
|
}
|
|
return that
|
|
}
|
|
|
|
function fromString (that, string, encoding) {
|
|
if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'
|
|
|
|
// Assumption: byteLength() return value is always < kMaxLength.
|
|
var length = byteLength(string, encoding) | 0
|
|
that = allocate(that, length)
|
|
|
|
that.write(string, encoding)
|
|
return that
|
|
}
|
|
|
|
function fromObject (that, object) {
|
|
if (Buffer.isBuffer(object)) return fromBuffer(that, object)
|
|
|
|
if (isArray(object)) return fromArray(that, object)
|
|
|
|
if (object == null) {
|
|
throw new TypeError('must start with number, buffer, array or string')
|
|
}
|
|
|
|
if (typeof ArrayBuffer !== 'undefined') {
|
|
if (object.buffer instanceof ArrayBuffer) {
|
|
return fromTypedArray(that, object)
|
|
}
|
|
if (object instanceof ArrayBuffer) {
|
|
return fromArrayBuffer(that, object)
|
|
}
|
|
}
|
|
|
|
if (object.length) return fromArrayLike(that, object)
|
|
|
|
return fromJsonObject(that, object)
|
|
}
|
|
|
|
function fromBuffer (that, buffer) {
|
|
var length = checked(buffer.length) | 0
|
|
that = allocate(that, length)
|
|
buffer.copy(that, 0, 0, length)
|
|
return that
|
|
}
|
|
|
|
function fromArray (that, array) {
|
|
var length = checked(array.length) | 0
|
|
that = allocate(that, length)
|
|
for (var i = 0; i < length; i += 1) {
|
|
that[i] = array[i] & 255
|
|
}
|
|
return that
|
|
}
|
|
|
|
// Duplicate of fromArray() to keep fromArray() monomorphic.
|
|
function fromTypedArray (that, array) {
|
|
var length = checked(array.length) | 0
|
|
that = allocate(that, length)
|
|
// Truncating the elements is probably not what people expect from typed
|
|
// arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
|
|
// of the old Buffer constructor.
|
|
for (var i = 0; i < length; i += 1) {
|
|
that[i] = array[i] & 255
|
|
}
|
|
return that
|
|
}
|
|
|
|
function fromArrayBuffer (that, array) {
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
// Return an augmented `Uint8Array` instance, for best performance
|
|
array.byteLength
|
|
that = Buffer._augment(new Uint8Array(array))
|
|
} else {
|
|
// Fallback: Return an object instance of the Buffer class
|
|
that = fromTypedArray(that, new Uint8Array(array))
|
|
}
|
|
return that
|
|
}
|
|
|
|
function fromArrayLike (that, array) {
|
|
var length = checked(array.length) | 0
|
|
that = allocate(that, length)
|
|
for (var i = 0; i < length; i += 1) {
|
|
that[i] = array[i] & 255
|
|
}
|
|
return that
|
|
}
|
|
|
|
// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
|
|
// Returns a zero-length buffer for inputs that don't conform to the spec.
|
|
function fromJsonObject (that, object) {
|
|
var array
|
|
var length = 0
|
|
|
|
if (object.type === 'Buffer' && isArray(object.data)) {
|
|
array = object.data
|
|
length = checked(array.length) | 0
|
|
}
|
|
that = allocate(that, length)
|
|
|
|
for (var i = 0; i < length; i += 1) {
|
|
that[i] = array[i] & 255
|
|
}
|
|
return that
|
|
}
|
|
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
Buffer.prototype.__proto__ = Uint8Array.prototype
|
|
Buffer.__proto__ = Uint8Array
|
|
} else {
|
|
// pre-set for values that may exist in the future
|
|
Buffer.prototype.length = undefined
|
|
Buffer.prototype.parent = undefined
|
|
}
|
|
|
|
function allocate (that, length) {
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
// Return an augmented `Uint8Array` instance, for best performance
|
|
that = Buffer._augment(new Uint8Array(length))
|
|
that.__proto__ = Buffer.prototype
|
|
} else {
|
|
// Fallback: Return an object instance of the Buffer class
|
|
that.length = length
|
|
that._isBuffer = true
|
|
}
|
|
|
|
var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
|
|
if (fromPool) that.parent = rootParent
|
|
|
|
return that
|
|
}
|
|
|
|
function checked (length) {
|
|
// Note: cannot use `length < kMaxLength` here because that fails when
|
|
// length is NaN (which is otherwise coerced to zero.)
|
|
if (length >= kMaxLength()) {
|
|
throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
|
|
'size: 0x' + kMaxLength().toString(16) + ' bytes')
|
|
}
|
|
return length | 0
|
|
}
|
|
|
|
function SlowBuffer (subject, encoding) {
|
|
if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)
|
|
|
|
var buf = new Buffer(subject, encoding)
|
|
delete buf.parent
|
|
return buf
|
|
}
|
|
|
|
Buffer.isBuffer = function isBuffer (b) {
|
|
return !!(b != null && b._isBuffer)
|
|
}
|
|
|
|
Buffer.compare = function compare (a, b) {
|
|
if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
|
|
throw new TypeError('Arguments must be Buffers')
|
|
}
|
|
|
|
if (a === b) return 0
|
|
|
|
var x = a.length
|
|
var y = b.length
|
|
|
|
var i = 0
|
|
var len = Math.min(x, y)
|
|
while (i < len) {
|
|
if (a[i] !== b[i]) break
|
|
|
|
++i
|
|
}
|
|
|
|
if (i !== len) {
|
|
x = a[i]
|
|
y = b[i]
|
|
}
|
|
|
|
if (x < y) return -1
|
|
if (y < x) return 1
|
|
return 0
|
|
}
|
|
|
|
Buffer.isEncoding = function isEncoding (encoding) {
|
|
switch (String(encoding).toLowerCase()) {
|
|
case 'hex':
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
case 'ascii':
|
|
case 'binary':
|
|
case 'base64':
|
|
case 'raw':
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
case 'utf16le':
|
|
case 'utf-16le':
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
Buffer.concat = function concat (list, length) {
|
|
if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')
|
|
|
|
if (list.length === 0) {
|
|
return new Buffer(0)
|
|
}
|
|
|
|
var i
|
|
if (length === undefined) {
|
|
length = 0
|
|
for (i = 0; i < list.length; i++) {
|
|
length += list[i].length
|
|
}
|
|
}
|
|
|
|
var buf = new Buffer(length)
|
|
var pos = 0
|
|
for (i = 0; i < list.length; i++) {
|
|
var item = list[i]
|
|
item.copy(buf, pos)
|
|
pos += item.length
|
|
}
|
|
return buf
|
|
}
|
|
|
|
function byteLength (string, encoding) {
|
|
if (typeof string !== 'string') string = '' + string
|
|
|
|
var len = string.length
|
|
if (len === 0) return 0
|
|
|
|
// Use a for loop to avoid recursion
|
|
var loweredCase = false
|
|
for (;;) {
|
|
switch (encoding) {
|
|
case 'ascii':
|
|
case 'binary':
|
|
// Deprecated
|
|
case 'raw':
|
|
case 'raws':
|
|
return len
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return utf8ToBytes(string).length
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
case 'utf16le':
|
|
case 'utf-16le':
|
|
return len * 2
|
|
case 'hex':
|
|
return len >>> 1
|
|
case 'base64':
|
|
return base64ToBytes(string).length
|
|
default:
|
|
if (loweredCase) return utf8ToBytes(string).length // assume utf8
|
|
encoding = ('' + encoding).toLowerCase()
|
|
loweredCase = true
|
|
}
|
|
}
|
|
}
|
|
Buffer.byteLength = byteLength
|
|
|
|
function slowToString (encoding, start, end) {
|
|
var loweredCase = false
|
|
|
|
start = start | 0
|
|
end = end === undefined || end === Infinity ? this.length : end | 0
|
|
|
|
if (!encoding) encoding = 'utf8'
|
|
if (start < 0) start = 0
|
|
if (end > this.length) end = this.length
|
|
if (end <= start) return ''
|
|
|
|
while (true) {
|
|
switch (encoding) {
|
|
case 'hex':
|
|
return hexSlice(this, start, end)
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return utf8Slice(this, start, end)
|
|
|
|
case 'ascii':
|
|
return asciiSlice(this, start, end)
|
|
|
|
case 'binary':
|
|
return binarySlice(this, start, end)
|
|
|
|
case 'base64':
|
|
return base64Slice(this, start, end)
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
case 'utf16le':
|
|
case 'utf-16le':
|
|
return utf16leSlice(this, start, end)
|
|
|
|
default:
|
|
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
|
|
encoding = (encoding + '').toLowerCase()
|
|
loweredCase = true
|
|
}
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.toString = function toString () {
|
|
var length = this.length | 0
|
|
if (length === 0) return ''
|
|
if (arguments.length === 0) return utf8Slice(this, 0, length)
|
|
return slowToString.apply(this, arguments)
|
|
}
|
|
|
|
Buffer.prototype.equals = function equals (b) {
|
|
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
|
|
if (this === b) return true
|
|
return Buffer.compare(this, b) === 0
|
|
}
|
|
|
|
Buffer.prototype.inspect = function inspect () {
|
|
var str = ''
|
|
var max = exports.INSPECT_MAX_BYTES
|
|
if (this.length > 0) {
|
|
str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
|
|
if (this.length > max) str += ' ... '
|
|
}
|
|
return '<Buffer ' + str + '>'
|
|
}
|
|
|
|
Buffer.prototype.compare = function compare (b) {
|
|
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
|
|
if (this === b) return 0
|
|
return Buffer.compare(this, b)
|
|
}
|
|
|
|
Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
|
|
if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
|
|
else if (byteOffset < -0x80000000) byteOffset = -0x80000000
|
|
byteOffset >>= 0
|
|
|
|
if (this.length === 0) return -1
|
|
if (byteOffset >= this.length) return -1
|
|
|
|
// Negative offsets start from the end of the buffer
|
|
if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)
|
|
|
|
if (typeof val === 'string') {
|
|
if (val.length === 0) return -1 // special case: looking for empty string always fails
|
|
return String.prototype.indexOf.call(this, val, byteOffset)
|
|
}
|
|
if (Buffer.isBuffer(val)) {
|
|
return arrayIndexOf(this, val, byteOffset)
|
|
}
|
|
if (typeof val === 'number') {
|
|
if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
|
|
return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
|
|
}
|
|
return arrayIndexOf(this, [ val ], byteOffset)
|
|
}
|
|
|
|
function arrayIndexOf (arr, val, byteOffset) {
|
|
var foundIndex = -1
|
|
for (var i = 0; byteOffset + i < arr.length; i++) {
|
|
if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
|
|
if (foundIndex === -1) foundIndex = i
|
|
if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
|
|
} else {
|
|
foundIndex = -1
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
throw new TypeError('val must be string, number or Buffer')
|
|
}
|
|
|
|
// `get` is deprecated
|
|
Buffer.prototype.get = function get (offset) {
|
|
console.log('.get() is deprecated. Access using array indexes instead.')
|
|
return this.readUInt8(offset)
|
|
}
|
|
|
|
// `set` is deprecated
|
|
Buffer.prototype.set = function set (v, offset) {
|
|
console.log('.set() is deprecated. Access using array indexes instead.')
|
|
return this.writeUInt8(v, offset)
|
|
}
|
|
|
|
function hexWrite (buf, string, offset, length) {
|
|
offset = Number(offset) || 0
|
|
var remaining = buf.length - offset
|
|
if (!length) {
|
|
length = remaining
|
|
} else {
|
|
length = Number(length)
|
|
if (length > remaining) {
|
|
length = remaining
|
|
}
|
|
}
|
|
|
|
// must be an even number of digits
|
|
var strLen = string.length
|
|
if (strLen % 2 !== 0) throw new Error('Invalid hex string')
|
|
|
|
if (length > strLen / 2) {
|
|
length = strLen / 2
|
|
}
|
|
for (var i = 0; i < length; i++) {
|
|
var parsed = parseInt(string.substr(i * 2, 2), 16)
|
|
if (isNaN(parsed)) throw new Error('Invalid hex string')
|
|
buf[offset + i] = parsed
|
|
}
|
|
return i
|
|
}
|
|
|
|
function utf8Write (buf, string, offset, length) {
|
|
return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
|
|
}
|
|
|
|
function asciiWrite (buf, string, offset, length) {
|
|
return blitBuffer(asciiToBytes(string), buf, offset, length)
|
|
}
|
|
|
|
function binaryWrite (buf, string, offset, length) {
|
|
return asciiWrite(buf, string, offset, length)
|
|
}
|
|
|
|
function base64Write (buf, string, offset, length) {
|
|
return blitBuffer(base64ToBytes(string), buf, offset, length)
|
|
}
|
|
|
|
function ucs2Write (buf, string, offset, length) {
|
|
return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
|
|
}
|
|
|
|
Buffer.prototype.write = function write (string, offset, length, encoding) {
|
|
// Buffer#write(string)
|
|
if (offset === undefined) {
|
|
encoding = 'utf8'
|
|
length = this.length
|
|
offset = 0
|
|
// Buffer#write(string, encoding)
|
|
} else if (length === undefined && typeof offset === 'string') {
|
|
encoding = offset
|
|
length = this.length
|
|
offset = 0
|
|
// Buffer#write(string, offset[, length][, encoding])
|
|
} else if (isFinite(offset)) {
|
|
offset = offset | 0
|
|
if (isFinite(length)) {
|
|
length = length | 0
|
|
if (encoding === undefined) encoding = 'utf8'
|
|
} else {
|
|
encoding = length
|
|
length = undefined
|
|
}
|
|
// legacy write(string, encoding, offset, length) - remove in v0.13
|
|
} else {
|
|
var swap = encoding
|
|
encoding = offset
|
|
offset = length | 0
|
|
length = swap
|
|
}
|
|
|
|
var remaining = this.length - offset
|
|
if (length === undefined || length > remaining) length = remaining
|
|
|
|
if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
|
|
throw new RangeError('attempt to write outside buffer bounds')
|
|
}
|
|
|
|
if (!encoding) encoding = 'utf8'
|
|
|
|
var loweredCase = false
|
|
for (;;) {
|
|
switch (encoding) {
|
|
case 'hex':
|
|
return hexWrite(this, string, offset, length)
|
|
|
|
case 'utf8':
|
|
case 'utf-8':
|
|
return utf8Write(this, string, offset, length)
|
|
|
|
case 'ascii':
|
|
return asciiWrite(this, string, offset, length)
|
|
|
|
case 'binary':
|
|
return binaryWrite(this, string, offset, length)
|
|
|
|
case 'base64':
|
|
// Warning: maxLength not taken into account in base64Write
|
|
return base64Write(this, string, offset, length)
|
|
|
|
case 'ucs2':
|
|
case 'ucs-2':
|
|
case 'utf16le':
|
|
case 'utf-16le':
|
|
return ucs2Write(this, string, offset, length)
|
|
|
|
default:
|
|
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
|
|
encoding = ('' + encoding).toLowerCase()
|
|
loweredCase = true
|
|
}
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.toJSON = function toJSON () {
|
|
return {
|
|
type: 'Buffer',
|
|
data: Array.prototype.slice.call(this._arr || this, 0)
|
|
}
|
|
}
|
|
|
|
function base64Slice (buf, start, end) {
|
|
if (start === 0 && end === buf.length) {
|
|
return base64.fromByteArray(buf)
|
|
} else {
|
|
return base64.fromByteArray(buf.slice(start, end))
|
|
}
|
|
}
|
|
|
|
function utf8Slice (buf, start, end) {
|
|
end = Math.min(buf.length, end)
|
|
var res = []
|
|
|
|
var i = start
|
|
while (i < end) {
|
|
var firstByte = buf[i]
|
|
var codePoint = null
|
|
var bytesPerSequence = (firstByte > 0xEF) ? 4
|
|
: (firstByte > 0xDF) ? 3
|
|
: (firstByte > 0xBF) ? 2
|
|
: 1
|
|
|
|
if (i + bytesPerSequence <= end) {
|
|
var secondByte, thirdByte, fourthByte, tempCodePoint
|
|
|
|
switch (bytesPerSequence) {
|
|
case 1:
|
|
if (firstByte < 0x80) {
|
|
codePoint = firstByte
|
|
}
|
|
break
|
|
case 2:
|
|
secondByte = buf[i + 1]
|
|
if ((secondByte & 0xC0) === 0x80) {
|
|
tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
|
|
if (tempCodePoint > 0x7F) {
|
|
codePoint = tempCodePoint
|
|
}
|
|
}
|
|
break
|
|
case 3:
|
|
secondByte = buf[i + 1]
|
|
thirdByte = buf[i + 2]
|
|
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
|
|
tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
|
|
if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
|
|
codePoint = tempCodePoint
|
|
}
|
|
}
|
|
break
|
|
case 4:
|
|
secondByte = buf[i + 1]
|
|
thirdByte = buf[i + 2]
|
|
fourthByte = buf[i + 3]
|
|
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
|
|
tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
|
|
if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
|
|
codePoint = tempCodePoint
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (codePoint === null) {
|
|
// we did not generate a valid codePoint so insert a
|
|
// replacement char (U+FFFD) and advance only 1 byte
|
|
codePoint = 0xFFFD
|
|
bytesPerSequence = 1
|
|
} else if (codePoint > 0xFFFF) {
|
|
// encode to utf16 (surrogate pair dance)
|
|
codePoint -= 0x10000
|
|
res.push(codePoint >>> 10 & 0x3FF | 0xD800)
|
|
codePoint = 0xDC00 | codePoint & 0x3FF
|
|
}
|
|
|
|
res.push(codePoint)
|
|
i += bytesPerSequence
|
|
}
|
|
|
|
return decodeCodePointsArray(res)
|
|
}
|
|
|
|
// Based on http://stackoverflow.com/a/22747272/680742, the browser with
|
|
// the lowest limit is Chrome, with 0x10000 args.
|
|
// We go 1 magnitude less, for safety
|
|
var MAX_ARGUMENTS_LENGTH = 0x1000
|
|
|
|
function decodeCodePointsArray (codePoints) {
|
|
var len = codePoints.length
|
|
if (len <= MAX_ARGUMENTS_LENGTH) {
|
|
return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
|
|
}
|
|
|
|
// Decode in chunks to avoid "call stack size exceeded".
|
|
var res = ''
|
|
var i = 0
|
|
while (i < len) {
|
|
res += String.fromCharCode.apply(
|
|
String,
|
|
codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
|
|
)
|
|
}
|
|
return res
|
|
}
|
|
|
|
function asciiSlice (buf, start, end) {
|
|
var ret = ''
|
|
end = Math.min(buf.length, end)
|
|
|
|
for (var i = start; i < end; i++) {
|
|
ret += String.fromCharCode(buf[i] & 0x7F)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
function binarySlice (buf, start, end) {
|
|
var ret = ''
|
|
end = Math.min(buf.length, end)
|
|
|
|
for (var i = start; i < end; i++) {
|
|
ret += String.fromCharCode(buf[i])
|
|
}
|
|
return ret
|
|
}
|
|
|
|
function hexSlice (buf, start, end) {
|
|
var len = buf.length
|
|
|
|
if (!start || start < 0) start = 0
|
|
if (!end || end < 0 || end > len) end = len
|
|
|
|
var out = ''
|
|
for (var i = start; i < end; i++) {
|
|
out += toHex(buf[i])
|
|
}
|
|
return out
|
|
}
|
|
|
|
function utf16leSlice (buf, start, end) {
|
|
var bytes = buf.slice(start, end)
|
|
var res = ''
|
|
for (var i = 0; i < bytes.length; i += 2) {
|
|
res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
|
|
}
|
|
return res
|
|
}
|
|
|
|
Buffer.prototype.slice = function slice (start, end) {
|
|
var len = this.length
|
|
start = ~~start
|
|
end = end === undefined ? len : ~~end
|
|
|
|
if (start < 0) {
|
|
start += len
|
|
if (start < 0) start = 0
|
|
} else if (start > len) {
|
|
start = len
|
|
}
|
|
|
|
if (end < 0) {
|
|
end += len
|
|
if (end < 0) end = 0
|
|
} else if (end > len) {
|
|
end = len
|
|
}
|
|
|
|
if (end < start) end = start
|
|
|
|
var newBuf
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
newBuf = Buffer._augment(this.subarray(start, end))
|
|
} else {
|
|
var sliceLen = end - start
|
|
newBuf = new Buffer(sliceLen, undefined)
|
|
for (var i = 0; i < sliceLen; i++) {
|
|
newBuf[i] = this[i + start]
|
|
}
|
|
}
|
|
|
|
if (newBuf.length) newBuf.parent = this.parent || this
|
|
|
|
return newBuf
|
|
}
|
|
|
|
/*
|
|
* Need to make sure that buffer isn't trying to write out of bounds.
|
|
*/
|
|
function checkOffset (offset, ext, length) {
|
|
if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
|
|
if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
|
|
}
|
|
|
|
Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
|
|
offset = offset | 0
|
|
byteLength = byteLength | 0
|
|
if (!noAssert) checkOffset(offset, byteLength, this.length)
|
|
|
|
var val = this[offset]
|
|
var mul = 1
|
|
var i = 0
|
|
while (++i < byteLength && (mul *= 0x100)) {
|
|
val += this[offset + i] * mul
|
|
}
|
|
|
|
return val
|
|
}
|
|
|
|
Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
|
|
offset = offset | 0
|
|
byteLength = byteLength | 0
|
|
if (!noAssert) {
|
|
checkOffset(offset, byteLength, this.length)
|
|
}
|
|
|
|
var val = this[offset + --byteLength]
|
|
var mul = 1
|
|
while (byteLength > 0 && (mul *= 0x100)) {
|
|
val += this[offset + --byteLength] * mul
|
|
}
|
|
|
|
return val
|
|
}
|
|
|
|
Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 1, this.length)
|
|
return this[offset]
|
|
}
|
|
|
|
Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 2, this.length)
|
|
return this[offset] | (this[offset + 1] << 8)
|
|
}
|
|
|
|
Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 2, this.length)
|
|
return (this[offset] << 8) | this[offset + 1]
|
|
}
|
|
|
|
Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
|
|
return ((this[offset]) |
|
|
(this[offset + 1] << 8) |
|
|
(this[offset + 2] << 16)) +
|
|
(this[offset + 3] * 0x1000000)
|
|
}
|
|
|
|
Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
|
|
return (this[offset] * 0x1000000) +
|
|
((this[offset + 1] << 16) |
|
|
(this[offset + 2] << 8) |
|
|
this[offset + 3])
|
|
}
|
|
|
|
Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
|
|
offset = offset | 0
|
|
byteLength = byteLength | 0
|
|
if (!noAssert) checkOffset(offset, byteLength, this.length)
|
|
|
|
var val = this[offset]
|
|
var mul = 1
|
|
var i = 0
|
|
while (++i < byteLength && (mul *= 0x100)) {
|
|
val += this[offset + i] * mul
|
|
}
|
|
mul *= 0x80
|
|
|
|
if (val >= mul) val -= Math.pow(2, 8 * byteLength)
|
|
|
|
return val
|
|
}
|
|
|
|
Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
|
|
offset = offset | 0
|
|
byteLength = byteLength | 0
|
|
if (!noAssert) checkOffset(offset, byteLength, this.length)
|
|
|
|
var i = byteLength
|
|
var mul = 1
|
|
var val = this[offset + --i]
|
|
while (i > 0 && (mul *= 0x100)) {
|
|
val += this[offset + --i] * mul
|
|
}
|
|
mul *= 0x80
|
|
|
|
if (val >= mul) val -= Math.pow(2, 8 * byteLength)
|
|
|
|
return val
|
|
}
|
|
|
|
Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 1, this.length)
|
|
if (!(this[offset] & 0x80)) return (this[offset])
|
|
return ((0xff - this[offset] + 1) * -1)
|
|
}
|
|
|
|
Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 2, this.length)
|
|
var val = this[offset] | (this[offset + 1] << 8)
|
|
return (val & 0x8000) ? val | 0xFFFF0000 : val
|
|
}
|
|
|
|
Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 2, this.length)
|
|
var val = this[offset + 1] | (this[offset] << 8)
|
|
return (val & 0x8000) ? val | 0xFFFF0000 : val
|
|
}
|
|
|
|
Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
|
|
return (this[offset]) |
|
|
(this[offset + 1] << 8) |
|
|
(this[offset + 2] << 16) |
|
|
(this[offset + 3] << 24)
|
|
}
|
|
|
|
Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
|
|
return (this[offset] << 24) |
|
|
(this[offset + 1] << 16) |
|
|
(this[offset + 2] << 8) |
|
|
(this[offset + 3])
|
|
}
|
|
|
|
Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
return ieee754.read(this, offset, true, 23, 4)
|
|
}
|
|
|
|
Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 4, this.length)
|
|
return ieee754.read(this, offset, false, 23, 4)
|
|
}
|
|
|
|
Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 8, this.length)
|
|
return ieee754.read(this, offset, true, 52, 8)
|
|
}
|
|
|
|
Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
|
|
if (!noAssert) checkOffset(offset, 8, this.length)
|
|
return ieee754.read(this, offset, false, 52, 8)
|
|
}
|
|
|
|
function checkInt (buf, value, offset, ext, max, min) {
|
|
if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
|
|
if (value > max || value < min) throw new RangeError('value is out of bounds')
|
|
if (offset + ext > buf.length) throw new RangeError('index out of range')
|
|
}
|
|
|
|
Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
byteLength = byteLength | 0
|
|
if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
|
|
|
|
var mul = 1
|
|
var i = 0
|
|
this[offset] = value & 0xFF
|
|
while (++i < byteLength && (mul *= 0x100)) {
|
|
this[offset + i] = (value / mul) & 0xFF
|
|
}
|
|
|
|
return offset + byteLength
|
|
}
|
|
|
|
Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
byteLength = byteLength | 0
|
|
if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
|
|
|
|
var i = byteLength - 1
|
|
var mul = 1
|
|
this[offset + i] = value & 0xFF
|
|
while (--i >= 0 && (mul *= 0x100)) {
|
|
this[offset + i] = (value / mul) & 0xFF
|
|
}
|
|
|
|
return offset + byteLength
|
|
}
|
|
|
|
Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
|
|
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
|
|
this[offset] = (value & 0xff)
|
|
return offset + 1
|
|
}
|
|
|
|
function objectWriteUInt16 (buf, value, offset, littleEndian) {
|
|
if (value < 0) value = 0xffff + value + 1
|
|
for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
|
|
buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
|
|
(littleEndian ? i : 1 - i) * 8
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value & 0xff)
|
|
this[offset + 1] = (value >>> 8)
|
|
} else {
|
|
objectWriteUInt16(this, value, offset, true)
|
|
}
|
|
return offset + 2
|
|
}
|
|
|
|
Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value >>> 8)
|
|
this[offset + 1] = (value & 0xff)
|
|
} else {
|
|
objectWriteUInt16(this, value, offset, false)
|
|
}
|
|
return offset + 2
|
|
}
|
|
|
|
function objectWriteUInt32 (buf, value, offset, littleEndian) {
|
|
if (value < 0) value = 0xffffffff + value + 1
|
|
for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
|
|
buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
|
|
}
|
|
}
|
|
|
|
Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset + 3] = (value >>> 24)
|
|
this[offset + 2] = (value >>> 16)
|
|
this[offset + 1] = (value >>> 8)
|
|
this[offset] = (value & 0xff)
|
|
} else {
|
|
objectWriteUInt32(this, value, offset, true)
|
|
}
|
|
return offset + 4
|
|
}
|
|
|
|
Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value >>> 24)
|
|
this[offset + 1] = (value >>> 16)
|
|
this[offset + 2] = (value >>> 8)
|
|
this[offset + 3] = (value & 0xff)
|
|
} else {
|
|
objectWriteUInt32(this, value, offset, false)
|
|
}
|
|
return offset + 4
|
|
}
|
|
|
|
Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) {
|
|
var limit = Math.pow(2, 8 * byteLength - 1)
|
|
|
|
checkInt(this, value, offset, byteLength, limit - 1, -limit)
|
|
}
|
|
|
|
var i = 0
|
|
var mul = 1
|
|
var sub = value < 0 ? 1 : 0
|
|
this[offset] = value & 0xFF
|
|
while (++i < byteLength && (mul *= 0x100)) {
|
|
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
|
|
}
|
|
|
|
return offset + byteLength
|
|
}
|
|
|
|
Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) {
|
|
var limit = Math.pow(2, 8 * byteLength - 1)
|
|
|
|
checkInt(this, value, offset, byteLength, limit - 1, -limit)
|
|
}
|
|
|
|
var i = byteLength - 1
|
|
var mul = 1
|
|
var sub = value < 0 ? 1 : 0
|
|
this[offset + i] = value & 0xFF
|
|
while (--i >= 0 && (mul *= 0x100)) {
|
|
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
|
|
}
|
|
|
|
return offset + byteLength
|
|
}
|
|
|
|
Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
|
|
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
|
|
if (value < 0) value = 0xff + value + 1
|
|
this[offset] = (value & 0xff)
|
|
return offset + 1
|
|
}
|
|
|
|
Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value & 0xff)
|
|
this[offset + 1] = (value >>> 8)
|
|
} else {
|
|
objectWriteUInt16(this, value, offset, true)
|
|
}
|
|
return offset + 2
|
|
}
|
|
|
|
Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value >>> 8)
|
|
this[offset + 1] = (value & 0xff)
|
|
} else {
|
|
objectWriteUInt16(this, value, offset, false)
|
|
}
|
|
return offset + 2
|
|
}
|
|
|
|
Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value & 0xff)
|
|
this[offset + 1] = (value >>> 8)
|
|
this[offset + 2] = (value >>> 16)
|
|
this[offset + 3] = (value >>> 24)
|
|
} else {
|
|
objectWriteUInt32(this, value, offset, true)
|
|
}
|
|
return offset + 4
|
|
}
|
|
|
|
Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
|
|
value = +value
|
|
offset = offset | 0
|
|
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
|
|
if (value < 0) value = 0xffffffff + value + 1
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
this[offset] = (value >>> 24)
|
|
this[offset + 1] = (value >>> 16)
|
|
this[offset + 2] = (value >>> 8)
|
|
this[offset + 3] = (value & 0xff)
|
|
} else {
|
|
objectWriteUInt32(this, value, offset, false)
|
|
}
|
|
return offset + 4
|
|
}
|
|
|
|
function checkIEEE754 (buf, value, offset, ext, max, min) {
|
|
if (value > max || value < min) throw new RangeError('value is out of bounds')
|
|
if (offset + ext > buf.length) throw new RangeError('index out of range')
|
|
if (offset < 0) throw new RangeError('index out of range')
|
|
}
|
|
|
|
function writeFloat (buf, value, offset, littleEndian, noAssert) {
|
|
if (!noAssert) {
|
|
checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
|
|
}
|
|
ieee754.write(buf, value, offset, littleEndian, 23, 4)
|
|
return offset + 4
|
|
}
|
|
|
|
Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
|
|
return writeFloat(this, value, offset, true, noAssert)
|
|
}
|
|
|
|
Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
|
|
return writeFloat(this, value, offset, false, noAssert)
|
|
}
|
|
|
|
function writeDouble (buf, value, offset, littleEndian, noAssert) {
|
|
if (!noAssert) {
|
|
checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
|
|
}
|
|
ieee754.write(buf, value, offset, littleEndian, 52, 8)
|
|
return offset + 8
|
|
}
|
|
|
|
Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
|
|
return writeDouble(this, value, offset, true, noAssert)
|
|
}
|
|
|
|
Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
|
|
return writeDouble(this, value, offset, false, noAssert)
|
|
}
|
|
|
|
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
|
|
Buffer.prototype.copy = function copy (target, targetStart, start, end) {
|
|
if (!start) start = 0
|
|
if (!end && end !== 0) end = this.length
|
|
if (targetStart >= target.length) targetStart = target.length
|
|
if (!targetStart) targetStart = 0
|
|
if (end > 0 && end < start) end = start
|
|
|
|
// Copy 0 bytes; we're done
|
|
if (end === start) return 0
|
|
if (target.length === 0 || this.length === 0) return 0
|
|
|
|
// Fatal error conditions
|
|
if (targetStart < 0) {
|
|
throw new RangeError('targetStart out of bounds')
|
|
}
|
|
if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
|
|
if (end < 0) throw new RangeError('sourceEnd out of bounds')
|
|
|
|
// Are we oob?
|
|
if (end > this.length) end = this.length
|
|
if (target.length - targetStart < end - start) {
|
|
end = target.length - targetStart + start
|
|
}
|
|
|
|
var len = end - start
|
|
var i
|
|
|
|
if (this === target && start < targetStart && targetStart < end) {
|
|
// descending copy from end
|
|
for (i = len - 1; i >= 0; i--) {
|
|
target[i + targetStart] = this[i + start]
|
|
}
|
|
} else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
|
|
// ascending copy from start
|
|
for (i = 0; i < len; i++) {
|
|
target[i + targetStart] = this[i + start]
|
|
}
|
|
} else {
|
|
target._set(this.subarray(start, start + len), targetStart)
|
|
}
|
|
|
|
return len
|
|
}
|
|
|
|
// fill(value, start=0, end=buffer.length)
|
|
Buffer.prototype.fill = function fill (value, start, end) {
|
|
if (!value) value = 0
|
|
if (!start) start = 0
|
|
if (!end) end = this.length
|
|
|
|
if (end < start) throw new RangeError('end < start')
|
|
|
|
// Fill 0 bytes; we're done
|
|
if (end === start) return
|
|
if (this.length === 0) return
|
|
|
|
if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
|
|
if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
|
|
|
|
var i
|
|
if (typeof value === 'number') {
|
|
for (i = start; i < end; i++) {
|
|
this[i] = value
|
|
}
|
|
} else {
|
|
var bytes = utf8ToBytes(value.toString())
|
|
var len = bytes.length
|
|
for (i = start; i < end; i++) {
|
|
this[i] = bytes[i % len]
|
|
}
|
|
}
|
|
|
|
return this
|
|
}
|
|
|
|
/**
|
|
* Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
|
|
* Added in Node 0.12. Only available in browsers that support ArrayBuffer.
|
|
*/
|
|
Buffer.prototype.toArrayBuffer = function toArrayBuffer () {
|
|
if (typeof Uint8Array !== 'undefined') {
|
|
if (Buffer.TYPED_ARRAY_SUPPORT) {
|
|
return (new Buffer(this)).buffer
|
|
} else {
|
|
var buf = new Uint8Array(this.length)
|
|
for (var i = 0, len = buf.length; i < len; i += 1) {
|
|
buf[i] = this[i]
|
|
}
|
|
return buf.buffer
|
|
}
|
|
} else {
|
|
throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
|
|
}
|
|
}
|
|
|
|
// HELPER FUNCTIONS
|
|
// ================
|
|
|
|
var BP = Buffer.prototype
|
|
|
|
/**
|
|
* Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
|
|
*/
|
|
Buffer._augment = function _augment (arr) {
|
|
arr.constructor = Buffer
|
|
arr._isBuffer = true
|
|
|
|
// save reference to original Uint8Array set method before overwriting
|
|
arr._set = arr.set
|
|
|
|
// deprecated
|
|
arr.get = BP.get
|
|
arr.set = BP.set
|
|
|
|
arr.write = BP.write
|
|
arr.toString = BP.toString
|
|
arr.toLocaleString = BP.toString
|
|
arr.toJSON = BP.toJSON
|
|
arr.equals = BP.equals
|
|
arr.compare = BP.compare
|
|
arr.indexOf = BP.indexOf
|
|
arr.copy = BP.copy
|
|
arr.slice = BP.slice
|
|
arr.readUIntLE = BP.readUIntLE
|
|
arr.readUIntBE = BP.readUIntBE
|
|
arr.readUInt8 = BP.readUInt8
|
|
arr.readUInt16LE = BP.readUInt16LE
|
|
arr.readUInt16BE = BP.readUInt16BE
|
|
arr.readUInt32LE = BP.readUInt32LE
|
|
arr.readUInt32BE = BP.readUInt32BE
|
|
arr.readIntLE = BP.readIntLE
|
|
arr.readIntBE = BP.readIntBE
|
|
arr.readInt8 = BP.readInt8
|
|
arr.readInt16LE = BP.readInt16LE
|
|
arr.readInt16BE = BP.readInt16BE
|
|
arr.readInt32LE = BP.readInt32LE
|
|
arr.readInt32BE = BP.readInt32BE
|
|
arr.readFloatLE = BP.readFloatLE
|
|
arr.readFloatBE = BP.readFloatBE
|
|
arr.readDoubleLE = BP.readDoubleLE
|
|
arr.readDoubleBE = BP.readDoubleBE
|
|
arr.writeUInt8 = BP.writeUInt8
|
|
arr.writeUIntLE = BP.writeUIntLE
|
|
arr.writeUIntBE = BP.writeUIntBE
|
|
arr.writeUInt16LE = BP.writeUInt16LE
|
|
arr.writeUInt16BE = BP.writeUInt16BE
|
|
arr.writeUInt32LE = BP.writeUInt32LE
|
|
arr.writeUInt32BE = BP.writeUInt32BE
|
|
arr.writeIntLE = BP.writeIntLE
|
|
arr.writeIntBE = BP.writeIntBE
|
|
arr.writeInt8 = BP.writeInt8
|
|
arr.writeInt16LE = BP.writeInt16LE
|
|
arr.writeInt16BE = BP.writeInt16BE
|
|
arr.writeInt32LE = BP.writeInt32LE
|
|
arr.writeInt32BE = BP.writeInt32BE
|
|
arr.writeFloatLE = BP.writeFloatLE
|
|
arr.writeFloatBE = BP.writeFloatBE
|
|
arr.writeDoubleLE = BP.writeDoubleLE
|
|
arr.writeDoubleBE = BP.writeDoubleBE
|
|
arr.fill = BP.fill
|
|
arr.inspect = BP.inspect
|
|
arr.toArrayBuffer = BP.toArrayBuffer
|
|
|
|
return arr
|
|
}
|
|
|
|
var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
|
|
|
|
function base64clean (str) {
|
|
// Node strips out invalid characters like \n and \t from the string, base64-js does not
|
|
str = stringtrim(str).replace(INVALID_BASE64_RE, '')
|
|
// Node converts strings with length < 2 to ''
|
|
if (str.length < 2) return ''
|
|
// Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
|
|
while (str.length % 4 !== 0) {
|
|
str = str + '='
|
|
}
|
|
return str
|
|
}
|
|
|
|
function stringtrim (str) {
|
|
if (str.trim) return str.trim()
|
|
return str.replace(/^\s+|\s+$/g, '')
|
|
}
|
|
|
|
function toHex (n) {
|
|
if (n < 16) return '0' + n.toString(16)
|
|
return n.toString(16)
|
|
}
|
|
|
|
function utf8ToBytes (string, units) {
|
|
units = units || Infinity
|
|
var codePoint
|
|
var length = string.length
|
|
var leadSurrogate = null
|
|
var bytes = []
|
|
|
|
for (var i = 0; i < length; i++) {
|
|
codePoint = string.charCodeAt(i)
|
|
|
|
// is surrogate component
|
|
if (codePoint > 0xD7FF && codePoint < 0xE000) {
|
|
// last char was a lead
|
|
if (!leadSurrogate) {
|
|
// no lead yet
|
|
if (codePoint > 0xDBFF) {
|
|
// unexpected trail
|
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
|
continue
|
|
} else if (i + 1 === length) {
|
|
// unpaired lead
|
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
|
continue
|
|
}
|
|
|
|
// valid lead
|
|
leadSurrogate = codePoint
|
|
|
|
continue
|
|
}
|
|
|
|
// 2 leads in a row
|
|
if (codePoint < 0xDC00) {
|
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
|
leadSurrogate = codePoint
|
|
continue
|
|
}
|
|
|
|
// valid surrogate pair
|
|
codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
|
|
} else if (leadSurrogate) {
|
|
// valid bmp char, but last char was a lead
|
|
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
|
|
}
|
|
|
|
leadSurrogate = null
|
|
|
|
// encode utf8
|
|
if (codePoint < 0x80) {
|
|
if ((units -= 1) < 0) break
|
|
bytes.push(codePoint)
|
|
} else if (codePoint < 0x800) {
|
|
if ((units -= 2) < 0) break
|
|
bytes.push(
|
|
codePoint >> 0x6 | 0xC0,
|
|
codePoint & 0x3F | 0x80
|
|
)
|
|
} else if (codePoint < 0x10000) {
|
|
if ((units -= 3) < 0) break
|
|
bytes.push(
|
|
codePoint >> 0xC | 0xE0,
|
|
codePoint >> 0x6 & 0x3F | 0x80,
|
|
codePoint & 0x3F | 0x80
|
|
)
|
|
} else if (codePoint < 0x110000) {
|
|
if ((units -= 4) < 0) break
|
|
bytes.push(
|
|
codePoint >> 0x12 | 0xF0,
|
|
codePoint >> 0xC & 0x3F | 0x80,
|
|
codePoint >> 0x6 & 0x3F | 0x80,
|
|
codePoint & 0x3F | 0x80
|
|
)
|
|
} else {
|
|
throw new Error('Invalid code point')
|
|
}
|
|
}
|
|
|
|
return bytes
|
|
}
|
|
|
|
function asciiToBytes (str) {
|
|
var byteArray = []
|
|
for (var i = 0; i < str.length; i++) {
|
|
// Node's code seems to be doing this and not & 0x7F..
|
|
byteArray.push(str.charCodeAt(i) & 0xFF)
|
|
}
|
|
return byteArray
|
|
}
|
|
|
|
function utf16leToBytes (str, units) {
|
|
var c, hi, lo
|
|
var byteArray = []
|
|
for (var i = 0; i < str.length; i++) {
|
|
if ((units -= 2) < 0) break
|
|
|
|
c = str.charCodeAt(i)
|
|
hi = c >> 8
|
|
lo = c % 256
|
|
byteArray.push(lo)
|
|
byteArray.push(hi)
|
|
}
|
|
|
|
return byteArray
|
|
}
|
|
|
|
function base64ToBytes (str) {
|
|
return base64.toByteArray(base64clean(str))
|
|
}
|
|
|
|
function blitBuffer (src, dst, offset, length) {
|
|
for (var i = 0; i < length; i++) {
|
|
if ((i + offset >= dst.length) || (i >= src.length)) break
|
|
dst[i + offset] = src[i]
|
|
}
|
|
return i
|
|
}
|
|
|
|
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
},{"base64-js":5,"ieee754":47,"isarray":9}],9:[function(require,module,exports){
|
|
var toString = {}.toString;
|
|
|
|
module.exports = Array.isArray || function (arr) {
|
|
return toString.call(arr) == '[object Array]';
|
|
};
|
|
|
|
},{}],10:[function(require,module,exports){
|
|
/*!
|
|
* domready (c) Dustin Diaz 2014 - License MIT
|
|
*/
|
|
!function (name, definition) {
|
|
|
|
if (typeof module != 'undefined') module.exports = definition()
|
|
else if (typeof define == 'function' && typeof define.amd == 'object') define(definition)
|
|
else this[name] = definition()
|
|
|
|
}('domready', function () {
|
|
|
|
var fns = [], listener
|
|
, doc = document
|
|
, hack = doc.documentElement.doScroll
|
|
, domContentLoaded = 'DOMContentLoaded'
|
|
, loaded = (hack ? /^loaded|^c/ : /^loaded|^i|^c/).test(doc.readyState)
|
|
|
|
|
|
if (!loaded)
|
|
doc.addEventListener(domContentLoaded, listener = function () {
|
|
doc.removeEventListener(domContentLoaded, listener)
|
|
loaded = 1
|
|
while (listener = fns.shift()) listener()
|
|
})
|
|
|
|
return function (fn) {
|
|
loaded ? setTimeout(fn, 0) : fns.push(fn)
|
|
}
|
|
|
|
});
|
|
|
|
},{}],11:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
function dupe_array(count, value, i) {
|
|
var c = count[i]|0
|
|
if(c <= 0) {
|
|
return []
|
|
}
|
|
var result = new Array(c), j
|
|
if(i === count.length-1) {
|
|
for(j=0; j<c; ++j) {
|
|
result[j] = value
|
|
}
|
|
} else {
|
|
for(j=0; j<c; ++j) {
|
|
result[j] = dupe_array(count, value, i+1)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
function dupe_number(count, value) {
|
|
var result, i
|
|
result = new Array(count)
|
|
for(i=0; i<count; ++i) {
|
|
result[i] = value
|
|
}
|
|
return result
|
|
}
|
|
|
|
function dupe(count, value) {
|
|
if(typeof value === "undefined") {
|
|
value = 0
|
|
}
|
|
switch(typeof count) {
|
|
case "number":
|
|
if(count > 0) {
|
|
return dupe_number(count|0, value)
|
|
}
|
|
break
|
|
case "object":
|
|
if(typeof (count.length) === "number") {
|
|
return dupe_array(count, value, 0)
|
|
}
|
|
break
|
|
}
|
|
return []
|
|
}
|
|
|
|
module.exports = dupe
|
|
},{}],12:[function(require,module,exports){
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
function EventEmitter() {
|
|
this._events = this._events || {};
|
|
this._maxListeners = this._maxListeners || undefined;
|
|
}
|
|
module.exports = EventEmitter;
|
|
|
|
// Backwards-compat with node 0.10.x
|
|
EventEmitter.EventEmitter = EventEmitter;
|
|
|
|
EventEmitter.prototype._events = undefined;
|
|
EventEmitter.prototype._maxListeners = undefined;
|
|
|
|
// By default EventEmitters will print a warning if more than 10 listeners are
|
|
// added to it. This is a useful default which helps finding memory leaks.
|
|
EventEmitter.defaultMaxListeners = 10;
|
|
|
|
// Obviously not all Emitters should be limited to 10. This function allows
|
|
// that to be increased. Set to zero for unlimited.
|
|
EventEmitter.prototype.setMaxListeners = function(n) {
|
|
if (!isNumber(n) || n < 0 || isNaN(n))
|
|
throw TypeError('n must be a positive number');
|
|
this._maxListeners = n;
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.emit = function(type) {
|
|
var er, handler, len, args, i, listeners;
|
|
|
|
if (!this._events)
|
|
this._events = {};
|
|
|
|
// If there is no 'error' event listener then throw.
|
|
if (type === 'error') {
|
|
if (!this._events.error ||
|
|
(isObject(this._events.error) && !this._events.error.length)) {
|
|
er = arguments[1];
|
|
if (er instanceof Error) {
|
|
throw er; // Unhandled 'error' event
|
|
}
|
|
throw TypeError('Uncaught, unspecified "error" event.');
|
|
}
|
|
}
|
|
|
|
handler = this._events[type];
|
|
|
|
if (isUndefined(handler))
|
|
return false;
|
|
|
|
if (isFunction(handler)) {
|
|
switch (arguments.length) {
|
|
// fast cases
|
|
case 1:
|
|
handler.call(this);
|
|
break;
|
|
case 2:
|
|
handler.call(this, arguments[1]);
|
|
break;
|
|
case 3:
|
|
handler.call(this, arguments[1], arguments[2]);
|
|
break;
|
|
// slower
|
|
default:
|
|
len = arguments.length;
|
|
args = new Array(len - 1);
|
|
for (i = 1; i < len; i++)
|
|
args[i - 1] = arguments[i];
|
|
handler.apply(this, args);
|
|
}
|
|
} else if (isObject(handler)) {
|
|
len = arguments.length;
|
|
args = new Array(len - 1);
|
|
for (i = 1; i < len; i++)
|
|
args[i - 1] = arguments[i];
|
|
|
|
listeners = handler.slice();
|
|
len = listeners.length;
|
|
for (i = 0; i < len; i++)
|
|
listeners[i].apply(this, args);
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
EventEmitter.prototype.addListener = function(type, listener) {
|
|
var m;
|
|
|
|
if (!isFunction(listener))
|
|
throw TypeError('listener must be a function');
|
|
|
|
if (!this._events)
|
|
this._events = {};
|
|
|
|
// To avoid recursion in the case that type === "newListener"! Before
|
|
// adding it to the listeners, first emit "newListener".
|
|
if (this._events.newListener)
|
|
this.emit('newListener', type,
|
|
isFunction(listener.listener) ?
|
|
listener.listener : listener);
|
|
|
|
if (!this._events[type])
|
|
// Optimize the case of one listener. Don't need the extra array object.
|
|
this._events[type] = listener;
|
|
else if (isObject(this._events[type]))
|
|
// If we've already got an array, just append.
|
|
this._events[type].push(listener);
|
|
else
|
|
// Adding the second element, need to change to array.
|
|
this._events[type] = [this._events[type], listener];
|
|
|
|
// Check for listener leak
|
|
if (isObject(this._events[type]) && !this._events[type].warned) {
|
|
var m;
|
|
if (!isUndefined(this._maxListeners)) {
|
|
m = this._maxListeners;
|
|
} else {
|
|
m = EventEmitter.defaultMaxListeners;
|
|
}
|
|
|
|
if (m && m > 0 && this._events[type].length > m) {
|
|
this._events[type].warned = true;
|
|
console.error('(node) warning: possible EventEmitter memory ' +
|
|
'leak detected. %d listeners added. ' +
|
|
'Use emitter.setMaxListeners() to increase limit.',
|
|
this._events[type].length);
|
|
if (typeof console.trace === 'function') {
|
|
// not supported in IE 10
|
|
console.trace();
|
|
}
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
|
|
|
EventEmitter.prototype.once = function(type, listener) {
|
|
if (!isFunction(listener))
|
|
throw TypeError('listener must be a function');
|
|
|
|
var fired = false;
|
|
|
|
function g() {
|
|
this.removeListener(type, g);
|
|
|
|
if (!fired) {
|
|
fired = true;
|
|
listener.apply(this, arguments);
|
|
}
|
|
}
|
|
|
|
g.listener = listener;
|
|
this.on(type, g);
|
|
|
|
return this;
|
|
};
|
|
|
|
// emits a 'removeListener' event iff the listener was removed
|
|
EventEmitter.prototype.removeListener = function(type, listener) {
|
|
var list, position, length, i;
|
|
|
|
if (!isFunction(listener))
|
|
throw TypeError('listener must be a function');
|
|
|
|
if (!this._events || !this._events[type])
|
|
return this;
|
|
|
|
list = this._events[type];
|
|
length = list.length;
|
|
position = -1;
|
|
|
|
if (list === listener ||
|
|
(isFunction(list.listener) && list.listener === listener)) {
|
|
delete this._events[type];
|
|
if (this._events.removeListener)
|
|
this.emit('removeListener', type, listener);
|
|
|
|
} else if (isObject(list)) {
|
|
for (i = length; i-- > 0;) {
|
|
if (list[i] === listener ||
|
|
(list[i].listener && list[i].listener === listener)) {
|
|
position = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (position < 0)
|
|
return this;
|
|
|
|
if (list.length === 1) {
|
|
list.length = 0;
|
|
delete this._events[type];
|
|
} else {
|
|
list.splice(position, 1);
|
|
}
|
|
|
|
if (this._events.removeListener)
|
|
this.emit('removeListener', type, listener);
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.removeAllListeners = function(type) {
|
|
var key, listeners;
|
|
|
|
if (!this._events)
|
|
return this;
|
|
|
|
// not listening for removeListener, no need to emit
|
|
if (!this._events.removeListener) {
|
|
if (arguments.length === 0)
|
|
this._events = {};
|
|
else if (this._events[type])
|
|
delete this._events[type];
|
|
return this;
|
|
}
|
|
|
|
// emit removeListener for all listeners on all events
|
|
if (arguments.length === 0) {
|
|
for (key in this._events) {
|
|
if (key === 'removeListener') continue;
|
|
this.removeAllListeners(key);
|
|
}
|
|
this.removeAllListeners('removeListener');
|
|
this._events = {};
|
|
return this;
|
|
}
|
|
|
|
listeners = this._events[type];
|
|
|
|
if (isFunction(listeners)) {
|
|
this.removeListener(type, listeners);
|
|
} else {
|
|
// LIFO order
|
|
while (listeners.length)
|
|
this.removeListener(type, listeners[listeners.length - 1]);
|
|
}
|
|
delete this._events[type];
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.listeners = function(type) {
|
|
var ret;
|
|
if (!this._events || !this._events[type])
|
|
ret = [];
|
|
else if (isFunction(this._events[type]))
|
|
ret = [this._events[type]];
|
|
else
|
|
ret = this._events[type].slice();
|
|
return ret;
|
|
};
|
|
|
|
EventEmitter.listenerCount = function(emitter, type) {
|
|
var ret;
|
|
if (!emitter._events || !emitter._events[type])
|
|
ret = 0;
|
|
else if (isFunction(emitter._events[type]))
|
|
ret = 1;
|
|
else
|
|
ret = emitter._events[type].length;
|
|
return ret;
|
|
};
|
|
|
|
function isFunction(arg) {
|
|
return typeof arg === 'function';
|
|
}
|
|
|
|
function isNumber(arg) {
|
|
return typeof arg === 'number';
|
|
}
|
|
|
|
function isObject(arg) {
|
|
return typeof arg === 'object' && arg !== null;
|
|
}
|
|
|
|
function isUndefined(arg) {
|
|
return arg === void 0;
|
|
}
|
|
|
|
},{}],13:[function(require,module,exports){
|
|
if(typeof window.performance === "object") {
|
|
if(window.performance.now) {
|
|
module.exports = function() { return window.performance.now() }
|
|
} else if(window.performance.webkitNow) {
|
|
module.exports = function() { return window.performance.webkitNow() }
|
|
}
|
|
} else if(Date.now) {
|
|
module.exports = Date.now
|
|
} else {
|
|
module.exports = function() { return (new Date()).getTime() }
|
|
}
|
|
|
|
},{}],14:[function(require,module,exports){
|
|
//Adapted from here: https://developer.mozilla.org/en-US/docs/Web/Reference/Events/wheel?redirectlocale=en-US&redirectslug=DOM%2FMozilla_event_reference%2Fwheel
|
|
|
|
var prefix = "", _addEventListener, onwheel, support;
|
|
|
|
// detect event model
|
|
if ( window.addEventListener ) {
|
|
_addEventListener = "addEventListener";
|
|
} else {
|
|
_addEventListener = "attachEvent";
|
|
prefix = "on";
|
|
}
|
|
|
|
// detect available wheel event
|
|
support = "onwheel" in document.createElement("div") ? "wheel" : // Modern browsers support "wheel"
|
|
document.onmousewheel !== undefined ? "mousewheel" : // Webkit and IE support at least "mousewheel"
|
|
"DOMMouseScroll"; // let's assume that remaining browsers are older Firefox
|
|
|
|
function _addWheelListener( elem, eventName, callback, useCapture ) {
|
|
elem[ _addEventListener ]( prefix + eventName, support == "wheel" ? callback : function( originalEvent ) {
|
|
!originalEvent && ( originalEvent = window.event );
|
|
|
|
// create a normalized event object
|
|
var event = {
|
|
// keep a ref to the original event object
|
|
originalEvent: originalEvent,
|
|
target: originalEvent.target || originalEvent.srcElement,
|
|
type: "wheel",
|
|
deltaMode: originalEvent.type == "MozMousePixelScroll" ? 0 : 1,
|
|
deltaX: 0,
|
|
delatZ: 0,
|
|
preventDefault: function() {
|
|
originalEvent.preventDefault ?
|
|
originalEvent.preventDefault() :
|
|
originalEvent.returnValue = false;
|
|
}
|
|
};
|
|
|
|
// calculate deltaY (and deltaX) according to the event
|
|
if ( support == "mousewheel" ) {
|
|
event.deltaY = - 1/40 * originalEvent.wheelDelta;
|
|
// Webkit also support wheelDeltaX
|
|
originalEvent.wheelDeltaX && ( event.deltaX = - 1/40 * originalEvent.wheelDeltaX );
|
|
} else {
|
|
event.deltaY = originalEvent.detail;
|
|
}
|
|
|
|
// it's time to fire the callback
|
|
return callback( event );
|
|
}, useCapture || false );
|
|
}
|
|
|
|
module.exports = function( elem, callback, useCapture ) {
|
|
_addWheelListener( elem, support, callback, useCapture );
|
|
|
|
// handle MozMousePixelScroll in older Firefox
|
|
if( support == "DOMMouseScroll" ) {
|
|
_addWheelListener( elem, "MozMousePixelScroll", callback, useCapture );
|
|
}
|
|
};
|
|
},{}],15:[function(require,module,exports){
|
|
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
|
|
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
|
|
|
|
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
|
|
|
|
// MIT license
|
|
var lastTime = 0;
|
|
var vendors = ['ms', 'moz', 'webkit', 'o'];
|
|
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
|
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
|
|
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
|
|
|| window[vendors[x]+'CancelRequestAnimationFrame'];
|
|
}
|
|
|
|
if (!window.requestAnimationFrame)
|
|
window.requestAnimationFrame = function(callback, element) {
|
|
var currTime = new Date().getTime();
|
|
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
|
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
|
|
timeToCall);
|
|
lastTime = currTime + timeToCall;
|
|
return id;
|
|
};
|
|
|
|
if (!window.cancelAnimationFrame)
|
|
window.cancelAnimationFrame = function(id) {
|
|
clearTimeout(id);
|
|
};
|
|
|
|
},{}],16:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
var EventEmitter = require("events").EventEmitter
|
|
, util = require("util")
|
|
, domready = require("domready")
|
|
, vkey = require("vkey")
|
|
, invert = require("invert-hash")
|
|
, uniq = require("uniq")
|
|
, bsearch = require("binary-search-bounds")
|
|
, iota = require("iota-array")
|
|
, min = Math.min
|
|
|
|
//Browser compatibility hacks
|
|
require("./lib/raf-polyfill.js")
|
|
var addMouseWheel = require("./lib/mousewheel-polyfill.js")
|
|
var hrtime = require("./lib/hrtime-polyfill.js")
|
|
|
|
//Remove angle braces and other useless crap
|
|
var filtered_vkey = (function() {
|
|
var result = new Array(256)
|
|
, i, j, k
|
|
for(i=0; i<256; ++i) {
|
|
result[i] = "UNK"
|
|
}
|
|
for(i in vkey) {
|
|
k = vkey[i]
|
|
if(k.charAt(0) === '<' && k.charAt(k.length-1) === '>') {
|
|
k = k.substring(1, k.length-1)
|
|
}
|
|
k = k.replace(/\s/g, "-")
|
|
result[parseInt(i)] = k
|
|
}
|
|
return result
|
|
})()
|
|
|
|
//Compute minimal common set of keyboard functions
|
|
var keyNames = uniq(Object.keys(invert(filtered_vkey)))
|
|
|
|
//Translates a virtual keycode to a normalized keycode
|
|
function virtualKeyCode(key) {
|
|
return bsearch.eq(keyNames, key)
|
|
}
|
|
|
|
//Maps a physical keycode to a normalized keycode
|
|
function physicalKeyCode(key) {
|
|
return virtualKeyCode(filtered_vkey[key])
|
|
}
|
|
|
|
//Game shell
|
|
function GameShell() {
|
|
EventEmitter.call(this)
|
|
this._curKeyState = new Array(keyNames.length)
|
|
this._pressCount = new Array(keyNames.length)
|
|
this._releaseCount = new Array(keyNames.length)
|
|
|
|
this._tickInterval = null
|
|
this._rafHandle = null
|
|
this._tickRate = 0
|
|
this._lastTick = hrtime()
|
|
this._frameTime = 0.0
|
|
this._paused = true
|
|
this._width = 0
|
|
this._height = 0
|
|
|
|
this._wantFullscreen = false
|
|
this._wantPointerLock = false
|
|
this._fullscreenActive = false
|
|
this._pointerLockActive = false
|
|
|
|
this._render = render.bind(undefined, this)
|
|
|
|
this.preventDefaults = true
|
|
this.stopPropagation = false
|
|
|
|
for(var i=0; i<keyNames.length; ++i) {
|
|
this._curKeyState[i] = false
|
|
this._pressCount[i] = this._releaseCount[i] = 0
|
|
}
|
|
|
|
//Public members
|
|
this.element = null
|
|
this.bindings = {}
|
|
this.frameSkip = 100.0
|
|
this.tickCount = 0
|
|
this.frameCount = 0
|
|
this.startTime = hrtime()
|
|
this.tickTime = this._tickRate
|
|
this.frameTime = 10.0
|
|
this.stickyFullscreen = false
|
|
this.stickyPointerLock = false
|
|
|
|
//Scroll stuff
|
|
this.scroll = [0,0,0]
|
|
|
|
//Mouse state
|
|
this.mouseX = 0
|
|
this.mouseY = 0
|
|
this.prevMouseX = 0
|
|
this.prevMouseY = 0
|
|
}
|
|
|
|
util.inherits(GameShell, EventEmitter)
|
|
|
|
var proto = GameShell.prototype
|
|
|
|
//Bind keynames
|
|
proto.keyNames = keyNames
|
|
|
|
//Binds a virtual keyboard event to a physical key
|
|
proto.bind = function(virtual_key) {
|
|
//Look up previous key bindings
|
|
var arr
|
|
if(virtual_key in this.bindings) {
|
|
arr = this.bindings[virtual_key]
|
|
} else {
|
|
arr = []
|
|
}
|
|
//Add keys to list
|
|
var physical_key
|
|
for(var i=1, n=arguments.length; i<n; ++i) {
|
|
physical_key = arguments[i]
|
|
if(virtualKeyCode(physical_key) >= 0) {
|
|
arr.push(physical_key)
|
|
} else if(physical_key in this.bindings) {
|
|
var keybinds = this.bindings[physical_key]
|
|
for(var j=0; j<keybinds.length; ++j) {
|
|
arr.push(keybinds[j])
|
|
}
|
|
}
|
|
}
|
|
//Remove any duplicate keys
|
|
arr = uniq(arr)
|
|
if(arr.length > 0) {
|
|
this.bindings[virtual_key] = arr
|
|
}
|
|
this.emit('bind', virtual_key, arr)
|
|
}
|
|
|
|
//Unbinds a virtual keyboard event
|
|
proto.unbind = function(virtual_key) {
|
|
if(virtual_key in this.bindings) {
|
|
delete this.bindings[virtual_key]
|
|
}
|
|
this.emit('unbind', virtual_key)
|
|
}
|
|
|
|
//Checks if a key is set in a given state
|
|
function lookupKey(state, bindings, key) {
|
|
if(key in bindings) {
|
|
var arr = bindings[key]
|
|
for(var i=0, n=arr.length; i<n; ++i) {
|
|
if(state[virtualKeyCode(arr[i])]) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
var kc = virtualKeyCode(key)
|
|
if(kc >= 0) {
|
|
return state[kc]
|
|
}
|
|
return false
|
|
}
|
|
|
|
//Checks if a key is set in a given state
|
|
function lookupCount(state, bindings, key) {
|
|
if(key in bindings) {
|
|
var arr = bindings[key], r = 0
|
|
for(var i=0, n=arr.length; i<n; ++i) {
|
|
r += state[virtualKeyCode(arr[i])]
|
|
}
|
|
return r
|
|
}
|
|
var kc = virtualKeyCode(key)
|
|
if(kc >= 0) {
|
|
return state[kc]
|
|
}
|
|
return 0
|
|
}
|
|
|
|
//Checks if a key (either physical or virtual) is currently held down
|
|
proto.down = function(key) {
|
|
return lookupKey(this._curKeyState, this.bindings, key)
|
|
}
|
|
|
|
//Checks if a key was ever down
|
|
proto.wasDown = function(key) {
|
|
return this.down(key) || !!this.press(key)
|
|
}
|
|
|
|
//Opposite of down
|
|
proto.up = function(key) {
|
|
return !this.down(key)
|
|
}
|
|
|
|
//Checks if a key was released during previous frame
|
|
proto.wasUp = function(key) {
|
|
return this.up(key) || !!this.release(key)
|
|
}
|
|
|
|
//Returns the number of times a key was pressed since last tick
|
|
proto.press = function(key) {
|
|
return lookupCount(this._pressCount, this.bindings, key)
|
|
}
|
|
|
|
//Returns the number of times a key was released since last tick
|
|
proto.release = function(key) {
|
|
return lookupCount(this._releaseCount, this.bindings, key)
|
|
}
|
|
|
|
//Pause/unpause the game loop
|
|
Object.defineProperty(proto, "paused", {
|
|
get: function() {
|
|
return this._paused
|
|
},
|
|
set: function(state) {
|
|
var ns = !!state
|
|
if(ns !== this._paused) {
|
|
if(!this._paused) {
|
|
this._paused = true
|
|
this._frameTime = min(1.0, (hrtime() - this._lastTick) / this._tickRate)
|
|
clearInterval(this._tickInterval)
|
|
//cancelAnimationFrame(this._rafHandle)
|
|
} else {
|
|
this._paused = false
|
|
this._lastTick = hrtime() - Math.floor(this._frameTime * this._tickRate)
|
|
this._tickInterval = setInterval(tick, this._tickRate, this)
|
|
this._rafHandle = requestAnimationFrame(this._render)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
//Fullscreen state toggle
|
|
|
|
function tryFullscreen(shell) {
|
|
//Request full screen
|
|
var elem = shell.element
|
|
|
|
if(shell._wantFullscreen && !shell._fullscreenActive) {
|
|
var fs = elem.requestFullscreen ||
|
|
elem.requestFullScreen ||
|
|
elem.webkitRequestFullscreen ||
|
|
elem.webkitRequestFullScreen ||
|
|
elem.mozRequestFullscreen ||
|
|
elem.mozRequestFullScreen ||
|
|
function() {}
|
|
fs.call(elem)
|
|
}
|
|
if(shell._wantPointerLock && !shell._pointerLockActive) {
|
|
var pl = elem.requestPointerLock ||
|
|
elem.webkitRequestPointerLock ||
|
|
elem.mozRequestPointerLock ||
|
|
elem.msRequestPointerLock ||
|
|
elem.oRequestPointerLock ||
|
|
function() {}
|
|
pl.call(elem)
|
|
}
|
|
}
|
|
|
|
var cancelFullscreen = document.exitFullscreen ||
|
|
document.cancelFullscreen || //Why can no one agree on this?
|
|
document.cancelFullScreen ||
|
|
document.webkitCancelFullscreen ||
|
|
document.webkitCancelFullScreen ||
|
|
document.mozCancelFullscreen ||
|
|
document.mozCancelFullScreen ||
|
|
function(){}
|
|
|
|
Object.defineProperty(proto, "fullscreen", {
|
|
get: function() {
|
|
return this._fullscreenActive
|
|
},
|
|
set: function(state) {
|
|
var ns = !!state
|
|
if(!ns) {
|
|
this._wantFullscreen = false
|
|
cancelFullscreen.call(document)
|
|
} else {
|
|
this._wantFullscreen = true
|
|
tryFullscreen(this)
|
|
}
|
|
return this._fullscreenActive
|
|
}
|
|
})
|
|
|
|
function handleFullscreen(shell) {
|
|
shell._fullscreenActive = document.fullscreen ||
|
|
document.mozFullScreen ||
|
|
document.webkitIsFullScreen ||
|
|
false
|
|
if(!shell.stickyFullscreen && shell._fullscreenActive) {
|
|
shell._wantFullscreen = false
|
|
}
|
|
}
|
|
|
|
//Pointer lock state toggle
|
|
var exitPointerLock = document.exitPointerLock ||
|
|
document.webkitExitPointerLock ||
|
|
document.mozExitPointerLock ||
|
|
function() {}
|
|
|
|
Object.defineProperty(proto, "pointerLock", {
|
|
get: function() {
|
|
return this._pointerLockActive
|
|
},
|
|
set: function(state) {
|
|
var ns = !!state
|
|
if(!ns) {
|
|
this._wantPointerLock = false
|
|
exitPointerLock.call(document)
|
|
} else {
|
|
this._wantPointerLock = true
|
|
tryFullscreen(this)
|
|
}
|
|
return this._pointerLockActive
|
|
}
|
|
})
|
|
|
|
function handlePointerLockChange(shell, event) {
|
|
shell._pointerLockActive = shell.element === (
|
|
document.pointerLockElement ||
|
|
document.mozPointerLockElement ||
|
|
document.webkitPointerLockElement ||
|
|
null)
|
|
if(!shell.stickyPointerLock && shell._pointerLockActive) {
|
|
shell._wantPointerLock = false
|
|
}
|
|
}
|
|
|
|
//Width and height
|
|
Object.defineProperty(proto, "width", {
|
|
get: function() {
|
|
return this.element.clientWidth
|
|
}
|
|
})
|
|
Object.defineProperty(proto, "height", {
|
|
get: function() {
|
|
return this.element.clientHeight
|
|
}
|
|
})
|
|
|
|
//Set key state
|
|
function setKeyState(shell, key, state) {
|
|
var ps = shell._curKeyState[key]
|
|
if(ps !== state) {
|
|
if(state) {
|
|
shell._pressCount[key]++
|
|
} else {
|
|
shell._releaseCount[key]++
|
|
}
|
|
shell._curKeyState[key] = state
|
|
}
|
|
}
|
|
|
|
//Ticks the game state one update
|
|
function tick(shell) {
|
|
var skip = hrtime() + shell.frameSkip
|
|
, pCount = shell._pressCount
|
|
, rCount = shell._releaseCount
|
|
, i, s, t
|
|
, tr = shell._tickRate
|
|
, n = keyNames.length
|
|
while(!shell._paused &&
|
|
hrtime() >= shell._lastTick + tr) {
|
|
|
|
//Skip frames if we are over budget
|
|
if(hrtime() > skip) {
|
|
shell._lastTick = hrtime() + tr
|
|
return
|
|
}
|
|
|
|
//Tick the game
|
|
s = hrtime()
|
|
shell.emit("tick")
|
|
t = hrtime()
|
|
shell.tickTime = t - s
|
|
|
|
//Update counters and time
|
|
++shell.tickCount
|
|
shell._lastTick += tr
|
|
|
|
//Shift input state
|
|
for(i=0; i<n; ++i) {
|
|
pCount[i] = rCount[i] = 0
|
|
}
|
|
if(shell._pointerLockActive) {
|
|
shell.prevMouseX = shell.mouseX = shell.width>>1
|
|
shell.prevMouseY = shell.mouseY = shell.height>>1
|
|
} else {
|
|
shell.prevMouseX = shell.mouseX
|
|
shell.prevMouseY = shell.mouseY
|
|
}
|
|
shell.scroll[0] = shell.scroll[1] = shell.scroll[2] = 0
|
|
}
|
|
}
|
|
|
|
//Render stuff
|
|
function render(shell) {
|
|
|
|
//Request next frame
|
|
shell._rafHandle = requestAnimationFrame(shell._render)
|
|
|
|
//Tick the shell
|
|
tick(shell)
|
|
|
|
//Compute frame time
|
|
var dt
|
|
if(shell._paused) {
|
|
dt = shell._frameTime
|
|
} else {
|
|
dt = min(1.0, (hrtime() - shell._lastTick) / shell._tickRate)
|
|
}
|
|
|
|
//Draw a frame
|
|
++shell.frameCount
|
|
var s = hrtime()
|
|
shell.emit("render", dt)
|
|
var t = hrtime()
|
|
shell.frameTime = t - s
|
|
|
|
}
|
|
|
|
function isFocused(shell) {
|
|
return (document.activeElement === document.body) ||
|
|
(document.activeElement === shell.element)
|
|
}
|
|
|
|
function handleEvent(shell, ev) {
|
|
if(shell.preventDefaults) {
|
|
ev.preventDefault()
|
|
}
|
|
if(shell.stopPropagation) {
|
|
ev.stopPropagation()
|
|
}
|
|
}
|
|
|
|
//Set key up
|
|
function handleKeyUp(shell, ev) {
|
|
handleEvent(shell, ev)
|
|
var kc = physicalKeyCode(ev.keyCode || ev.char || ev.which || ev.charCode)
|
|
if(kc >= 0) {
|
|
setKeyState(shell, kc, false)
|
|
}
|
|
}
|
|
|
|
//Set key down
|
|
function handleKeyDown(shell, ev) {
|
|
if(!isFocused(shell)) {
|
|
return
|
|
}
|
|
handleEvent(shell, ev)
|
|
if(ev.metaKey) {
|
|
//Hack: Clear key state when meta gets pressed to prevent keys sticking
|
|
handleBlur(shell, ev)
|
|
} else {
|
|
var kc = physicalKeyCode(ev.keyCode || ev.char || ev.which || ev.charCode)
|
|
if(kc >= 0) {
|
|
setKeyState(shell, kc, true)
|
|
}
|
|
}
|
|
}
|
|
|
|
//Mouse events are really annoying
|
|
var mouseCodes = iota(32).map(function(n) {
|
|
return virtualKeyCode("mouse-" + (n+1))
|
|
})
|
|
|
|
function setMouseButtons(shell, buttons) {
|
|
for(var i=0; i<32; ++i) {
|
|
setKeyState(shell, mouseCodes[i], !!(buttons & (1<<i)))
|
|
}
|
|
}
|
|
|
|
function handleMouseMove(shell, ev) {
|
|
handleEvent(shell, ev)
|
|
if(shell._pointerLockActive) {
|
|
var movementX = ev.movementX ||
|
|
ev.mozMovementX ||
|
|
ev.webkitMovementX ||
|
|
0,
|
|
movementY = ev.movementY ||
|
|
ev.mozMovementY ||
|
|
ev.webkitMovementY ||
|
|
0
|
|
shell.mouseX += movementX
|
|
shell.mouseY += movementY
|
|
} else {
|
|
shell.mouseX = ev.clientX - shell.element.offsetLeft
|
|
shell.mouseY = ev.clientY - shell.element.offsetTop
|
|
}
|
|
return false
|
|
}
|
|
|
|
function handleMouseDown(shell, ev) {
|
|
handleEvent(shell, ev)
|
|
setKeyState(shell, mouseCodes[ev.button], true)
|
|
return false
|
|
}
|
|
|
|
function handleMouseUp(shell, ev) {
|
|
handleEvent(shell, ev)
|
|
setKeyState(shell, mouseCodes[ev.button], false)
|
|
return false
|
|
}
|
|
|
|
function handleMouseEnter(shell, ev) {
|
|
handleEvent(shell, ev)
|
|
if(shell._pointerLockActive) {
|
|
shell.prevMouseX = shell.mouseX = shell.width>>1
|
|
shell.prevMouseY = shell.mouseY = shell.height>>1
|
|
} else {
|
|
shell.prevMouseX = shell.mouseX = ev.clientX - shell.element.offsetLeft
|
|
shell.prevMouseY = shell.mouseY = ev.clientY - shell.element.offsetTop
|
|
}
|
|
return false
|
|
}
|
|
|
|
function handleMouseLeave(shell, ev) {
|
|
handleEvent(shell, ev)
|
|
setMouseButtons(shell, 0)
|
|
return false
|
|
}
|
|
|
|
//Handle mouse wheel events
|
|
function handleMouseWheel(shell, ev) {
|
|
handleEvent(shell, ev)
|
|
var scale = 1
|
|
switch(ev.deltaMode) {
|
|
case 0: //Pixel
|
|
scale = 1
|
|
break
|
|
case 1: //Line
|
|
scale = 12
|
|
break
|
|
case 2: //Page
|
|
scale = shell.height
|
|
break
|
|
}
|
|
//Add scroll
|
|
shell.scroll[0] += ev.deltaX * scale
|
|
shell.scroll[1] += ev.deltaY * scale
|
|
shell.scroll[2] += (ev.deltaZ * scale)||0.0
|
|
return false
|
|
}
|
|
|
|
function handleContexMenu(shell, ev) {
|
|
handleEvent(shell, ev)
|
|
return false
|
|
}
|
|
|
|
function handleBlur(shell, ev) {
|
|
var n = keyNames.length
|
|
, c = shell._curKeyState
|
|
, r = shell._releaseCount
|
|
, i
|
|
for(i=0; i<n; ++i) {
|
|
if(c[i]) {
|
|
++r[i]
|
|
}
|
|
c[i] = false
|
|
}
|
|
return false
|
|
}
|
|
|
|
function handleResizeElement(shell, ev) {
|
|
var w = shell.element.clientWidth|0
|
|
var h = shell.element.clientHeight|0
|
|
if((w !== shell._width) || (h !== shell._height)) {
|
|
shell._width = w
|
|
shell._height = h
|
|
shell.emit("resize", w, h)
|
|
}
|
|
}
|
|
|
|
function makeDefaultContainer() {
|
|
var container = document.createElement("div")
|
|
container.tabindex = 1
|
|
container.style.position = "absolute"
|
|
container.style.left = "0px"
|
|
container.style.right = "0px"
|
|
container.style.top = "0px"
|
|
container.style.bottom = "0px"
|
|
container.style.height = "100%"
|
|
container.style.overflow = "hidden"
|
|
document.body.appendChild(container)
|
|
document.body.style.overflow = "hidden" //Prevent bounce
|
|
document.body.style.height = "100%"
|
|
return container
|
|
}
|
|
|
|
function createShell(options) {
|
|
options = options || {}
|
|
|
|
//Check fullscreen and pointer lock flags
|
|
var useFullscreen = !!options.fullscreen
|
|
var usePointerLock = useFullscreen
|
|
if(typeof options.pointerLock !== undefined) {
|
|
usePointerLock = !!options.pointerLock
|
|
}
|
|
|
|
//Create initial shell
|
|
var shell = new GameShell()
|
|
shell._tickRate = options.tickRate || 30
|
|
shell.frameSkip = options.frameSkip || (shell._tickRate+5) * 5
|
|
shell.stickyFullscreen = !!options.stickyFullscreen || !!options.sticky
|
|
shell.stickyPointerLock = !!options.stickyPointerLock || !!options.sticky
|
|
|
|
//Set bindings
|
|
if(options.bindings) {
|
|
shell.bindings = options.bindings
|
|
}
|
|
|
|
//Wait for dom to intiailize
|
|
setTimeout(function() { domready(function initGameShell() {
|
|
|
|
//Retrieve element
|
|
var element = options.element
|
|
if(typeof element === "string") {
|
|
var e = document.querySelector(element)
|
|
if(!e) {
|
|
e = document.getElementById(element)
|
|
}
|
|
if(!e) {
|
|
e = document.getElementByClass(element)[0]
|
|
}
|
|
if(!e) {
|
|
e = makeDefaultContainer()
|
|
}
|
|
shell.element = e
|
|
} else if(typeof element === "object" && !!element) {
|
|
shell.element = element
|
|
} else if(typeof element === "function") {
|
|
shell.element = element()
|
|
} else {
|
|
shell.element = makeDefaultContainer()
|
|
}
|
|
|
|
//Disable user-select
|
|
if(shell.element.style) {
|
|
shell.element.style["-webkit-touch-callout"] = "none"
|
|
shell.element.style["-webkit-user-select"] = "none"
|
|
shell.element.style["-khtml-user-select"] = "none"
|
|
shell.element.style["-moz-user-select"] = "none"
|
|
shell.element.style["-ms-user-select"] = "none"
|
|
shell.element.style["user-select"] = "none"
|
|
}
|
|
|
|
//Hook resize handler
|
|
shell._width = shell.element.clientWidth
|
|
shell._height = shell.element.clientHeight
|
|
var handleResize = handleResizeElement.bind(undefined, shell)
|
|
if(typeof MutationObserver !== "undefined") {
|
|
var observer = new MutationObserver(handleResize)
|
|
observer.observe(shell.element, {
|
|
attributes: true,
|
|
subtree: true
|
|
})
|
|
} else {
|
|
shell.element.addEventListener("DOMSubtreeModified", handleResize, false)
|
|
}
|
|
window.addEventListener("resize", handleResize, false)
|
|
|
|
//Hook keyboard listener
|
|
window.addEventListener("keydown", handleKeyDown.bind(undefined, shell), false)
|
|
window.addEventListener("keyup", handleKeyUp.bind(undefined, shell), false)
|
|
|
|
//Disable right click
|
|
shell.element.oncontextmenu = handleContexMenu.bind(undefined, shell)
|
|
|
|
//Hook mouse listeners
|
|
shell.element.addEventListener("mousedown", handleMouseDown.bind(undefined, shell), false)
|
|
shell.element.addEventListener("mouseup", handleMouseUp.bind(undefined, shell), false)
|
|
shell.element.addEventListener("mousemove", handleMouseMove.bind(undefined, shell), false)
|
|
shell.element.addEventListener("mouseenter", handleMouseEnter.bind(undefined, shell), false)
|
|
|
|
//Mouse leave
|
|
var leave = handleMouseLeave.bind(undefined, shell)
|
|
shell.element.addEventListener("mouseleave", leave, false)
|
|
shell.element.addEventListener("mouseout", leave, false)
|
|
window.addEventListener("mouseleave", leave, false)
|
|
window.addEventListener("mouseout", leave, false)
|
|
|
|
//Blur event
|
|
var blur = handleBlur.bind(undefined, shell)
|
|
shell.element.addEventListener("blur", blur, false)
|
|
shell.element.addEventListener("focusout", blur, false)
|
|
shell.element.addEventListener("focus", blur, false)
|
|
window.addEventListener("blur", blur, false)
|
|
window.addEventListener("focusout", blur, false)
|
|
window.addEventListener("focus", blur, false)
|
|
|
|
//Mouse wheel handler
|
|
addMouseWheel(shell.element, handleMouseWheel.bind(undefined, shell), false)
|
|
|
|
//Fullscreen handler
|
|
var fullscreenChange = handleFullscreen.bind(undefined, shell)
|
|
document.addEventListener("fullscreenchange", fullscreenChange, false)
|
|
document.addEventListener("mozfullscreenchange", fullscreenChange, false)
|
|
document.addEventListener("webkitfullscreenchange", fullscreenChange, false)
|
|
|
|
//Stupid fullscreen hack
|
|
shell.element.addEventListener("click", tryFullscreen.bind(undefined, shell), false)
|
|
|
|
//Pointer lock change handler
|
|
var pointerLockChange = handlePointerLockChange.bind(undefined, shell)
|
|
document.addEventListener("pointerlockchange", pointerLockChange, false)
|
|
document.addEventListener("mozpointerlockchange", pointerLockChange, false)
|
|
document.addEventListener("webkitpointerlockchange", pointerLockChange, false)
|
|
document.addEventListener("pointerlocklost", pointerLockChange, false)
|
|
document.addEventListener("webkitpointerlocklost", pointerLockChange, false)
|
|
document.addEventListener("mozpointerlocklost", pointerLockChange, false)
|
|
|
|
//Update flags
|
|
shell.fullscreen = useFullscreen
|
|
shell.pointerLock = usePointerLock
|
|
|
|
//Default mouse button aliases
|
|
shell.bind("mouse-left", "mouse-1")
|
|
shell.bind("mouse-right", "mouse-3")
|
|
shell.bind("mouse-middle", "mouse-2")
|
|
|
|
//Initialize tick counter
|
|
shell._lastTick = hrtime()
|
|
shell.startTime = hrtime()
|
|
|
|
//Unpause shell
|
|
shell.paused = false
|
|
|
|
//Emit initialize event
|
|
shell.emit("init")
|
|
})}, 0)
|
|
|
|
return shell
|
|
}
|
|
|
|
module.exports = createShell
|
|
|
|
},{"./lib/hrtime-polyfill.js":13,"./lib/mousewheel-polyfill.js":14,"./lib/raf-polyfill.js":15,"binary-search-bounds":6,"domready":10,"events":12,"invert-hash":48,"iota-array":49,"uniq":62,"util":65,"vkey":66}],17:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
var pool = require("typedarray-pool")
|
|
var ops = require("ndarray-ops")
|
|
var ndarray = require("ndarray")
|
|
|
|
function GLBuffer(gl, type, handle, length, usage) {
|
|
this.gl = gl
|
|
this.type = type
|
|
this.handle = handle
|
|
this.length = length
|
|
this.usage = usage
|
|
}
|
|
|
|
GLBuffer.prototype.bind = function() {
|
|
this.gl.bindBuffer(this.type, this.handle)
|
|
}
|
|
|
|
GLBuffer.prototype.dispose = function() {
|
|
this.gl.deleteBuffer(this.handle)
|
|
}
|
|
|
|
function updateTypeArray(gl, type, len, usage, data, offset) {
|
|
if(offset <= 0 && data.length > len) {
|
|
gl.bufferData(type, data, usage)
|
|
return data.length
|
|
}
|
|
if(data.length + offset > len) {
|
|
throw new Error("gl-buffer: If resizing buffer, offset must be 0")
|
|
}
|
|
gl.bufferSubData(type, offset, data)
|
|
return len
|
|
}
|
|
|
|
function makeScratchTypeArray(array, dtype) {
|
|
var res = pool.malloc(array.length, dtype)
|
|
var n = array.length
|
|
for(var i=0; i<n; ++i) {
|
|
res[i] = array[i]
|
|
}
|
|
return res
|
|
}
|
|
|
|
GLBuffer.prototype.update = function(array, offset) {
|
|
if(!offset) {
|
|
offset = 0
|
|
}
|
|
this.bind()
|
|
if(typeof array === "number") {
|
|
if(offset > 0) {
|
|
throw new Error("gl-buffer: Cannot specify offset when resizing buffer")
|
|
}
|
|
this.gl.bufferData(this.type, array, this.usage)
|
|
this.length = array
|
|
} else if(array.shape) {
|
|
var dtype = array.dtype
|
|
if(dtype === "float64" || dtype === "array" || dtype === "generic") {
|
|
dtype = "float32"
|
|
}
|
|
if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) {
|
|
dtype = "uint16"
|
|
}
|
|
if(array.shape.length !== 1) {
|
|
throw new Error("gl-buffer: Array length must be 1")
|
|
}
|
|
if(dtype === array.dtype && array.stride[0] === 1) {
|
|
if(array.offset === 0 && array.data.length === array.shape[0]) {
|
|
this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data, offset)
|
|
} else {
|
|
this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data.subarray(array.offset, array.shape[0]), offset)
|
|
}
|
|
} else {
|
|
var tmp = pool.malloc(array.shape[0], dtype)
|
|
var ndt = ndarray(tmp)
|
|
ops.assign(ndt, array)
|
|
this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, tmp, offset)
|
|
pool.free(tmp)
|
|
}
|
|
} else if(Array.isArray(array)) {
|
|
if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) {
|
|
var t = makeScratchTypeArray(array, "uint16")
|
|
this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t.subarray(0, array.length), offset)
|
|
pool.freeUint16(t)
|
|
} else {
|
|
var t = makeScratchTypeArray(array, "float32")
|
|
this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t.subarray(0, array.length), offset)
|
|
pool.freeFloat32(t)
|
|
}
|
|
} else {
|
|
this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array, offset)
|
|
}
|
|
}
|
|
|
|
GLBuffer.prototype.draw = function(mode, count, offset) {
|
|
offset = offset || 0
|
|
var gl = this.gl
|
|
if(this.type === gl.ARRAY_BUFFER) {
|
|
gl.drawArrays(mode, offset, count)
|
|
} else if(this.type === gl.ELEMENT_ARRAY_BUFFER) {
|
|
this.bind()
|
|
gl.drawElements(mode, count, gl.UNSIGNED_SHORT, offset)
|
|
} else {
|
|
throw new Error("Invalid type for WebGL buffer")
|
|
}
|
|
}
|
|
|
|
function createBuffer(gl, type, data, usage) {
|
|
if(data === undefined) {
|
|
data = type
|
|
type = gl.ARRAY_BUFFER
|
|
}
|
|
if(!usage) {
|
|
usage = gl.DYNAMIC_DRAW
|
|
}
|
|
var len = 0
|
|
var handle = gl.createBuffer()
|
|
gl.bindBuffer(type, handle)
|
|
if(typeof data === "number") {
|
|
gl.bufferData(type, data, usage)
|
|
len = data
|
|
} else if(data instanceof Array) {
|
|
if(type === gl.ELEMENT_ARRAY_BUFFER) {
|
|
gl.bufferData(type, new Uint16Array(data), usage)
|
|
} else {
|
|
gl.bufferData(type, new Float32Array(data), usage)
|
|
}
|
|
len = data.length
|
|
} else if(data.length) {
|
|
gl.bufferData(type, data, usage)
|
|
len = data.length
|
|
} else if(data.shape) {
|
|
var dtype = data.dtype
|
|
if(dtype === "float64" || dtype === "array" || dtype === "generic") {
|
|
dtype = "float32"
|
|
}
|
|
if(type === gl.ELEMENT_ARRAY_BUFFER) {
|
|
dtype = "uint16"
|
|
}
|
|
if(data.shape.length !== 1) {
|
|
throw new Error("gl-buffer: Array shape must be 1D")
|
|
}
|
|
var len = data.shape[0]
|
|
if(dtype === data.type && data.stride[0] === 1) {
|
|
gl.bufferData(type, data.data.subarray(data.offset, data.offset+len), usage)
|
|
} else {
|
|
var tmp = pool.malloc(data.shape[0], dtype)
|
|
var ndt = ndarray(tmp)
|
|
ops.assign(ndt, data)
|
|
gl.bufferData(type, tmp, usage)
|
|
pool.free(tmp)
|
|
}
|
|
} else {
|
|
throw new Error("gl-buffer: Invalid format for buffer data")
|
|
}
|
|
if(type !== gl.ARRAY_BUFFER && type !== gl.ELEMENT_ARRAY_BUFFER) {
|
|
throw new Error("gl-buffer: Invalid type for webgl buffer")
|
|
}
|
|
if(usage !== gl.DYNAMIC_DRAW && usage !== gl.STATIC_DRAW && usage !== gl.STREAM_DRAW) {
|
|
throw new Error("gl-buffer: Invalid usage for buffer")
|
|
}
|
|
return new GLBuffer(gl, type, handle, len, usage)
|
|
}
|
|
|
|
module.exports = createBuffer
|
|
},{"ndarray":55,"ndarray-ops":51,"typedarray-pool":61}],18:[function(require,module,exports){
|
|
module.exports = {
|
|
0: 'NONE',
|
|
1: 'ONE',
|
|
2: 'LINE_LOOP',
|
|
3: 'LINE_STRIP',
|
|
4: 'TRIANGLES',
|
|
5: 'TRIANGLE_STRIP',
|
|
6: 'TRIANGLE_FAN',
|
|
256: 'DEPTH_BUFFER_BIT',
|
|
512: 'NEVER',
|
|
513: 'LESS',
|
|
514: 'EQUAL',
|
|
515: 'LEQUAL',
|
|
516: 'GREATER',
|
|
517: 'NOTEQUAL',
|
|
518: 'GEQUAL',
|
|
519: 'ALWAYS',
|
|
768: 'SRC_COLOR',
|
|
769: 'ONE_MINUS_SRC_COLOR',
|
|
770: 'SRC_ALPHA',
|
|
771: 'ONE_MINUS_SRC_ALPHA',
|
|
772: 'DST_ALPHA',
|
|
773: 'ONE_MINUS_DST_ALPHA',
|
|
774: 'DST_COLOR',
|
|
775: 'ONE_MINUS_DST_COLOR',
|
|
776: 'SRC_ALPHA_SATURATE',
|
|
1024: 'STENCIL_BUFFER_BIT',
|
|
1028: 'FRONT',
|
|
1029: 'BACK',
|
|
1032: 'FRONT_AND_BACK',
|
|
1280: 'INVALID_ENUM',
|
|
1281: 'INVALID_VALUE',
|
|
1282: 'INVALID_OPERATION',
|
|
1285: 'OUT_OF_MEMORY',
|
|
1286: 'INVALID_FRAMEBUFFER_OPERATION',
|
|
2304: 'CW',
|
|
2305: 'CCW',
|
|
2849: 'LINE_WIDTH',
|
|
2884: 'CULL_FACE',
|
|
2885: 'CULL_FACE_MODE',
|
|
2886: 'FRONT_FACE',
|
|
2928: 'DEPTH_RANGE',
|
|
2929: 'DEPTH_TEST',
|
|
2930: 'DEPTH_WRITEMASK',
|
|
2931: 'DEPTH_CLEAR_VALUE',
|
|
2932: 'DEPTH_FUNC',
|
|
2960: 'STENCIL_TEST',
|
|
2961: 'STENCIL_CLEAR_VALUE',
|
|
2962: 'STENCIL_FUNC',
|
|
2963: 'STENCIL_VALUE_MASK',
|
|
2964: 'STENCIL_FAIL',
|
|
2965: 'STENCIL_PASS_DEPTH_FAIL',
|
|
2966: 'STENCIL_PASS_DEPTH_PASS',
|
|
2967: 'STENCIL_REF',
|
|
2968: 'STENCIL_WRITEMASK',
|
|
2978: 'VIEWPORT',
|
|
3024: 'DITHER',
|
|
3042: 'BLEND',
|
|
3088: 'SCISSOR_BOX',
|
|
3089: 'SCISSOR_TEST',
|
|
3106: 'COLOR_CLEAR_VALUE',
|
|
3107: 'COLOR_WRITEMASK',
|
|
3317: 'UNPACK_ALIGNMENT',
|
|
3333: 'PACK_ALIGNMENT',
|
|
3379: 'MAX_TEXTURE_SIZE',
|
|
3386: 'MAX_VIEWPORT_DIMS',
|
|
3408: 'SUBPIXEL_BITS',
|
|
3410: 'RED_BITS',
|
|
3411: 'GREEN_BITS',
|
|
3412: 'BLUE_BITS',
|
|
3413: 'ALPHA_BITS',
|
|
3414: 'DEPTH_BITS',
|
|
3415: 'STENCIL_BITS',
|
|
3553: 'TEXTURE_2D',
|
|
4352: 'DONT_CARE',
|
|
4353: 'FASTEST',
|
|
4354: 'NICEST',
|
|
5120: 'BYTE',
|
|
5121: 'UNSIGNED_BYTE',
|
|
5122: 'SHORT',
|
|
5123: 'UNSIGNED_SHORT',
|
|
5124: 'INT',
|
|
5125: 'UNSIGNED_INT',
|
|
5126: 'FLOAT',
|
|
5386: 'INVERT',
|
|
5890: 'TEXTURE',
|
|
6401: 'STENCIL_INDEX',
|
|
6402: 'DEPTH_COMPONENT',
|
|
6406: 'ALPHA',
|
|
6407: 'RGB',
|
|
6408: 'RGBA',
|
|
6409: 'LUMINANCE',
|
|
6410: 'LUMINANCE_ALPHA',
|
|
7680: 'KEEP',
|
|
7681: 'REPLACE',
|
|
7682: 'INCR',
|
|
7683: 'DECR',
|
|
7936: 'VENDOR',
|
|
7937: 'RENDERER',
|
|
7938: 'VERSION',
|
|
9728: 'NEAREST',
|
|
9729: 'LINEAR',
|
|
9984: 'NEAREST_MIPMAP_NEAREST',
|
|
9985: 'LINEAR_MIPMAP_NEAREST',
|
|
9986: 'NEAREST_MIPMAP_LINEAR',
|
|
9987: 'LINEAR_MIPMAP_LINEAR',
|
|
10240: 'TEXTURE_MAG_FILTER',
|
|
10241: 'TEXTURE_MIN_FILTER',
|
|
10242: 'TEXTURE_WRAP_S',
|
|
10243: 'TEXTURE_WRAP_T',
|
|
10497: 'REPEAT',
|
|
10752: 'POLYGON_OFFSET_UNITS',
|
|
16384: 'COLOR_BUFFER_BIT',
|
|
32769: 'CONSTANT_COLOR',
|
|
32770: 'ONE_MINUS_CONSTANT_COLOR',
|
|
32771: 'CONSTANT_ALPHA',
|
|
32772: 'ONE_MINUS_CONSTANT_ALPHA',
|
|
32773: 'BLEND_COLOR',
|
|
32774: 'FUNC_ADD',
|
|
32777: 'BLEND_EQUATION_RGB',
|
|
32778: 'FUNC_SUBTRACT',
|
|
32779: 'FUNC_REVERSE_SUBTRACT',
|
|
32819: 'UNSIGNED_SHORT_4_4_4_4',
|
|
32820: 'UNSIGNED_SHORT_5_5_5_1',
|
|
32823: 'POLYGON_OFFSET_FILL',
|
|
32824: 'POLYGON_OFFSET_FACTOR',
|
|
32854: 'RGBA4',
|
|
32855: 'RGB5_A1',
|
|
32873: 'TEXTURE_BINDING_2D',
|
|
32926: 'SAMPLE_ALPHA_TO_COVERAGE',
|
|
32928: 'SAMPLE_COVERAGE',
|
|
32936: 'SAMPLE_BUFFERS',
|
|
32937: 'SAMPLES',
|
|
32938: 'SAMPLE_COVERAGE_VALUE',
|
|
32939: 'SAMPLE_COVERAGE_INVERT',
|
|
32968: 'BLEND_DST_RGB',
|
|
32969: 'BLEND_SRC_RGB',
|
|
32970: 'BLEND_DST_ALPHA',
|
|
32971: 'BLEND_SRC_ALPHA',
|
|
33071: 'CLAMP_TO_EDGE',
|
|
33170: 'GENERATE_MIPMAP_HINT',
|
|
33189: 'DEPTH_COMPONENT16',
|
|
33306: 'DEPTH_STENCIL_ATTACHMENT',
|
|
33635: 'UNSIGNED_SHORT_5_6_5',
|
|
33648: 'MIRRORED_REPEAT',
|
|
33901: 'ALIASED_POINT_SIZE_RANGE',
|
|
33902: 'ALIASED_LINE_WIDTH_RANGE',
|
|
33984: 'TEXTURE0',
|
|
33985: 'TEXTURE1',
|
|
33986: 'TEXTURE2',
|
|
33987: 'TEXTURE3',
|
|
33988: 'TEXTURE4',
|
|
33989: 'TEXTURE5',
|
|
33990: 'TEXTURE6',
|
|
33991: 'TEXTURE7',
|
|
33992: 'TEXTURE8',
|
|
33993: 'TEXTURE9',
|
|
33994: 'TEXTURE10',
|
|
33995: 'TEXTURE11',
|
|
33996: 'TEXTURE12',
|
|
33997: 'TEXTURE13',
|
|
33998: 'TEXTURE14',
|
|
33999: 'TEXTURE15',
|
|
34000: 'TEXTURE16',
|
|
34001: 'TEXTURE17',
|
|
34002: 'TEXTURE18',
|
|
34003: 'TEXTURE19',
|
|
34004: 'TEXTURE20',
|
|
34005: 'TEXTURE21',
|
|
34006: 'TEXTURE22',
|
|
34007: 'TEXTURE23',
|
|
34008: 'TEXTURE24',
|
|
34009: 'TEXTURE25',
|
|
34010: 'TEXTURE26',
|
|
34011: 'TEXTURE27',
|
|
34012: 'TEXTURE28',
|
|
34013: 'TEXTURE29',
|
|
34014: 'TEXTURE30',
|
|
34015: 'TEXTURE31',
|
|
34016: 'ACTIVE_TEXTURE',
|
|
34024: 'MAX_RENDERBUFFER_SIZE',
|
|
34041: 'DEPTH_STENCIL',
|
|
34055: 'INCR_WRAP',
|
|
34056: 'DECR_WRAP',
|
|
34067: 'TEXTURE_CUBE_MAP',
|
|
34068: 'TEXTURE_BINDING_CUBE_MAP',
|
|
34069: 'TEXTURE_CUBE_MAP_POSITIVE_X',
|
|
34070: 'TEXTURE_CUBE_MAP_NEGATIVE_X',
|
|
34071: 'TEXTURE_CUBE_MAP_POSITIVE_Y',
|
|
34072: 'TEXTURE_CUBE_MAP_NEGATIVE_Y',
|
|
34073: 'TEXTURE_CUBE_MAP_POSITIVE_Z',
|
|
34074: 'TEXTURE_CUBE_MAP_NEGATIVE_Z',
|
|
34076: 'MAX_CUBE_MAP_TEXTURE_SIZE',
|
|
34338: 'VERTEX_ATTRIB_ARRAY_ENABLED',
|
|
34339: 'VERTEX_ATTRIB_ARRAY_SIZE',
|
|
34340: 'VERTEX_ATTRIB_ARRAY_STRIDE',
|
|
34341: 'VERTEX_ATTRIB_ARRAY_TYPE',
|
|
34342: 'CURRENT_VERTEX_ATTRIB',
|
|
34373: 'VERTEX_ATTRIB_ARRAY_POINTER',
|
|
34466: 'NUM_COMPRESSED_TEXTURE_FORMATS',
|
|
34467: 'COMPRESSED_TEXTURE_FORMATS',
|
|
34660: 'BUFFER_SIZE',
|
|
34661: 'BUFFER_USAGE',
|
|
34816: 'STENCIL_BACK_FUNC',
|
|
34817: 'STENCIL_BACK_FAIL',
|
|
34818: 'STENCIL_BACK_PASS_DEPTH_FAIL',
|
|
34819: 'STENCIL_BACK_PASS_DEPTH_PASS',
|
|
34877: 'BLEND_EQUATION_ALPHA',
|
|
34921: 'MAX_VERTEX_ATTRIBS',
|
|
34922: 'VERTEX_ATTRIB_ARRAY_NORMALIZED',
|
|
34930: 'MAX_TEXTURE_IMAGE_UNITS',
|
|
34962: 'ARRAY_BUFFER',
|
|
34963: 'ELEMENT_ARRAY_BUFFER',
|
|
34964: 'ARRAY_BUFFER_BINDING',
|
|
34965: 'ELEMENT_ARRAY_BUFFER_BINDING',
|
|
34975: 'VERTEX_ATTRIB_ARRAY_BUFFER_BINDING',
|
|
35040: 'STREAM_DRAW',
|
|
35044: 'STATIC_DRAW',
|
|
35048: 'DYNAMIC_DRAW',
|
|
35632: 'FRAGMENT_SHADER',
|
|
35633: 'VERTEX_SHADER',
|
|
35660: 'MAX_VERTEX_TEXTURE_IMAGE_UNITS',
|
|
35661: 'MAX_COMBINED_TEXTURE_IMAGE_UNITS',
|
|
35663: 'SHADER_TYPE',
|
|
35664: 'FLOAT_VEC2',
|
|
35665: 'FLOAT_VEC3',
|
|
35666: 'FLOAT_VEC4',
|
|
35667: 'INT_VEC2',
|
|
35668: 'INT_VEC3',
|
|
35669: 'INT_VEC4',
|
|
35670: 'BOOL',
|
|
35671: 'BOOL_VEC2',
|
|
35672: 'BOOL_VEC3',
|
|
35673: 'BOOL_VEC4',
|
|
35674: 'FLOAT_MAT2',
|
|
35675: 'FLOAT_MAT3',
|
|
35676: 'FLOAT_MAT4',
|
|
35678: 'SAMPLER_2D',
|
|
35680: 'SAMPLER_CUBE',
|
|
35712: 'DELETE_STATUS',
|
|
35713: 'COMPILE_STATUS',
|
|
35714: 'LINK_STATUS',
|
|
35715: 'VALIDATE_STATUS',
|
|
35716: 'INFO_LOG_LENGTH',
|
|
35717: 'ATTACHED_SHADERS',
|
|
35718: 'ACTIVE_UNIFORMS',
|
|
35719: 'ACTIVE_UNIFORM_MAX_LENGTH',
|
|
35720: 'SHADER_SOURCE_LENGTH',
|
|
35721: 'ACTIVE_ATTRIBUTES',
|
|
35722: 'ACTIVE_ATTRIBUTE_MAX_LENGTH',
|
|
35724: 'SHADING_LANGUAGE_VERSION',
|
|
35725: 'CURRENT_PROGRAM',
|
|
36003: 'STENCIL_BACK_REF',
|
|
36004: 'STENCIL_BACK_VALUE_MASK',
|
|
36005: 'STENCIL_BACK_WRITEMASK',
|
|
36006: 'FRAMEBUFFER_BINDING',
|
|
36007: 'RENDERBUFFER_BINDING',
|
|
36048: 'FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE',
|
|
36049: 'FRAMEBUFFER_ATTACHMENT_OBJECT_NAME',
|
|
36050: 'FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL',
|
|
36051: 'FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE',
|
|
36053: 'FRAMEBUFFER_COMPLETE',
|
|
36054: 'FRAMEBUFFER_INCOMPLETE_ATTACHMENT',
|
|
36055: 'FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT',
|
|
36057: 'FRAMEBUFFER_INCOMPLETE_DIMENSIONS',
|
|
36061: 'FRAMEBUFFER_UNSUPPORTED',
|
|
36064: 'COLOR_ATTACHMENT0',
|
|
36096: 'DEPTH_ATTACHMENT',
|
|
36128: 'STENCIL_ATTACHMENT',
|
|
36160: 'FRAMEBUFFER',
|
|
36161: 'RENDERBUFFER',
|
|
36162: 'RENDERBUFFER_WIDTH',
|
|
36163: 'RENDERBUFFER_HEIGHT',
|
|
36164: 'RENDERBUFFER_INTERNAL_FORMAT',
|
|
36168: 'STENCIL_INDEX8',
|
|
36176: 'RENDERBUFFER_RED_SIZE',
|
|
36177: 'RENDERBUFFER_GREEN_SIZE',
|
|
36178: 'RENDERBUFFER_BLUE_SIZE',
|
|
36179: 'RENDERBUFFER_ALPHA_SIZE',
|
|
36180: 'RENDERBUFFER_DEPTH_SIZE',
|
|
36181: 'RENDERBUFFER_STENCIL_SIZE',
|
|
36194: 'RGB565',
|
|
36336: 'LOW_FLOAT',
|
|
36337: 'MEDIUM_FLOAT',
|
|
36338: 'HIGH_FLOAT',
|
|
36339: 'LOW_INT',
|
|
36340: 'MEDIUM_INT',
|
|
36341: 'HIGH_INT',
|
|
36346: 'SHADER_COMPILER',
|
|
36347: 'MAX_VERTEX_UNIFORM_VECTORS',
|
|
36348: 'MAX_VARYING_VECTORS',
|
|
36349: 'MAX_FRAGMENT_UNIFORM_VECTORS',
|
|
37440: 'UNPACK_FLIP_Y_WEBGL',
|
|
37441: 'UNPACK_PREMULTIPLY_ALPHA_WEBGL',
|
|
37442: 'CONTEXT_LOST_WEBGL',
|
|
37443: 'UNPACK_COLORSPACE_CONVERSION_WEBGL',
|
|
37444: 'BROWSER_DEFAULT_WEBGL'
|
|
}
|
|
|
|
},{}],19:[function(require,module,exports){
|
|
var gl10 = require('./1.0/numbers')
|
|
|
|
module.exports = function lookupConstant (number) {
|
|
return gl10[number]
|
|
}
|
|
|
|
},{"./1.0/numbers":18}],20:[function(require,module,exports){
|
|
var raf = require('raf-component')
|
|
|
|
module.exports = createContext
|
|
|
|
function createContext(canvas, opts, render) {
|
|
if (typeof opts === 'function') {
|
|
render = opts
|
|
opts = {}
|
|
} else {
|
|
opts = opts || {}
|
|
}
|
|
|
|
var gl = (
|
|
canvas.getContext('webgl', opts) ||
|
|
canvas.getContext('webgl-experimental', opts) ||
|
|
canvas.getContext('experimental-webgl', opts)
|
|
)
|
|
|
|
if (!gl) {
|
|
throw new Error('Unable to initialize WebGL')
|
|
}
|
|
|
|
if (render) raf(tick)
|
|
|
|
return gl
|
|
|
|
function tick() {
|
|
render(gl)
|
|
raf(tick)
|
|
}
|
|
}
|
|
|
|
},{"raf-component":58}],21:[function(require,module,exports){
|
|
|
|
var sprintf = require('sprintf-js').sprintf;
|
|
var glConstants = require('gl-constants/lookup');
|
|
var shaderName = require('glsl-shader-name');
|
|
var addLineNumbers = require('add-line-numbers');
|
|
|
|
module.exports = formatCompilerError;
|
|
|
|
function formatCompilerError(errLog, src, type) {
|
|
"use strict";
|
|
|
|
var name = shaderName(src) || 'of unknown name (see npm glsl-shader-name)';
|
|
|
|
var typeName = 'unknown type';
|
|
if (type !== undefined) {
|
|
typeName = type === glConstants.FRAGMENT_SHADER ? 'fragment' : 'vertex'
|
|
}
|
|
|
|
var longForm = sprintf('Error compiling %s shader %s:\n', typeName, name);
|
|
var shortForm = sprintf("%s%s", longForm, errLog);
|
|
|
|
var errorStrings = errLog.split('\n');
|
|
var errors = {};
|
|
|
|
for (var i = 0; i < errorStrings.length; i++) {
|
|
var errorString = errorStrings[i];
|
|
if (errorString === '' || errorString === "\0") continue;
|
|
var lineNo = parseInt(errorString.split(':')[2]);
|
|
if (isNaN(lineNo)) {
|
|
throw new Error(sprintf('Could not parse error: %s', errorString));
|
|
}
|
|
errors[lineNo] = errorString;
|
|
}
|
|
|
|
var lines = addLineNumbers(src).split('\n');
|
|
|
|
for (var i = 0; i < lines.length; i++) {
|
|
if (!errors[i+3] && !errors[i+2] && !errors[i+1]) continue;
|
|
var line = lines[i];
|
|
longForm += line + '\n';
|
|
if (errors[i+1]) {
|
|
var e = errors[i+1];
|
|
e = e.substr(e.split(':', 3).join(':').length + 1).trim();
|
|
longForm += sprintf('^^^ %s\n\n', e);
|
|
}
|
|
}
|
|
|
|
return {
|
|
long: longForm.trim(),
|
|
short: shortForm.trim()
|
|
};
|
|
}
|
|
|
|
|
|
},{"add-line-numbers":3,"gl-constants/lookup":19,"glsl-shader-name":39,"sprintf-js":60}],22:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
var makeGameShell = require("game-shell")
|
|
var webglew = require("webglew")
|
|
|
|
function createGLShell(options) {
|
|
options = options || {}
|
|
|
|
var extensions = options.extensions || []
|
|
|
|
//First create shell
|
|
var shell = makeGameShell(options)
|
|
var scale = shell.scale || 1
|
|
|
|
shell.on("init", function initGLNow() {
|
|
|
|
//Create canvas
|
|
var canvas = document.createElement("canvas")
|
|
|
|
//Try initializing WebGL
|
|
var gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl")
|
|
if(!gl) {
|
|
shell.emit("gl-error", new Error("Unable to initialize WebGL"))
|
|
return
|
|
}
|
|
|
|
//Check extensions
|
|
var ext = webglew(gl)
|
|
for(var i=0; i<extensions.length; ++i) {
|
|
if(!(extensions[i] in ext)) {
|
|
shell.emit("gl-error", new Error("Missing extension: " + extensions[i]))
|
|
return
|
|
}
|
|
}
|
|
|
|
//Set canvas style
|
|
canvas.style.position = "absolute"
|
|
canvas.style.left = "0px"
|
|
canvas.style.top = "0px"
|
|
shell.element.appendChild(canvas)
|
|
|
|
//Add variables to game-shell
|
|
shell.canvas = canvas
|
|
shell.gl = gl
|
|
|
|
//Load width/height
|
|
resize()
|
|
|
|
//Load default parameters
|
|
shell.clearFlags = options.clearFlags === undefined ? (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) : options.clearFlags
|
|
shell.clearColor = options.clearColor || [0,0,0,0]
|
|
shell.clearDepth = options.clearDepth || 1.0
|
|
shell.clearStencil = options.clearStencil || 0
|
|
|
|
shell.on("resize", resize)
|
|
|
|
//Hook render event
|
|
shell.on("render", function renderGLNow(t) {
|
|
|
|
//Bind default framebuffer
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null)
|
|
|
|
//Set viewport
|
|
gl.viewport(0, 0, (shell._width / scale)|0, (shell._height / scale)|0)
|
|
|
|
//Clear buffers
|
|
if(shell.clearFlags & gl.STENCIL_BUFFER_BIT) {
|
|
gl.clearStencil(shell.clearStencil)
|
|
}
|
|
if(shell.clearFlags & gl.COLOR_BUFFER_BIT) {
|
|
gl.clearColor(shell.clearColor[0], shell.clearColor[1], shell.clearColor[2], shell.clearColor[3])
|
|
}
|
|
if(shell.clearFlags & gl.DEPTH_BUFFER_BIT) {
|
|
gl.clearDepth(shell.clearDepth)
|
|
}
|
|
if(shell.clearFlags) {
|
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)
|
|
}
|
|
|
|
//Render frame
|
|
shell.emit("gl-render", t)
|
|
})
|
|
|
|
//WebGL initialized
|
|
shell.emit("gl-init")
|
|
})
|
|
|
|
function resize() {
|
|
var nw = (shell._width/scale)|0
|
|
var nh = (shell._height/scale)|0
|
|
shell.canvas.width = nw
|
|
shell.canvas.height = nh
|
|
shell.canvas.style.width = shell._width + 'px'
|
|
shell.canvas.style.height = shell._height + 'px'
|
|
shell.emit("gl-resize", nw, nh)
|
|
}
|
|
|
|
Object.defineProperty(shell, 'scale', {
|
|
get: function() {
|
|
return scale
|
|
},
|
|
set: function(_scale) {
|
|
_scale = +_scale
|
|
if((_scale <= 0) || isNaN(_scale) || (scale === _scale)) {
|
|
return scale
|
|
}
|
|
scale = _scale
|
|
resize()
|
|
return scale
|
|
}
|
|
})
|
|
|
|
Object.defineProperty(shell, "width", {
|
|
get: function() {
|
|
return (shell._width / scale)|0
|
|
}
|
|
})
|
|
|
|
Object.defineProperty(shell, "height", {
|
|
get: function() {
|
|
return (shell._height / scale)|0
|
|
}
|
|
})
|
|
|
|
Object.defineProperty(shell, "mouse", {
|
|
get: function() {
|
|
return [shell.mouseX/scale, shell.mouseY/scale]
|
|
}
|
|
})
|
|
|
|
Object.defineProperty(shell, "prevMouse", {
|
|
get: function() {
|
|
return [shell.prevMouseX/scale, shell.prevMouseY/scale]
|
|
}
|
|
})
|
|
|
|
return shell
|
|
}
|
|
|
|
module.exports = createGLShell
|
|
},{"game-shell":16,"webglew":71}],23:[function(require,module,exports){
|
|
'use strict'
|
|
|
|
var createUniformWrapper = require('./lib/create-uniforms')
|
|
var createAttributeWrapper = require('./lib/create-attributes')
|
|
var makeReflect = require('./lib/reflect')
|
|
var shaderCache = require('./lib/shader-cache')
|
|
var runtime = require('./lib/runtime-reflect')
|
|
var GLError = require("./lib/GLError")
|
|
|
|
//Shader object
|
|
function Shader(gl) {
|
|
this.gl = gl
|
|
this.gl.lastAttribCount = 0 // fixme where else should we store info, safe but not nice on the gl object
|
|
|
|
//Default initialize these to null
|
|
this._vref =
|
|
this._fref =
|
|
this._relink =
|
|
this.vertShader =
|
|
this.fragShader =
|
|
this.program =
|
|
this.attributes =
|
|
this.uniforms =
|
|
this.types = null
|
|
}
|
|
|
|
var proto = Shader.prototype
|
|
|
|
proto.bind = function() {
|
|
if(!this.program) {
|
|
this._relink()
|
|
}
|
|
|
|
// ensuring that we have the right number of enabled vertex attributes
|
|
var i
|
|
var newAttribCount = this.gl.getProgramParameter(this.program, this.gl.ACTIVE_ATTRIBUTES) // more robust approach
|
|
//var newAttribCount = Object.keys(this.attributes).length // avoids the probably immaterial introspection slowdown
|
|
var oldAttribCount = this.gl.lastAttribCount
|
|
if(newAttribCount > oldAttribCount) {
|
|
for(i = oldAttribCount; i < newAttribCount; i++) {
|
|
this.gl.enableVertexAttribArray(i)
|
|
}
|
|
} else if(oldAttribCount > newAttribCount) {
|
|
for(i = newAttribCount; i < oldAttribCount; i++) {
|
|
this.gl.disableVertexAttribArray(i)
|
|
}
|
|
}
|
|
|
|
this.gl.lastAttribCount = newAttribCount
|
|
|
|
this.gl.useProgram(this.program)
|
|
}
|
|
|
|
proto.dispose = function() {
|
|
|
|
// disabling vertex attributes so new shader starts with zero
|
|
// and it's also useful if all shaders are disposed but the
|
|
// gl context is reused for subsequent replotting
|
|
var oldAttribCount = this.gl.lastAttribCount
|
|
for (var i = 0; i < oldAttribCount; i++) {
|
|
this.gl.disableVertexAttribArray(i)
|
|
}
|
|
this.gl.lastAttribCount = 0
|
|
|
|
if(this._fref) {
|
|
this._fref.dispose()
|
|
}
|
|
if(this._vref) {
|
|
this._vref.dispose()
|
|
}
|
|
this.attributes =
|
|
this.types =
|
|
this.vertShader =
|
|
this.fragShader =
|
|
this.program =
|
|
this._relink =
|
|
this._fref =
|
|
this._vref = null
|
|
}
|
|
|
|
function compareAttributes(a, b) {
|
|
if(a.name < b.name) {
|
|
return -1
|
|
}
|
|
return 1
|
|
}
|
|
|
|
//Update export hook for glslify-live
|
|
proto.update = function(
|
|
vertSource
|
|
, fragSource
|
|
, uniforms
|
|
, attributes) {
|
|
|
|
//If only one object passed, assume glslify style output
|
|
if(!fragSource || arguments.length === 1) {
|
|
var obj = vertSource
|
|
vertSource = obj.vertex
|
|
fragSource = obj.fragment
|
|
uniforms = obj.uniforms
|
|
attributes = obj.attributes
|
|
}
|
|
|
|
var wrapper = this
|
|
var gl = wrapper.gl
|
|
|
|
//Compile vertex and fragment shaders
|
|
var pvref = wrapper._vref
|
|
wrapper._vref = shaderCache.shader(gl, gl.VERTEX_SHADER, vertSource)
|
|
if(pvref) {
|
|
pvref.dispose()
|
|
}
|
|
wrapper.vertShader = wrapper._vref.shader
|
|
var pfref = this._fref
|
|
wrapper._fref = shaderCache.shader(gl, gl.FRAGMENT_SHADER, fragSource)
|
|
if(pfref) {
|
|
pfref.dispose()
|
|
}
|
|
wrapper.fragShader = wrapper._fref.shader
|
|
|
|
//If uniforms/attributes is not specified, use RT reflection
|
|
if(!uniforms || !attributes) {
|
|
|
|
//Create initial test program
|
|
var testProgram = gl.createProgram()
|
|
gl.attachShader(testProgram, wrapper.fragShader)
|
|
gl.attachShader(testProgram, wrapper.vertShader)
|
|
gl.linkProgram(testProgram)
|
|
if(!gl.getProgramParameter(testProgram, gl.LINK_STATUS)) {
|
|
var errLog = gl.getProgramInfoLog(testProgram)
|
|
throw new GLError(errLog, 'Error linking program:' + errLog)
|
|
}
|
|
|
|
//Load data from runtime
|
|
uniforms = uniforms || runtime.uniforms(gl, testProgram)
|
|
attributes = attributes || runtime.attributes(gl, testProgram)
|
|
|
|
//Release test program
|
|
gl.deleteProgram(testProgram)
|
|
}
|
|
|
|
//Sort attributes lexicographically
|
|
// overrides undefined WebGL behavior for attribute locations
|
|
attributes = attributes.slice()
|
|
attributes.sort(compareAttributes)
|
|
|
|
//Convert attribute types, read out locations
|
|
var attributeUnpacked = []
|
|
var attributeNames = []
|
|
var attributeLocations = []
|
|
var i
|
|
for(i=0; i<attributes.length; ++i) {
|
|
var attr = attributes[i]
|
|
if(attr.type.indexOf('mat') >= 0) {
|
|
var size = attr.type.charAt(attr.type.length-1)|0
|
|
var locVector = new Array(size)
|
|
for(var j=0; j<size; ++j) {
|
|
locVector[j] = attributeLocations.length
|
|
attributeNames.push(attr.name + '[' + j + ']')
|
|
if(typeof attr.location === 'number') {
|
|
attributeLocations.push(attr.location + j)
|
|
} else if(Array.isArray(attr.location) &&
|
|
attr.location.length === size &&
|
|
typeof attr.location[j] === 'number') {
|
|
attributeLocations.push(attr.location[j]|0)
|
|
} else {
|
|
attributeLocations.push(-1)
|
|
}
|
|
}
|
|
attributeUnpacked.push({
|
|
name: attr.name,
|
|
type: attr.type,
|
|
locations: locVector
|
|
})
|
|
} else {
|
|
attributeUnpacked.push({
|
|
name: attr.name,
|
|
type: attr.type,
|
|
locations: [ attributeLocations.length ]
|
|
})
|
|
attributeNames.push(attr.name)
|
|
if(typeof attr.location === 'number') {
|
|
attributeLocations.push(attr.location|0)
|
|
} else {
|
|
attributeLocations.push(-1)
|
|
}
|
|
}
|
|
}
|
|
|
|
//For all unspecified attributes, assign them lexicographically min attribute
|
|
var curLocation = 0
|
|
for(i=0; i<attributeLocations.length; ++i) {
|
|
if(attributeLocations[i] < 0) {
|
|
while(attributeLocations.indexOf(curLocation) >= 0) {
|
|
curLocation += 1
|
|
}
|
|
attributeLocations[i] = curLocation
|
|
}
|
|
}
|
|
|
|
//Rebuild program and recompute all uniform locations
|
|
var uniformLocations = new Array(uniforms.length)
|
|
function relink() {
|
|
wrapper.program = shaderCache.program(
|
|
gl
|
|
, wrapper._vref
|
|
, wrapper._fref
|
|
, attributeNames
|
|
, attributeLocations)
|
|
|
|
for(var i=0; i<uniforms.length; ++i) {
|
|
uniformLocations[i] = gl.getUniformLocation(
|
|
wrapper.program
|
|
, uniforms[i].name)
|
|
}
|
|
}
|
|
|
|
//Perform initial linking, reuse program used for reflection
|
|
relink()
|
|
|
|
//Save relinking procedure, defer until runtime
|
|
wrapper._relink = relink
|
|
|
|
//Generate type info
|
|
wrapper.types = {
|
|
uniforms: makeReflect(uniforms),
|
|
attributes: makeReflect(attributes)
|
|
}
|
|
|
|
//Generate attribute wrappers
|
|
wrapper.attributes = createAttributeWrapper(
|
|
gl
|
|
, wrapper
|
|
, attributeUnpacked
|
|
, attributeLocations)
|
|
|
|
//Generate uniform wrappers
|
|
Object.defineProperty(wrapper, 'uniforms', createUniformWrapper(
|
|
gl
|
|
, wrapper
|
|
, uniforms
|
|
, uniformLocations))
|
|
}
|
|
|
|
//Compiles and links a shader program with the given attribute and vertex list
|
|
function createShader(
|
|
gl
|
|
, vertSource
|
|
, fragSource
|
|
, uniforms
|
|
, attributes) {
|
|
|
|
var shader = new Shader(gl)
|
|
|
|
shader.update(
|
|
vertSource
|
|
, fragSource
|
|
, uniforms
|
|
, attributes)
|
|
|
|
return shader
|
|
}
|
|
|
|
module.exports = createShader
|
|
|
|
},{"./lib/GLError":24,"./lib/create-attributes":25,"./lib/create-uniforms":26,"./lib/reflect":27,"./lib/runtime-reflect":28,"./lib/shader-cache":29}],24:[function(require,module,exports){
|
|
function GLError (rawError, shortMessage, longMessage) {
|
|
this.shortMessage = shortMessage || ''
|
|
this.longMessage = longMessage || ''
|
|
this.rawError = rawError || ''
|
|
this.message =
|
|
'gl-shader: ' + (shortMessage || rawError || '') +
|
|
(longMessage ? '\n'+longMessage : '')
|
|
this.stack = (new Error()).stack
|
|
}
|
|
GLError.prototype = new Error
|
|
GLError.prototype.name = 'GLError'
|
|
GLError.prototype.constructor = GLError
|
|
module.exports = GLError
|
|
|
|
},{}],25:[function(require,module,exports){
|
|
'use strict'
|
|
|
|
module.exports = createAttributeWrapper
|
|
|
|
var GLError = require("./GLError")
|
|
|
|
function ShaderAttribute(
|
|
gl
|
|
, wrapper
|
|
, index
|
|
, locations
|
|
, dimension
|
|
, constFunc) {
|
|
this._gl = gl
|
|
this._wrapper = wrapper
|
|
this._index = index
|
|
this._locations = locations
|
|
this._dimension = dimension
|
|
this._constFunc = constFunc
|
|
}
|
|
|
|
var proto = ShaderAttribute.prototype
|
|
|
|
proto.pointer = function setAttribPointer(
|
|
type
|
|
, normalized
|
|
, stride
|
|
, offset) {
|
|
|
|
var self = this
|
|
var gl = self._gl
|
|
var location = self._locations[self._index]
|
|
|
|
gl.vertexAttribPointer(
|
|
location
|
|
, self._dimension
|
|
, type || gl.FLOAT
|
|
, !!normalized
|
|
, stride || 0
|
|
, offset || 0)
|
|
gl.enableVertexAttribArray(location)
|
|
}
|
|
|
|
proto.set = function(x0, x1, x2, x3) {
|
|
return this._constFunc(this._locations[this._index], x0, x1, x2, x3)
|
|
}
|
|
|
|
Object.defineProperty(proto, 'location', {
|
|
get: function() {
|
|
return this._locations[this._index]
|
|
}
|
|
, set: function(v) {
|
|
if(v !== this._locations[this._index]) {
|
|
this._locations[this._index] = v|0
|
|
this._wrapper.program = null
|
|
}
|
|
return v|0
|
|
}
|
|
})
|
|
|
|
var allFns = [
|
|
function (gl, v, x0) {
|
|
if (x0.length === undefined) {
|
|
return gl.vertexAttrib1f(v, x0)
|
|
} else {
|
|
return gl.vertexAttrib1fv(v, x0)
|
|
}
|
|
},
|
|
|
|
function (gl, v, x0, x1) {
|
|
if (x0.length === undefined) {
|
|
return gl.vertexAttrib2f(v, x0, x1)
|
|
} else {
|
|
return gl.vertexAttrib2fv(v, x0)
|
|
}
|
|
},
|
|
|
|
function (gl, v, x0, x1, x2) {
|
|
if (x0.length === undefined) {
|
|
return gl.vertexAttrib3f(v, x0, x1, x2)
|
|
} else {
|
|
return gl.vertexAttrib3fv(v, x0)
|
|
}
|
|
},
|
|
|
|
function (gl, v, x0, x1, x2, x3) {
|
|
if (x0.length === undefined) {
|
|
return gl.vertexAttrib4f(v, x0, x1, x2, x3)
|
|
} else {
|
|
return gl.vertexAttrib4fv(v, x0)
|
|
}
|
|
}
|
|
]
|
|
|
|
//Adds a vector attribute to obj
|
|
function addVectorAttribute(
|
|
gl
|
|
, wrapper
|
|
, index
|
|
, locations
|
|
, dimension
|
|
, obj
|
|
, name) {
|
|
|
|
var constFunc = allFns[dimension]
|
|
|
|
//Create attribute wrapper
|
|
var attr = new ShaderAttribute(
|
|
gl
|
|
, wrapper
|
|
, index
|
|
, locations
|
|
, dimension
|
|
, constFunc)
|
|
|
|
//Create accessor
|
|
Object.defineProperty(obj, name, {
|
|
set: function(x) {
|
|
gl.disableVertexAttribArray(locations[index])
|
|
constFunc(gl, locations[index], x)
|
|
return x
|
|
}
|
|
, get: function() {
|
|
return attr
|
|
}
|
|
, enumerable: true
|
|
})
|
|
}
|
|
|
|
function addMatrixAttribute(
|
|
gl
|
|
, wrapper
|
|
, index
|
|
, locations
|
|
, dimension
|
|
, obj
|
|
, name) {
|
|
|
|
var parts = new Array(dimension)
|
|
var attrs = new Array(dimension)
|
|
for(var i=0; i<dimension; ++i) {
|
|
addVectorAttribute(
|
|
gl
|
|
, wrapper
|
|
, index[i]
|
|
, locations
|
|
, dimension
|
|
, parts
|
|
, i)
|
|
attrs[i] = parts[i]
|
|
}
|
|
|
|
Object.defineProperty(parts, 'location', {
|
|
set: function(v) {
|
|
if(Array.isArray(v)) {
|
|
for(var i=0; i<dimension; ++i) {
|
|
attrs[i].location = v[i]
|
|
}
|
|
} else {
|
|
for(var i=0; i<dimension; ++i) {
|
|
attrs[i].location = v + i
|
|
}
|
|
}
|
|
return v
|
|
}
|
|
, get: function() {
|
|
var result = new Array(dimension)
|
|
for(var i=0; i<dimension; ++i) {
|
|
result[i] = locations[index[i]]
|
|
}
|
|
return result
|
|
}
|
|
, enumerable: true
|
|
})
|
|
|
|
parts.pointer = function(type, normalized, stride, offset) {
|
|
type = type || gl.FLOAT
|
|
normalized = !!normalized
|
|
stride = stride || (dimension * dimension)
|
|
offset = offset || 0
|
|
for(var i=0; i<dimension; ++i) {
|
|
var location = locations[index[i]]
|
|
gl.vertexAttribPointer(
|
|
location
|
|
, dimension
|
|
, type
|
|
, normalized
|
|
, stride
|
|
, offset + i * dimension)
|
|
gl.enableVertexAttribArray(location)
|
|
}
|
|
}
|
|
|
|
var scratch = new Array(dimension)
|
|
var vertexAttrib = gl['vertexAttrib' + dimension + 'fv']
|
|
|
|
Object.defineProperty(obj, name, {
|
|
set: function(x) {
|
|
for(var i=0; i<dimension; ++i) {
|
|
var loc = locations[index[i]]
|
|
gl.disableVertexAttribArray(loc)
|
|
if(Array.isArray(x[0])) {
|
|
vertexAttrib.call(gl, loc, x[i])
|
|
} else {
|
|
for(var j=0; j<dimension; ++j) {
|
|
scratch[j] = x[dimension*i + j]
|
|
}
|
|
vertexAttrib.call(gl, loc, scratch)
|
|
}
|
|
}
|
|
return x
|
|
}
|
|
, get: function() {
|
|
return parts
|
|
}
|
|
, enumerable: true
|
|
})
|
|
}
|
|
|
|
//Create shims for attributes
|
|
function createAttributeWrapper(
|
|
gl
|
|
, wrapper
|
|
, attributes
|
|
, locations) {
|
|
|
|
var obj = {}
|
|
for(var i=0, n=attributes.length; i<n; ++i) {
|
|
|
|
var a = attributes[i]
|
|
var name = a.name
|
|
var type = a.type
|
|
var locs = a.locations
|
|
|
|
switch(type) {
|
|
case 'bool':
|
|
case 'int':
|
|
case 'float':
|
|
addVectorAttribute(
|
|
gl
|
|
, wrapper
|
|
, locs[0]
|
|
, locations
|
|
, 1
|
|
, obj
|
|
, name)
|
|
break
|
|
|
|
default:
|
|
if(type.indexOf('vec') >= 0) {
|
|
var d = type.charCodeAt(type.length-1) - 48
|
|
if(d < 2 || d > 4) {
|
|
throw new GLError('', 'Invalid data type for attribute ' + name + ': ' + type)
|
|
}
|
|
addVectorAttribute(
|
|
gl
|
|
, wrapper
|
|
, locs[0]
|
|
, locations
|
|
, d
|
|
, obj
|
|
, name)
|
|
} else if(type.indexOf('mat') >= 0) {
|
|
var d = type.charCodeAt(type.length-1) - 48
|
|
if(d < 2 || d > 4) {
|
|
throw new GLError('', 'Invalid data type for attribute ' + name + ': ' + type)
|
|
}
|
|
addMatrixAttribute(
|
|
gl
|
|
, wrapper
|
|
, locs
|
|
, locations
|
|
, d
|
|
, obj
|
|
, name)
|
|
} else {
|
|
throw new GLError('', 'Unknown data type for attribute ' + name + ': ' + type)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
return obj
|
|
}
|
|
|
|
},{"./GLError":24}],26:[function(require,module,exports){
|
|
'use strict'
|
|
|
|
var coallesceUniforms = require('./reflect')
|
|
var GLError = require("./GLError")
|
|
|
|
module.exports = createUniformWrapper
|
|
|
|
//Binds a function and returns a value
|
|
function identity(x) {
|
|
return function() {
|
|
return x
|
|
}
|
|
}
|
|
|
|
function makeVector(length, fill) {
|
|
var result = new Array(length)
|
|
for(var i=0; i<length; ++i) {
|
|
result[i] = fill
|
|
}
|
|
return result
|
|
}
|
|
|
|
//Create shims for uniforms
|
|
function createUniformWrapper(gl, wrapper, uniforms, locations) {
|
|
|
|
function makeGetter(idx) {
|
|
return function(gl, wrapper, locations) {
|
|
return gl.getUniform(wrapper.program, locations[idx])
|
|
}
|
|
}
|
|
|
|
function makeSetter(type) {
|
|
return function updateProperty(obj){
|
|
var indices = enumerateIndices('', type)
|
|
for(var i=0; i<indices.length; ++i) {
|
|
var item = indices[i]
|
|
var path = item[0]
|
|
var idx = item[1]
|
|
if(locations[idx]) {
|
|
var objPath = obj
|
|
if(typeof path === 'string' && (
|
|
path.indexOf('.') === 0 ||
|
|
path.indexOf('[') === 0
|
|
)) {
|
|
var key = path
|
|
if(path.indexOf('.') === 0) {
|
|
key = path.slice(1)
|
|
}
|
|
|
|
if(key.indexOf(']') === key.length - 1) {
|
|
var j = key.indexOf('[')
|
|
var k1 = key.slice(0, j)
|
|
var k2 = key.slice(j + 1, key.length - 1)
|
|
objPath = k1? obj[k1][k2] : obj[k2]
|
|
} else {
|
|
objPath = obj[key]
|
|
}
|
|
}
|
|
|
|
var t = uniforms[idx].type
|
|
var d
|
|
switch(t) {
|
|
case 'bool':
|
|
case 'int':
|
|
case 'sampler2D':
|
|
case 'samplerCube':
|
|
gl.uniform1i(locations[idx], objPath)
|
|
break
|
|
case 'float':
|
|
gl.uniform1f(locations[idx], objPath)
|
|
break
|
|
default:
|
|
var vidx = t.indexOf('vec')
|
|
if(0 <= vidx && vidx <= 1 && t.length === 4 + vidx) {
|
|
d = t.charCodeAt(t.length-1) - 48
|
|
if(d < 2 || d > 4) {
|
|
throw new GLError('', 'Invalid data type')
|
|
}
|
|
switch(t.charAt(0)) {
|
|
case 'b':
|
|
case 'i':
|
|
gl['uniform' + d + 'iv'](locations[idx], objPath)
|
|
break
|
|
case 'v':
|
|
gl['uniform' + d + 'fv'](locations[idx], objPath)
|
|
break
|
|
default:
|
|
throw new GLError('', 'Unrecognized data type for vector ' + name + ': ' + t)
|
|
}
|
|
} else if(t.indexOf('mat') === 0 && t.length === 4) {
|
|
d = t.charCodeAt(t.length-1) - 48
|
|
if(d < 2 || d > 4) {
|
|
throw new GLError('', 'Invalid uniform dimension type for matrix ' + name + ': ' + t)
|
|
}
|
|
gl['uniformMatrix' + d + 'fv'](locations[idx], false, objPath)
|
|
break
|
|
} else {
|
|
throw new GLError('', 'Unknown uniform data type for ' + name + ': ' + t)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function enumerateIndices(prefix, type) {
|
|
if(typeof type !== 'object') {
|
|
return [ [prefix, type] ]
|
|
}
|
|
var indices = []
|
|
for(var id in type) {
|
|
var prop = type[id]
|
|
var tprefix = prefix
|
|
if(parseInt(id) + '' === id) {
|
|
tprefix += '[' + id + ']'
|
|
} else {
|
|
tprefix += '.' + id
|
|
}
|
|
if(typeof prop === 'object') {
|
|
indices.push.apply(indices, enumerateIndices(tprefix, prop))
|
|
} else {
|
|
indices.push([tprefix, prop])
|
|
}
|
|
}
|
|
return indices
|
|
}
|
|
|
|
|
|
function defaultValue(type) {
|
|
switch(type) {
|
|
case 'bool':
|
|
return false
|
|
case 'int':
|
|
case 'sampler2D':
|
|
case 'samplerCube':
|
|
return 0
|
|
case 'float':
|
|
return 0.0
|
|
default:
|
|
var vidx = type.indexOf('vec')
|
|
if(0 <= vidx && vidx <= 1 && type.length === 4 + vidx) {
|
|
var d = type.charCodeAt(type.length-1) - 48
|
|
if(d < 2 || d > 4) {
|
|
throw new GLError('', 'Invalid data type')
|
|
}
|
|
if(type.charAt(0) === 'b') {
|
|
return makeVector(d, false)
|
|
}
|
|
return makeVector(d, 0)
|
|
} else if(type.indexOf('mat') === 0 && type.length === 4) {
|
|
var d = type.charCodeAt(type.length-1) - 48
|
|
if(d < 2 || d > 4) {
|
|
throw new GLError('', 'Invalid uniform dimension type for matrix ' + name + ': ' + type)
|
|
}
|
|
return makeVector(d*d, 0)
|
|
} else {
|
|
throw new GLError('', 'Unknown uniform data type for ' + name + ': ' + type)
|
|
}
|
|
}
|
|
}
|
|
|
|
function storeProperty(obj, prop, type) {
|
|
if(typeof type === 'object') {
|
|
var child = processObject(type)
|
|
Object.defineProperty(obj, prop, {
|
|
get: identity(child),
|
|
set: makeSetter(type),
|
|
enumerable: true,
|
|
configurable: false
|
|
})
|
|
} else {
|
|
if(locations[type]) {
|
|
Object.defineProperty(obj, prop, {
|
|
get: makeGetter(type),
|
|
set: makeSetter(type),
|
|
enumerable: true,
|
|
configurable: false
|
|
})
|
|
} else {
|
|
obj[prop] = defaultValue(uniforms[type].type)
|
|
}
|
|
}
|
|
}
|
|
|
|
function processObject(obj) {
|
|
var result
|
|
if(Array.isArray(obj)) {
|
|
result = new Array(obj.length)
|
|
for(var i=0; i<obj.length; ++i) {
|
|
storeProperty(result, i, obj[i])
|
|
}
|
|
} else {
|
|
result = {}
|
|
for(var id in obj) {
|
|
storeProperty(result, id, obj[id])
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
//Return data
|
|
var coallesced = coallesceUniforms(uniforms, true)
|
|
return {
|
|
get: identity(processObject(coallesced)),
|
|
set: makeSetter(coallesced),
|
|
enumerable: true,
|
|
configurable: true
|
|
}
|
|
}
|
|
|
|
},{"./GLError":24,"./reflect":27}],27:[function(require,module,exports){
|
|
'use strict'
|
|
|
|
module.exports = makeReflectTypes
|
|
|
|
//Construct type info for reflection.
|
|
//
|
|
// This iterates over the flattened list of uniform type values and smashes them into a JSON object.
|
|
//
|
|
// The leaves of the resulting object are either indices or type strings representing primitive glslify types
|
|
function makeReflectTypes(uniforms, useIndex) {
|
|
var obj = {}
|
|
for(var i=0; i<uniforms.length; ++i) {
|
|
var n = uniforms[i].name
|
|
var parts = n.split(".")
|
|
var o = obj
|
|
for(var j=0; j<parts.length; ++j) {
|
|
var x = parts[j].split("[")
|
|
if(x.length > 1) {
|
|
if(!(x[0] in o)) {
|
|
o[x[0]] = []
|
|
}
|
|
o = o[x[0]]
|
|
for(var k=1; k<x.length; ++k) {
|
|
var y = parseInt(x[k])
|
|
if(k<x.length-1 || j<parts.length-1) {
|
|
if(!(y in o)) {
|
|
if(k < x.length-1) {
|
|
o[y] = []
|
|
} else {
|
|
o[y] = {}
|
|
}
|
|
}
|
|
o = o[y]
|
|
} else {
|
|
if(useIndex) {
|
|
o[y] = i
|
|
} else {
|
|
o[y] = uniforms[i].type
|
|
}
|
|
}
|
|
}
|
|
} else if(j < parts.length-1) {
|
|
if(!(x[0] in o)) {
|
|
o[x[0]] = {}
|
|
}
|
|
o = o[x[0]]
|
|
} else {
|
|
if(useIndex) {
|
|
o[x[0]] = i
|
|
} else {
|
|
o[x[0]] = uniforms[i].type
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return obj
|
|
}
|
|
},{}],28:[function(require,module,exports){
|
|
'use strict'
|
|
|
|
exports.uniforms = runtimeUniforms
|
|
exports.attributes = runtimeAttributes
|
|
|
|
var GL_TO_GLSL_TYPES = {
|
|
'FLOAT': 'float',
|
|
'FLOAT_VEC2': 'vec2',
|
|
'FLOAT_VEC3': 'vec3',
|
|
'FLOAT_VEC4': 'vec4',
|
|
'INT': 'int',
|
|
'INT_VEC2': 'ivec2',
|
|
'INT_VEC3': 'ivec3',
|
|
'INT_VEC4': 'ivec4',
|
|
'BOOL': 'bool',
|
|
'BOOL_VEC2': 'bvec2',
|
|
'BOOL_VEC3': 'bvec3',
|
|
'BOOL_VEC4': 'bvec4',
|
|
'FLOAT_MAT2': 'mat2',
|
|
'FLOAT_MAT3': 'mat3',
|
|
'FLOAT_MAT4': 'mat4',
|
|
'SAMPLER_2D': 'sampler2D',
|
|
'SAMPLER_CUBE':'samplerCube'
|
|
}
|
|
|
|
var GL_TABLE = null
|
|
|
|
function getType(gl, type) {
|
|
if(!GL_TABLE) {
|
|
var typeNames = Object.keys(GL_TO_GLSL_TYPES)
|
|
GL_TABLE = {}
|
|
for(var i=0; i<typeNames.length; ++i) {
|
|
var tn = typeNames[i]
|
|
GL_TABLE[gl[tn]] = GL_TO_GLSL_TYPES[tn]
|
|
}
|
|
}
|
|
return GL_TABLE[type]
|
|
}
|
|
|
|
function runtimeUniforms(gl, program) {
|
|
var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS)
|
|
var result = []
|
|
for(var i=0; i<numUniforms; ++i) {
|
|
var info = gl.getActiveUniform(program, i)
|
|
if(info) {
|
|
var type = getType(gl, info.type)
|
|
if(info.size > 1) {
|
|
for(var j=0; j<info.size; ++j) {
|
|
result.push({
|
|
name: info.name.replace('[0]', '[' + j + ']'),
|
|
type: type
|
|
})
|
|
}
|
|
} else {
|
|
result.push({
|
|
name: info.name,
|
|
type: type
|
|
})
|
|
}
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
function runtimeAttributes(gl, program) {
|
|
var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES)
|
|
var result = []
|
|
for(var i=0; i<numAttributes; ++i) {
|
|
var info = gl.getActiveAttrib(program, i)
|
|
if(info) {
|
|
result.push({
|
|
name: info.name,
|
|
type: getType(gl, info.type)
|
|
})
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
},{}],29:[function(require,module,exports){
|
|
'use strict'
|
|
|
|
exports.shader = getShaderReference
|
|
exports.program = createProgram
|
|
|
|
var GLError = require("./GLError")
|
|
var formatCompilerError = require('gl-format-compiler-error');
|
|
|
|
var weakMap = typeof WeakMap === 'undefined' ? require('weakmap-shim') : WeakMap
|
|
var CACHE = new weakMap()
|
|
|
|
var SHADER_COUNTER = 0
|
|
|
|
function ShaderReference(id, src, type, shader, programs, count, cache) {
|
|
this.id = id
|
|
this.src = src
|
|
this.type = type
|
|
this.shader = shader
|
|
this.count = count
|
|
this.programs = []
|
|
this.cache = cache
|
|
}
|
|
|
|
ShaderReference.prototype.dispose = function() {
|
|
if(--this.count === 0) {
|
|
var cache = this.cache
|
|
var gl = cache.gl
|
|
|
|
//Remove program references
|
|
var programs = this.programs
|
|
for(var i=0, n=programs.length; i<n; ++i) {
|
|
var p = cache.programs[programs[i]]
|
|
if(p) {
|
|
delete cache.programs[i]
|
|
gl.deleteProgram(p)
|
|
}
|
|
}
|
|
|
|
//Remove shader reference
|
|
gl.deleteShader(this.shader)
|
|
delete cache.shaders[(this.type === gl.FRAGMENT_SHADER)|0][this.src]
|
|
}
|
|
}
|
|
|
|
function ContextCache(gl) {
|
|
this.gl = gl
|
|
this.shaders = [{}, {}]
|
|
this.programs = {}
|
|
}
|
|
|
|
var proto = ContextCache.prototype
|
|
|
|
function compileShader(gl, type, src) {
|
|
var shader = gl.createShader(type)
|
|
gl.shaderSource(shader, src)
|
|
gl.compileShader(shader)
|
|
if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
var errLog = gl.getShaderInfoLog(shader)
|
|
try {
|
|
var fmt = formatCompilerError(errLog, src, type);
|
|
} catch (e){
|
|
console.warn('Failed to format compiler error: ' + e);
|
|
throw new GLError(errLog, 'Error compiling shader:\n' + errLog)
|
|
}
|
|
throw new GLError(errLog, fmt.short, fmt.long)
|
|
}
|
|
return shader
|
|
}
|
|
|
|
proto.getShaderReference = function(type, src) {
|
|
var gl = this.gl
|
|
var shaders = this.shaders[(type === gl.FRAGMENT_SHADER)|0]
|
|
var shader = shaders[src]
|
|
if(!shader || !gl.isShader(shader.shader)) {
|
|
var shaderObj = compileShader(gl, type, src)
|
|
shader = shaders[src] = new ShaderReference(
|
|
SHADER_COUNTER++,
|
|
src,
|
|
type,
|
|
shaderObj,
|
|
[],
|
|
1,
|
|
this)
|
|
} else {
|
|
shader.count += 1
|
|
}
|
|
return shader
|
|
}
|
|
|
|
function linkProgram(gl, vshader, fshader, attribs, locations) {
|
|
var program = gl.createProgram()
|
|
gl.attachShader(program, vshader)
|
|
gl.attachShader(program, fshader)
|
|
for(var i=0; i<attribs.length; ++i) {
|
|
gl.bindAttribLocation(program, locations[i], attribs[i])
|
|
}
|
|
gl.linkProgram(program)
|
|
if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
var errLog = gl.getProgramInfoLog(program)
|
|
throw new GLError(errLog, 'Error linking program: ' + errLog)
|
|
}
|
|
return program
|
|
}
|
|
|
|
proto.getProgram = function(vref, fref, attribs, locations) {
|
|
var token = [vref.id, fref.id, attribs.join(':'), locations.join(':')].join('@')
|
|
var prog = this.programs[token]
|
|
if(!prog || !this.gl.isProgram(prog)) {
|
|
this.programs[token] = prog = linkProgram(
|
|
this.gl,
|
|
vref.shader,
|
|
fref.shader,
|
|
attribs,
|
|
locations)
|
|
vref.programs.push(token)
|
|
fref.programs.push(token)
|
|
}
|
|
return prog
|
|
}
|
|
|
|
function getCache(gl) {
|
|
var ctxCache = CACHE.get(gl)
|
|
if(!ctxCache) {
|
|
ctxCache = new ContextCache(gl)
|
|
CACHE.set(gl, ctxCache)
|
|
}
|
|
return ctxCache
|
|
}
|
|
|
|
function getShaderReference(gl, type, src) {
|
|
return getCache(gl).getShaderReference(type, src)
|
|
}
|
|
|
|
function createProgram(gl, vref, fref, attribs, locations) {
|
|
return getCache(gl).getProgram(vref, fref, attribs, locations)
|
|
}
|
|
|
|
},{"./GLError":24,"gl-format-compiler-error":21,"weakmap-shim":70}],30:[function(require,module,exports){
|
|
arguments[4][11][0].apply(exports,arguments)
|
|
},{"dup":11}],31:[function(require,module,exports){
|
|
arguments[4][7][0].apply(exports,arguments)
|
|
},{"dup":7}],32:[function(require,module,exports){
|
|
(function (global){
|
|
'use strict'
|
|
|
|
var bits = require('bit-twiddle')
|
|
var dup = require('dup')
|
|
var Buffer = require('buffer').Buffer
|
|
|
|
//Legacy pool support
|
|
if(!global.__TYPEDARRAY_POOL) {
|
|
global.__TYPEDARRAY_POOL = {
|
|
UINT8 : dup([32, 0])
|
|
, UINT16 : dup([32, 0])
|
|
, UINT32 : dup([32, 0])
|
|
, BIGUINT64 : dup([32, 0])
|
|
, INT8 : dup([32, 0])
|
|
, INT16 : dup([32, 0])
|
|
, INT32 : dup([32, 0])
|
|
, BIGINT64 : dup([32, 0])
|
|
, FLOAT : dup([32, 0])
|
|
, DOUBLE : dup([32, 0])
|
|
, DATA : dup([32, 0])
|
|
, UINT8C : dup([32, 0])
|
|
, BUFFER : dup([32, 0])
|
|
}
|
|
}
|
|
|
|
var hasUint8C = (typeof Uint8ClampedArray) !== 'undefined'
|
|
var hasBigUint64 = (typeof BigUint64Array) !== 'undefined'
|
|
var hasBigInt64 = (typeof BigInt64Array) !== 'undefined'
|
|
var POOL = global.__TYPEDARRAY_POOL
|
|
|
|
//Upgrade pool
|
|
if(!POOL.UINT8C) {
|
|
POOL.UINT8C = dup([32, 0])
|
|
}
|
|
if(!POOL.BIGUINT64) {
|
|
POOL.BIGUINT64 = dup([32, 0])
|
|
}
|
|
if(!POOL.BIGINT64) {
|
|
POOL.BIGINT64 = dup([32, 0])
|
|
}
|
|
if(!POOL.BUFFER) {
|
|
POOL.BUFFER = dup([32, 0])
|
|
}
|
|
|
|
//New technique: Only allocate from ArrayBufferView and Buffer
|
|
var DATA = POOL.DATA
|
|
, BUFFER = POOL.BUFFER
|
|
|
|
exports.free = function free(array) {
|
|
if(Buffer.isBuffer(array)) {
|
|
BUFFER[bits.log2(array.length)].push(array)
|
|
} else {
|
|
if(Object.prototype.toString.call(array) !== '[object ArrayBuffer]') {
|
|
array = array.buffer
|
|
}
|
|
if(!array) {
|
|
return
|
|
}
|
|
var n = array.length || array.byteLength
|
|
var log_n = bits.log2(n)|0
|
|
DATA[log_n].push(array)
|
|
}
|
|
}
|
|
|
|
function freeArrayBuffer(buffer) {
|
|
if(!buffer) {
|
|
return
|
|
}
|
|
var n = buffer.length || buffer.byteLength
|
|
var log_n = bits.log2(n)
|
|
DATA[log_n].push(buffer)
|
|
}
|
|
|
|
function freeTypedArray(array) {
|
|
freeArrayBuffer(array.buffer)
|
|
}
|
|
|
|
exports.freeUint8 =
|
|
exports.freeUint16 =
|
|
exports.freeUint32 =
|
|
exports.freeBigUint64 =
|
|
exports.freeInt8 =
|
|
exports.freeInt16 =
|
|
exports.freeInt32 =
|
|
exports.freeBigInt64 =
|
|
exports.freeFloat32 =
|
|
exports.freeFloat =
|
|
exports.freeFloat64 =
|
|
exports.freeDouble =
|
|
exports.freeUint8Clamped =
|
|
exports.freeDataView = freeTypedArray
|
|
|
|
exports.freeArrayBuffer = freeArrayBuffer
|
|
|
|
exports.freeBuffer = function freeBuffer(array) {
|
|
BUFFER[bits.log2(array.length)].push(array)
|
|
}
|
|
|
|
exports.malloc = function malloc(n, dtype) {
|
|
if(dtype === undefined || dtype === 'arraybuffer') {
|
|
return mallocArrayBuffer(n)
|
|
} else {
|
|
switch(dtype) {
|
|
case 'uint8':
|
|
return mallocUint8(n)
|
|
case 'uint16':
|
|
return mallocUint16(n)
|
|
case 'uint32':
|
|
return mallocUint32(n)
|
|
case 'int8':
|
|
return mallocInt8(n)
|
|
case 'int16':
|
|
return mallocInt16(n)
|
|
case 'int32':
|
|
return mallocInt32(n)
|
|
case 'float':
|
|
case 'float32':
|
|
return mallocFloat(n)
|
|
case 'double':
|
|
case 'float64':
|
|
return mallocDouble(n)
|
|
case 'uint8_clamped':
|
|
return mallocUint8Clamped(n)
|
|
case 'bigint64':
|
|
return mallocBigInt64(n)
|
|
case 'biguint64':
|
|
return mallocBigUint64(n)
|
|
case 'buffer':
|
|
return mallocBuffer(n)
|
|
case 'data':
|
|
case 'dataview':
|
|
return mallocDataView(n)
|
|
|
|
default:
|
|
return null
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
function mallocArrayBuffer(n) {
|
|
var n = bits.nextPow2(n)
|
|
var log_n = bits.log2(n)
|
|
var d = DATA[log_n]
|
|
if(d.length > 0) {
|
|
return d.pop()
|
|
}
|
|
return new ArrayBuffer(n)
|
|
}
|
|
exports.mallocArrayBuffer = mallocArrayBuffer
|
|
|
|
function mallocUint8(n) {
|
|
return new Uint8Array(mallocArrayBuffer(n), 0, n)
|
|
}
|
|
exports.mallocUint8 = mallocUint8
|
|
|
|
function mallocUint16(n) {
|
|
return new Uint16Array(mallocArrayBuffer(2*n), 0, n)
|
|
}
|
|
exports.mallocUint16 = mallocUint16
|
|
|
|
function mallocUint32(n) {
|
|
return new Uint32Array(mallocArrayBuffer(4*n), 0, n)
|
|
}
|
|
exports.mallocUint32 = mallocUint32
|
|
|
|
function mallocInt8(n) {
|
|
return new Int8Array(mallocArrayBuffer(n), 0, n)
|
|
}
|
|
exports.mallocInt8 = mallocInt8
|
|
|
|
function mallocInt16(n) {
|
|
return new Int16Array(mallocArrayBuffer(2*n), 0, n)
|
|
}
|
|
exports.mallocInt16 = mallocInt16
|
|
|
|
function mallocInt32(n) {
|
|
return new Int32Array(mallocArrayBuffer(4*n), 0, n)
|
|
}
|
|
exports.mallocInt32 = mallocInt32
|
|
|
|
function mallocFloat(n) {
|
|
return new Float32Array(mallocArrayBuffer(4*n), 0, n)
|
|
}
|
|
exports.mallocFloat32 = exports.mallocFloat = mallocFloat
|
|
|
|
function mallocDouble(n) {
|
|
return new Float64Array(mallocArrayBuffer(8*n), 0, n)
|
|
}
|
|
exports.mallocFloat64 = exports.mallocDouble = mallocDouble
|
|
|
|
function mallocUint8Clamped(n) {
|
|
if(hasUint8C) {
|
|
return new Uint8ClampedArray(mallocArrayBuffer(n), 0, n)
|
|
} else {
|
|
return mallocUint8(n)
|
|
}
|
|
}
|
|
exports.mallocUint8Clamped = mallocUint8Clamped
|
|
|
|
function mallocBigUint64(n) {
|
|
if(hasBigUint64) {
|
|
return new BigUint64Array(mallocArrayBuffer(8*n), 0, n)
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
exports.mallocBigUint64 = mallocBigUint64
|
|
|
|
function mallocBigInt64(n) {
|
|
if (hasBigInt64) {
|
|
return new BigInt64Array(mallocArrayBuffer(8*n), 0, n)
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
exports.mallocBigInt64 = mallocBigInt64
|
|
|
|
function mallocDataView(n) {
|
|
return new DataView(mallocArrayBuffer(n), 0, n)
|
|
}
|
|
exports.mallocDataView = mallocDataView
|
|
|
|
function mallocBuffer(n) {
|
|
n = bits.nextPow2(n)
|
|
var log_n = bits.log2(n)
|
|
var cache = BUFFER[log_n]
|
|
if(cache.length > 0) {
|
|
return cache.pop()
|
|
}
|
|
return new Buffer(n)
|
|
}
|
|
exports.mallocBuffer = mallocBuffer
|
|
|
|
exports.clearCache = function clearCache() {
|
|
for(var i=0; i<32; ++i) {
|
|
POOL.UINT8[i].length = 0
|
|
POOL.UINT16[i].length = 0
|
|
POOL.UINT32[i].length = 0
|
|
POOL.INT8[i].length = 0
|
|
POOL.INT16[i].length = 0
|
|
POOL.INT32[i].length = 0
|
|
POOL.FLOAT[i].length = 0
|
|
POOL.DOUBLE[i].length = 0
|
|
POOL.BIGUINT64[i].length = 0
|
|
POOL.BIGINT64[i].length = 0
|
|
POOL.UINT8C[i].length = 0
|
|
DATA[i].length = 0
|
|
BUFFER[i].length = 0
|
|
}
|
|
}
|
|
|
|
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
},{"bit-twiddle":31,"buffer":8,"dup":30}],33:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
var ndarray = require("ndarray")
|
|
var ops = require("ndarray-ops")
|
|
var pool = require("typedarray-pool")
|
|
var webglew = require("webglew")
|
|
|
|
var linearTypes = null
|
|
var filterTypes = null
|
|
var wrapTypes = null
|
|
|
|
function lazyInitLinearTypes(gl) {
|
|
linearTypes = [
|
|
gl.LINEAR,
|
|
gl.NEAREST_MIPMAP_LINEAR,
|
|
gl.LINEAR_MIPMAP_NEAREST,
|
|
gl.LINEAR_MIPMAP_NEAREST
|
|
]
|
|
filterTypes = [
|
|
gl.NEAREST,
|
|
gl.LINEAR,
|
|
gl.NEAREST_MIPMAP_NEAREST,
|
|
gl.NEAREST_MIPMAP_LINEAR,
|
|
gl.LINEAR_MIPMAP_NEAREST,
|
|
gl.LINEAR_MIPMAP_LINEAR
|
|
]
|
|
wrapTypes = [
|
|
gl.REPEAT,
|
|
gl.CLAMP_TO_EDGE,
|
|
gl.MIRRORED_REPEAT
|
|
]
|
|
}
|
|
|
|
var convertFloatToUint8 = function(out, inp) {
|
|
ops.muls(out, inp, 255.0)
|
|
}
|
|
|
|
function Texture2D(gl, handle, width, height, format, type) {
|
|
this.gl = gl
|
|
this.handle = handle
|
|
this.shape = [ height, width ]
|
|
this.format = format
|
|
this.type = type
|
|
this._mipLevels = [0]
|
|
this._magFilter = gl.NEAREST
|
|
this._minFilter = gl.NEAREST
|
|
this._wrapS = gl.CLAMP_TO_EDGE
|
|
this._wrapT = gl.CLAMP_TO_EDGE
|
|
this._anisoSamples = 1
|
|
}
|
|
|
|
Object.defineProperty(Texture2D.prototype, "minFilter", {
|
|
get: function() {
|
|
return this._minFilter
|
|
},
|
|
set: function(v) {
|
|
this.bind()
|
|
var gl = this.gl
|
|
if(this.type === gl.FLOAT && linearTypes.indexOf(v) >= 0) {
|
|
if(!webglew(gl).OES_texture_float_linear) {
|
|
v = gl.NEAREST
|
|
}
|
|
}
|
|
if(filterTypes.indexOf(v) < 0) {
|
|
throw new Error("gl-texture2d: Unknown filter mode " + v)
|
|
}
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, v)
|
|
return this._minFilter = v
|
|
}
|
|
})
|
|
|
|
var proto = Texture2D.prototype
|
|
|
|
Object.defineProperty(proto, "magFilter", {
|
|
get: function() {
|
|
return this._magFilter
|
|
},
|
|
set: function(v) {
|
|
this.bind()
|
|
var gl = this.gl
|
|
if(this.type === gl.FLOAT && linearTypes.indexOf(v) >= 0) {
|
|
if(!webglew(gl).OES_texture_float_linear) {
|
|
v = gl.NEAREST
|
|
}
|
|
}
|
|
if(filterTypes.indexOf(v) < 0) {
|
|
throw new Error("gl-texture2d: Unknown filter mode " + v)
|
|
}
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, v)
|
|
return this._magFilter = v
|
|
}
|
|
})
|
|
|
|
Object.defineProperty(proto, "wrapS", {
|
|
get: function() {
|
|
return this._wrapS
|
|
},
|
|
set: function(v) {
|
|
this.bind()
|
|
if(wrapTypes.indexOf(v) < 0) {
|
|
throw new Error("gl-texture2d: Unknown wrap mode " + v)
|
|
}
|
|
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, v)
|
|
return this._wrapS = v
|
|
}
|
|
})
|
|
|
|
Object.defineProperty(proto, "wrapT", {
|
|
get: function() {
|
|
return this._wrapT
|
|
},
|
|
set: function(v) {
|
|
this.bind()
|
|
if(wrapTypes.indexOf(v) < 0) {
|
|
throw new Error("gl-texture2d: Unknown wrap mode " + v)
|
|
}
|
|
this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, v)
|
|
return this._wrapT = v
|
|
}
|
|
})
|
|
|
|
Object.defineProperty(proto, "mipSamples", {
|
|
get: function() {
|
|
return this._anisoSamples
|
|
},
|
|
set: function(i) {
|
|
var psamples = this._anisoSamples
|
|
this._anisoSamples = Math.max(i, 1)|0
|
|
if(psamples !== this._anisoSamples) {
|
|
var ext = webglew(this.gl).EXT_texture_filter_anisotropic
|
|
if(ext) {
|
|
this.gl.texParameterf(this.gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisoSamples)
|
|
}
|
|
}
|
|
return this._anisoSamples
|
|
}
|
|
})
|
|
|
|
proto.bind = function bindTexture2D(unit) {
|
|
var gl = this.gl
|
|
if(unit !== undefined) {
|
|
gl.activeTexture(gl.TEXTURE0 + (unit|0))
|
|
}
|
|
gl.bindTexture(gl.TEXTURE_2D, this.handle)
|
|
if(unit !== undefined) {
|
|
return unit
|
|
}
|
|
return gl.getParameter(gl.ACTIVE_TEXTURE) - gl.TEXTURE0
|
|
}
|
|
|
|
proto.dispose = function disposeTexture2D() {
|
|
this.gl.deleteTexture(this.handle)
|
|
}
|
|
|
|
proto.generateMipmap = function() {
|
|
this.bind()
|
|
this.gl.generateMipmap(this.gl.TEXTURE_2D)
|
|
|
|
//Update mip levels
|
|
var l = Math.min(this.shape[0], this.shape[1])
|
|
for(var i=0; l>0; ++i, l>>>=1) {
|
|
if(this._mipLevels.indexOf(i) < 0) {
|
|
this._mipLevels.push(i)
|
|
}
|
|
}
|
|
}
|
|
|
|
proto.setPixels = function(data, x_off, y_off, mip_level) {
|
|
var gl = this.gl
|
|
this.bind()
|
|
x_off = x_off || 0
|
|
y_off = y_off || 0
|
|
mip_level = mip_level || 0
|
|
if(data instanceof HTMLCanvasElement ||
|
|
data instanceof ImageData ||
|
|
data instanceof HTMLImageElement ||
|
|
data instanceof HTMLVideoElement) {
|
|
var needsMip = this._mipLevels.indexOf(mip_level) < 0
|
|
if(needsMip) {
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, data)
|
|
this._mipLevels.push(mip_level)
|
|
} else {
|
|
gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, this.format, this.type, data)
|
|
}
|
|
} else if(data.shape && data.stride && data.data) {
|
|
if(data.shape.length < 2 ||
|
|
x_off + data.shape[1] > this.shape[1]>>>mip_level ||
|
|
y_off + data.shape[0] > this.shape[0]>>>mip_level ||
|
|
x_off < 0 ||
|
|
y_off < 0) {
|
|
throw new Error("Texture dimensions are out of bounds")
|
|
}
|
|
texSubImageArray(gl, x_off, y_off, mip_level, this.format, this.type, this._mipLevels, data)
|
|
} else {
|
|
throw new Error("Unsupported data type")
|
|
}
|
|
}
|
|
|
|
function texSubImageArray(gl, x_off, y_off, mip_level, cformat, ctype, mipLevels, array) {
|
|
var dtype = array.dtype || ndarray.dtype(array)
|
|
var shape = array.shape
|
|
var packed = isPacked(array)
|
|
var type = 0, format = 0
|
|
if(dtype === "float32") {
|
|
type = gl.FLOAT
|
|
} else if(dtype === "float64") {
|
|
type = gl.FLOAT
|
|
packed = false
|
|
dtype = "float32"
|
|
} else if(dtype === "uint8") {
|
|
type = gl.UNSIGNED_BYTE
|
|
} else {
|
|
type = gl.UNSIGNED_BYTE
|
|
packed = false
|
|
}
|
|
if(shape.length === 2) {
|
|
format = gl.LUMINANCE
|
|
} else if(shape.length === 3) {
|
|
if(shape[2] === 1) {
|
|
format = gl.ALPHA
|
|
} else if(shape[2] === 2) {
|
|
format = gl.LUMINANCE_ALPHA
|
|
} else if(shape[2] === 3) {
|
|
format = gl.RGB
|
|
} else if(shape[2] === 4) {
|
|
format = gl.RGBA
|
|
} else {
|
|
throw new Error("Invalid shape for pixel coords")
|
|
}
|
|
} else {
|
|
throw new Error("Invalid shape for texture")
|
|
}
|
|
//For 1-channel textures allow conversion between formats
|
|
if((format === gl.LUMINANCE || format === gl.ALPHA) &&
|
|
(cformat === gl.LUMINANCE || cformat === gl.ALPHA)) {
|
|
format = cformat
|
|
}
|
|
if(format !== cformat) {
|
|
throw new Error("Incompatible texture format for setPixels")
|
|
}
|
|
var size = array.size
|
|
if(typeof size !== "number") {
|
|
size = ndarray.size(array)
|
|
}
|
|
var needsMip = mipLevels.indexOf(mip_level) < 0
|
|
if(needsMip) {
|
|
mipLevels.push(mip_level)
|
|
}
|
|
if(type === ctype && packed) {
|
|
//Array data types are compatible, can directly copy into texture
|
|
if(array.offset === 0 && array.data.length === size) {
|
|
if(needsMip) {
|
|
gl.texImage2D(gl.TEXTURE_2D, mip_level, cformat, shape[1], shape[0], 0, cformat, ctype, array.data)
|
|
} else {
|
|
gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, shape[1], shape[0], cformat, ctype, array.data)
|
|
}
|
|
} else {
|
|
if(needsMip) {
|
|
gl.texImage2D(gl.TEXTURE_2D, mip_level, cformat, shape[1], shape[0], 0, cformat, ctype, array.data.subarray(array.offset, array.offset+size))
|
|
} else {
|
|
gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, shape[1], shape[0], cformat, ctype, array.data.subarray(array.offset, array.offset+size))
|
|
}
|
|
}
|
|
} else {
|
|
//Need to do type conversion to pack data into buffer
|
|
var pack_buffer
|
|
if(ctype === gl.FLOAT) {
|
|
pack_buffer = pool.mallocFloat32(size)
|
|
} else {
|
|
pack_buffer = pool.mallocUint8(size)
|
|
}
|
|
var pack_view = ndarray(pack_buffer, shape)
|
|
if(type === gl.FLOAT && ctype === gl.UNSIGNED_BYTE) {
|
|
convertFloatToUint8(pack_view, array)
|
|
} else {
|
|
ops.assign(pack_view, array)
|
|
}
|
|
if(needsMip) {
|
|
gl.texImage2D(gl.TEXTURE_2D, mip_level, cformat, shape[1], shape[0], 0, cformat, ctype, pack_buffer.subarray(0, size))
|
|
} else {
|
|
gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, shape[1], shape[0], cformat, ctype, pack_buffer.subarray(0, size))
|
|
}
|
|
if(ctype === gl.FLOAT) {
|
|
pool.freeFloat32(pack_buffer)
|
|
} else {
|
|
pool.freeUint8(pack_buffer)
|
|
}
|
|
}
|
|
}
|
|
|
|
function initTexture(gl) {
|
|
var tex = gl.createTexture()
|
|
gl.bindTexture(gl.TEXTURE_2D, tex)
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
|
|
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)
|
|
return tex
|
|
}
|
|
|
|
function createTextureShape(gl, width, height, format, type) {
|
|
var tex = initTexture(gl)
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, type, null)
|
|
return new Texture2D(gl, tex, width, height, format, type)
|
|
}
|
|
|
|
function createTextureDOM(gl, element, format, type) {
|
|
var tex = initTexture(gl)
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, format, format, type, element)
|
|
return new Texture2D(gl, tex, element.width|0, element.height|0, format, type)
|
|
}
|
|
|
|
function isPacked(array) {
|
|
var shape = array.shape
|
|
var stride = array.stride
|
|
var s = 1
|
|
for(var i=shape.length-1; i>=0; --i) {
|
|
if(stride[i] !== s) {
|
|
return false
|
|
}
|
|
s *= shape[i]
|
|
}
|
|
return true
|
|
}
|
|
|
|
//Creates a texture from an ndarray
|
|
function createTextureArray(gl, array) {
|
|
var dtype = array.dtype || ndarray.dtype(array)
|
|
var shape = array.shape
|
|
var packed = isPacked(array)
|
|
var type = 0
|
|
if(dtype === "float32") {
|
|
type = gl.FLOAT
|
|
} else if(dtype === "float64") {
|
|
type = gl.FLOAT
|
|
packed = false
|
|
dtype = "float32"
|
|
} else if(dtype === "uint8") {
|
|
type = gl.UNSIGNED_BYTE
|
|
} else {
|
|
type = gl.UNSIGNED_BYTE
|
|
packed = false
|
|
}
|
|
var format = 0
|
|
if(shape.length === 2) {
|
|
format = gl.LUMINANCE
|
|
} else if(shape.length === 3) {
|
|
if(shape[2] === 1) {
|
|
format = gl.ALPHA
|
|
} else if(shape[2] === 2) {
|
|
format = gl.LUMINANCE_ALPHA
|
|
} else if(shape[2] === 3) {
|
|
format = gl.RGB
|
|
} else if(shape[2] === 4) {
|
|
format = gl.RGBA
|
|
} else {
|
|
throw new Error("Invalid shape for pixel coords")
|
|
}
|
|
} else {
|
|
throw new Error("Invalid shape for texture")
|
|
}
|
|
if(type === gl.FLOAT && !!webglew(gl).texture_float) {
|
|
type = gl.UNSIGNED_BYTE
|
|
packed = false
|
|
}
|
|
var buffer, buf_store
|
|
if(!packed) {
|
|
var sz = 1
|
|
var stride = new Array(shape.length)
|
|
for(var i=shape.length-1; i>=0; --i) {
|
|
stride[i] = sz
|
|
sz *= shape[i]
|
|
}
|
|
buf_store = pool.malloc(sz, dtype)
|
|
var buf_array = ndarray(buf_store, array.shape, stride, 0)
|
|
if((dtype === "float32" || dtype === "float64") && type === gl.UNSIGNED_BYTE) {
|
|
convertFloatToUint8(buf_array, array)
|
|
} else {
|
|
ops.assign(buf_array, array)
|
|
}
|
|
buffer = buf_store.subarray(0, sz)
|
|
} else {
|
|
var array_size = array.size
|
|
if(typeof array_size !== "number") {
|
|
array_size = ndarray.size(array)
|
|
}
|
|
buffer = array.data.subarray(array.offset, array.offset + array_size)
|
|
}
|
|
var tex = initTexture(gl)
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, format, shape[1], shape[0], 0, format, type, buffer)
|
|
if(!packed) {
|
|
pool.free(buf_store)
|
|
}
|
|
return new Texture2D(gl, tex, shape[1], shape[0], format, type)
|
|
}
|
|
|
|
function createTexture2D(gl) {
|
|
if(arguments.length <= 1) {
|
|
throw new Error("Missing arguments for texture2d constructor")
|
|
}
|
|
if(!linearTypes) {
|
|
lazyInitLinearTypes(gl)
|
|
}
|
|
if(typeof arguments[1] === "number") {
|
|
return createTextureShape(gl, arguments[1], arguments[2], arguments[3]||gl.RGBA, arguments[4]||gl.UNSIGNED_BYTE)
|
|
}
|
|
if(typeof arguments[1] === "object") {
|
|
var obj = arguments[1]
|
|
if(obj instanceof HTMLCanvasElement ||
|
|
obj instanceof HTMLImageElement ||
|
|
obj instanceof HTMLVideoElement ||
|
|
obj instanceof ImageData) {
|
|
return createTextureDOM(gl, obj, arguments[2]||gl.RGBA, arguments[3]||gl.UNSIGNED_BYTE)
|
|
} else if(obj.shape && obj.data && obj.stride) {
|
|
return createTextureArray(gl, obj)
|
|
}
|
|
}
|
|
throw new Error("Invalid arguments for texture2d constructor")
|
|
}
|
|
module.exports = createTexture2D
|
|
|
|
},{"ndarray":55,"ndarray-ops":51,"typedarray-pool":32,"webglew":71}],34:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
function doBind(gl, elements, attributes) {
|
|
if(elements) {
|
|
elements.bind()
|
|
} else {
|
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null)
|
|
}
|
|
var nattribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS)|0
|
|
if(attributes) {
|
|
if(attributes.length > nattribs) {
|
|
throw new Error("Too many vertex attributes")
|
|
}
|
|
for(var i=0; i<attributes.length; ++i) {
|
|
var attrib = attributes[i]
|
|
if(attrib.buffer) {
|
|
var buffer = attrib.buffer
|
|
var size = attrib.size || 4
|
|
var type = attrib.type || gl.FLOAT
|
|
var normalized = !!attrib.normalized
|
|
var stride = attrib.stride || 0
|
|
var offset = attrib.offset || 0
|
|
buffer.bind()
|
|
gl.vertexAttribPointer(i, size, type, normalized, stride, offset)
|
|
gl.enableVertexAttribArray(i)
|
|
} else {
|
|
if(typeof attrib === "number") {
|
|
gl.vertexAttrib1f(i, attrib)
|
|
} else if(attrib.length === 1) {
|
|
gl.vertexAttrib1f(i, attrib[0])
|
|
} else if(attrib.length === 2) {
|
|
gl.vertexAttrib2f(i, attrib[0], attrib[1])
|
|
} else if(attrib.length === 3) {
|
|
gl.vertexAttrib3f(i, attrib[0], attrib[1], attrib[2])
|
|
} else if(attrib.length === 4) {
|
|
gl.vertexAttrib4f(i, attrib[0], attrib[1], attrib[2], attrib[3])
|
|
} else {
|
|
throw new Error("Invalid vertex attribute")
|
|
}
|
|
gl.disableVertexAttribArray(i)
|
|
}
|
|
}
|
|
for(; i<nattribs; ++i) {
|
|
gl.disableVertexAttribArray(i)
|
|
}
|
|
} else {
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, null)
|
|
for(var i=0; i<nattribs; ++i) {
|
|
gl.disableVertexAttribArray(i)
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = doBind
|
|
},{}],35:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
var bindAttribs = require("./do-bind.js")
|
|
|
|
function VAOEmulated(gl) {
|
|
this.gl = gl
|
|
this.elements = null
|
|
this.attributes = null
|
|
}
|
|
|
|
VAOEmulated.prototype.bind = function() {
|
|
bindAttribs(this.gl, this.elements, this.attributes)
|
|
}
|
|
|
|
VAOEmulated.prototype.update = function(elements, attributes) {
|
|
this.elements = elements
|
|
this.attributes = attributes
|
|
}
|
|
|
|
VAOEmulated.prototype.dispose = function() { }
|
|
VAOEmulated.prototype.unbind = function() { }
|
|
|
|
function createVAOEmulated(gl) {
|
|
return new VAOEmulated(gl)
|
|
}
|
|
|
|
module.exports = createVAOEmulated
|
|
},{"./do-bind.js":34}],36:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
var bindAttribs = require("./do-bind.js")
|
|
|
|
function VAONative(gl, ext, handle) {
|
|
this.gl = gl
|
|
this.ext = ext
|
|
this.handle = handle
|
|
}
|
|
|
|
VAONative.prototype.bind = function() {
|
|
this.ext.bindVertexArrayOES(this.handle)
|
|
}
|
|
|
|
VAONative.prototype.unbind = function() {
|
|
this.ext.bindVertexArrayOES(null)
|
|
}
|
|
|
|
VAONative.prototype.dispose = function() {
|
|
this.ext.deleteVertexArrayOES(this.handle)
|
|
}
|
|
|
|
VAONative.prototype.update = function(elements, attributes) {
|
|
this.bind()
|
|
bindAttribs(this.gl, elements, attributes)
|
|
this.unbind()
|
|
}
|
|
|
|
function createVAONative(gl, ext) {
|
|
return new VAONative(gl, ext, ext.createVertexArrayOES())
|
|
}
|
|
|
|
module.exports = createVAONative
|
|
},{"./do-bind.js":34}],37:[function(require,module,exports){
|
|
"use strict";
|
|
|
|
var VENDOR_PREFIX = [
|
|
"WEBKIT_",
|
|
"MOZ_"
|
|
];
|
|
|
|
function baseName(ext_name) {
|
|
for(var i=0; i<VENDOR_PREFIX.length; ++i) {
|
|
var prefix = VENDOR_PREFIX[i];
|
|
if(ext_name.indexOf(prefix) === 0) {
|
|
return ext_name.slice(prefix.length);
|
|
}
|
|
}
|
|
return ext_name;
|
|
}
|
|
|
|
function initWebGLEW(gl) {
|
|
if(gl._webglew_struct) {
|
|
return gl._webglew_struct;
|
|
}
|
|
var extensions = {};
|
|
var supported = gl.getSupportedExtensions();
|
|
for(var i=0; i<supported.length; ++i) {
|
|
var ext = gl.getExtension(supported[i]);
|
|
if(!ext) {
|
|
continue;
|
|
}
|
|
extensions[supported[i]] = ext;
|
|
extensions[baseName(supported[i])] = ext; //Add version without VENDOR
|
|
}
|
|
gl._webglew_struct = extensions;
|
|
return extensions;
|
|
}
|
|
module.exports = initWebGLEW;
|
|
},{}],38:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
var webglew = require("webglew")
|
|
var createVAONative = require("./lib/vao-native.js")
|
|
var createVAOEmulated = require("./lib/vao-emulated.js")
|
|
|
|
function createVAO(gl, elements, attributes) {
|
|
var ext = webglew(gl).OES_vertex_array_object
|
|
var vao
|
|
if(ext) {
|
|
vao = createVAONative(gl, ext)
|
|
} else {
|
|
vao = createVAOEmulated(gl)
|
|
}
|
|
vao.update(elements, attributes)
|
|
return vao
|
|
}
|
|
|
|
module.exports = createVAO
|
|
},{"./lib/vao-emulated.js":35,"./lib/vao-native.js":36,"webglew":37}],39:[function(require,module,exports){
|
|
var tokenize = require('glsl-tokenizer')
|
|
var atob = require('atob-lite')
|
|
|
|
module.exports = getName
|
|
|
|
function getName(src) {
|
|
var tokens = Array.isArray(src)
|
|
? src
|
|
: tokenize(src)
|
|
|
|
for (var i = 0; i < tokens.length; i++) {
|
|
var token = tokens[i]
|
|
if (token.type !== 'preprocessor') continue
|
|
var match = token.data.match(/\#define\s+SHADER_NAME(_B64)?\s+(.+)$/)
|
|
if (!match) continue
|
|
if (!match[2]) continue
|
|
|
|
var b64 = match[1]
|
|
var name = match[2]
|
|
|
|
return (b64 ? atob(name) : name).trim()
|
|
}
|
|
}
|
|
|
|
},{"atob-lite":4,"glsl-tokenizer":46}],40:[function(require,module,exports){
|
|
module.exports = tokenize
|
|
|
|
var literals100 = require('./lib/literals')
|
|
, operators = require('./lib/operators')
|
|
, builtins100 = require('./lib/builtins')
|
|
, literals300es = require('./lib/literals-300es')
|
|
, builtins300es = require('./lib/builtins-300es')
|
|
|
|
var NORMAL = 999 // <-- never emitted
|
|
, TOKEN = 9999 // <-- never emitted
|
|
, BLOCK_COMMENT = 0
|
|
, LINE_COMMENT = 1
|
|
, PREPROCESSOR = 2
|
|
, OPERATOR = 3
|
|
, INTEGER = 4
|
|
, FLOAT = 5
|
|
, IDENT = 6
|
|
, BUILTIN = 7
|
|
, KEYWORD = 8
|
|
, WHITESPACE = 9
|
|
, EOF = 10
|
|
, HEX = 11
|
|
|
|
var map = [
|
|
'block-comment'
|
|
, 'line-comment'
|
|
, 'preprocessor'
|
|
, 'operator'
|
|
, 'integer'
|
|
, 'float'
|
|
, 'ident'
|
|
, 'builtin'
|
|
, 'keyword'
|
|
, 'whitespace'
|
|
, 'eof'
|
|
, 'integer'
|
|
]
|
|
|
|
function tokenize(opt) {
|
|
var i = 0
|
|
, total = 0
|
|
, mode = NORMAL
|
|
, c
|
|
, last
|
|
, content = []
|
|
, tokens = []
|
|
, token_idx = 0
|
|
, token_offs = 0
|
|
, line = 1
|
|
, col = 0
|
|
, start = 0
|
|
, isnum = false
|
|
, isoperator = false
|
|
, input = ''
|
|
, len
|
|
|
|
opt = opt || {}
|
|
var allBuiltins = builtins100
|
|
var allLiterals = literals100
|
|
if (opt.version === '300 es') {
|
|
allBuiltins = builtins300es
|
|
allLiterals = literals300es
|
|
}
|
|
|
|
// cache by name
|
|
var builtinsDict = {}, literalsDict = {}
|
|
for (var i = 0; i < allBuiltins.length; i++) {
|
|
builtinsDict[allBuiltins[i]] = true
|
|
}
|
|
for (var i = 0; i < allLiterals.length; i++) {
|
|
literalsDict[allLiterals[i]] = true
|
|
}
|
|
|
|
return function(data) {
|
|
tokens = []
|
|
if (data !== null) return write(data)
|
|
return end()
|
|
}
|
|
|
|
function token(data) {
|
|
if (data.length) {
|
|
tokens.push({
|
|
type: map[mode]
|
|
, data: data
|
|
, position: start
|
|
, line: line
|
|
, column: col
|
|
})
|
|
}
|
|
}
|
|
|
|
function write(chunk) {
|
|
i = 0
|
|
|
|
if (chunk.toString) chunk = chunk.toString()
|
|
|
|
input += chunk.replace(/\r\n/g, '\n')
|
|
len = input.length
|
|
|
|
|
|
var last
|
|
|
|
while(c = input[i], i < len) {
|
|
last = i
|
|
|
|
switch(mode) {
|
|
case BLOCK_COMMENT: i = block_comment(); break
|
|
case LINE_COMMENT: i = line_comment(); break
|
|
case PREPROCESSOR: i = preprocessor(); break
|
|
case OPERATOR: i = operator(); break
|
|
case INTEGER: i = integer(); break
|
|
case HEX: i = hex(); break
|
|
case FLOAT: i = decimal(); break
|
|
case TOKEN: i = readtoken(); break
|
|
case WHITESPACE: i = whitespace(); break
|
|
case NORMAL: i = normal(); break
|
|
}
|
|
|
|
if(last !== i) {
|
|
switch(input[last]) {
|
|
case '\n': col = 0; ++line; break
|
|
default: ++col; break
|
|
}
|
|
}
|
|
}
|
|
|
|
total += i
|
|
input = input.slice(i)
|
|
return tokens
|
|
}
|
|
|
|
function end(chunk) {
|
|
if(content.length) {
|
|
token(content.join(''))
|
|
}
|
|
|
|
mode = EOF
|
|
token('(eof)')
|
|
return tokens
|
|
}
|
|
|
|
function normal() {
|
|
content = content.length ? [] : content
|
|
|
|
if(last === '/' && c === '*') {
|
|
start = total + i - 1
|
|
mode = BLOCK_COMMENT
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
if(last === '/' && c === '/') {
|
|
start = total + i - 1
|
|
mode = LINE_COMMENT
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
if(c === '#') {
|
|
mode = PREPROCESSOR
|
|
start = total + i
|
|
return i
|
|
}
|
|
|
|
if(/\s/.test(c)) {
|
|
mode = WHITESPACE
|
|
start = total + i
|
|
return i
|
|
}
|
|
|
|
isnum = /\d/.test(c)
|
|
isoperator = /[^\w_]/.test(c)
|
|
|
|
start = total + i
|
|
mode = isnum ? INTEGER : isoperator ? OPERATOR : TOKEN
|
|
return i
|
|
}
|
|
|
|
function whitespace() {
|
|
if(/[^\s]/g.test(c)) {
|
|
token(content.join(''))
|
|
mode = NORMAL
|
|
return i
|
|
}
|
|
content.push(c)
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
function preprocessor() {
|
|
if((c === '\r' || c === '\n') && last !== '\\') {
|
|
token(content.join(''))
|
|
mode = NORMAL
|
|
return i
|
|
}
|
|
content.push(c)
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
function line_comment() {
|
|
return preprocessor()
|
|
}
|
|
|
|
function block_comment() {
|
|
if(c === '/' && last === '*') {
|
|
content.push(c)
|
|
token(content.join(''))
|
|
mode = NORMAL
|
|
return i + 1
|
|
}
|
|
|
|
content.push(c)
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
function operator() {
|
|
if(last === '.' && /\d/.test(c)) {
|
|
mode = FLOAT
|
|
return i
|
|
}
|
|
|
|
if(last === '/' && c === '*') {
|
|
mode = BLOCK_COMMENT
|
|
return i
|
|
}
|
|
|
|
if(last === '/' && c === '/') {
|
|
mode = LINE_COMMENT
|
|
return i
|
|
}
|
|
|
|
if(c === '.' && content.length) {
|
|
while(determine_operator(content));
|
|
|
|
mode = FLOAT
|
|
return i
|
|
}
|
|
|
|
if(c === ';' || c === ')' || c === '(') {
|
|
if(content.length) while(determine_operator(content));
|
|
token(c)
|
|
mode = NORMAL
|
|
return i + 1
|
|
}
|
|
|
|
var is_composite_operator = content.length === 2 && c !== '='
|
|
if(/[\w_\d\s]/.test(c) || is_composite_operator) {
|
|
while(determine_operator(content));
|
|
mode = NORMAL
|
|
return i
|
|
}
|
|
|
|
content.push(c)
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
function determine_operator(buf) {
|
|
var j = 0
|
|
, idx
|
|
, res
|
|
|
|
do {
|
|
idx = operators.indexOf(buf.slice(0, buf.length + j).join(''))
|
|
res = operators[idx]
|
|
|
|
if(idx === -1) {
|
|
if(j-- + buf.length > 0) continue
|
|
res = buf.slice(0, 1).join('')
|
|
}
|
|
|
|
token(res)
|
|
|
|
start += res.length
|
|
content = content.slice(res.length)
|
|
return content.length
|
|
} while(1)
|
|
}
|
|
|
|
function hex() {
|
|
if(/[^a-fA-F0-9]/.test(c)) {
|
|
token(content.join(''))
|
|
mode = NORMAL
|
|
return i
|
|
}
|
|
|
|
content.push(c)
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
function integer() {
|
|
if(c === '.') {
|
|
content.push(c)
|
|
mode = FLOAT
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
if(/[eE]/.test(c)) {
|
|
content.push(c)
|
|
mode = FLOAT
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
if(c === 'x' && content.length === 1 && content[0] === '0') {
|
|
mode = HEX
|
|
content.push(c)
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
if(/[^\d]/.test(c)) {
|
|
token(content.join(''))
|
|
mode = NORMAL
|
|
return i
|
|
}
|
|
|
|
content.push(c)
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
function decimal() {
|
|
if(c === 'f') {
|
|
content.push(c)
|
|
last = c
|
|
i += 1
|
|
}
|
|
|
|
if(/[eE]/.test(c)) {
|
|
content.push(c)
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
if ((c === '-' || c === '+') && /[eE]/.test(last)) {
|
|
content.push(c)
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
if(/[^\d]/.test(c)) {
|
|
token(content.join(''))
|
|
mode = NORMAL
|
|
return i
|
|
}
|
|
|
|
content.push(c)
|
|
last = c
|
|
return i + 1
|
|
}
|
|
|
|
function readtoken() {
|
|
if(/[^\d\w_]/.test(c)) {
|
|
var contentstr = content.join('')
|
|
if(literalsDict[contentstr]) {
|
|
mode = KEYWORD
|
|
} else if(builtinsDict[contentstr]) {
|
|
mode = BUILTIN
|
|
} else {
|
|
mode = IDENT
|
|
}
|
|
token(content.join(''))
|
|
mode = NORMAL
|
|
return i
|
|
}
|
|
content.push(c)
|
|
last = c
|
|
return i + 1
|
|
}
|
|
}
|
|
|
|
},{"./lib/builtins":42,"./lib/builtins-300es":41,"./lib/literals":44,"./lib/literals-300es":43,"./lib/operators":45}],41:[function(require,module,exports){
|
|
// 300es builtins/reserved words that were previously valid in v100
|
|
var v100 = require('./builtins')
|
|
|
|
// The texture2D|Cube functions have been removed
|
|
// And the gl_ features are updated
|
|
v100 = v100.slice().filter(function (b) {
|
|
return !/^(gl\_|texture)/.test(b)
|
|
})
|
|
|
|
module.exports = v100.concat([
|
|
// the updated gl_ constants
|
|
'gl_VertexID'
|
|
, 'gl_InstanceID'
|
|
, 'gl_Position'
|
|
, 'gl_PointSize'
|
|
, 'gl_FragCoord'
|
|
, 'gl_FrontFacing'
|
|
, 'gl_FragDepth'
|
|
, 'gl_PointCoord'
|
|
, 'gl_MaxVertexAttribs'
|
|
, 'gl_MaxVertexUniformVectors'
|
|
, 'gl_MaxVertexOutputVectors'
|
|
, 'gl_MaxFragmentInputVectors'
|
|
, 'gl_MaxVertexTextureImageUnits'
|
|
, 'gl_MaxCombinedTextureImageUnits'
|
|
, 'gl_MaxTextureImageUnits'
|
|
, 'gl_MaxFragmentUniformVectors'
|
|
, 'gl_MaxDrawBuffers'
|
|
, 'gl_MinProgramTexelOffset'
|
|
, 'gl_MaxProgramTexelOffset'
|
|
, 'gl_DepthRangeParameters'
|
|
, 'gl_DepthRange'
|
|
|
|
// other builtins
|
|
, 'trunc'
|
|
, 'round'
|
|
, 'roundEven'
|
|
, 'isnan'
|
|
, 'isinf'
|
|
, 'floatBitsToInt'
|
|
, 'floatBitsToUint'
|
|
, 'intBitsToFloat'
|
|
, 'uintBitsToFloat'
|
|
, 'packSnorm2x16'
|
|
, 'unpackSnorm2x16'
|
|
, 'packUnorm2x16'
|
|
, 'unpackUnorm2x16'
|
|
, 'packHalf2x16'
|
|
, 'unpackHalf2x16'
|
|
, 'outerProduct'
|
|
, 'transpose'
|
|
, 'determinant'
|
|
, 'inverse'
|
|
, 'texture'
|
|
, 'textureSize'
|
|
, 'textureProj'
|
|
, 'textureLod'
|
|
, 'textureOffset'
|
|
, 'texelFetch'
|
|
, 'texelFetchOffset'
|
|
, 'textureProjOffset'
|
|
, 'textureLodOffset'
|
|
, 'textureProjLod'
|
|
, 'textureProjLodOffset'
|
|
, 'textureGrad'
|
|
, 'textureGradOffset'
|
|
, 'textureProjGrad'
|
|
, 'textureProjGradOffset'
|
|
])
|
|
|
|
},{"./builtins":42}],42:[function(require,module,exports){
|
|
module.exports = [
|
|
// Keep this list sorted
|
|
'abs'
|
|
, 'acos'
|
|
, 'all'
|
|
, 'any'
|
|
, 'asin'
|
|
, 'atan'
|
|
, 'ceil'
|
|
, 'clamp'
|
|
, 'cos'
|
|
, 'cross'
|
|
, 'dFdx'
|
|
, 'dFdy'
|
|
, 'degrees'
|
|
, 'distance'
|
|
, 'dot'
|
|
, 'equal'
|
|
, 'exp'
|
|
, 'exp2'
|
|
, 'faceforward'
|
|
, 'floor'
|
|
, 'fract'
|
|
, 'gl_BackColor'
|
|
, 'gl_BackLightModelProduct'
|
|
, 'gl_BackLightProduct'
|
|
, 'gl_BackMaterial'
|
|
, 'gl_BackSecondaryColor'
|
|
, 'gl_ClipPlane'
|
|
, 'gl_ClipVertex'
|
|
, 'gl_Color'
|
|
, 'gl_DepthRange'
|
|
, 'gl_DepthRangeParameters'
|
|
, 'gl_EyePlaneQ'
|
|
, 'gl_EyePlaneR'
|
|
, 'gl_EyePlaneS'
|
|
, 'gl_EyePlaneT'
|
|
, 'gl_Fog'
|
|
, 'gl_FogCoord'
|
|
, 'gl_FogFragCoord'
|
|
, 'gl_FogParameters'
|
|
, 'gl_FragColor'
|
|
, 'gl_FragCoord'
|
|
, 'gl_FragData'
|
|
, 'gl_FragDepth'
|
|
, 'gl_FragDepthEXT'
|
|
, 'gl_FrontColor'
|
|
, 'gl_FrontFacing'
|
|
, 'gl_FrontLightModelProduct'
|
|
, 'gl_FrontLightProduct'
|
|
, 'gl_FrontMaterial'
|
|
, 'gl_FrontSecondaryColor'
|
|
, 'gl_LightModel'
|
|
, 'gl_LightModelParameters'
|
|
, 'gl_LightModelProducts'
|
|
, 'gl_LightProducts'
|
|
, 'gl_LightSource'
|
|
, 'gl_LightSourceParameters'
|
|
, 'gl_MaterialParameters'
|
|
, 'gl_MaxClipPlanes'
|
|
, 'gl_MaxCombinedTextureImageUnits'
|
|
, 'gl_MaxDrawBuffers'
|
|
, 'gl_MaxFragmentUniformComponents'
|
|
, 'gl_MaxLights'
|
|
, 'gl_MaxTextureCoords'
|
|
, 'gl_MaxTextureImageUnits'
|
|
, 'gl_MaxTextureUnits'
|
|
, 'gl_MaxVaryingFloats'
|
|
, 'gl_MaxVertexAttribs'
|
|
, 'gl_MaxVertexTextureImageUnits'
|
|
, 'gl_MaxVertexUniformComponents'
|
|
, 'gl_ModelViewMatrix'
|
|
, 'gl_ModelViewMatrixInverse'
|
|
, 'gl_ModelViewMatrixInverseTranspose'
|
|
, 'gl_ModelViewMatrixTranspose'
|
|
, 'gl_ModelViewProjectionMatrix'
|
|
, 'gl_ModelViewProjectionMatrixInverse'
|
|
, 'gl_ModelViewProjectionMatrixInverseTranspose'
|
|
, 'gl_ModelViewProjectionMatrixTranspose'
|
|
, 'gl_MultiTexCoord0'
|
|
, 'gl_MultiTexCoord1'
|
|
, 'gl_MultiTexCoord2'
|
|
, 'gl_MultiTexCoord3'
|
|
, 'gl_MultiTexCoord4'
|
|
, 'gl_MultiTexCoord5'
|
|
, 'gl_MultiTexCoord6'
|
|
, 'gl_MultiTexCoord7'
|
|
, 'gl_Normal'
|
|
, 'gl_NormalMatrix'
|
|
, 'gl_NormalScale'
|
|
, 'gl_ObjectPlaneQ'
|
|
, 'gl_ObjectPlaneR'
|
|
, 'gl_ObjectPlaneS'
|
|
, 'gl_ObjectPlaneT'
|
|
, 'gl_Point'
|
|
, 'gl_PointCoord'
|
|
, 'gl_PointParameters'
|
|
, 'gl_PointSize'
|
|
, 'gl_Position'
|
|
, 'gl_ProjectionMatrix'
|
|
, 'gl_ProjectionMatrixInverse'
|
|
, 'gl_ProjectionMatrixInverseTranspose'
|
|
, 'gl_ProjectionMatrixTranspose'
|
|
, 'gl_SecondaryColor'
|
|
, 'gl_TexCoord'
|
|
, 'gl_TextureEnvColor'
|
|
, 'gl_TextureMatrix'
|
|
, 'gl_TextureMatrixInverse'
|
|
, 'gl_TextureMatrixInverseTranspose'
|
|
, 'gl_TextureMatrixTranspose'
|
|
, 'gl_Vertex'
|
|
, 'greaterThan'
|
|
, 'greaterThanEqual'
|
|
, 'inversesqrt'
|
|
, 'length'
|
|
, 'lessThan'
|
|
, 'lessThanEqual'
|
|
, 'log'
|
|
, 'log2'
|
|
, 'matrixCompMult'
|
|
, 'max'
|
|
, 'min'
|
|
, 'mix'
|
|
, 'mod'
|
|
, 'normalize'
|
|
, 'not'
|
|
, 'notEqual'
|
|
, 'pow'
|
|
, 'radians'
|
|
, 'reflect'
|
|
, 'refract'
|
|
, 'sign'
|
|
, 'sin'
|
|
, 'smoothstep'
|
|
, 'sqrt'
|
|
, 'step'
|
|
, 'tan'
|
|
, 'texture2D'
|
|
, 'texture2DLod'
|
|
, 'texture2DProj'
|
|
, 'texture2DProjLod'
|
|
, 'textureCube'
|
|
, 'textureCubeLod'
|
|
, 'texture2DLodEXT'
|
|
, 'texture2DProjLodEXT'
|
|
, 'textureCubeLodEXT'
|
|
, 'texture2DGradEXT'
|
|
, 'texture2DProjGradEXT'
|
|
, 'textureCubeGradEXT'
|
|
]
|
|
|
|
},{}],43:[function(require,module,exports){
|
|
var v100 = require('./literals')
|
|
|
|
module.exports = v100.slice().concat([
|
|
'layout'
|
|
, 'centroid'
|
|
, 'smooth'
|
|
, 'case'
|
|
, 'mat2x2'
|
|
, 'mat2x3'
|
|
, 'mat2x4'
|
|
, 'mat3x2'
|
|
, 'mat3x3'
|
|
, 'mat3x4'
|
|
, 'mat4x2'
|
|
, 'mat4x3'
|
|
, 'mat4x4'
|
|
, 'uvec2'
|
|
, 'uvec3'
|
|
, 'uvec4'
|
|
, 'samplerCubeShadow'
|
|
, 'sampler2DArray'
|
|
, 'sampler2DArrayShadow'
|
|
, 'isampler2D'
|
|
, 'isampler3D'
|
|
, 'isamplerCube'
|
|
, 'isampler2DArray'
|
|
, 'usampler2D'
|
|
, 'usampler3D'
|
|
, 'usamplerCube'
|
|
, 'usampler2DArray'
|
|
, 'coherent'
|
|
, 'restrict'
|
|
, 'readonly'
|
|
, 'writeonly'
|
|
, 'resource'
|
|
, 'atomic_uint'
|
|
, 'noperspective'
|
|
, 'patch'
|
|
, 'sample'
|
|
, 'subroutine'
|
|
, 'common'
|
|
, 'partition'
|
|
, 'active'
|
|
, 'filter'
|
|
, 'image1D'
|
|
, 'image2D'
|
|
, 'image3D'
|
|
, 'imageCube'
|
|
, 'iimage1D'
|
|
, 'iimage2D'
|
|
, 'iimage3D'
|
|
, 'iimageCube'
|
|
, 'uimage1D'
|
|
, 'uimage2D'
|
|
, 'uimage3D'
|
|
, 'uimageCube'
|
|
, 'image1DArray'
|
|
, 'image2DArray'
|
|
, 'iimage1DArray'
|
|
, 'iimage2DArray'
|
|
, 'uimage1DArray'
|
|
, 'uimage2DArray'
|
|
, 'image1DShadow'
|
|
, 'image2DShadow'
|
|
, 'image1DArrayShadow'
|
|
, 'image2DArrayShadow'
|
|
, 'imageBuffer'
|
|
, 'iimageBuffer'
|
|
, 'uimageBuffer'
|
|
, 'sampler1DArray'
|
|
, 'sampler1DArrayShadow'
|
|
, 'isampler1D'
|
|
, 'isampler1DArray'
|
|
, 'usampler1D'
|
|
, 'usampler1DArray'
|
|
, 'isampler2DRect'
|
|
, 'usampler2DRect'
|
|
, 'samplerBuffer'
|
|
, 'isamplerBuffer'
|
|
, 'usamplerBuffer'
|
|
, 'sampler2DMS'
|
|
, 'isampler2DMS'
|
|
, 'usampler2DMS'
|
|
, 'sampler2DMSArray'
|
|
, 'isampler2DMSArray'
|
|
, 'usampler2DMSArray'
|
|
])
|
|
|
|
},{"./literals":44}],44:[function(require,module,exports){
|
|
module.exports = [
|
|
// current
|
|
'precision'
|
|
, 'highp'
|
|
, 'mediump'
|
|
, 'lowp'
|
|
, 'attribute'
|
|
, 'const'
|
|
, 'uniform'
|
|
, 'varying'
|
|
, 'break'
|
|
, 'continue'
|
|
, 'do'
|
|
, 'for'
|
|
, 'while'
|
|
, 'if'
|
|
, 'else'
|
|
, 'in'
|
|
, 'out'
|
|
, 'inout'
|
|
, 'float'
|
|
, 'int'
|
|
, 'uint'
|
|
, 'void'
|
|
, 'bool'
|
|
, 'true'
|
|
, 'false'
|
|
, 'discard'
|
|
, 'return'
|
|
, 'mat2'
|
|
, 'mat3'
|
|
, 'mat4'
|
|
, 'vec2'
|
|
, 'vec3'
|
|
, 'vec4'
|
|
, 'ivec2'
|
|
, 'ivec3'
|
|
, 'ivec4'
|
|
, 'bvec2'
|
|
, 'bvec3'
|
|
, 'bvec4'
|
|
, 'sampler1D'
|
|
, 'sampler2D'
|
|
, 'sampler3D'
|
|
, 'samplerCube'
|
|
, 'sampler1DShadow'
|
|
, 'sampler2DShadow'
|
|
, 'struct'
|
|
|
|
// future
|
|
, 'asm'
|
|
, 'class'
|
|
, 'union'
|
|
, 'enum'
|
|
, 'typedef'
|
|
, 'template'
|
|
, 'this'
|
|
, 'packed'
|
|
, 'goto'
|
|
, 'switch'
|
|
, 'default'
|
|
, 'inline'
|
|
, 'noinline'
|
|
, 'volatile'
|
|
, 'public'
|
|
, 'static'
|
|
, 'extern'
|
|
, 'external'
|
|
, 'interface'
|
|
, 'long'
|
|
, 'short'
|
|
, 'double'
|
|
, 'half'
|
|
, 'fixed'
|
|
, 'unsigned'
|
|
, 'input'
|
|
, 'output'
|
|
, 'hvec2'
|
|
, 'hvec3'
|
|
, 'hvec4'
|
|
, 'dvec2'
|
|
, 'dvec3'
|
|
, 'dvec4'
|
|
, 'fvec2'
|
|
, 'fvec3'
|
|
, 'fvec4'
|
|
, 'sampler2DRect'
|
|
, 'sampler3DRect'
|
|
, 'sampler2DRectShadow'
|
|
, 'sizeof'
|
|
, 'cast'
|
|
, 'namespace'
|
|
, 'using'
|
|
]
|
|
|
|
},{}],45:[function(require,module,exports){
|
|
module.exports = [
|
|
'<<='
|
|
, '>>='
|
|
, '++'
|
|
, '--'
|
|
, '<<'
|
|
, '>>'
|
|
, '<='
|
|
, '>='
|
|
, '=='
|
|
, '!='
|
|
, '&&'
|
|
, '||'
|
|
, '+='
|
|
, '-='
|
|
, '*='
|
|
, '/='
|
|
, '%='
|
|
, '&='
|
|
, '^^'
|
|
, '^='
|
|
, '|='
|
|
, '('
|
|
, ')'
|
|
, '['
|
|
, ']'
|
|
, '.'
|
|
, '!'
|
|
, '~'
|
|
, '*'
|
|
, '/'
|
|
, '%'
|
|
, '+'
|
|
, '-'
|
|
, '<'
|
|
, '>'
|
|
, '&'
|
|
, '^'
|
|
, '|'
|
|
, '?'
|
|
, ':'
|
|
, '='
|
|
, ','
|
|
, ';'
|
|
, '{'
|
|
, '}'
|
|
]
|
|
|
|
},{}],46:[function(require,module,exports){
|
|
var tokenize = require('./index')
|
|
|
|
module.exports = tokenizeString
|
|
|
|
function tokenizeString(str, opt) {
|
|
var generator = tokenize(opt)
|
|
var tokens = []
|
|
|
|
tokens = tokens.concat(generator(str))
|
|
tokens = tokens.concat(generator(null))
|
|
|
|
return tokens
|
|
}
|
|
|
|
},{"./index":40}],47:[function(require,module,exports){
|
|
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
|
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
|
|
var e, m
|
|
var eLen = (nBytes * 8) - mLen - 1
|
|
var eMax = (1 << eLen) - 1
|
|
var eBias = eMax >> 1
|
|
var nBits = -7
|
|
var i = isLE ? (nBytes - 1) : 0
|
|
var d = isLE ? -1 : 1
|
|
var s = buffer[offset + i]
|
|
|
|
i += d
|
|
|
|
e = s & ((1 << (-nBits)) - 1)
|
|
s >>= (-nBits)
|
|
nBits += eLen
|
|
for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}
|
|
|
|
m = e & ((1 << (-nBits)) - 1)
|
|
e >>= (-nBits)
|
|
nBits += mLen
|
|
for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}
|
|
|
|
if (e === 0) {
|
|
e = 1 - eBias
|
|
} else if (e === eMax) {
|
|
return m ? NaN : ((s ? -1 : 1) * Infinity)
|
|
} else {
|
|
m = m + Math.pow(2, mLen)
|
|
e = e - eBias
|
|
}
|
|
return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
|
|
}
|
|
|
|
exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
|
|
var e, m, c
|
|
var eLen = (nBytes * 8) - mLen - 1
|
|
var eMax = (1 << eLen) - 1
|
|
var eBias = eMax >> 1
|
|
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
|
|
var i = isLE ? 0 : (nBytes - 1)
|
|
var d = isLE ? 1 : -1
|
|
var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
|
|
|
|
value = Math.abs(value)
|
|
|
|
if (isNaN(value) || value === Infinity) {
|
|
m = isNaN(value) ? 1 : 0
|
|
e = eMax
|
|
} else {
|
|
e = Math.floor(Math.log(value) / Math.LN2)
|
|
if (value * (c = Math.pow(2, -e)) < 1) {
|
|
e--
|
|
c *= 2
|
|
}
|
|
if (e + eBias >= 1) {
|
|
value += rt / c
|
|
} else {
|
|
value += rt * Math.pow(2, 1 - eBias)
|
|
}
|
|
if (value * c >= 2) {
|
|
e++
|
|
c /= 2
|
|
}
|
|
|
|
if (e + eBias >= eMax) {
|
|
m = 0
|
|
e = eMax
|
|
} else if (e + eBias >= 1) {
|
|
m = ((value * c) - 1) * Math.pow(2, mLen)
|
|
e = e + eBias
|
|
} else {
|
|
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
|
|
e = 0
|
|
}
|
|
}
|
|
|
|
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
|
|
|
|
e = (e << mLen) | m
|
|
eLen += mLen
|
|
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
|
|
|
|
buffer[offset + i - d] |= s * 128
|
|
}
|
|
|
|
},{}],48:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
function invert(hash) {
|
|
var result = {}
|
|
for(var i in hash) {
|
|
if(hash.hasOwnProperty(i)) {
|
|
result[hash[i]] = i
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
module.exports = invert
|
|
},{}],49:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
function iota(n) {
|
|
var result = new Array(n)
|
|
for(var i=0; i<n; ++i) {
|
|
result[i] = i
|
|
}
|
|
return result
|
|
}
|
|
|
|
module.exports = iota
|
|
},{}],50:[function(require,module,exports){
|
|
/*!
|
|
* Determine if an object is a Buffer
|
|
*
|
|
* @author Feross Aboukhadijeh <https://feross.org>
|
|
* @license MIT
|
|
*/
|
|
|
|
// The _isBuffer check is for Safari 5-7 support, because it's missing
|
|
// Object.prototype.constructor. Remove this eventually
|
|
module.exports = function (obj) {
|
|
return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
|
|
}
|
|
|
|
function isBuffer (obj) {
|
|
return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
|
|
}
|
|
|
|
// For Node v0.10 support. Remove this eventually.
|
|
function isSlowBuffer (obj) {
|
|
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
|
|
}
|
|
|
|
},{}],51:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
var compile = require("cwise-compiler")
|
|
|
|
var EmptyProc = {
|
|
body: "",
|
|
args: [],
|
|
thisVars: [],
|
|
localVars: []
|
|
}
|
|
|
|
function fixup(x) {
|
|
if(!x) {
|
|
return EmptyProc
|
|
}
|
|
for(var i=0; i<x.args.length; ++i) {
|
|
var a = x.args[i]
|
|
if(i === 0) {
|
|
x.args[i] = {name: a, lvalue:true, rvalue: !!x.rvalue, count:x.count||1 }
|
|
} else {
|
|
x.args[i] = {name: a, lvalue:false, rvalue:true, count: 1}
|
|
}
|
|
}
|
|
if(!x.thisVars) {
|
|
x.thisVars = []
|
|
}
|
|
if(!x.localVars) {
|
|
x.localVars = []
|
|
}
|
|
return x
|
|
}
|
|
|
|
function pcompile(user_args) {
|
|
return compile({
|
|
args: user_args.args,
|
|
pre: fixup(user_args.pre),
|
|
body: fixup(user_args.body),
|
|
post: fixup(user_args.proc),
|
|
funcName: user_args.funcName
|
|
})
|
|
}
|
|
|
|
function makeOp(user_args) {
|
|
var args = []
|
|
for(var i=0; i<user_args.args.length; ++i) {
|
|
args.push("a"+i)
|
|
}
|
|
var wrapper = new Function("P", [
|
|
"return function ", user_args.funcName, "_ndarrayops(", args.join(","), ") {P(", args.join(","), ");return a0}"
|
|
].join(""))
|
|
return wrapper(pcompile(user_args))
|
|
}
|
|
|
|
var assign_ops = {
|
|
add: "+",
|
|
sub: "-",
|
|
mul: "*",
|
|
div: "/",
|
|
mod: "%",
|
|
band: "&",
|
|
bor: "|",
|
|
bxor: "^",
|
|
lshift: "<<",
|
|
rshift: ">>",
|
|
rrshift: ">>>"
|
|
}
|
|
;(function(){
|
|
for(var id in assign_ops) {
|
|
var op = assign_ops[id]
|
|
exports[id] = makeOp({
|
|
args: ["array","array","array"],
|
|
body: {args:["a","b","c"],
|
|
body: "a=b"+op+"c"},
|
|
funcName: id
|
|
})
|
|
exports[id+"eq"] = makeOp({
|
|
args: ["array","array"],
|
|
body: {args:["a","b"],
|
|
body:"a"+op+"=b"},
|
|
rvalue: true,
|
|
funcName: id+"eq"
|
|
})
|
|
exports[id+"s"] = makeOp({
|
|
args: ["array", "array", "scalar"],
|
|
body: {args:["a","b","s"],
|
|
body:"a=b"+op+"s"},
|
|
funcName: id+"s"
|
|
})
|
|
exports[id+"seq"] = makeOp({
|
|
args: ["array","scalar"],
|
|
body: {args:["a","s"],
|
|
body:"a"+op+"=s"},
|
|
rvalue: true,
|
|
funcName: id+"seq"
|
|
})
|
|
}
|
|
})();
|
|
|
|
var unary_ops = {
|
|
not: "!",
|
|
bnot: "~",
|
|
neg: "-",
|
|
recip: "1.0/"
|
|
}
|
|
;(function(){
|
|
for(var id in unary_ops) {
|
|
var op = unary_ops[id]
|
|
exports[id] = makeOp({
|
|
args: ["array", "array"],
|
|
body: {args:["a","b"],
|
|
body:"a="+op+"b"},
|
|
funcName: id
|
|
})
|
|
exports[id+"eq"] = makeOp({
|
|
args: ["array"],
|
|
body: {args:["a"],
|
|
body:"a="+op+"a"},
|
|
rvalue: true,
|
|
count: 2,
|
|
funcName: id+"eq"
|
|
})
|
|
}
|
|
})();
|
|
|
|
var binary_ops = {
|
|
and: "&&",
|
|
or: "||",
|
|
eq: "===",
|
|
neq: "!==",
|
|
lt: "<",
|
|
gt: ">",
|
|
leq: "<=",
|
|
geq: ">="
|
|
}
|
|
;(function() {
|
|
for(var id in binary_ops) {
|
|
var op = binary_ops[id]
|
|
exports[id] = makeOp({
|
|
args: ["array","array","array"],
|
|
body: {args:["a", "b", "c"],
|
|
body:"a=b"+op+"c"},
|
|
funcName: id
|
|
})
|
|
exports[id+"s"] = makeOp({
|
|
args: ["array","array","scalar"],
|
|
body: {args:["a", "b", "s"],
|
|
body:"a=b"+op+"s"},
|
|
funcName: id+"s"
|
|
})
|
|
exports[id+"eq"] = makeOp({
|
|
args: ["array", "array"],
|
|
body: {args:["a", "b"],
|
|
body:"a=a"+op+"b"},
|
|
rvalue:true,
|
|
count:2,
|
|
funcName: id+"eq"
|
|
})
|
|
exports[id+"seq"] = makeOp({
|
|
args: ["array", "scalar"],
|
|
body: {args:["a","s"],
|
|
body:"a=a"+op+"s"},
|
|
rvalue:true,
|
|
count:2,
|
|
funcName: id+"seq"
|
|
})
|
|
}
|
|
})();
|
|
|
|
var math_unary = [
|
|
"abs",
|
|
"acos",
|
|
"asin",
|
|
"atan",
|
|
"ceil",
|
|
"cos",
|
|
"exp",
|
|
"floor",
|
|
"log",
|
|
"round",
|
|
"sin",
|
|
"sqrt",
|
|
"tan"
|
|
]
|
|
;(function() {
|
|
for(var i=0; i<math_unary.length; ++i) {
|
|
var f = math_unary[i]
|
|
exports[f] = makeOp({
|
|
args: ["array", "array"],
|
|
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
|
|
body: {args:["a","b"], body:"a=this_f(b)", thisVars:["this_f"]},
|
|
funcName: f
|
|
})
|
|
exports[f+"eq"] = makeOp({
|
|
args: ["array"],
|
|
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
|
|
body: {args: ["a"], body:"a=this_f(a)", thisVars:["this_f"]},
|
|
rvalue: true,
|
|
count: 2,
|
|
funcName: f+"eq"
|
|
})
|
|
}
|
|
})();
|
|
|
|
var math_comm = [
|
|
"max",
|
|
"min",
|
|
"atan2",
|
|
"pow"
|
|
]
|
|
;(function(){
|
|
for(var i=0; i<math_comm.length; ++i) {
|
|
var f= math_comm[i]
|
|
exports[f] = makeOp({
|
|
args:["array", "array", "array"],
|
|
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
|
|
body: {args:["a","b","c"], body:"a=this_f(b,c)", thisVars:["this_f"]},
|
|
funcName: f
|
|
})
|
|
exports[f+"s"] = makeOp({
|
|
args:["array", "array", "scalar"],
|
|
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
|
|
body: {args:["a","b","c"], body:"a=this_f(b,c)", thisVars:["this_f"]},
|
|
funcName: f+"s"
|
|
})
|
|
exports[f+"eq"] = makeOp({ args:["array", "array"],
|
|
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
|
|
body: {args:["a","b"], body:"a=this_f(a,b)", thisVars:["this_f"]},
|
|
rvalue: true,
|
|
count: 2,
|
|
funcName: f+"eq"
|
|
})
|
|
exports[f+"seq"] = makeOp({ args:["array", "scalar"],
|
|
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
|
|
body: {args:["a","b"], body:"a=this_f(a,b)", thisVars:["this_f"]},
|
|
rvalue:true,
|
|
count:2,
|
|
funcName: f+"seq"
|
|
})
|
|
}
|
|
})();
|
|
|
|
var math_noncomm = [
|
|
"atan2",
|
|
"pow"
|
|
]
|
|
;(function(){
|
|
for(var i=0; i<math_noncomm.length; ++i) {
|
|
var f= math_noncomm[i]
|
|
exports[f+"op"] = makeOp({
|
|
args:["array", "array", "array"],
|
|
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
|
|
body: {args:["a","b","c"], body:"a=this_f(c,b)", thisVars:["this_f"]},
|
|
funcName: f+"op"
|
|
})
|
|
exports[f+"ops"] = makeOp({
|
|
args:["array", "array", "scalar"],
|
|
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
|
|
body: {args:["a","b","c"], body:"a=this_f(c,b)", thisVars:["this_f"]},
|
|
funcName: f+"ops"
|
|
})
|
|
exports[f+"opeq"] = makeOp({ args:["array", "array"],
|
|
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
|
|
body: {args:["a","b"], body:"a=this_f(b,a)", thisVars:["this_f"]},
|
|
rvalue: true,
|
|
count: 2,
|
|
funcName: f+"opeq"
|
|
})
|
|
exports[f+"opseq"] = makeOp({ args:["array", "scalar"],
|
|
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
|
|
body: {args:["a","b"], body:"a=this_f(b,a)", thisVars:["this_f"]},
|
|
rvalue:true,
|
|
count:2,
|
|
funcName: f+"opseq"
|
|
})
|
|
}
|
|
})();
|
|
|
|
exports.any = compile({
|
|
args:["array"],
|
|
pre: EmptyProc,
|
|
body: {args:[{name:"a", lvalue:false, rvalue:true, count:1}], body: "if(a){return true}", localVars: [], thisVars: []},
|
|
post: {args:[], localVars:[], thisVars:[], body:"return false"},
|
|
funcName: "any"
|
|
})
|
|
|
|
exports.all = compile({
|
|
args:["array"],
|
|
pre: EmptyProc,
|
|
body: {args:[{name:"x", lvalue:false, rvalue:true, count:1}], body: "if(!x){return false}", localVars: [], thisVars: []},
|
|
post: {args:[], localVars:[], thisVars:[], body:"return true"},
|
|
funcName: "all"
|
|
})
|
|
|
|
exports.sum = compile({
|
|
args:["array"],
|
|
pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
|
|
body: {args:[{name:"a", lvalue:false, rvalue:true, count:1}], body: "this_s+=a", localVars: [], thisVars: ["this_s"]},
|
|
post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
|
|
funcName: "sum"
|
|
})
|
|
|
|
exports.prod = compile({
|
|
args:["array"],
|
|
pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=1"},
|
|
body: {args:[{name:"a", lvalue:false, rvalue:true, count:1}], body: "this_s*=a", localVars: [], thisVars: ["this_s"]},
|
|
post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
|
|
funcName: "prod"
|
|
})
|
|
|
|
exports.norm2squared = compile({
|
|
args:["array"],
|
|
pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
|
|
body: {args:[{name:"a", lvalue:false, rvalue:true, count:2}], body: "this_s+=a*a", localVars: [], thisVars: ["this_s"]},
|
|
post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
|
|
funcName: "norm2squared"
|
|
})
|
|
|
|
exports.norm2 = compile({
|
|
args:["array"],
|
|
pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
|
|
body: {args:[{name:"a", lvalue:false, rvalue:true, count:2}], body: "this_s+=a*a", localVars: [], thisVars: ["this_s"]},
|
|
post: {args:[], localVars:[], thisVars:["this_s"], body:"return Math.sqrt(this_s)"},
|
|
funcName: "norm2"
|
|
})
|
|
|
|
|
|
exports.norminf = compile({
|
|
args:["array"],
|
|
pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
|
|
body: {args:[{name:"a", lvalue:false, rvalue:true, count:4}], body:"if(-a>this_s){this_s=-a}else if(a>this_s){this_s=a}", localVars: [], thisVars: ["this_s"]},
|
|
post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
|
|
funcName: "norminf"
|
|
})
|
|
|
|
exports.norm1 = compile({
|
|
args:["array"],
|
|
pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
|
|
body: {args:[{name:"a", lvalue:false, rvalue:true, count:3}], body: "this_s+=a<0?-a:a", localVars: [], thisVars: ["this_s"]},
|
|
post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
|
|
funcName: "norm1"
|
|
})
|
|
|
|
exports.sup = compile({
|
|
args: [ "array" ],
|
|
pre:
|
|
{ body: "this_h=-Infinity",
|
|
args: [],
|
|
thisVars: [ "this_h" ],
|
|
localVars: [] },
|
|
body:
|
|
{ body: "if(_inline_1_arg0_>this_h)this_h=_inline_1_arg0_",
|
|
args: [{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":2} ],
|
|
thisVars: [ "this_h" ],
|
|
localVars: [] },
|
|
post:
|
|
{ body: "return this_h",
|
|
args: [],
|
|
thisVars: [ "this_h" ],
|
|
localVars: [] }
|
|
})
|
|
|
|
exports.inf = compile({
|
|
args: [ "array" ],
|
|
pre:
|
|
{ body: "this_h=Infinity",
|
|
args: [],
|
|
thisVars: [ "this_h" ],
|
|
localVars: [] },
|
|
body:
|
|
{ body: "if(_inline_1_arg0_<this_h)this_h=_inline_1_arg0_",
|
|
args: [{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":2} ],
|
|
thisVars: [ "this_h" ],
|
|
localVars: [] },
|
|
post:
|
|
{ body: "return this_h",
|
|
args: [],
|
|
thisVars: [ "this_h" ],
|
|
localVars: [] }
|
|
})
|
|
|
|
exports.argmin = compile({
|
|
args:["index","array","shape"],
|
|
pre:{
|
|
body:"{this_v=Infinity;this_i=_inline_0_arg2_.slice(0)}",
|
|
args:[
|
|
{name:"_inline_0_arg0_",lvalue:false,rvalue:false,count:0},
|
|
{name:"_inline_0_arg1_",lvalue:false,rvalue:false,count:0},
|
|
{name:"_inline_0_arg2_",lvalue:false,rvalue:true,count:1}
|
|
],
|
|
thisVars:["this_i","this_v"],
|
|
localVars:[]},
|
|
body:{
|
|
body:"{if(_inline_1_arg1_<this_v){this_v=_inline_1_arg1_;for(var _inline_1_k=0;_inline_1_k<_inline_1_arg0_.length;++_inline_1_k){this_i[_inline_1_k]=_inline_1_arg0_[_inline_1_k]}}}",
|
|
args:[
|
|
{name:"_inline_1_arg0_",lvalue:false,rvalue:true,count:2},
|
|
{name:"_inline_1_arg1_",lvalue:false,rvalue:true,count:2}],
|
|
thisVars:["this_i","this_v"],
|
|
localVars:["_inline_1_k"]},
|
|
post:{
|
|
body:"{return this_i}",
|
|
args:[],
|
|
thisVars:["this_i"],
|
|
localVars:[]}
|
|
})
|
|
|
|
exports.argmax = compile({
|
|
args:["index","array","shape"],
|
|
pre:{
|
|
body:"{this_v=-Infinity;this_i=_inline_0_arg2_.slice(0)}",
|
|
args:[
|
|
{name:"_inline_0_arg0_",lvalue:false,rvalue:false,count:0},
|
|
{name:"_inline_0_arg1_",lvalue:false,rvalue:false,count:0},
|
|
{name:"_inline_0_arg2_",lvalue:false,rvalue:true,count:1}
|
|
],
|
|
thisVars:["this_i","this_v"],
|
|
localVars:[]},
|
|
body:{
|
|
body:"{if(_inline_1_arg1_>this_v){this_v=_inline_1_arg1_;for(var _inline_1_k=0;_inline_1_k<_inline_1_arg0_.length;++_inline_1_k){this_i[_inline_1_k]=_inline_1_arg0_[_inline_1_k]}}}",
|
|
args:[
|
|
{name:"_inline_1_arg0_",lvalue:false,rvalue:true,count:2},
|
|
{name:"_inline_1_arg1_",lvalue:false,rvalue:true,count:2}],
|
|
thisVars:["this_i","this_v"],
|
|
localVars:["_inline_1_k"]},
|
|
post:{
|
|
body:"{return this_i}",
|
|
args:[],
|
|
thisVars:["this_i"],
|
|
localVars:[]}
|
|
})
|
|
|
|
exports.random = makeOp({
|
|
args: ["array"],
|
|
pre: {args:[], body:"this_f=Math.random", thisVars:["this_f"]},
|
|
body: {args: ["a"], body:"a=this_f()", thisVars:["this_f"]},
|
|
funcName: "random"
|
|
})
|
|
|
|
exports.assign = makeOp({
|
|
args:["array", "array"],
|
|
body: {args:["a", "b"], body:"a=b"},
|
|
funcName: "assign" })
|
|
|
|
exports.assigns = makeOp({
|
|
args:["array", "scalar"],
|
|
body: {args:["a", "b"], body:"a=b"},
|
|
funcName: "assigns" })
|
|
|
|
|
|
exports.equals = compile({
|
|
args:["array", "array"],
|
|
pre: EmptyProc,
|
|
body: {args:[{name:"x", lvalue:false, rvalue:true, count:1},
|
|
{name:"y", lvalue:false, rvalue:true, count:1}],
|
|
body: "if(x!==y){return false}",
|
|
localVars: [],
|
|
thisVars: []},
|
|
post: {args:[], localVars:[], thisVars:[], body:"return true"},
|
|
funcName: "equals"
|
|
})
|
|
|
|
|
|
|
|
},{"cwise-compiler":52}],52:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
var createThunk = require("./lib/thunk.js")
|
|
|
|
function Procedure() {
|
|
this.argTypes = []
|
|
this.shimArgs = []
|
|
this.arrayArgs = []
|
|
this.arrayBlockIndices = []
|
|
this.scalarArgs = []
|
|
this.offsetArgs = []
|
|
this.offsetArgIndex = []
|
|
this.indexArgs = []
|
|
this.shapeArgs = []
|
|
this.funcName = ""
|
|
this.pre = null
|
|
this.body = null
|
|
this.post = null
|
|
this.debug = false
|
|
}
|
|
|
|
function compileCwise(user_args) {
|
|
//Create procedure
|
|
var proc = new Procedure()
|
|
|
|
//Parse blocks
|
|
proc.pre = user_args.pre
|
|
proc.body = user_args.body
|
|
proc.post = user_args.post
|
|
|
|
//Parse arguments
|
|
var proc_args = user_args.args.slice(0)
|
|
proc.argTypes = proc_args
|
|
for(var i=0; i<proc_args.length; ++i) {
|
|
var arg_type = proc_args[i]
|
|
if(arg_type === "array" || (typeof arg_type === "object" && arg_type.blockIndices)) {
|
|
proc.argTypes[i] = "array"
|
|
proc.arrayArgs.push(i)
|
|
proc.arrayBlockIndices.push(arg_type.blockIndices ? arg_type.blockIndices : 0)
|
|
proc.shimArgs.push("array" + i)
|
|
if(i < proc.pre.args.length && proc.pre.args[i].count>0) {
|
|
throw new Error("cwise: pre() block may not reference array args")
|
|
}
|
|
if(i < proc.post.args.length && proc.post.args[i].count>0) {
|
|
throw new Error("cwise: post() block may not reference array args")
|
|
}
|
|
} else if(arg_type === "scalar") {
|
|
proc.scalarArgs.push(i)
|
|
proc.shimArgs.push("scalar" + i)
|
|
} else if(arg_type === "index") {
|
|
proc.indexArgs.push(i)
|
|
if(i < proc.pre.args.length && proc.pre.args[i].count > 0) {
|
|
throw new Error("cwise: pre() block may not reference array index")
|
|
}
|
|
if(i < proc.body.args.length && proc.body.args[i].lvalue) {
|
|
throw new Error("cwise: body() block may not write to array index")
|
|
}
|
|
if(i < proc.post.args.length && proc.post.args[i].count > 0) {
|
|
throw new Error("cwise: post() block may not reference array index")
|
|
}
|
|
} else if(arg_type === "shape") {
|
|
proc.shapeArgs.push(i)
|
|
if(i < proc.pre.args.length && proc.pre.args[i].lvalue) {
|
|
throw new Error("cwise: pre() block may not write to array shape")
|
|
}
|
|
if(i < proc.body.args.length && proc.body.args[i].lvalue) {
|
|
throw new Error("cwise: body() block may not write to array shape")
|
|
}
|
|
if(i < proc.post.args.length && proc.post.args[i].lvalue) {
|
|
throw new Error("cwise: post() block may not write to array shape")
|
|
}
|
|
} else if(typeof arg_type === "object" && arg_type.offset) {
|
|
proc.argTypes[i] = "offset"
|
|
proc.offsetArgs.push({ array: arg_type.array, offset:arg_type.offset })
|
|
proc.offsetArgIndex.push(i)
|
|
} else {
|
|
throw new Error("cwise: Unknown argument type " + proc_args[i])
|
|
}
|
|
}
|
|
|
|
//Make sure at least one array argument was specified
|
|
if(proc.arrayArgs.length <= 0) {
|
|
throw new Error("cwise: No array arguments specified")
|
|
}
|
|
|
|
//Make sure arguments are correct
|
|
if(proc.pre.args.length > proc_args.length) {
|
|
throw new Error("cwise: Too many arguments in pre() block")
|
|
}
|
|
if(proc.body.args.length > proc_args.length) {
|
|
throw new Error("cwise: Too many arguments in body() block")
|
|
}
|
|
if(proc.post.args.length > proc_args.length) {
|
|
throw new Error("cwise: Too many arguments in post() block")
|
|
}
|
|
|
|
//Check debug flag
|
|
proc.debug = !!user_args.printCode || !!user_args.debug
|
|
|
|
//Retrieve name
|
|
proc.funcName = user_args.funcName || "cwise"
|
|
|
|
//Read in block size
|
|
proc.blockSize = user_args.blockSize || 64
|
|
|
|
return createThunk(proc)
|
|
}
|
|
|
|
module.exports = compileCwise
|
|
|
|
},{"./lib/thunk.js":54}],53:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
var uniq = require("uniq")
|
|
|
|
// This function generates very simple loops analogous to how you typically traverse arrays (the outermost loop corresponds to the slowest changing index, the innermost loop to the fastest changing index)
|
|
// TODO: If two arrays have the same strides (and offsets) there is potential for decreasing the number of "pointers" and related variables. The drawback is that the type signature would become more specific and that there would thus be less potential for caching, but it might still be worth it, especially when dealing with large numbers of arguments.
|
|
function innerFill(order, proc, body) {
|
|
var dimension = order.length
|
|
, nargs = proc.arrayArgs.length
|
|
, has_index = proc.indexArgs.length>0
|
|
, code = []
|
|
, vars = []
|
|
, idx=0, pidx=0, i, j
|
|
for(i=0; i<dimension; ++i) { // Iteration variables
|
|
vars.push(["i",i,"=0"].join(""))
|
|
}
|
|
//Compute scan deltas
|
|
for(j=0; j<nargs; ++j) {
|
|
for(i=0; i<dimension; ++i) {
|
|
pidx = idx
|
|
idx = order[i]
|
|
if(i === 0) { // The innermost/fastest dimension's delta is simply its stride
|
|
vars.push(["d",j,"s",i,"=t",j,"p",idx].join(""))
|
|
} else { // For other dimensions the delta is basically the stride minus something which essentially "rewinds" the previous (more inner) dimension
|
|
vars.push(["d",j,"s",i,"=(t",j,"p",idx,"-s",pidx,"*t",j,"p",pidx,")"].join(""))
|
|
}
|
|
}
|
|
}
|
|
if (vars.length > 0) {
|
|
code.push("var " + vars.join(","))
|
|
}
|
|
//Scan loop
|
|
for(i=dimension-1; i>=0; --i) { // Start at largest stride and work your way inwards
|
|
idx = order[i]
|
|
code.push(["for(i",i,"=0;i",i,"<s",idx,";++i",i,"){"].join(""))
|
|
}
|
|
//Push body of inner loop
|
|
code.push(body)
|
|
//Advance scan pointers
|
|
for(i=0; i<dimension; ++i) {
|
|
pidx = idx
|
|
idx = order[i]
|
|
for(j=0; j<nargs; ++j) {
|
|
code.push(["p",j,"+=d",j,"s",i].join(""))
|
|
}
|
|
if(has_index) {
|
|
if(i > 0) {
|
|
code.push(["index[",pidx,"]-=s",pidx].join(""))
|
|
}
|
|
code.push(["++index[",idx,"]"].join(""))
|
|
}
|
|
code.push("}")
|
|
}
|
|
return code.join("\n")
|
|
}
|
|
|
|
// Generate "outer" loops that loop over blocks of data, applying "inner" loops to the blocks by manipulating the local variables in such a way that the inner loop only "sees" the current block.
|
|
// TODO: If this is used, then the previous declaration (done by generateCwiseOp) of s* is essentially unnecessary.
|
|
// I believe the s* are not used elsewhere (in particular, I don't think they're used in the pre/post parts and "shape" is defined independently), so it would be possible to make defining the s* dependent on what loop method is being used.
|
|
function outerFill(matched, order, proc, body) {
|
|
var dimension = order.length
|
|
, nargs = proc.arrayArgs.length
|
|
, blockSize = proc.blockSize
|
|
, has_index = proc.indexArgs.length > 0
|
|
, code = []
|
|
for(var i=0; i<nargs; ++i) {
|
|
code.push(["var offset",i,"=p",i].join(""))
|
|
}
|
|
//Generate loops for unmatched dimensions
|
|
// The order in which these dimensions are traversed is fairly arbitrary (from small stride to large stride, for the first argument)
|
|
// TODO: It would be nice if the order in which these loops are placed would also be somehow "optimal" (at the very least we should check that it really doesn't hurt us if they're not).
|
|
for(var i=matched; i<dimension; ++i) {
|
|
code.push(["for(var j"+i+"=SS[", order[i], "]|0;j", i, ">0;){"].join("")) // Iterate back to front
|
|
code.push(["if(j",i,"<",blockSize,"){"].join("")) // Either decrease j by blockSize (s = blockSize), or set it to zero (after setting s = j).
|
|
code.push(["s",order[i],"=j",i].join(""))
|
|
code.push(["j",i,"=0"].join(""))
|
|
code.push(["}else{s",order[i],"=",blockSize].join(""))
|
|
code.push(["j",i,"-=",blockSize,"}"].join(""))
|
|
if(has_index) {
|
|
code.push(["index[",order[i],"]=j",i].join(""))
|
|
}
|
|
}
|
|
for(var i=0; i<nargs; ++i) {
|
|
var indexStr = ["offset"+i]
|
|
for(var j=matched; j<dimension; ++j) {
|
|
indexStr.push(["j",j,"*t",i,"p",order[j]].join(""))
|
|
}
|
|
code.push(["p",i,"=(",indexStr.join("+"),")"].join(""))
|
|
}
|
|
code.push(innerFill(order, proc, body))
|
|
for(var i=matched; i<dimension; ++i) {
|
|
code.push("}")
|
|
}
|
|
return code.join("\n")
|
|
}
|
|
|
|
//Count the number of compatible inner orders
|
|
// This is the length of the longest common prefix of the arrays in orders.
|
|
// Each array in orders lists the dimensions of the correspond ndarray in order of increasing stride.
|
|
// This is thus the maximum number of dimensions that can be efficiently traversed by simple nested loops for all arrays.
|
|
function countMatches(orders) {
|
|
var matched = 0, dimension = orders[0].length
|
|
while(matched < dimension) {
|
|
for(var j=1; j<orders.length; ++j) {
|
|
if(orders[j][matched] !== orders[0][matched]) {
|
|
return matched
|
|
}
|
|
}
|
|
++matched
|
|
}
|
|
return matched
|
|
}
|
|
|
|
//Processes a block according to the given data types
|
|
// Replaces variable names by different ones, either "local" ones (that are then ferried in and out of the given array) or ones matching the arguments that the function performing the ultimate loop will accept.
|
|
function processBlock(block, proc, dtypes) {
|
|
var code = block.body
|
|
var pre = []
|
|
var post = []
|
|
for(var i=0; i<block.args.length; ++i) {
|
|
var carg = block.args[i]
|
|
if(carg.count <= 0) {
|
|
continue
|
|
}
|
|
var re = new RegExp(carg.name, "g")
|
|
var ptrStr = ""
|
|
var arrNum = proc.arrayArgs.indexOf(i)
|
|
switch(proc.argTypes[i]) {
|
|
case "offset":
|
|
var offArgIndex = proc.offsetArgIndex.indexOf(i)
|
|
var offArg = proc.offsetArgs[offArgIndex]
|
|
arrNum = offArg.array
|
|
ptrStr = "+q" + offArgIndex // Adds offset to the "pointer" in the array
|
|
case "array":
|
|
ptrStr = "p" + arrNum + ptrStr
|
|
var localStr = "l" + i
|
|
var arrStr = "a" + arrNum
|
|
if (proc.arrayBlockIndices[arrNum] === 0) { // Argument to body is just a single value from this array
|
|
if(carg.count === 1) { // Argument/array used only once(?)
|
|
if(dtypes[arrNum] === "generic") {
|
|
if(carg.lvalue) {
|
|
pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join("")) // Is this necessary if the argument is ONLY used as an lvalue? (keep in mind that we can have a += something, so we would actually need to check carg.rvalue)
|
|
code = code.replace(re, localStr)
|
|
post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join(""))
|
|
} else {
|
|
code = code.replace(re, [arrStr, ".get(", ptrStr, ")"].join(""))
|
|
}
|
|
} else {
|
|
code = code.replace(re, [arrStr, "[", ptrStr, "]"].join(""))
|
|
}
|
|
} else if(dtypes[arrNum] === "generic") {
|
|
pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join("")) // TODO: Could we optimize by checking for carg.rvalue?
|
|
code = code.replace(re, localStr)
|
|
if(carg.lvalue) {
|
|
post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join(""))
|
|
}
|
|
} else {
|
|
pre.push(["var ", localStr, "=", arrStr, "[", ptrStr, "]"].join("")) // TODO: Could we optimize by checking for carg.rvalue?
|
|
code = code.replace(re, localStr)
|
|
if(carg.lvalue) {
|
|
post.push([arrStr, "[", ptrStr, "]=", localStr].join(""))
|
|
}
|
|
}
|
|
} else { // Argument to body is a "block"
|
|
var reStrArr = [carg.name], ptrStrArr = [ptrStr]
|
|
for(var j=0; j<Math.abs(proc.arrayBlockIndices[arrNum]); j++) {
|
|
reStrArr.push("\\s*\\[([^\\]]+)\\]")
|
|
ptrStrArr.push("$" + (j+1) + "*t" + arrNum + "b" + j) // Matched index times stride
|
|
}
|
|
re = new RegExp(reStrArr.join(""), "g")
|
|
ptrStr = ptrStrArr.join("+")
|
|
if(dtypes[arrNum] === "generic") {
|
|
/*if(carg.lvalue) {
|
|
pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join("")) // Is this necessary if the argument is ONLY used as an lvalue? (keep in mind that we can have a += something, so we would actually need to check carg.rvalue)
|
|
code = code.replace(re, localStr)
|
|
post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join(""))
|
|
} else {
|
|
code = code.replace(re, [arrStr, ".get(", ptrStr, ")"].join(""))
|
|
}*/
|
|
throw new Error("cwise: Generic arrays not supported in combination with blocks!")
|
|
} else {
|
|
// This does not produce any local variables, even if variables are used multiple times. It would be possible to do so, but it would complicate things quite a bit.
|
|
code = code.replace(re, [arrStr, "[", ptrStr, "]"].join(""))
|
|
}
|
|
}
|
|
break
|
|
case "scalar":
|
|
code = code.replace(re, "Y" + proc.scalarArgs.indexOf(i))
|
|
break
|
|
case "index":
|
|
code = code.replace(re, "index")
|
|
break
|
|
case "shape":
|
|
code = code.replace(re, "shape")
|
|
break
|
|
}
|
|
}
|
|
return [pre.join("\n"), code, post.join("\n")].join("\n").trim()
|
|
}
|
|
|
|
function typeSummary(dtypes) {
|
|
var summary = new Array(dtypes.length)
|
|
var allEqual = true
|
|
for(var i=0; i<dtypes.length; ++i) {
|
|
var t = dtypes[i]
|
|
var digits = t.match(/\d+/)
|
|
if(!digits) {
|
|
digits = ""
|
|
} else {
|
|
digits = digits[0]
|
|
}
|
|
if(t.charAt(0) === 0) {
|
|
summary[i] = "u" + t.charAt(1) + digits
|
|
} else {
|
|
summary[i] = t.charAt(0) + digits
|
|
}
|
|
if(i > 0) {
|
|
allEqual = allEqual && summary[i] === summary[i-1]
|
|
}
|
|
}
|
|
if(allEqual) {
|
|
return summary[0]
|
|
}
|
|
return summary.join("")
|
|
}
|
|
|
|
//Generates a cwise operator
|
|
function generateCWiseOp(proc, typesig) {
|
|
|
|
//Compute dimension
|
|
// Arrays get put first in typesig, and there are two entries per array (dtype and order), so this gets the number of dimensions in the first array arg.
|
|
var dimension = (typesig[1].length - Math.abs(proc.arrayBlockIndices[0]))|0
|
|
var orders = new Array(proc.arrayArgs.length)
|
|
var dtypes = new Array(proc.arrayArgs.length)
|
|
for(var i=0; i<proc.arrayArgs.length; ++i) {
|
|
dtypes[i] = typesig[2*i]
|
|
orders[i] = typesig[2*i+1]
|
|
}
|
|
|
|
//Determine where block and loop indices start and end
|
|
var blockBegin = [], blockEnd = [] // These indices are exposed as blocks
|
|
var loopBegin = [], loopEnd = [] // These indices are iterated over
|
|
var loopOrders = [] // orders restricted to the loop indices
|
|
for(var i=0; i<proc.arrayArgs.length; ++i) {
|
|
if (proc.arrayBlockIndices[i]<0) {
|
|
loopBegin.push(0)
|
|
loopEnd.push(dimension)
|
|
blockBegin.push(dimension)
|
|
blockEnd.push(dimension+proc.arrayBlockIndices[i])
|
|
} else {
|
|
loopBegin.push(proc.arrayBlockIndices[i]) // Non-negative
|
|
loopEnd.push(proc.arrayBlockIndices[i]+dimension)
|
|
blockBegin.push(0)
|
|
blockEnd.push(proc.arrayBlockIndices[i])
|
|
}
|
|
var newOrder = []
|
|
for(var j=0; j<orders[i].length; j++) {
|
|
if (loopBegin[i]<=orders[i][j] && orders[i][j]<loopEnd[i]) {
|
|
newOrder.push(orders[i][j]-loopBegin[i]) // If this is a loop index, put it in newOrder, subtracting loopBegin, to make sure that all loopOrders are using a common set of indices.
|
|
}
|
|
}
|
|
loopOrders.push(newOrder)
|
|
}
|
|
|
|
//First create arguments for procedure
|
|
var arglist = ["SS"] // SS is the overall shape over which we iterate
|
|
var code = ["'use strict'"]
|
|
var vars = []
|
|
|
|
for(var j=0; j<dimension; ++j) {
|
|
vars.push(["s", j, "=SS[", j, "]"].join("")) // The limits for each dimension.
|
|
}
|
|
for(var i=0; i<proc.arrayArgs.length; ++i) {
|
|
arglist.push("a"+i) // Actual data array
|
|
arglist.push("t"+i) // Strides
|
|
arglist.push("p"+i) // Offset in the array at which the data starts (also used for iterating over the data)
|
|
|
|
for(var j=0; j<dimension; ++j) { // Unpack the strides into vars for looping
|
|
vars.push(["t",i,"p",j,"=t",i,"[",loopBegin[i]+j,"]"].join(""))
|
|
}
|
|
|
|
for(var j=0; j<Math.abs(proc.arrayBlockIndices[i]); ++j) { // Unpack the strides into vars for block iteration
|
|
vars.push(["t",i,"b",j,"=t",i,"[",blockBegin[i]+j,"]"].join(""))
|
|
}
|
|
}
|
|
for(var i=0; i<proc.scalarArgs.length; ++i) {
|
|
arglist.push("Y" + i)
|
|
}
|
|
if(proc.shapeArgs.length > 0) {
|
|
vars.push("shape=SS.slice(0)") // Makes the shape over which we iterate available to the user defined functions (so you can use width/height for example)
|
|
}
|
|
if(proc.indexArgs.length > 0) {
|
|
// Prepare an array to keep track of the (logical) indices, initialized to dimension zeroes.
|
|
var zeros = new Array(dimension)
|
|
for(var i=0; i<dimension; ++i) {
|
|
zeros[i] = "0"
|
|
}
|
|
vars.push(["index=[", zeros.join(","), "]"].join(""))
|
|
}
|
|
for(var i=0; i<proc.offsetArgs.length; ++i) { // Offset arguments used for stencil operations
|
|
var off_arg = proc.offsetArgs[i]
|
|
var init_string = []
|
|
for(var j=0; j<off_arg.offset.length; ++j) {
|
|
if(off_arg.offset[j] === 0) {
|
|
continue
|
|
} else if(off_arg.offset[j] === 1) {
|
|
init_string.push(["t", off_arg.array, "p", j].join(""))
|
|
} else {
|
|
init_string.push([off_arg.offset[j], "*t", off_arg.array, "p", j].join(""))
|
|
}
|
|
}
|
|
if(init_string.length === 0) {
|
|
vars.push("q" + i + "=0")
|
|
} else {
|
|
vars.push(["q", i, "=", init_string.join("+")].join(""))
|
|
}
|
|
}
|
|
|
|
//Prepare this variables
|
|
var thisVars = uniq([].concat(proc.pre.thisVars)
|
|
.concat(proc.body.thisVars)
|
|
.concat(proc.post.thisVars))
|
|
vars = vars.concat(thisVars)
|
|
if (vars.length > 0) {
|
|
code.push("var " + vars.join(","))
|
|
}
|
|
for(var i=0; i<proc.arrayArgs.length; ++i) {
|
|
code.push("p"+i+"|=0")
|
|
}
|
|
|
|
//Inline prelude
|
|
if(proc.pre.body.length > 3) {
|
|
code.push(processBlock(proc.pre, proc, dtypes))
|
|
}
|
|
|
|
//Process body
|
|
var body = processBlock(proc.body, proc, dtypes)
|
|
var matched = countMatches(loopOrders)
|
|
if(matched < dimension) {
|
|
code.push(outerFill(matched, loopOrders[0], proc, body)) // TODO: Rather than passing loopOrders[0], it might be interesting to look at passing an order that represents the majority of the arguments for example.
|
|
} else {
|
|
code.push(innerFill(loopOrders[0], proc, body))
|
|
}
|
|
|
|
//Inline epilog
|
|
if(proc.post.body.length > 3) {
|
|
code.push(processBlock(proc.post, proc, dtypes))
|
|
}
|
|
|
|
if(proc.debug) {
|
|
console.log("-----Generated cwise routine for ", typesig, ":\n" + code.join("\n") + "\n----------")
|
|
}
|
|
|
|
var loopName = [(proc.funcName||"unnamed"), "_cwise_loop_", orders[0].join("s"),"m",matched,typeSummary(dtypes)].join("")
|
|
var f = new Function(["function ",loopName,"(", arglist.join(","),"){", code.join("\n"),"} return ", loopName].join(""))
|
|
return f()
|
|
}
|
|
module.exports = generateCWiseOp
|
|
|
|
},{"uniq":62}],54:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
// The function below is called when constructing a cwise function object, and does the following:
|
|
// A function object is constructed which accepts as argument a compilation function and returns another function.
|
|
// It is this other function that is eventually returned by createThunk, and this function is the one that actually
|
|
// checks whether a certain pattern of arguments has already been used before and compiles new loops as needed.
|
|
// The compilation passed to the first function object is used for compiling new functions.
|
|
// Once this function object is created, it is called with compile as argument, where the first argument of compile
|
|
// is bound to "proc" (essentially containing a preprocessed version of the user arguments to cwise).
|
|
// So createThunk roughly works like this:
|
|
// function createThunk(proc) {
|
|
// var thunk = function(compileBound) {
|
|
// var CACHED = {}
|
|
// return function(arrays and scalars) {
|
|
// if (dtype and order of arrays in CACHED) {
|
|
// var func = CACHED[dtype and order of arrays]
|
|
// } else {
|
|
// var func = CACHED[dtype and order of arrays] = compileBound(dtype and order of arrays)
|
|
// }
|
|
// return func(arrays and scalars)
|
|
// }
|
|
// }
|
|
// return thunk(compile.bind1(proc))
|
|
// }
|
|
|
|
var compile = require("./compile.js")
|
|
|
|
function createThunk(proc) {
|
|
var code = ["'use strict'", "var CACHED={}"]
|
|
var vars = []
|
|
var thunkName = proc.funcName + "_cwise_thunk"
|
|
|
|
//Build thunk
|
|
code.push(["return function ", thunkName, "(", proc.shimArgs.join(","), "){"].join(""))
|
|
var typesig = []
|
|
var string_typesig = []
|
|
var proc_args = [["array",proc.arrayArgs[0],".shape.slice(", // Slice shape so that we only retain the shape over which we iterate (which gets passed to the cwise operator as SS).
|
|
Math.max(0,proc.arrayBlockIndices[0]),proc.arrayBlockIndices[0]<0?(","+proc.arrayBlockIndices[0]+")"):")"].join("")]
|
|
var shapeLengthConditions = [], shapeConditions = []
|
|
// Process array arguments
|
|
for(var i=0; i<proc.arrayArgs.length; ++i) {
|
|
var j = proc.arrayArgs[i]
|
|
vars.push(["t", j, "=array", j, ".dtype,",
|
|
"r", j, "=array", j, ".order"].join(""))
|
|
typesig.push("t" + j)
|
|
typesig.push("r" + j)
|
|
string_typesig.push("t"+j)
|
|
string_typesig.push("r"+j+".join()")
|
|
proc_args.push("array" + j + ".data")
|
|
proc_args.push("array" + j + ".stride")
|
|
proc_args.push("array" + j + ".offset|0")
|
|
if (i>0) { // Gather conditions to check for shape equality (ignoring block indices)
|
|
shapeLengthConditions.push("array" + proc.arrayArgs[0] + ".shape.length===array" + j + ".shape.length+" + (Math.abs(proc.arrayBlockIndices[0])-Math.abs(proc.arrayBlockIndices[i])))
|
|
shapeConditions.push("array" + proc.arrayArgs[0] + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[0]) + "]===array" + j + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[i]) + "]")
|
|
}
|
|
}
|
|
// Check for shape equality
|
|
if (proc.arrayArgs.length > 1) {
|
|
code.push("if (!(" + shapeLengthConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same dimensionality!')")
|
|
code.push("for(var shapeIndex=array" + proc.arrayArgs[0] + ".shape.length-" + Math.abs(proc.arrayBlockIndices[0]) + "; shapeIndex-->0;) {")
|
|
code.push("if (!(" + shapeConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same shape!')")
|
|
code.push("}")
|
|
}
|
|
// Process scalar arguments
|
|
for(var i=0; i<proc.scalarArgs.length; ++i) {
|
|
proc_args.push("scalar" + proc.scalarArgs[i])
|
|
}
|
|
// Check for cached function (and if not present, generate it)
|
|
vars.push(["type=[", string_typesig.join(","), "].join()"].join(""))
|
|
vars.push("proc=CACHED[type]")
|
|
code.push("var " + vars.join(","))
|
|
|
|
code.push(["if(!proc){",
|
|
"CACHED[type]=proc=compile([", typesig.join(","), "])}",
|
|
"return proc(", proc_args.join(","), ")}"].join(""))
|
|
|
|
if(proc.debug) {
|
|
console.log("-----Generated thunk:\n" + code.join("\n") + "\n----------")
|
|
}
|
|
|
|
//Compile thunk
|
|
var thunk = new Function("compile", code.join("\n"))
|
|
return thunk(compile.bind(undefined, proc))
|
|
}
|
|
|
|
module.exports = createThunk
|
|
|
|
},{"./compile.js":53}],55:[function(require,module,exports){
|
|
var iota = require("iota-array")
|
|
var isBuffer = require("is-buffer")
|
|
|
|
var hasTypedArrays = ((typeof Float64Array) !== "undefined")
|
|
|
|
function compare1st(a, b) {
|
|
return a[0] - b[0]
|
|
}
|
|
|
|
function order() {
|
|
var stride = this.stride
|
|
var terms = new Array(stride.length)
|
|
var i
|
|
for(i=0; i<terms.length; ++i) {
|
|
terms[i] = [Math.abs(stride[i]), i]
|
|
}
|
|
terms.sort(compare1st)
|
|
var result = new Array(terms.length)
|
|
for(i=0; i<result.length; ++i) {
|
|
result[i] = terms[i][1]
|
|
}
|
|
return result
|
|
}
|
|
|
|
function compileConstructor(dtype, dimension) {
|
|
var className = ["View", dimension, "d", dtype].join("")
|
|
if(dimension < 0) {
|
|
className = "View_Nil" + dtype
|
|
}
|
|
var useGetters = (dtype === "generic")
|
|
|
|
if(dimension === -1) {
|
|
//Special case for trivial arrays
|
|
var code =
|
|
"function "+className+"(a){this.data=a;};\
|
|
var proto="+className+".prototype;\
|
|
proto.dtype='"+dtype+"';\
|
|
proto.index=function(){return -1};\
|
|
proto.size=0;\
|
|
proto.dimension=-1;\
|
|
proto.shape=proto.stride=proto.order=[];\
|
|
proto.lo=proto.hi=proto.transpose=proto.step=\
|
|
function(){return new "+className+"(this.data);};\
|
|
proto.get=proto.set=function(){};\
|
|
proto.pick=function(){return null};\
|
|
return function construct_"+className+"(a){return new "+className+"(a);}"
|
|
var procedure = new Function(code)
|
|
return procedure()
|
|
} else if(dimension === 0) {
|
|
//Special case for 0d arrays
|
|
var code =
|
|
"function "+className+"(a,d) {\
|
|
this.data = a;\
|
|
this.offset = d\
|
|
};\
|
|
var proto="+className+".prototype;\
|
|
proto.dtype='"+dtype+"';\
|
|
proto.index=function(){return this.offset};\
|
|
proto.dimension=0;\
|
|
proto.size=1;\
|
|
proto.shape=\
|
|
proto.stride=\
|
|
proto.order=[];\
|
|
proto.lo=\
|
|
proto.hi=\
|
|
proto.transpose=\
|
|
proto.step=function "+className+"_copy() {\
|
|
return new "+className+"(this.data,this.offset)\
|
|
};\
|
|
proto.pick=function "+className+"_pick(){\
|
|
return TrivialArray(this.data);\
|
|
};\
|
|
proto.valueOf=proto.get=function "+className+"_get(){\
|
|
return "+(useGetters ? "this.data.get(this.offset)" : "this.data[this.offset]")+
|
|
"};\
|
|
proto.set=function "+className+"_set(v){\
|
|
return "+(useGetters ? "this.data.set(this.offset,v)" : "this.data[this.offset]=v")+"\
|
|
};\
|
|
return function construct_"+className+"(a,b,c,d){return new "+className+"(a,d)}"
|
|
var procedure = new Function("TrivialArray", code)
|
|
return procedure(CACHED_CONSTRUCTORS[dtype][0])
|
|
}
|
|
|
|
var code = ["'use strict'"]
|
|
|
|
//Create constructor for view
|
|
var indices = iota(dimension)
|
|
var args = indices.map(function(i) { return "i"+i })
|
|
var index_str = "this.offset+" + indices.map(function(i) {
|
|
return "this.stride[" + i + "]*i" + i
|
|
}).join("+")
|
|
var shapeArg = indices.map(function(i) {
|
|
return "b"+i
|
|
}).join(",")
|
|
var strideArg = indices.map(function(i) {
|
|
return "c"+i
|
|
}).join(",")
|
|
code.push(
|
|
"function "+className+"(a," + shapeArg + "," + strideArg + ",d){this.data=a",
|
|
"this.shape=[" + shapeArg + "]",
|
|
"this.stride=[" + strideArg + "]",
|
|
"this.offset=d|0}",
|
|
"var proto="+className+".prototype",
|
|
"proto.dtype='"+dtype+"'",
|
|
"proto.dimension="+dimension)
|
|
|
|
//view.size:
|
|
code.push("Object.defineProperty(proto,'size',{get:function "+className+"_size(){\
|
|
return "+indices.map(function(i) { return "this.shape["+i+"]" }).join("*"),
|
|
"}})")
|
|
|
|
//view.order:
|
|
if(dimension === 1) {
|
|
code.push("proto.order=[0]")
|
|
} else {
|
|
code.push("Object.defineProperty(proto,'order',{get:")
|
|
if(dimension < 4) {
|
|
code.push("function "+className+"_order(){")
|
|
if(dimension === 2) {
|
|
code.push("return (Math.abs(this.stride[0])>Math.abs(this.stride[1]))?[1,0]:[0,1]}})")
|
|
} else if(dimension === 3) {
|
|
code.push(
|
|
"var s0=Math.abs(this.stride[0]),s1=Math.abs(this.stride[1]),s2=Math.abs(this.stride[2]);\
|
|
if(s0>s1){\
|
|
if(s1>s2){\
|
|
return [2,1,0];\
|
|
}else if(s0>s2){\
|
|
return [1,2,0];\
|
|
}else{\
|
|
return [1,0,2];\
|
|
}\
|
|
}else if(s0>s2){\
|
|
return [2,0,1];\
|
|
}else if(s2>s1){\
|
|
return [0,1,2];\
|
|
}else{\
|
|
return [0,2,1];\
|
|
}}})")
|
|
}
|
|
} else {
|
|
code.push("ORDER})")
|
|
}
|
|
}
|
|
|
|
//view.set(i0, ..., v):
|
|
code.push(
|
|
"proto.set=function "+className+"_set("+args.join(",")+",v){")
|
|
if(useGetters) {
|
|
code.push("return this.data.set("+index_str+",v)}")
|
|
} else {
|
|
code.push("return this.data["+index_str+"]=v}")
|
|
}
|
|
|
|
//view.get(i0, ...):
|
|
code.push("proto.get=function "+className+"_get("+args.join(",")+"){")
|
|
if(useGetters) {
|
|
code.push("return this.data.get("+index_str+")}")
|
|
} else {
|
|
code.push("return this.data["+index_str+"]}")
|
|
}
|
|
|
|
//view.index:
|
|
code.push(
|
|
"proto.index=function "+className+"_index(", args.join(), "){return "+index_str+"}")
|
|
|
|
//view.hi():
|
|
code.push("proto.hi=function "+className+"_hi("+args.join(",")+"){return new "+className+"(this.data,"+
|
|
indices.map(function(i) {
|
|
return ["(typeof i",i,"!=='number'||i",i,"<0)?this.shape[", i, "]:i", i,"|0"].join("")
|
|
}).join(",")+","+
|
|
indices.map(function(i) {
|
|
return "this.stride["+i + "]"
|
|
}).join(",")+",this.offset)}")
|
|
|
|
//view.lo():
|
|
var a_vars = indices.map(function(i) { return "a"+i+"=this.shape["+i+"]" })
|
|
var c_vars = indices.map(function(i) { return "c"+i+"=this.stride["+i+"]" })
|
|
code.push("proto.lo=function "+className+"_lo("+args.join(",")+"){var b=this.offset,d=0,"+a_vars.join(",")+","+c_vars.join(","))
|
|
for(var i=0; i<dimension; ++i) {
|
|
code.push(
|
|
"if(typeof i"+i+"==='number'&&i"+i+">=0){\
|
|
d=i"+i+"|0;\
|
|
b+=c"+i+"*d;\
|
|
a"+i+"-=d}")
|
|
}
|
|
code.push("return new "+className+"(this.data,"+
|
|
indices.map(function(i) {
|
|
return "a"+i
|
|
}).join(",")+","+
|
|
indices.map(function(i) {
|
|
return "c"+i
|
|
}).join(",")+",b)}")
|
|
|
|
//view.step():
|
|
code.push("proto.step=function "+className+"_step("+args.join(",")+"){var "+
|
|
indices.map(function(i) {
|
|
return "a"+i+"=this.shape["+i+"]"
|
|
}).join(",")+","+
|
|
indices.map(function(i) {
|
|
return "b"+i+"=this.stride["+i+"]"
|
|
}).join(",")+",c=this.offset,d=0,ceil=Math.ceil")
|
|
for(var i=0; i<dimension; ++i) {
|
|
code.push(
|
|
"if(typeof i"+i+"==='number'){\
|
|
d=i"+i+"|0;\
|
|
if(d<0){\
|
|
c+=b"+i+"*(a"+i+"-1);\
|
|
a"+i+"=ceil(-a"+i+"/d)\
|
|
}else{\
|
|
a"+i+"=ceil(a"+i+"/d)\
|
|
}\
|
|
b"+i+"*=d\
|
|
}")
|
|
}
|
|
code.push("return new "+className+"(this.data,"+
|
|
indices.map(function(i) {
|
|
return "a" + i
|
|
}).join(",")+","+
|
|
indices.map(function(i) {
|
|
return "b" + i
|
|
}).join(",")+",c)}")
|
|
|
|
//view.transpose():
|
|
var tShape = new Array(dimension)
|
|
var tStride = new Array(dimension)
|
|
for(var i=0; i<dimension; ++i) {
|
|
tShape[i] = "a[i"+i+"]"
|
|
tStride[i] = "b[i"+i+"]"
|
|
}
|
|
code.push("proto.transpose=function "+className+"_transpose("+args+"){"+
|
|
args.map(function(n,idx) { return n + "=(" + n + "===undefined?" + idx + ":" + n + "|0)"}).join(";"),
|
|
"var a=this.shape,b=this.stride;return new "+className+"(this.data,"+tShape.join(",")+","+tStride.join(",")+",this.offset)}")
|
|
|
|
//view.pick():
|
|
code.push("proto.pick=function "+className+"_pick("+args+"){var a=[],b=[],c=this.offset")
|
|
for(var i=0; i<dimension; ++i) {
|
|
code.push("if(typeof i"+i+"==='number'&&i"+i+">=0){c=(c+this.stride["+i+"]*i"+i+")|0}else{a.push(this.shape["+i+"]);b.push(this.stride["+i+"])}")
|
|
}
|
|
code.push("var ctor=CTOR_LIST[a.length+1];return ctor(this.data,a,b,c)}")
|
|
|
|
//Add return statement
|
|
code.push("return function construct_"+className+"(data,shape,stride,offset){return new "+className+"(data,"+
|
|
indices.map(function(i) {
|
|
return "shape["+i+"]"
|
|
}).join(",")+","+
|
|
indices.map(function(i) {
|
|
return "stride["+i+"]"
|
|
}).join(",")+",offset)}")
|
|
|
|
//Compile procedure
|
|
var procedure = new Function("CTOR_LIST", "ORDER", code.join("\n"))
|
|
return procedure(CACHED_CONSTRUCTORS[dtype], order)
|
|
}
|
|
|
|
function arrayDType(data) {
|
|
if(isBuffer(data)) {
|
|
return "buffer"
|
|
}
|
|
if(hasTypedArrays) {
|
|
switch(Object.prototype.toString.call(data)) {
|
|
case "[object Float64Array]":
|
|
return "float64"
|
|
case "[object Float32Array]":
|
|
return "float32"
|
|
case "[object Int8Array]":
|
|
return "int8"
|
|
case "[object Int16Array]":
|
|
return "int16"
|
|
case "[object Int32Array]":
|
|
return "int32"
|
|
case "[object Uint8Array]":
|
|
return "uint8"
|
|
case "[object Uint16Array]":
|
|
return "uint16"
|
|
case "[object Uint32Array]":
|
|
return "uint32"
|
|
case "[object Uint8ClampedArray]":
|
|
return "uint8_clamped"
|
|
case "[object BigInt64Array]":
|
|
return "bigint64"
|
|
case "[object BigUint64Array]":
|
|
return "biguint64"
|
|
}
|
|
}
|
|
if(Array.isArray(data)) {
|
|
return "array"
|
|
}
|
|
return "generic"
|
|
}
|
|
|
|
var CACHED_CONSTRUCTORS = {
|
|
"float32":[],
|
|
"float64":[],
|
|
"int8":[],
|
|
"int16":[],
|
|
"int32":[],
|
|
"uint8":[],
|
|
"uint16":[],
|
|
"uint32":[],
|
|
"array":[],
|
|
"uint8_clamped":[],
|
|
"bigint64": [],
|
|
"biguint64": [],
|
|
"buffer":[],
|
|
"generic":[]
|
|
}
|
|
|
|
;(function() {
|
|
for(var id in CACHED_CONSTRUCTORS) {
|
|
CACHED_CONSTRUCTORS[id].push(compileConstructor(id, -1))
|
|
}
|
|
});
|
|
|
|
function wrappedNDArrayCtor(data, shape, stride, offset) {
|
|
if(data === undefined) {
|
|
var ctor = CACHED_CONSTRUCTORS.array[0]
|
|
return ctor([])
|
|
} else if(typeof data === "number") {
|
|
data = [data]
|
|
}
|
|
if(shape === undefined) {
|
|
shape = [ data.length ]
|
|
}
|
|
var d = shape.length
|
|
if(stride === undefined) {
|
|
stride = new Array(d)
|
|
for(var i=d-1, sz=1; i>=0; --i) {
|
|
stride[i] = sz
|
|
sz *= shape[i]
|
|
}
|
|
}
|
|
if(offset === undefined) {
|
|
offset = 0
|
|
for(var i=0; i<d; ++i) {
|
|
if(stride[i] < 0) {
|
|
offset -= (shape[i]-1)*stride[i]
|
|
}
|
|
}
|
|
}
|
|
var dtype = arrayDType(data)
|
|
var ctor_list = CACHED_CONSTRUCTORS[dtype]
|
|
while(ctor_list.length <= d+1) {
|
|
ctor_list.push(compileConstructor(dtype, ctor_list.length-1))
|
|
}
|
|
var ctor = ctor_list[d+1]
|
|
return ctor(data, shape, stride, offset)
|
|
}
|
|
|
|
module.exports = wrappedNDArrayCtor
|
|
|
|
},{"iota-array":49,"is-buffer":50}],56:[function(require,module,exports){
|
|
/*!
|
|
* pad-left <https://github.com/jonschlinkert/pad-left>
|
|
*
|
|
* Copyright (c) 2014-2015, Jon Schlinkert.
|
|
* Licensed under the MIT license.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
var repeat = require('repeat-string');
|
|
|
|
module.exports = function padLeft(str, num, ch) {
|
|
ch = typeof ch !== 'undefined' ? (ch + '') : ' ';
|
|
return repeat(ch, num) + str;
|
|
};
|
|
},{"repeat-string":59}],57:[function(require,module,exports){
|
|
// shim for using process in browser
|
|
|
|
var process = module.exports = {};
|
|
var queue = [];
|
|
var draining = false;
|
|
|
|
function drainQueue() {
|
|
if (draining) {
|
|
return;
|
|
}
|
|
draining = true;
|
|
var currentQueue;
|
|
var len = queue.length;
|
|
while(len) {
|
|
currentQueue = queue;
|
|
queue = [];
|
|
var i = -1;
|
|
while (++i < len) {
|
|
currentQueue[i]();
|
|
}
|
|
len = queue.length;
|
|
}
|
|
draining = false;
|
|
}
|
|
process.nextTick = function (fun) {
|
|
queue.push(fun);
|
|
if (!draining) {
|
|
setTimeout(drainQueue, 0);
|
|
}
|
|
};
|
|
|
|
process.title = 'browser';
|
|
process.browser = true;
|
|
process.env = {};
|
|
process.argv = [];
|
|
process.version = ''; // empty string to avoid regexp issues
|
|
process.versions = {};
|
|
|
|
function noop() {}
|
|
|
|
process.on = noop;
|
|
process.addListener = noop;
|
|
process.once = noop;
|
|
process.off = noop;
|
|
process.removeListener = noop;
|
|
process.removeAllListeners = noop;
|
|
process.emit = noop;
|
|
|
|
process.binding = function (name) {
|
|
throw new Error('process.binding is not supported');
|
|
};
|
|
|
|
// TODO(shtylman)
|
|
process.cwd = function () { return '/' };
|
|
process.chdir = function (dir) {
|
|
throw new Error('process.chdir is not supported');
|
|
};
|
|
process.umask = function() { return 0; };
|
|
|
|
},{}],58:[function(require,module,exports){
|
|
/**
|
|
* Expose `requestAnimationFrame()`.
|
|
*/
|
|
|
|
exports = module.exports = window.requestAnimationFrame
|
|
|| window.webkitRequestAnimationFrame
|
|
|| window.mozRequestAnimationFrame
|
|
|| window.oRequestAnimationFrame
|
|
|| window.msRequestAnimationFrame
|
|
|| fallback;
|
|
|
|
/**
|
|
* Fallback implementation.
|
|
*/
|
|
|
|
var prev = new Date().getTime();
|
|
function fallback(fn) {
|
|
var curr = new Date().getTime();
|
|
var ms = Math.max(0, 16 - (curr - prev));
|
|
var req = setTimeout(fn, ms);
|
|
prev = curr;
|
|
return req;
|
|
}
|
|
|
|
/**
|
|
* Cancel.
|
|
*/
|
|
|
|
var cancel = window.cancelAnimationFrame
|
|
|| window.webkitCancelAnimationFrame
|
|
|| window.mozCancelAnimationFrame
|
|
|| window.oCancelAnimationFrame
|
|
|| window.msCancelAnimationFrame
|
|
|| window.clearTimeout;
|
|
|
|
exports.cancel = function(id){
|
|
cancel.call(window, id);
|
|
};
|
|
|
|
},{}],59:[function(require,module,exports){
|
|
/*!
|
|
* repeat-string <https://github.com/jonschlinkert/repeat-string>
|
|
*
|
|
* Copyright (c) 2014-2015, Jon Schlinkert.
|
|
* Licensed under the MIT License.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
/**
|
|
* Results cache
|
|
*/
|
|
|
|
var res = '';
|
|
var cache;
|
|
|
|
/**
|
|
* Expose `repeat`
|
|
*/
|
|
|
|
module.exports = repeat;
|
|
|
|
/**
|
|
* Repeat the given `string` the specified `number`
|
|
* of times.
|
|
*
|
|
* **Example:**
|
|
*
|
|
* ```js
|
|
* var repeat = require('repeat-string');
|
|
* repeat('A', 5);
|
|
* //=> AAAAA
|
|
* ```
|
|
*
|
|
* @param {String} `string` The string to repeat
|
|
* @param {Number} `number` The number of times to repeat the string
|
|
* @return {String} Repeated string
|
|
* @api public
|
|
*/
|
|
|
|
function repeat(str, num) {
|
|
if (typeof str !== 'string') {
|
|
throw new TypeError('expected a string');
|
|
}
|
|
|
|
// cover common, quick use cases
|
|
if (num === 1) return str;
|
|
if (num === 2) return str + str;
|
|
|
|
var max = str.length * num;
|
|
if (cache !== str || typeof cache === 'undefined') {
|
|
cache = str;
|
|
res = '';
|
|
} else if (res.length >= max) {
|
|
return res.substr(0, max);
|
|
}
|
|
|
|
while (max > res.length && num > 1) {
|
|
if (num & 1) {
|
|
res += str;
|
|
}
|
|
|
|
num >>= 1;
|
|
str += str;
|
|
}
|
|
|
|
res += str;
|
|
res = res.substr(0, max);
|
|
return res;
|
|
}
|
|
|
|
},{}],60:[function(require,module,exports){
|
|
/* global window, exports, define */
|
|
|
|
!function() {
|
|
'use strict'
|
|
|
|
var re = {
|
|
not_string: /[^s]/,
|
|
not_bool: /[^t]/,
|
|
not_type: /[^T]/,
|
|
not_primitive: /[^v]/,
|
|
number: /[diefg]/,
|
|
numeric_arg: /[bcdiefguxX]/,
|
|
json: /[j]/,
|
|
not_json: /[^j]/,
|
|
text: /^[^\x25]+/,
|
|
modulo: /^\x25{2}/,
|
|
placeholder: /^\x25(?:([1-9]\d*)\$|\(([^)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijostTuvxX])/,
|
|
key: /^([a-z_][a-z_\d]*)/i,
|
|
key_access: /^\.([a-z_][a-z_\d]*)/i,
|
|
index_access: /^\[(\d+)\]/,
|
|
sign: /^[+-]/
|
|
}
|
|
|
|
function sprintf(key) {
|
|
// `arguments` is not an array, but should be fine for this call
|
|
return sprintf_format(sprintf_parse(key), arguments)
|
|
}
|
|
|
|
function vsprintf(fmt, argv) {
|
|
return sprintf.apply(null, [fmt].concat(argv || []))
|
|
}
|
|
|
|
function sprintf_format(parse_tree, argv) {
|
|
var cursor = 1, tree_length = parse_tree.length, arg, output = '', i, k, ph, pad, pad_character, pad_length, is_positive, sign
|
|
for (i = 0; i < tree_length; i++) {
|
|
if (typeof parse_tree[i] === 'string') {
|
|
output += parse_tree[i]
|
|
}
|
|
else if (typeof parse_tree[i] === 'object') {
|
|
ph = parse_tree[i] // convenience purposes only
|
|
if (ph.keys) { // keyword argument
|
|
arg = argv[cursor]
|
|
for (k = 0; k < ph.keys.length; k++) {
|
|
if (arg == undefined) {
|
|
throw new Error(sprintf('[sprintf] Cannot access property "%s" of undefined value "%s"', ph.keys[k], ph.keys[k-1]))
|
|
}
|
|
arg = arg[ph.keys[k]]
|
|
}
|
|
}
|
|
else if (ph.param_no) { // positional argument (explicit)
|
|
arg = argv[ph.param_no]
|
|
}
|
|
else { // positional argument (implicit)
|
|
arg = argv[cursor++]
|
|
}
|
|
|
|
if (re.not_type.test(ph.type) && re.not_primitive.test(ph.type) && arg instanceof Function) {
|
|
arg = arg()
|
|
}
|
|
|
|
if (re.numeric_arg.test(ph.type) && (typeof arg !== 'number' && isNaN(arg))) {
|
|
throw new TypeError(sprintf('[sprintf] expecting number but found %T', arg))
|
|
}
|
|
|
|
if (re.number.test(ph.type)) {
|
|
is_positive = arg >= 0
|
|
}
|
|
|
|
switch (ph.type) {
|
|
case 'b':
|
|
arg = parseInt(arg, 10).toString(2)
|
|
break
|
|
case 'c':
|
|
arg = String.fromCharCode(parseInt(arg, 10))
|
|
break
|
|
case 'd':
|
|
case 'i':
|
|
arg = parseInt(arg, 10)
|
|
break
|
|
case 'j':
|
|
arg = JSON.stringify(arg, null, ph.width ? parseInt(ph.width) : 0)
|
|
break
|
|
case 'e':
|
|
arg = ph.precision ? parseFloat(arg).toExponential(ph.precision) : parseFloat(arg).toExponential()
|
|
break
|
|
case 'f':
|
|
arg = ph.precision ? parseFloat(arg).toFixed(ph.precision) : parseFloat(arg)
|
|
break
|
|
case 'g':
|
|
arg = ph.precision ? String(Number(arg.toPrecision(ph.precision))) : parseFloat(arg)
|
|
break
|
|
case 'o':
|
|
arg = (parseInt(arg, 10) >>> 0).toString(8)
|
|
break
|
|
case 's':
|
|
arg = String(arg)
|
|
arg = (ph.precision ? arg.substring(0, ph.precision) : arg)
|
|
break
|
|
case 't':
|
|
arg = String(!!arg)
|
|
arg = (ph.precision ? arg.substring(0, ph.precision) : arg)
|
|
break
|
|
case 'T':
|
|
arg = Object.prototype.toString.call(arg).slice(8, -1).toLowerCase()
|
|
arg = (ph.precision ? arg.substring(0, ph.precision) : arg)
|
|
break
|
|
case 'u':
|
|
arg = parseInt(arg, 10) >>> 0
|
|
break
|
|
case 'v':
|
|
arg = arg.valueOf()
|
|
arg = (ph.precision ? arg.substring(0, ph.precision) : arg)
|
|
break
|
|
case 'x':
|
|
arg = (parseInt(arg, 10) >>> 0).toString(16)
|
|
break
|
|
case 'X':
|
|
arg = (parseInt(arg, 10) >>> 0).toString(16).toUpperCase()
|
|
break
|
|
}
|
|
if (re.json.test(ph.type)) {
|
|
output += arg
|
|
}
|
|
else {
|
|
if (re.number.test(ph.type) && (!is_positive || ph.sign)) {
|
|
sign = is_positive ? '+' : '-'
|
|
arg = arg.toString().replace(re.sign, '')
|
|
}
|
|
else {
|
|
sign = ''
|
|
}
|
|
pad_character = ph.pad_char ? ph.pad_char === '0' ? '0' : ph.pad_char.charAt(1) : ' '
|
|
pad_length = ph.width - (sign + arg).length
|
|
pad = ph.width ? (pad_length > 0 ? pad_character.repeat(pad_length) : '') : ''
|
|
output += ph.align ? sign + arg + pad : (pad_character === '0' ? sign + pad + arg : pad + sign + arg)
|
|
}
|
|
}
|
|
}
|
|
return output
|
|
}
|
|
|
|
var sprintf_cache = Object.create(null)
|
|
|
|
function sprintf_parse(fmt) {
|
|
if (sprintf_cache[fmt]) {
|
|
return sprintf_cache[fmt]
|
|
}
|
|
|
|
var _fmt = fmt, match, parse_tree = [], arg_names = 0
|
|
while (_fmt) {
|
|
if ((match = re.text.exec(_fmt)) !== null) {
|
|
parse_tree.push(match[0])
|
|
}
|
|
else if ((match = re.modulo.exec(_fmt)) !== null) {
|
|
parse_tree.push('%')
|
|
}
|
|
else if ((match = re.placeholder.exec(_fmt)) !== null) {
|
|
if (match[2]) {
|
|
arg_names |= 1
|
|
var field_list = [], replacement_field = match[2], field_match = []
|
|
if ((field_match = re.key.exec(replacement_field)) !== null) {
|
|
field_list.push(field_match[1])
|
|
while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
|
|
if ((field_match = re.key_access.exec(replacement_field)) !== null) {
|
|
field_list.push(field_match[1])
|
|
}
|
|
else if ((field_match = re.index_access.exec(replacement_field)) !== null) {
|
|
field_list.push(field_match[1])
|
|
}
|
|
else {
|
|
throw new SyntaxError('[sprintf] failed to parse named argument key')
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
throw new SyntaxError('[sprintf] failed to parse named argument key')
|
|
}
|
|
match[2] = field_list
|
|
}
|
|
else {
|
|
arg_names |= 2
|
|
}
|
|
if (arg_names === 3) {
|
|
throw new Error('[sprintf] mixing positional and named placeholders is not (yet) supported')
|
|
}
|
|
|
|
parse_tree.push(
|
|
{
|
|
placeholder: match[0],
|
|
param_no: match[1],
|
|
keys: match[2],
|
|
sign: match[3],
|
|
pad_char: match[4],
|
|
align: match[5],
|
|
width: match[6],
|
|
precision: match[7],
|
|
type: match[8]
|
|
}
|
|
)
|
|
}
|
|
else {
|
|
throw new SyntaxError('[sprintf] unexpected placeholder')
|
|
}
|
|
_fmt = _fmt.substring(match[0].length)
|
|
}
|
|
return sprintf_cache[fmt] = parse_tree
|
|
}
|
|
|
|
/**
|
|
* export to either browser or node.js
|
|
*/
|
|
/* eslint-disable quote-props */
|
|
if (typeof exports !== 'undefined') {
|
|
exports['sprintf'] = sprintf
|
|
exports['vsprintf'] = vsprintf
|
|
}
|
|
if (typeof window !== 'undefined') {
|
|
window['sprintf'] = sprintf
|
|
window['vsprintf'] = vsprintf
|
|
|
|
if (typeof define === 'function' && define['amd']) {
|
|
define(function() {
|
|
return {
|
|
'sprintf': sprintf,
|
|
'vsprintf': vsprintf
|
|
}
|
|
})
|
|
}
|
|
}
|
|
/* eslint-enable quote-props */
|
|
}(); // eslint-disable-line
|
|
|
|
},{}],61:[function(require,module,exports){
|
|
(function (global){
|
|
"use strict"
|
|
|
|
var bits = require("bit-twiddle")
|
|
var dup = require("dup")
|
|
if(!global.__TYPEDARRAY_POOL) {
|
|
global.__TYPEDARRAY_POOL = {
|
|
UINT8 : dup([32, 0])
|
|
, UINT16 : dup([32, 0])
|
|
, UINT32 : dup([32, 0])
|
|
, INT8 : dup([32, 0])
|
|
, INT16 : dup([32, 0])
|
|
, INT32 : dup([32, 0])
|
|
, FLOAT : dup([32, 0])
|
|
, DOUBLE : dup([32, 0])
|
|
, DATA : dup([32, 0])
|
|
}
|
|
}
|
|
var POOL = global.__TYPEDARRAY_POOL
|
|
var UINT8 = POOL.UINT8
|
|
, UINT16 = POOL.UINT16
|
|
, UINT32 = POOL.UINT32
|
|
, INT8 = POOL.INT8
|
|
, INT16 = POOL.INT16
|
|
, INT32 = POOL.INT32
|
|
, FLOAT = POOL.FLOAT
|
|
, DOUBLE = POOL.DOUBLE
|
|
, DATA = POOL.DATA
|
|
|
|
exports.free = function free(array) {
|
|
if(array instanceof ArrayBuffer) {
|
|
var n = array.byteLength|0
|
|
, log_n = bits.log2(n)
|
|
DATA[log_n].push(array)
|
|
} else {
|
|
var n = array.length|0
|
|
, log_n = bits.log2(n)
|
|
if(array instanceof Uint8Array) {
|
|
UINT8[log_n].push(array)
|
|
} else if(array instanceof Uint16Array) {
|
|
UINT16[log_n].push(array)
|
|
} else if(array instanceof Uint32Array) {
|
|
UINT32[log_n].push(array)
|
|
} else if(array instanceof Int8Array) {
|
|
INT8[log_n].push(array)
|
|
} else if(array instanceof Int16Array) {
|
|
INT16[log_n].push(array)
|
|
} else if(array instanceof Int32Array) {
|
|
INT32[log_n].push(array)
|
|
} else if(array instanceof Float32Array) {
|
|
FLOAT[log_n].push(array)
|
|
} else if(array instanceof Float64Array) {
|
|
DOUBLE[log_n].push(array)
|
|
}
|
|
}
|
|
}
|
|
|
|
exports.freeUint8 = function freeUint8(array) {
|
|
UINT8[bits.log2(array.length)].push(array)
|
|
}
|
|
|
|
exports.freeUint16 = function freeUint16(array) {
|
|
UINT16[bits.log2(array.length)].push(array)
|
|
}
|
|
|
|
exports.freeUint32 = function freeUint32(array) {
|
|
UINT32[bits.log2(array.length)].push(array)
|
|
}
|
|
|
|
exports.freeInt8 = function freeInt8(array) {
|
|
INT8[bits.log2(array.length)].push(array)
|
|
}
|
|
|
|
exports.freeInt16 = function freeInt16(array) {
|
|
INT16[bits.log2(array.length)].push(array)
|
|
}
|
|
|
|
exports.freeInt32 = function freeInt32(array) {
|
|
INT32[bits.log2(array.length)].push(array)
|
|
}
|
|
|
|
exports.freeFloat32 = exports.freeFloat = function freeFloat(array) {
|
|
FLOAT[bits.log2(array.length)].push(array)
|
|
}
|
|
|
|
exports.freeFloat64 = exports.freeDouble = function freeDouble(array) {
|
|
DOUBLE[bits.log2(array.length)].push(array)
|
|
}
|
|
|
|
exports.freeArrayBuffer = function freeArrayBuffer(array) {
|
|
DATA[bits.log2(array.length)].push(array)
|
|
}
|
|
|
|
exports.malloc = function malloc(n, dtype) {
|
|
n = bits.nextPow2(n)
|
|
var log_n = bits.log2(n)
|
|
if(dtype === undefined) {
|
|
var d = DATA[log_n]
|
|
if(d.length > 0) {
|
|
var r = d[d.length-1]
|
|
d.pop()
|
|
return r
|
|
}
|
|
return new ArrayBuffer(n)
|
|
} else {
|
|
switch(dtype) {
|
|
case "uint8":
|
|
var u8 = UINT8[log_n]
|
|
if(u8.length > 0) {
|
|
return u8.pop()
|
|
}
|
|
return new Uint8Array(n)
|
|
break
|
|
|
|
case "uint16":
|
|
var u16 = UINT16[log_n]
|
|
if(u16.length > 0) {
|
|
return u16.pop()
|
|
}
|
|
return new Uint16Array(n)
|
|
break
|
|
|
|
case "uint32":
|
|
var u32 = UINT32[log_n]
|
|
if(u32.length > 0) {
|
|
return u32.pop()
|
|
}
|
|
return new Uint32Array(n)
|
|
break
|
|
|
|
case "int8":
|
|
var i8 = INT8[log_n]
|
|
if(i8.length > 0) {
|
|
return i8.pop()
|
|
}
|
|
return new Int8Array(n)
|
|
break
|
|
|
|
case "int16":
|
|
var i16 = INT16[log_n]
|
|
if(i16.length > 0) {
|
|
return i16.pop()
|
|
}
|
|
return new Int16Array(n)
|
|
break
|
|
|
|
case "int32":
|
|
var i32 = INT32[log_n]
|
|
if(i32.length > 0) {
|
|
return i32.pop()
|
|
}
|
|
return new Int32Array(n)
|
|
break
|
|
|
|
case "float":
|
|
case "float32":
|
|
var f = FLOAT[log_n]
|
|
if(f.length > 0) {
|
|
return f.pop()
|
|
}
|
|
return new Float32Array(n)
|
|
break
|
|
|
|
case "double":
|
|
case "float64":
|
|
var dd = DOUBLE[log_n]
|
|
if(dd.length > 0) {
|
|
return dd.pop()
|
|
}
|
|
return new Float64Array(n)
|
|
break
|
|
|
|
default:
|
|
return null
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
exports.mallocUint8 = function mallocUint8(n) {
|
|
n = bits.nextPow2(n)
|
|
var log_n = bits.log2(n)
|
|
var cache = UINT8[log_n]
|
|
if(cache.length > 0) {
|
|
return cache.pop()
|
|
}
|
|
return new Uint8Array(n)
|
|
}
|
|
|
|
exports.mallocUint16 = function mallocUint16(n) {
|
|
n = bits.nextPow2(n)
|
|
var log_n = bits.log2(n)
|
|
var cache = UINT16[log_n]
|
|
if(cache.length > 0) {
|
|
return cache.pop()
|
|
}
|
|
return new Uint16Array(n)
|
|
}
|
|
|
|
exports.mallocUint32 = function mallocUint32(n) {
|
|
n = bits.nextPow2(n)
|
|
var log_n = bits.log2(n)
|
|
var cache = UINT32[log_n]
|
|
if(cache.length > 0) {
|
|
return cache.pop()
|
|
}
|
|
return new Uint32Array(n)
|
|
}
|
|
|
|
exports.mallocInt8 = function mallocInt8(n) {
|
|
n = bits.nextPow2(n)
|
|
var log_n = bits.log2(n)
|
|
var cache = INT8[log_n]
|
|
if(cache.length > 0) {
|
|
return cache.pop()
|
|
}
|
|
return new Int8Array(n)
|
|
}
|
|
|
|
exports.mallocInt16 = function mallocInt16(n) {
|
|
n = bits.nextPow2(n)
|
|
var log_n = bits.log2(n)
|
|
var cache = INT16[log_n]
|
|
if(cache.length > 0) {
|
|
return cache.pop()
|
|
}
|
|
return new Int16Array(n)
|
|
}
|
|
|
|
exports.mallocInt32 = function mallocInt32(n) {
|
|
n = bits.nextPow2(n)
|
|
var log_n = bits.log2(n)
|
|
var cache = INT32[log_n]
|
|
if(cache.length > 0) {
|
|
return cache.pop()
|
|
}
|
|
return new Int32Array(n)
|
|
}
|
|
|
|
exports.mallocFloat32 = exports.mallocFloat = function mallocFloat(n) {
|
|
n = bits.nextPow2(n)
|
|
var log_n = bits.log2(n)
|
|
var cache = FLOAT[log_n]
|
|
if(cache.length > 0) {
|
|
return cache.pop()
|
|
}
|
|
return new Float32Array(n)
|
|
}
|
|
|
|
exports.mallocFloat64 = exports.mallocDouble = function mallocDouble(n) {
|
|
n = bits.nextPow2(n)
|
|
var log_n = bits.log2(n)
|
|
var cache = DOUBLE[log_n]
|
|
if(cache.length > 0) {
|
|
return cache.pop()
|
|
}
|
|
return new Float64Array(n)
|
|
}
|
|
|
|
exports.mallocArrayBuffer = function mallocArrayBuffer(n) {
|
|
n = bits.nextPow2(n)
|
|
var log_n = bits.log2(n)
|
|
var cache = DATA[log_n]
|
|
if(cache.length > 0) {
|
|
return cache.pop()
|
|
}
|
|
return new ArrayBuffer(n)
|
|
}
|
|
|
|
exports.clearCache = function clearCache() {
|
|
for(var i=0; i<32; ++i) {
|
|
UINT8[i].length = 0
|
|
UINT16[i].length = 0
|
|
UINT32[i].length = 0
|
|
INT8[i].length = 0
|
|
INT16[i].length = 0
|
|
INT32[i].length = 0
|
|
FLOAT[i].length = 0
|
|
DOUBLE[i].length = 0
|
|
DATA[i].length = 0
|
|
}
|
|
}
|
|
|
|
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
},{"bit-twiddle":7,"dup":11}],62:[function(require,module,exports){
|
|
"use strict"
|
|
|
|
function unique_pred(list, compare) {
|
|
var ptr = 1
|
|
, len = list.length
|
|
, a=list[0], b=list[0]
|
|
for(var i=1; i<len; ++i) {
|
|
b = a
|
|
a = list[i]
|
|
if(compare(a, b)) {
|
|
if(i === ptr) {
|
|
ptr++
|
|
continue
|
|
}
|
|
list[ptr++] = a
|
|
}
|
|
}
|
|
list.length = ptr
|
|
return list
|
|
}
|
|
|
|
function unique_eq(list) {
|
|
var ptr = 1
|
|
, len = list.length
|
|
, a=list[0], b = list[0]
|
|
for(var i=1; i<len; ++i, b=a) {
|
|
b = a
|
|
a = list[i]
|
|
if(a !== b) {
|
|
if(i === ptr) {
|
|
ptr++
|
|
continue
|
|
}
|
|
list[ptr++] = a
|
|
}
|
|
}
|
|
list.length = ptr
|
|
return list
|
|
}
|
|
|
|
function unique(list, compare, sorted) {
|
|
if(list.length === 0) {
|
|
return list
|
|
}
|
|
if(compare) {
|
|
if(!sorted) {
|
|
list.sort(compare)
|
|
}
|
|
return unique_pred(list, compare)
|
|
}
|
|
if(!sorted) {
|
|
list.sort()
|
|
}
|
|
return unique_eq(list)
|
|
}
|
|
|
|
module.exports = unique
|
|
|
|
},{}],63:[function(require,module,exports){
|
|
if (typeof Object.create === 'function') {
|
|
// implementation from standard node.js 'util' module
|
|
module.exports = function inherits(ctor, superCtor) {
|
|
ctor.super_ = superCtor
|
|
ctor.prototype = Object.create(superCtor.prototype, {
|
|
constructor: {
|
|
value: ctor,
|
|
enumerable: false,
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
});
|
|
};
|
|
} else {
|
|
// old school shim for old browsers
|
|
module.exports = function inherits(ctor, superCtor) {
|
|
ctor.super_ = superCtor
|
|
var TempCtor = function () {}
|
|
TempCtor.prototype = superCtor.prototype
|
|
ctor.prototype = new TempCtor()
|
|
ctor.prototype.constructor = ctor
|
|
}
|
|
}
|
|
|
|
},{}],64:[function(require,module,exports){
|
|
module.exports = function isBuffer(arg) {
|
|
return arg && typeof arg === 'object'
|
|
&& typeof arg.copy === 'function'
|
|
&& typeof arg.fill === 'function'
|
|
&& typeof arg.readUInt8 === 'function';
|
|
}
|
|
},{}],65:[function(require,module,exports){
|
|
(function (process,global){
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
var formatRegExp = /%[sdj%]/g;
|
|
exports.format = function(f) {
|
|
if (!isString(f)) {
|
|
var objects = [];
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
objects.push(inspect(arguments[i]));
|
|
}
|
|
return objects.join(' ');
|
|
}
|
|
|
|
var i = 1;
|
|
var args = arguments;
|
|
var len = args.length;
|
|
var str = String(f).replace(formatRegExp, function(x) {
|
|
if (x === '%%') return '%';
|
|
if (i >= len) return x;
|
|
switch (x) {
|
|
case '%s': return String(args[i++]);
|
|
case '%d': return Number(args[i++]);
|
|
case '%j':
|
|
try {
|
|
return JSON.stringify(args[i++]);
|
|
} catch (_) {
|
|
return '[Circular]';
|
|
}
|
|
default:
|
|
return x;
|
|
}
|
|
});
|
|
for (var x = args[i]; i < len; x = args[++i]) {
|
|
if (isNull(x) || !isObject(x)) {
|
|
str += ' ' + x;
|
|
} else {
|
|
str += ' ' + inspect(x);
|
|
}
|
|
}
|
|
return str;
|
|
};
|
|
|
|
|
|
// Mark that a method should not be used.
|
|
// Returns a modified function which warns once by default.
|
|
// If --no-deprecation is set, then it is a no-op.
|
|
exports.deprecate = function(fn, msg) {
|
|
// Allow for deprecating things in the process of starting up.
|
|
if (isUndefined(global.process)) {
|
|
return function() {
|
|
return exports.deprecate(fn, msg).apply(this, arguments);
|
|
};
|
|
}
|
|
|
|
if (process.noDeprecation === true) {
|
|
return fn;
|
|
}
|
|
|
|
var warned = false;
|
|
function deprecated() {
|
|
if (!warned) {
|
|
if (process.throwDeprecation) {
|
|
throw new Error(msg);
|
|
} else if (process.traceDeprecation) {
|
|
console.trace(msg);
|
|
} else {
|
|
console.error(msg);
|
|
}
|
|
warned = true;
|
|
}
|
|
return fn.apply(this, arguments);
|
|
}
|
|
|
|
return deprecated;
|
|
};
|
|
|
|
|
|
var debugs = {};
|
|
var debugEnviron;
|
|
exports.debuglog = function(set) {
|
|
if (isUndefined(debugEnviron))
|
|
debugEnviron = process.env.NODE_DEBUG || '';
|
|
set = set.toUpperCase();
|
|
if (!debugs[set]) {
|
|
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
|
|
var pid = process.pid;
|
|
debugs[set] = function() {
|
|
var msg = exports.format.apply(exports, arguments);
|
|
console.error('%s %d: %s', set, pid, msg);
|
|
};
|
|
} else {
|
|
debugs[set] = function() {};
|
|
}
|
|
}
|
|
return debugs[set];
|
|
};
|
|
|
|
|
|
/**
|
|
* Echos the value of a value. Trys to print the value out
|
|
* in the best way possible given the different types.
|
|
*
|
|
* @param {Object} obj The object to print out.
|
|
* @param {Object} opts Optional options object that alters the output.
|
|
*/
|
|
/* legacy: obj, showHidden, depth, colors*/
|
|
function inspect(obj, opts) {
|
|
// default options
|
|
var ctx = {
|
|
seen: [],
|
|
stylize: stylizeNoColor
|
|
};
|
|
// legacy...
|
|
if (arguments.length >= 3) ctx.depth = arguments[2];
|
|
if (arguments.length >= 4) ctx.colors = arguments[3];
|
|
if (isBoolean(opts)) {
|
|
// legacy...
|
|
ctx.showHidden = opts;
|
|
} else if (opts) {
|
|
// got an "options" object
|
|
exports._extend(ctx, opts);
|
|
}
|
|
// set default options
|
|
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
|
|
if (isUndefined(ctx.depth)) ctx.depth = 2;
|
|
if (isUndefined(ctx.colors)) ctx.colors = false;
|
|
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
|
|
if (ctx.colors) ctx.stylize = stylizeWithColor;
|
|
return formatValue(ctx, obj, ctx.depth);
|
|
}
|
|
exports.inspect = inspect;
|
|
|
|
|
|
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
|
inspect.colors = {
|
|
'bold' : [1, 22],
|
|
'italic' : [3, 23],
|
|
'underline' : [4, 24],
|
|
'inverse' : [7, 27],
|
|
'white' : [37, 39],
|
|
'grey' : [90, 39],
|
|
'black' : [30, 39],
|
|
'blue' : [34, 39],
|
|
'cyan' : [36, 39],
|
|
'green' : [32, 39],
|
|
'magenta' : [35, 39],
|
|
'red' : [31, 39],
|
|
'yellow' : [33, 39]
|
|
};
|
|
|
|
// Don't use 'blue' not visible on cmd.exe
|
|
inspect.styles = {
|
|
'special': 'cyan',
|
|
'number': 'yellow',
|
|
'boolean': 'yellow',
|
|
'undefined': 'grey',
|
|
'null': 'bold',
|
|
'string': 'green',
|
|
'date': 'magenta',
|
|
// "name": intentionally not styling
|
|
'regexp': 'red'
|
|
};
|
|
|
|
|
|
function stylizeWithColor(str, styleType) {
|
|
var style = inspect.styles[styleType];
|
|
|
|
if (style) {
|
|
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
|
|
'\u001b[' + inspect.colors[style][1] + 'm';
|
|
} else {
|
|
return str;
|
|
}
|
|
}
|
|
|
|
|
|
function stylizeNoColor(str, styleType) {
|
|
return str;
|
|
}
|
|
|
|
|
|
function arrayToHash(array) {
|
|
var hash = {};
|
|
|
|
array.forEach(function(val, idx) {
|
|
hash[val] = true;
|
|
});
|
|
|
|
return hash;
|
|
}
|
|
|
|
|
|
function formatValue(ctx, value, recurseTimes) {
|
|
// Provide a hook for user-specified inspect functions.
|
|
// Check that value is an object with an inspect function on it
|
|
if (ctx.customInspect &&
|
|
value &&
|
|
isFunction(value.inspect) &&
|
|
// Filter out the util module, it's inspect function is special
|
|
value.inspect !== exports.inspect &&
|
|
// Also filter out any prototype objects using the circular check.
|
|
!(value.constructor && value.constructor.prototype === value)) {
|
|
var ret = value.inspect(recurseTimes, ctx);
|
|
if (!isString(ret)) {
|
|
ret = formatValue(ctx, ret, recurseTimes);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// Primitive types cannot have properties
|
|
var primitive = formatPrimitive(ctx, value);
|
|
if (primitive) {
|
|
return primitive;
|
|
}
|
|
|
|
// Look up the keys of the object.
|
|
var keys = Object.keys(value);
|
|
var visibleKeys = arrayToHash(keys);
|
|
|
|
if (ctx.showHidden) {
|
|
keys = Object.getOwnPropertyNames(value);
|
|
}
|
|
|
|
// IE doesn't make error fields non-enumerable
|
|
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
|
|
if (isError(value)
|
|
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
|
|
return formatError(value);
|
|
}
|
|
|
|
// Some type of object without properties can be shortcutted.
|
|
if (keys.length === 0) {
|
|
if (isFunction(value)) {
|
|
var name = value.name ? ': ' + value.name : '';
|
|
return ctx.stylize('[Function' + name + ']', 'special');
|
|
}
|
|
if (isRegExp(value)) {
|
|
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
|
}
|
|
if (isDate(value)) {
|
|
return ctx.stylize(Date.prototype.toString.call(value), 'date');
|
|
}
|
|
if (isError(value)) {
|
|
return formatError(value);
|
|
}
|
|
}
|
|
|
|
var base = '', array = false, braces = ['{', '}'];
|
|
|
|
// Make Array say that they are Array
|
|
if (isArray(value)) {
|
|
array = true;
|
|
braces = ['[', ']'];
|
|
}
|
|
|
|
// Make functions say that they are functions
|
|
if (isFunction(value)) {
|
|
var n = value.name ? ': ' + value.name : '';
|
|
base = ' [Function' + n + ']';
|
|
}
|
|
|
|
// Make RegExps say that they are RegExps
|
|
if (isRegExp(value)) {
|
|
base = ' ' + RegExp.prototype.toString.call(value);
|
|
}
|
|
|
|
// Make dates with properties first say the date
|
|
if (isDate(value)) {
|
|
base = ' ' + Date.prototype.toUTCString.call(value);
|
|
}
|
|
|
|
// Make error with message first say the error
|
|
if (isError(value)) {
|
|
base = ' ' + formatError(value);
|
|
}
|
|
|
|
if (keys.length === 0 && (!array || value.length == 0)) {
|
|
return braces[0] + base + braces[1];
|
|
}
|
|
|
|
if (recurseTimes < 0) {
|
|
if (isRegExp(value)) {
|
|
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
|
} else {
|
|
return ctx.stylize('[Object]', 'special');
|
|
}
|
|
}
|
|
|
|
ctx.seen.push(value);
|
|
|
|
var output;
|
|
if (array) {
|
|
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
|
|
} else {
|
|
output = keys.map(function(key) {
|
|
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
|
|
});
|
|
}
|
|
|
|
ctx.seen.pop();
|
|
|
|
return reduceToSingleString(output, base, braces);
|
|
}
|
|
|
|
|
|
function formatPrimitive(ctx, value) {
|
|
if (isUndefined(value))
|
|
return ctx.stylize('undefined', 'undefined');
|
|
if (isString(value)) {
|
|
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
|
|
.replace(/'/g, "\\'")
|
|
.replace(/\\"/g, '"') + '\'';
|
|
return ctx.stylize(simple, 'string');
|
|
}
|
|
if (isNumber(value))
|
|
return ctx.stylize('' + value, 'number');
|
|
if (isBoolean(value))
|
|
return ctx.stylize('' + value, 'boolean');
|
|
// For some reason typeof null is "object", so special case here.
|
|
if (isNull(value))
|
|
return ctx.stylize('null', 'null');
|
|
}
|
|
|
|
|
|
function formatError(value) {
|
|
return '[' + Error.prototype.toString.call(value) + ']';
|
|
}
|
|
|
|
|
|
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
|
|
var output = [];
|
|
for (var i = 0, l = value.length; i < l; ++i) {
|
|
if (hasOwnProperty(value, String(i))) {
|
|
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
|
String(i), true));
|
|
} else {
|
|
output.push('');
|
|
}
|
|
}
|
|
keys.forEach(function(key) {
|
|
if (!key.match(/^\d+$/)) {
|
|
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
|
key, true));
|
|
}
|
|
});
|
|
return output;
|
|
}
|
|
|
|
|
|
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
|
|
var name, str, desc;
|
|
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
|
|
if (desc.get) {
|
|
if (desc.set) {
|
|
str = ctx.stylize('[Getter/Setter]', 'special');
|
|
} else {
|
|
str = ctx.stylize('[Getter]', 'special');
|
|
}
|
|
} else {
|
|
if (desc.set) {
|
|
str = ctx.stylize('[Setter]', 'special');
|
|
}
|
|
}
|
|
if (!hasOwnProperty(visibleKeys, key)) {
|
|
name = '[' + key + ']';
|
|
}
|
|
if (!str) {
|
|
if (ctx.seen.indexOf(desc.value) < 0) {
|
|
if (isNull(recurseTimes)) {
|
|
str = formatValue(ctx, desc.value, null);
|
|
} else {
|
|
str = formatValue(ctx, desc.value, recurseTimes - 1);
|
|
}
|
|
if (str.indexOf('\n') > -1) {
|
|
if (array) {
|
|
str = str.split('\n').map(function(line) {
|
|
return ' ' + line;
|
|
}).join('\n').substr(2);
|
|
} else {
|
|
str = '\n' + str.split('\n').map(function(line) {
|
|
return ' ' + line;
|
|
}).join('\n');
|
|
}
|
|
}
|
|
} else {
|
|
str = ctx.stylize('[Circular]', 'special');
|
|
}
|
|
}
|
|
if (isUndefined(name)) {
|
|
if (array && key.match(/^\d+$/)) {
|
|
return str;
|
|
}
|
|
name = JSON.stringify('' + key);
|
|
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
|
name = name.substr(1, name.length - 2);
|
|
name = ctx.stylize(name, 'name');
|
|
} else {
|
|
name = name.replace(/'/g, "\\'")
|
|
.replace(/\\"/g, '"')
|
|
.replace(/(^"|"$)/g, "'");
|
|
name = ctx.stylize(name, 'string');
|
|
}
|
|
}
|
|
|
|
return name + ': ' + str;
|
|
}
|
|
|
|
|
|
function reduceToSingleString(output, base, braces) {
|
|
var numLinesEst = 0;
|
|
var length = output.reduce(function(prev, cur) {
|
|
numLinesEst++;
|
|
if (cur.indexOf('\n') >= 0) numLinesEst++;
|
|
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
|
|
}, 0);
|
|
|
|
if (length > 60) {
|
|
return braces[0] +
|
|
(base === '' ? '' : base + '\n ') +
|
|
' ' +
|
|
output.join(',\n ') +
|
|
' ' +
|
|
braces[1];
|
|
}
|
|
|
|
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
|
}
|
|
|
|
|
|
// NOTE: These type checking functions intentionally don't use `instanceof`
|
|
// because it is fragile and can be easily faked with `Object.create()`.
|
|
function isArray(ar) {
|
|
return Array.isArray(ar);
|
|
}
|
|
exports.isArray = isArray;
|
|
|
|
function isBoolean(arg) {
|
|
return typeof arg === 'boolean';
|
|
}
|
|
exports.isBoolean = isBoolean;
|
|
|
|
function isNull(arg) {
|
|
return arg === null;
|
|
}
|
|
exports.isNull = isNull;
|
|
|
|
function isNullOrUndefined(arg) {
|
|
return arg == null;
|
|
}
|
|
exports.isNullOrUndefined = isNullOrUndefined;
|
|
|
|
function isNumber(arg) {
|
|
return typeof arg === 'number';
|
|
}
|
|
exports.isNumber = isNumber;
|
|
|
|
function isString(arg) {
|
|
return typeof arg === 'string';
|
|
}
|
|
exports.isString = isString;
|
|
|
|
function isSymbol(arg) {
|
|
return typeof arg === 'symbol';
|
|
}
|
|
exports.isSymbol = isSymbol;
|
|
|
|
function isUndefined(arg) {
|
|
return arg === void 0;
|
|
}
|
|
exports.isUndefined = isUndefined;
|
|
|
|
function isRegExp(re) {
|
|
return isObject(re) && objectToString(re) === '[object RegExp]';
|
|
}
|
|
exports.isRegExp = isRegExp;
|
|
|
|
function isObject(arg) {
|
|
return typeof arg === 'object' && arg !== null;
|
|
}
|
|
exports.isObject = isObject;
|
|
|
|
function isDate(d) {
|
|
return isObject(d) && objectToString(d) === '[object Date]';
|
|
}
|
|
exports.isDate = isDate;
|
|
|
|
function isError(e) {
|
|
return isObject(e) &&
|
|
(objectToString(e) === '[object Error]' || e instanceof Error);
|
|
}
|
|
exports.isError = isError;
|
|
|
|
function isFunction(arg) {
|
|
return typeof arg === 'function';
|
|
}
|
|
exports.isFunction = isFunction;
|
|
|
|
function isPrimitive(arg) {
|
|
return arg === null ||
|
|
typeof arg === 'boolean' ||
|
|
typeof arg === 'number' ||
|
|
typeof arg === 'string' ||
|
|
typeof arg === 'symbol' || // ES6 symbol
|
|
typeof arg === 'undefined';
|
|
}
|
|
exports.isPrimitive = isPrimitive;
|
|
|
|
exports.isBuffer = require('./support/isBuffer');
|
|
|
|
function objectToString(o) {
|
|
return Object.prototype.toString.call(o);
|
|
}
|
|
|
|
|
|
function pad(n) {
|
|
return n < 10 ? '0' + n.toString(10) : n.toString(10);
|
|
}
|
|
|
|
|
|
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
|
|
'Oct', 'Nov', 'Dec'];
|
|
|
|
// 26 Feb 16:19:34
|
|
function timestamp() {
|
|
var d = new Date();
|
|
var time = [pad(d.getHours()),
|
|
pad(d.getMinutes()),
|
|
pad(d.getSeconds())].join(':');
|
|
return [d.getDate(), months[d.getMonth()], time].join(' ');
|
|
}
|
|
|
|
|
|
// log is just a thin wrapper to console.log that prepends a timestamp
|
|
exports.log = function() {
|
|
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
|
|
};
|
|
|
|
|
|
/**
|
|
* Inherit the prototype methods from one constructor into another.
|
|
*
|
|
* The Function.prototype.inherits from lang.js rewritten as a standalone
|
|
* function (not on Function.prototype). NOTE: If this file is to be loaded
|
|
* during bootstrapping this function needs to be rewritten using some native
|
|
* functions as prototype setup using normal JavaScript does not work as
|
|
* expected during bootstrapping (see mirror.js in r114903).
|
|
*
|
|
* @param {function} ctor Constructor function which needs to inherit the
|
|
* prototype.
|
|
* @param {function} superCtor Constructor function to inherit prototype from.
|
|
*/
|
|
exports.inherits = require('inherits');
|
|
|
|
exports._extend = function(origin, add) {
|
|
// Don't do anything if add isn't an object
|
|
if (!add || !isObject(add)) return origin;
|
|
|
|
var keys = Object.keys(add);
|
|
var i = keys.length;
|
|
while (i--) {
|
|
origin[keys[i]] = add[keys[i]];
|
|
}
|
|
return origin;
|
|
};
|
|
|
|
function hasOwnProperty(obj, prop) {
|
|
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
}
|
|
|
|
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
|
},{"./support/isBuffer":64,"_process":57,"inherits":63}],66:[function(require,module,exports){
|
|
var ua = typeof window !== 'undefined' ? window.navigator.userAgent : ''
|
|
, isOSX = /OS X/.test(ua)
|
|
, isOpera = /Opera/.test(ua)
|
|
, maybeFirefox = !/like Gecko/.test(ua) && !isOpera
|
|
|
|
var i, output = module.exports = {
|
|
0: isOSX ? '<menu>' : '<UNK>'
|
|
, 1: '<mouse 1>'
|
|
, 2: '<mouse 2>'
|
|
, 3: '<break>'
|
|
, 4: '<mouse 3>'
|
|
, 5: '<mouse 4>'
|
|
, 6: '<mouse 5>'
|
|
, 8: '<backspace>'
|
|
, 9: '<tab>'
|
|
, 12: '<clear>'
|
|
, 13: '<enter>'
|
|
, 16: '<shift>'
|
|
, 17: '<control>'
|
|
, 18: '<alt>'
|
|
, 19: '<pause>'
|
|
, 20: '<caps-lock>'
|
|
, 21: '<ime-hangul>'
|
|
, 23: '<ime-junja>'
|
|
, 24: '<ime-final>'
|
|
, 25: '<ime-kanji>'
|
|
, 27: '<escape>'
|
|
, 28: '<ime-convert>'
|
|
, 29: '<ime-nonconvert>'
|
|
, 30: '<ime-accept>'
|
|
, 31: '<ime-mode-change>'
|
|
, 27: '<escape>'
|
|
, 32: '<space>'
|
|
, 33: '<page-up>'
|
|
, 34: '<page-down>'
|
|
, 35: '<end>'
|
|
, 36: '<home>'
|
|
, 37: '<left>'
|
|
, 38: '<up>'
|
|
, 39: '<right>'
|
|
, 40: '<down>'
|
|
, 41: '<select>'
|
|
, 42: '<print>'
|
|
, 43: '<execute>'
|
|
, 44: '<snapshot>'
|
|
, 45: '<insert>'
|
|
, 46: '<delete>'
|
|
, 47: '<help>'
|
|
, 91: '<meta>' // meta-left -- no one handles left and right properly, so we coerce into one.
|
|
, 92: '<meta>' // meta-right
|
|
, 93: isOSX ? '<meta>' : '<menu>' // chrome,opera,safari all report this for meta-right (osx mbp).
|
|
, 95: '<sleep>'
|
|
, 106: '<num-*>'
|
|
, 107: '<num-+>'
|
|
, 108: '<num-enter>'
|
|
, 109: '<num-->'
|
|
, 110: '<num-.>'
|
|
, 111: '<num-/>'
|
|
, 144: '<num-lock>'
|
|
, 145: '<scroll-lock>'
|
|
, 160: '<shift-left>'
|
|
, 161: '<shift-right>'
|
|
, 162: '<control-left>'
|
|
, 163: '<control-right>'
|
|
, 164: '<alt-left>'
|
|
, 165: '<alt-right>'
|
|
, 166: '<browser-back>'
|
|
, 167: '<browser-forward>'
|
|
, 168: '<browser-refresh>'
|
|
, 169: '<browser-stop>'
|
|
, 170: '<browser-search>'
|
|
, 171: '<browser-favorites>'
|
|
, 172: '<browser-home>'
|
|
|
|
// ff/osx reports '<volume-mute>' for '-'
|
|
, 173: isOSX && maybeFirefox ? '-' : '<volume-mute>'
|
|
, 174: '<volume-down>'
|
|
, 175: '<volume-up>'
|
|
, 176: '<next-track>'
|
|
, 177: '<prev-track>'
|
|
, 178: '<stop>'
|
|
, 179: '<play-pause>'
|
|
, 180: '<launch-mail>'
|
|
, 181: '<launch-media-select>'
|
|
, 182: '<launch-app 1>'
|
|
, 183: '<launch-app 2>'
|
|
, 186: ';'
|
|
, 187: '='
|
|
, 188: ','
|
|
, 189: '-'
|
|
, 190: '.'
|
|
, 191: '/'
|
|
, 192: '`'
|
|
, 219: '['
|
|
, 220: '\\'
|
|
, 221: ']'
|
|
, 222: "'"
|
|
, 223: '<meta>'
|
|
, 224: '<meta>' // firefox reports meta here.
|
|
, 226: '<alt-gr>'
|
|
, 229: '<ime-process>'
|
|
, 231: isOpera ? '`' : '<unicode>'
|
|
, 246: '<attention>'
|
|
, 247: '<crsel>'
|
|
, 248: '<exsel>'
|
|
, 249: '<erase-eof>'
|
|
, 250: '<play>'
|
|
, 251: '<zoom>'
|
|
, 252: '<no-name>'
|
|
, 253: '<pa-1>'
|
|
, 254: '<clear>'
|
|
}
|
|
|
|
for(i = 58; i < 65; ++i) {
|
|
output[i] = String.fromCharCode(i)
|
|
}
|
|
|
|
// 0-9
|
|
for(i = 48; i < 58; ++i) {
|
|
output[i] = (i - 48)+''
|
|
}
|
|
|
|
// A-Z
|
|
for(i = 65; i < 91; ++i) {
|
|
output[i] = String.fromCharCode(i)
|
|
}
|
|
|
|
// num0-9
|
|
for(i = 96; i < 106; ++i) {
|
|
output[i] = '<num-'+(i - 96)+'>'
|
|
}
|
|
|
|
// F1-F24
|
|
for(i = 112; i < 136; ++i) {
|
|
output[i] = 'F'+(i-111)
|
|
}
|
|
|
|
},{}],67:[function(require,module,exports){
|
|
// Copyright (C) 2011 Google Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
/**
|
|
* @fileoverview Install a leaky WeakMap emulation on platforms that
|
|
* don't provide a built-in one.
|
|
*
|
|
* <p>Assumes that an ES5 platform where, if {@code WeakMap} is
|
|
* already present, then it conforms to the anticipated ES6
|
|
* specification. To run this file on an ES5 or almost ES5
|
|
* implementation where the {@code WeakMap} specification does not
|
|
* quite conform, run <code>repairES5.js</code> first.
|
|
*
|
|
* <p>Even though WeakMapModule is not global, the linter thinks it
|
|
* is, which is why it is in the overrides list below.
|
|
*
|
|
* <p>NOTE: Before using this WeakMap emulation in a non-SES
|
|
* environment, see the note below about hiddenRecord.
|
|
*
|
|
* @author Mark S. Miller
|
|
* @requires crypto, ArrayBuffer, Uint8Array, navigator, console
|
|
* @overrides WeakMap, ses, Proxy
|
|
* @overrides WeakMapModule
|
|
*/
|
|
|
|
/**
|
|
* This {@code WeakMap} emulation is observably equivalent to the
|
|
* ES-Harmony WeakMap, but with leakier garbage collection properties.
|
|
*
|
|
* <p>As with true WeakMaps, in this emulation, a key does not
|
|
* retain maps indexed by that key and (crucially) a map does not
|
|
* retain the keys it indexes. A map by itself also does not retain
|
|
* the values associated with that map.
|
|
*
|
|
* <p>However, the values associated with a key in some map are
|
|
* retained so long as that key is retained and those associations are
|
|
* not overridden. For example, when used to support membranes, all
|
|
* values exported from a given membrane will live for the lifetime
|
|
* they would have had in the absence of an interposed membrane. Even
|
|
* when the membrane is revoked, all objects that would have been
|
|
* reachable in the absence of revocation will still be reachable, as
|
|
* far as the GC can tell, even though they will no longer be relevant
|
|
* to ongoing computation.
|
|
*
|
|
* <p>The API implemented here is approximately the API as implemented
|
|
* in FF6.0a1 and agreed to by MarkM, Andreas Gal, and Dave Herman,
|
|
* rather than the offially approved proposal page. TODO(erights):
|
|
* upgrade the ecmascript WeakMap proposal page to explain this API
|
|
* change and present to EcmaScript committee for their approval.
|
|
*
|
|
* <p>The first difference between the emulation here and that in
|
|
* FF6.0a1 is the presence of non enumerable {@code get___, has___,
|
|
* set___, and delete___} methods on WeakMap instances to represent
|
|
* what would be the hidden internal properties of a primitive
|
|
* implementation. Whereas the FF6.0a1 WeakMap.prototype methods
|
|
* require their {@code this} to be a genuine WeakMap instance (i.e.,
|
|
* an object of {@code [[Class]]} "WeakMap}), since there is nothing
|
|
* unforgeable about the pseudo-internal method names used here,
|
|
* nothing prevents these emulated prototype methods from being
|
|
* applied to non-WeakMaps with pseudo-internal methods of the same
|
|
* names.
|
|
*
|
|
* <p>Another difference is that our emulated {@code
|
|
* WeakMap.prototype} is not itself a WeakMap. A problem with the
|
|
* current FF6.0a1 API is that WeakMap.prototype is itself a WeakMap
|
|
* providing ambient mutability and an ambient communications
|
|
* channel. Thus, if a WeakMap is already present and has this
|
|
* problem, repairES5.js wraps it in a safe wrappper in order to
|
|
* prevent access to this channel. (See
|
|
* PATCH_MUTABLE_FROZEN_WEAKMAP_PROTO in repairES5.js).
|
|
*/
|
|
|
|
/**
|
|
* If this is a full <a href=
|
|
* "http://code.google.com/p/es-lab/wiki/SecureableES5"
|
|
* >secureable ES5</a> platform and the ES-Harmony {@code WeakMap} is
|
|
* absent, install an approximate emulation.
|
|
*
|
|
* <p>If WeakMap is present but cannot store some objects, use our approximate
|
|
* emulation as a wrapper.
|
|
*
|
|
* <p>If this is almost a secureable ES5 platform, then WeakMap.js
|
|
* should be run after repairES5.js.
|
|
*
|
|
* <p>See {@code WeakMap} for documentation of the garbage collection
|
|
* properties of this WeakMap emulation.
|
|
*/
|
|
(function WeakMapModule() {
|
|
"use strict";
|
|
|
|
if (typeof ses !== 'undefined' && ses.ok && !ses.ok()) {
|
|
// already too broken, so give up
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* In some cases (current Firefox), we must make a choice betweeen a
|
|
* WeakMap which is capable of using all varieties of host objects as
|
|
* keys and one which is capable of safely using proxies as keys. See
|
|
* comments below about HostWeakMap and DoubleWeakMap for details.
|
|
*
|
|
* This function (which is a global, not exposed to guests) marks a
|
|
* WeakMap as permitted to do what is necessary to index all host
|
|
* objects, at the cost of making it unsafe for proxies.
|
|
*
|
|
* Do not apply this function to anything which is not a genuine
|
|
* fresh WeakMap.
|
|
*/
|
|
function weakMapPermitHostObjects(map) {
|
|
// identity of function used as a secret -- good enough and cheap
|
|
if (map.permitHostObjects___) {
|
|
map.permitHostObjects___(weakMapPermitHostObjects);
|
|
}
|
|
}
|
|
if (typeof ses !== 'undefined') {
|
|
ses.weakMapPermitHostObjects = weakMapPermitHostObjects;
|
|
}
|
|
|
|
// IE 11 has no Proxy but has a broken WeakMap such that we need to patch
|
|
// it using DoubleWeakMap; this flag tells DoubleWeakMap so.
|
|
var doubleWeakMapCheckSilentFailure = false;
|
|
|
|
// Check if there is already a good-enough WeakMap implementation, and if so
|
|
// exit without replacing it.
|
|
if (typeof WeakMap === 'function') {
|
|
var HostWeakMap = WeakMap;
|
|
// There is a WeakMap -- is it good enough?
|
|
if (typeof navigator !== 'undefined' &&
|
|
/Firefox/.test(navigator.userAgent)) {
|
|
// We're now *assuming not*, because as of this writing (2013-05-06)
|
|
// Firefox's WeakMaps have a miscellany of objects they won't accept, and
|
|
// we don't want to make an exhaustive list, and testing for just one
|
|
// will be a problem if that one is fixed alone (as they did for Event).
|
|
|
|
// If there is a platform that we *can* reliably test on, here's how to
|
|
// do it:
|
|
// var problematic = ... ;
|
|
// var testHostMap = new HostWeakMap();
|
|
// try {
|
|
// testHostMap.set(problematic, 1); // Firefox 20 will throw here
|
|
// if (testHostMap.get(problematic) === 1) {
|
|
// return;
|
|
// }
|
|
// } catch (e) {}
|
|
|
|
} else {
|
|
// IE 11 bug: WeakMaps silently fail to store frozen objects.
|
|
var testMap = new HostWeakMap();
|
|
var testObject = Object.freeze({});
|
|
testMap.set(testObject, 1);
|
|
if (testMap.get(testObject) !== 1) {
|
|
doubleWeakMapCheckSilentFailure = true;
|
|
// Fall through to installing our WeakMap.
|
|
} else {
|
|
module.exports = WeakMap;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
var hop = Object.prototype.hasOwnProperty;
|
|
var gopn = Object.getOwnPropertyNames;
|
|
var defProp = Object.defineProperty;
|
|
var isExtensible = Object.isExtensible;
|
|
|
|
/**
|
|
* Security depends on HIDDEN_NAME being both <i>unguessable</i> and
|
|
* <i>undiscoverable</i> by untrusted code.
|
|
*
|
|
* <p>Given the known weaknesses of Math.random() on existing
|
|
* browsers, it does not generate unguessability we can be confident
|
|
* of.
|
|
*
|
|
* <p>It is the monkey patching logic in this file that is intended
|
|
* to ensure undiscoverability. The basic idea is that there are
|
|
* three fundamental means of discovering properties of an object:
|
|
* The for/in loop, Object.keys(), and Object.getOwnPropertyNames(),
|
|
* as well as some proposed ES6 extensions that appear on our
|
|
* whitelist. The first two only discover enumerable properties, and
|
|
* we only use HIDDEN_NAME to name a non-enumerable property, so the
|
|
* only remaining threat should be getOwnPropertyNames and some
|
|
* proposed ES6 extensions that appear on our whitelist. We monkey
|
|
* patch them to remove HIDDEN_NAME from the list of properties they
|
|
* returns.
|
|
*
|
|
* <p>TODO(erights): On a platform with built-in Proxies, proxies
|
|
* could be used to trap and thereby discover the HIDDEN_NAME, so we
|
|
* need to monkey patch Proxy.create, Proxy.createFunction, etc, in
|
|
* order to wrap the provided handler with the real handler which
|
|
* filters out all traps using HIDDEN_NAME.
|
|
*
|
|
* <p>TODO(erights): Revisit Mike Stay's suggestion that we use an
|
|
* encapsulated function at a not-necessarily-secret name, which
|
|
* uses the Stiegler shared-state rights amplification pattern to
|
|
* reveal the associated value only to the WeakMap in which this key
|
|
* is associated with that value. Since only the key retains the
|
|
* function, the function can also remember the key without causing
|
|
* leakage of the key, so this doesn't violate our general gc
|
|
* goals. In addition, because the name need not be a guarded
|
|
* secret, we could efficiently handle cross-frame frozen keys.
|
|
*/
|
|
var HIDDEN_NAME_PREFIX = 'weakmap:';
|
|
var HIDDEN_NAME = HIDDEN_NAME_PREFIX + 'ident:' + Math.random() + '___';
|
|
|
|
if (typeof crypto !== 'undefined' &&
|
|
typeof crypto.getRandomValues === 'function' &&
|
|
typeof ArrayBuffer === 'function' &&
|
|
typeof Uint8Array === 'function') {
|
|
var ab = new ArrayBuffer(25);
|
|
var u8s = new Uint8Array(ab);
|
|
crypto.getRandomValues(u8s);
|
|
HIDDEN_NAME = HIDDEN_NAME_PREFIX + 'rand:' +
|
|
Array.prototype.map.call(u8s, function(u8) {
|
|
return (u8 % 36).toString(36);
|
|
}).join('') + '___';
|
|
}
|
|
|
|
function isNotHiddenName(name) {
|
|
return !(
|
|
name.substr(0, HIDDEN_NAME_PREFIX.length) == HIDDEN_NAME_PREFIX &&
|
|
name.substr(name.length - 3) === '___');
|
|
}
|
|
|
|
/**
|
|
* Monkey patch getOwnPropertyNames to avoid revealing the
|
|
* HIDDEN_NAME.
|
|
*
|
|
* <p>The ES5.1 spec requires each name to appear only once, but as
|
|
* of this writing, this requirement is controversial for ES6, so we
|
|
* made this code robust against this case. If the resulting extra
|
|
* search turns out to be expensive, we can probably relax this once
|
|
* ES6 is adequately supported on all major browsers, iff no browser
|
|
* versions we support at that time have relaxed this constraint
|
|
* without providing built-in ES6 WeakMaps.
|
|
*/
|
|
defProp(Object, 'getOwnPropertyNames', {
|
|
value: function fakeGetOwnPropertyNames(obj) {
|
|
return gopn(obj).filter(isNotHiddenName);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* getPropertyNames is not in ES5 but it is proposed for ES6 and
|
|
* does appear in our whitelist, so we need to clean it too.
|
|
*/
|
|
if ('getPropertyNames' in Object) {
|
|
var originalGetPropertyNames = Object.getPropertyNames;
|
|
defProp(Object, 'getPropertyNames', {
|
|
value: function fakeGetPropertyNames(obj) {
|
|
return originalGetPropertyNames(obj).filter(isNotHiddenName);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* <p>To treat objects as identity-keys with reasonable efficiency
|
|
* on ES5 by itself (i.e., without any object-keyed collections), we
|
|
* need to add a hidden property to such key objects when we
|
|
* can. This raises several issues:
|
|
* <ul>
|
|
* <li>Arranging to add this property to objects before we lose the
|
|
* chance, and
|
|
* <li>Hiding the existence of this new property from most
|
|
* JavaScript code.
|
|
* <li>Preventing <i>certification theft</i>, where one object is
|
|
* created falsely claiming to be the key of an association
|
|
* actually keyed by another object.
|
|
* <li>Preventing <i>value theft</i>, where untrusted code with
|
|
* access to a key object but not a weak map nevertheless
|
|
* obtains access to the value associated with that key in that
|
|
* weak map.
|
|
* </ul>
|
|
* We do so by
|
|
* <ul>
|
|
* <li>Making the name of the hidden property unguessable, so "[]"
|
|
* indexing, which we cannot intercept, cannot be used to access
|
|
* a property without knowing the name.
|
|
* <li>Making the hidden property non-enumerable, so we need not
|
|
* worry about for-in loops or {@code Object.keys},
|
|
* <li>monkey patching those reflective methods that would
|
|
* prevent extensions, to add this hidden property first,
|
|
* <li>monkey patching those methods that would reveal this
|
|
* hidden property.
|
|
* </ul>
|
|
* Unfortunately, because of same-origin iframes, we cannot reliably
|
|
* add this hidden property before an object becomes
|
|
* non-extensible. Instead, if we encounter a non-extensible object
|
|
* without a hidden record that we can detect (whether or not it has
|
|
* a hidden record stored under a name secret to us), then we just
|
|
* use the key object itself to represent its identity in a brute
|
|
* force leaky map stored in the weak map, losing all the advantages
|
|
* of weakness for these.
|
|
*/
|
|
function getHiddenRecord(key) {
|
|
if (key !== Object(key)) {
|
|
throw new TypeError('Not an object: ' + key);
|
|
}
|
|
var hiddenRecord = key[HIDDEN_NAME];
|
|
if (hiddenRecord && hiddenRecord.key === key) { return hiddenRecord; }
|
|
if (!isExtensible(key)) {
|
|
// Weak map must brute force, as explained in doc-comment above.
|
|
return void 0;
|
|
}
|
|
|
|
// The hiddenRecord and the key point directly at each other, via
|
|
// the "key" and HIDDEN_NAME properties respectively. The key
|
|
// field is for quickly verifying that this hidden record is an
|
|
// own property, not a hidden record from up the prototype chain.
|
|
//
|
|
// NOTE: Because this WeakMap emulation is meant only for systems like
|
|
// SES where Object.prototype is frozen without any numeric
|
|
// properties, it is ok to use an object literal for the hiddenRecord.
|
|
// This has two advantages:
|
|
// * It is much faster in a performance critical place
|
|
// * It avoids relying on Object.create(null), which had been
|
|
// problematic on Chrome 28.0.1480.0. See
|
|
// https://code.google.com/p/google-caja/issues/detail?id=1687
|
|
hiddenRecord = { key: key };
|
|
|
|
// When using this WeakMap emulation on platforms where
|
|
// Object.prototype might not be frozen and Object.create(null) is
|
|
// reliable, use the following two commented out lines instead.
|
|
// hiddenRecord = Object.create(null);
|
|
// hiddenRecord.key = key;
|
|
|
|
// Please contact us if you need this to work on platforms where
|
|
// Object.prototype might not be frozen and
|
|
// Object.create(null) might not be reliable.
|
|
|
|
try {
|
|
defProp(key, HIDDEN_NAME, {
|
|
value: hiddenRecord,
|
|
writable: false,
|
|
enumerable: false,
|
|
configurable: false
|
|
});
|
|
return hiddenRecord;
|
|
} catch (error) {
|
|
// Under some circumstances, isExtensible seems to misreport whether
|
|
// the HIDDEN_NAME can be defined.
|
|
// The circumstances have not been isolated, but at least affect
|
|
// Node.js v0.10.26 on TravisCI / Linux, but not the same version of
|
|
// Node.js on OS X.
|
|
return void 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Monkey patch operations that would make their argument
|
|
* non-extensible.
|
|
*
|
|
* <p>The monkey patched versions throw a TypeError if their
|
|
* argument is not an object, so it should only be done to functions
|
|
* that should throw a TypeError anyway if their argument is not an
|
|
* object.
|
|
*/
|
|
(function(){
|
|
var oldFreeze = Object.freeze;
|
|
defProp(Object, 'freeze', {
|
|
value: function identifyingFreeze(obj) {
|
|
getHiddenRecord(obj);
|
|
return oldFreeze(obj);
|
|
}
|
|
});
|
|
var oldSeal = Object.seal;
|
|
defProp(Object, 'seal', {
|
|
value: function identifyingSeal(obj) {
|
|
getHiddenRecord(obj);
|
|
return oldSeal(obj);
|
|
}
|
|
});
|
|
var oldPreventExtensions = Object.preventExtensions;
|
|
defProp(Object, 'preventExtensions', {
|
|
value: function identifyingPreventExtensions(obj) {
|
|
getHiddenRecord(obj);
|
|
return oldPreventExtensions(obj);
|
|
}
|
|
});
|
|
})();
|
|
|
|
function constFunc(func) {
|
|
func.prototype = null;
|
|
return Object.freeze(func);
|
|
}
|
|
|
|
var calledAsFunctionWarningDone = false;
|
|
function calledAsFunctionWarning() {
|
|
// Future ES6 WeakMap is currently (2013-09-10) expected to reject WeakMap()
|
|
// but we used to permit it and do it ourselves, so warn only.
|
|
if (!calledAsFunctionWarningDone && typeof console !== 'undefined') {
|
|
calledAsFunctionWarningDone = true;
|
|
console.warn('WeakMap should be invoked as new WeakMap(), not ' +
|
|
'WeakMap(). This will be an error in the future.');
|
|
}
|
|
}
|
|
|
|
var nextId = 0;
|
|
|
|
var OurWeakMap = function() {
|
|
if (!(this instanceof OurWeakMap)) { // approximate test for new ...()
|
|
calledAsFunctionWarning();
|
|
}
|
|
|
|
// We are currently (12/25/2012) never encountering any prematurely
|
|
// non-extensible keys.
|
|
var keys = []; // brute force for prematurely non-extensible keys.
|
|
var values = []; // brute force for corresponding values.
|
|
var id = nextId++;
|
|
|
|
function get___(key, opt_default) {
|
|
var index;
|
|
var hiddenRecord = getHiddenRecord(key);
|
|
if (hiddenRecord) {
|
|
return id in hiddenRecord ? hiddenRecord[id] : opt_default;
|
|
} else {
|
|
index = keys.indexOf(key);
|
|
return index >= 0 ? values[index] : opt_default;
|
|
}
|
|
}
|
|
|
|
function has___(key) {
|
|
var hiddenRecord = getHiddenRecord(key);
|
|
if (hiddenRecord) {
|
|
return id in hiddenRecord;
|
|
} else {
|
|
return keys.indexOf(key) >= 0;
|
|
}
|
|
}
|
|
|
|
function set___(key, value) {
|
|
var index;
|
|
var hiddenRecord = getHiddenRecord(key);
|
|
if (hiddenRecord) {
|
|
hiddenRecord[id] = value;
|
|
} else {
|
|
index = keys.indexOf(key);
|
|
if (index >= 0) {
|
|
values[index] = value;
|
|
} else {
|
|
// Since some browsers preemptively terminate slow turns but
|
|
// then continue computing with presumably corrupted heap
|
|
// state, we here defensively get keys.length first and then
|
|
// use it to update both the values and keys arrays, keeping
|
|
// them in sync.
|
|
index = keys.length;
|
|
values[index] = value;
|
|
// If we crash here, values will be one longer than keys.
|
|
keys[index] = key;
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
|
|
function delete___(key) {
|
|
var hiddenRecord = getHiddenRecord(key);
|
|
var index, lastIndex;
|
|
if (hiddenRecord) {
|
|
return id in hiddenRecord && delete hiddenRecord[id];
|
|
} else {
|
|
index = keys.indexOf(key);
|
|
if (index < 0) {
|
|
return false;
|
|
}
|
|
// Since some browsers preemptively terminate slow turns but
|
|
// then continue computing with potentially corrupted heap
|
|
// state, we here defensively get keys.length first and then use
|
|
// it to update both the keys and the values array, keeping
|
|
// them in sync. We update the two with an order of assignments,
|
|
// such that any prefix of these assignments will preserve the
|
|
// key/value correspondence, either before or after the delete.
|
|
// Note that this needs to work correctly when index === lastIndex.
|
|
lastIndex = keys.length - 1;
|
|
keys[index] = void 0;
|
|
// If we crash here, there's a void 0 in the keys array, but
|
|
// no operation will cause a "keys.indexOf(void 0)", since
|
|
// getHiddenRecord(void 0) will always throw an error first.
|
|
values[index] = values[lastIndex];
|
|
// If we crash here, values[index] cannot be found here,
|
|
// because keys[index] is void 0.
|
|
keys[index] = keys[lastIndex];
|
|
// If index === lastIndex and we crash here, then keys[index]
|
|
// is still void 0, since the aliasing killed the previous key.
|
|
keys.length = lastIndex;
|
|
// If we crash here, keys will be one shorter than values.
|
|
values.length = lastIndex;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return Object.create(OurWeakMap.prototype, {
|
|
get___: { value: constFunc(get___) },
|
|
has___: { value: constFunc(has___) },
|
|
set___: { value: constFunc(set___) },
|
|
delete___: { value: constFunc(delete___) }
|
|
});
|
|
};
|
|
|
|
OurWeakMap.prototype = Object.create(Object.prototype, {
|
|
get: {
|
|
/**
|
|
* Return the value most recently associated with key, or
|
|
* opt_default if none.
|
|
*/
|
|
value: function get(key, opt_default) {
|
|
return this.get___(key, opt_default);
|
|
},
|
|
writable: true,
|
|
configurable: true
|
|
},
|
|
|
|
has: {
|
|
/**
|
|
* Is there a value associated with key in this WeakMap?
|
|
*/
|
|
value: function has(key) {
|
|
return this.has___(key);
|
|
},
|
|
writable: true,
|
|
configurable: true
|
|
},
|
|
|
|
set: {
|
|
/**
|
|
* Associate value with key in this WeakMap, overwriting any
|
|
* previous association if present.
|
|
*/
|
|
value: function set(key, value) {
|
|
return this.set___(key, value);
|
|
},
|
|
writable: true,
|
|
configurable: true
|
|
},
|
|
|
|
'delete': {
|
|
/**
|
|
* Remove any association for key in this WeakMap, returning
|
|
* whether there was one.
|
|
*
|
|
* <p>Note that the boolean return here does not work like the
|
|
* {@code delete} operator. The {@code delete} operator returns
|
|
* whether the deletion succeeds at bringing about a state in
|
|
* which the deleted property is absent. The {@code delete}
|
|
* operator therefore returns true if the property was already
|
|
* absent, whereas this {@code delete} method returns false if
|
|
* the association was already absent.
|
|
*/
|
|
value: function remove(key) {
|
|
return this.delete___(key);
|
|
},
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
});
|
|
|
|
if (typeof HostWeakMap === 'function') {
|
|
(function() {
|
|
// If we got here, then the platform has a WeakMap but we are concerned
|
|
// that it may refuse to store some key types. Therefore, make a map
|
|
// implementation which makes use of both as possible.
|
|
|
|
// In this mode we are always using double maps, so we are not proxy-safe.
|
|
// This combination does not occur in any known browser, but we had best
|
|
// be safe.
|
|
if (doubleWeakMapCheckSilentFailure && typeof Proxy !== 'undefined') {
|
|
Proxy = undefined;
|
|
}
|
|
|
|
function DoubleWeakMap() {
|
|
if (!(this instanceof OurWeakMap)) { // approximate test for new ...()
|
|
calledAsFunctionWarning();
|
|
}
|
|
|
|
// Preferable, truly weak map.
|
|
var hmap = new HostWeakMap();
|
|
|
|
// Our hidden-property-based pseudo-weak-map. Lazily initialized in the
|
|
// 'set' implementation; thus we can avoid performing extra lookups if
|
|
// we know all entries actually stored are entered in 'hmap'.
|
|
var omap = undefined;
|
|
|
|
// Hidden-property maps are not compatible with proxies because proxies
|
|
// can observe the hidden name and either accidentally expose it or fail
|
|
// to allow the hidden property to be set. Therefore, we do not allow
|
|
// arbitrary WeakMaps to switch to using hidden properties, but only
|
|
// those which need the ability, and unprivileged code is not allowed
|
|
// to set the flag.
|
|
//
|
|
// (Except in doubleWeakMapCheckSilentFailure mode in which case we
|
|
// disable proxies.)
|
|
var enableSwitching = false;
|
|
|
|
function dget(key, opt_default) {
|
|
if (omap) {
|
|
return hmap.has(key) ? hmap.get(key)
|
|
: omap.get___(key, opt_default);
|
|
} else {
|
|
return hmap.get(key, opt_default);
|
|
}
|
|
}
|
|
|
|
function dhas(key) {
|
|
return hmap.has(key) || (omap ? omap.has___(key) : false);
|
|
}
|
|
|
|
var dset;
|
|
if (doubleWeakMapCheckSilentFailure) {
|
|
dset = function(key, value) {
|
|
hmap.set(key, value);
|
|
if (!hmap.has(key)) {
|
|
if (!omap) { omap = new OurWeakMap(); }
|
|
omap.set(key, value);
|
|
}
|
|
return this;
|
|
};
|
|
} else {
|
|
dset = function(key, value) {
|
|
if (enableSwitching) {
|
|
try {
|
|
hmap.set(key, value);
|
|
} catch (e) {
|
|
if (!omap) { omap = new OurWeakMap(); }
|
|
omap.set___(key, value);
|
|
}
|
|
} else {
|
|
hmap.set(key, value);
|
|
}
|
|
return this;
|
|
};
|
|
}
|
|
|
|
function ddelete(key) {
|
|
var result = !!hmap['delete'](key);
|
|
if (omap) { return omap.delete___(key) || result; }
|
|
return result;
|
|
}
|
|
|
|
return Object.create(OurWeakMap.prototype, {
|
|
get___: { value: constFunc(dget) },
|
|
has___: { value: constFunc(dhas) },
|
|
set___: { value: constFunc(dset) },
|
|
delete___: { value: constFunc(ddelete) },
|
|
permitHostObjects___: { value: constFunc(function(token) {
|
|
if (token === weakMapPermitHostObjects) {
|
|
enableSwitching = true;
|
|
} else {
|
|
throw new Error('bogus call to permitHostObjects___');
|
|
}
|
|
})}
|
|
});
|
|
}
|
|
DoubleWeakMap.prototype = OurWeakMap.prototype;
|
|
module.exports = DoubleWeakMap;
|
|
|
|
// define .constructor to hide OurWeakMap ctor
|
|
Object.defineProperty(WeakMap.prototype, 'constructor', {
|
|
value: WeakMap,
|
|
enumerable: false, // as default .constructor is
|
|
configurable: true,
|
|
writable: true
|
|
});
|
|
})();
|
|
} else {
|
|
// There is no host WeakMap, so we must use the emulation.
|
|
|
|
// Emulated WeakMaps are incompatible with native proxies (because proxies
|
|
// can observe the hidden name), so we must disable Proxy usage (in
|
|
// ArrayLike and Domado, currently).
|
|
if (typeof Proxy !== 'undefined') {
|
|
Proxy = undefined;
|
|
}
|
|
|
|
module.exports = OurWeakMap;
|
|
}
|
|
})();
|
|
|
|
},{}],68:[function(require,module,exports){
|
|
var hiddenStore = require('./hidden-store.js');
|
|
|
|
module.exports = createStore;
|
|
|
|
function createStore() {
|
|
var key = {};
|
|
|
|
return function (obj) {
|
|
if ((typeof obj !== 'object' || obj === null) &&
|
|
typeof obj !== 'function'
|
|
) {
|
|
throw new Error('Weakmap-shim: Key must be object')
|
|
}
|
|
|
|
var store = obj.valueOf(key);
|
|
return store && store.identity === key ?
|
|
store : hiddenStore(obj, key);
|
|
};
|
|
}
|
|
|
|
},{"./hidden-store.js":69}],69:[function(require,module,exports){
|
|
module.exports = hiddenStore;
|
|
|
|
function hiddenStore(obj, key) {
|
|
var store = { identity: key };
|
|
var valueOf = obj.valueOf;
|
|
|
|
Object.defineProperty(obj, "valueOf", {
|
|
value: function (value) {
|
|
return value !== key ?
|
|
valueOf.apply(this, arguments) : store;
|
|
},
|
|
writable: true
|
|
});
|
|
|
|
return store;
|
|
}
|
|
|
|
},{}],70:[function(require,module,exports){
|
|
// Original - @Gozola.
|
|
// https://gist.github.com/Gozala/1269991
|
|
// This is a reimplemented version (with a few bug fixes).
|
|
|
|
var createStore = require('./create-store.js');
|
|
|
|
module.exports = weakMap;
|
|
|
|
function weakMap() {
|
|
var privates = createStore();
|
|
|
|
return {
|
|
'get': function (key, fallback) {
|
|
var store = privates(key)
|
|
return store.hasOwnProperty('value') ?
|
|
store.value : fallback
|
|
},
|
|
'set': function (key, value) {
|
|
privates(key).value = value;
|
|
return this;
|
|
},
|
|
'has': function(key) {
|
|
return 'value' in privates(key);
|
|
},
|
|
'delete': function (key) {
|
|
return delete privates(key).value;
|
|
}
|
|
}
|
|
}
|
|
|
|
},{"./create-store.js":68}],71:[function(require,module,exports){
|
|
'use strict'
|
|
|
|
var weakMap = typeof WeakMap === 'undefined' ? require('weak-map') : WeakMap
|
|
|
|
var WebGLEWStruct = new weakMap()
|
|
|
|
function baseName(ext_name) {
|
|
return ext_name.replace(/^[A-Z]+_/, '')
|
|
}
|
|
|
|
function initWebGLEW(gl) {
|
|
var struct = WebGLEWStruct.get(gl)
|
|
if(struct) {
|
|
return struct
|
|
}
|
|
var extensions = {}
|
|
var supported = gl.getSupportedExtensions()
|
|
for(var i=0; i<supported.length; ++i) {
|
|
var extName = supported[i]
|
|
|
|
//Skip MOZ_ extensions
|
|
if(extName.indexOf('MOZ_') === 0) {
|
|
continue
|
|
}
|
|
var ext = gl.getExtension(supported[i])
|
|
if(!ext) {
|
|
continue
|
|
}
|
|
while(true) {
|
|
extensions[extName] = ext
|
|
var base = baseName(extName)
|
|
if(base === extName) {
|
|
break
|
|
}
|
|
extName = base
|
|
}
|
|
}
|
|
WebGLEWStruct.set(gl, extensions)
|
|
return extensions
|
|
}
|
|
module.exports = initWebGLEW
|
|
},{"weak-map":67}]},{},[1]);
|