javascript
hello world(data uri)
code
<!doctype html><head><script>{
console.log(`hello world`)//hello world
}</script></head></html>
const, let(data uri)
code
<!doctype html><head><script>try{
console.log(`--const--`)
const v=`hello world`
console.log(v)//hello world
v=undefined
}catch(e){
console.log(e instanceof TypeError)//true
}
{
console.log(`--let--`)
let v
console.log(v)//undefined
v=`hello world`
console.log(v)//hello world
}</script></head></html>
Array(data uri)
code
<!doctype html><head><script>{
console.log(`--Array--`)
console.log([])//[]
console.log(Array())//[]
console.log([0])//[0]
console.log(Array(0))//[]
console.log([1])//[1]
console.log(Array(1))//[empty]
console.log([2])//[2]
console.log(Array(2))//[empty, empty]
console.log([0,1])//[0, 1]
console.log(Array(0,1))//[0, 1]
}
{
console.log(`--push, pop, reverse--`)
const vs=[]
console.log(vs.push(0))//1
console.log(vs)//[0]
console.log(vs.push(1,2))//3
console.log(vs)//[0, 1, 2]
console.log(vs[1]=3)//3
console.log(vs)//[0, 3, 2]
console.log(vs.pop())//2
console.log(vs)//[0, 3]
console.log(vs.reverse())//[3, 0]
console.log(vs)//[3, 0]
}
{
console.log(`--isArray--`)
console.log(Array.isArray([]))//true
console.log(Array.isArray(Array()))//true
console.log(Array.isArray(undefined))//false
console.log(Array.isArray(null))//false
console.log(Array.isArray(0))//false
console.log(Array.isArray(``))//false
}
{
console.log(`--equals--`)
Array.prototype.equals=function(v){
return v.length===this.length&&v.every((v,i)=>v===this[i])
}
console.log([].equals([]))//true
console.log([]===[])//false
}</script></head></html>
crypto.subtle(data uri)
code
<!doctype html><head><script>{
if(!crypto.subtle)throw Error(`available in secure contexts.`)
const string=`hello world`
,encoder=new TextEncoder()
,decoder=new TextDecoder()
,aesCTR=async(v,keyLength,length,hashParams)=>{
const algorithm={name:`AES-CTR`},signAlgorithm=`HMAC`,format=`raw`,signFormat=`raw`
,aesKeyGenParams=Object.assign({},algorithm,{length:keyLength})
,aesCtrParams=Object.assign({},algorithm,{counter:v,length:length})
,hmacKeyParams=Object.assign({},{name:signAlgorithm},hashParams)
,key=await crypto.subtle.generateKey(aesKeyGenParams,true,[`encrypt`])
,exportKey=await crypto.subtle.exportKey(format,key),encrypted=await crypto.subtle.encrypt(aesCtrParams,key,encoder.encode(string))
,signKey=await crypto.subtle.generateKey(hmacKeyParams,true,[`sign`])
,exportSignKey=await crypto.subtle.exportKey(signFormat,signKey)
,sign=await crypto.subtle.sign(signAlgorithm,signKey,encrypted)
console.log(algorithm.name)
console.log(await crypto.subtle.verify(signAlgorithm,await crypto.subtle.importKey(signFormat,exportSignKey,hmacKeyParams,false,[`verify`]),sign,encrypted))//true
console.log(decoder.decode(await crypto.subtle.decrypt(aesCtrParams,await crypto.subtle.importKey(format,exportKey,algorithm,false,[`decrypt`]),encrypted)))//hello world
}
,aesCBC=async(v,keyLength,hashParams)=>{
const algorithm={name:`AES-CBC`},signAlgorithm=`HMAC`,format=`raw`,signFormat=`raw`
,aesKeyGenParams=Object.assign({},algorithm,{length:keyLength})
,aesCbcParams=Object.assign({},algorithm,{iv:v})
,hmacKeyParams=Object.assign({},{name:signAlgorithm},hashParams)
,key=await crypto.subtle.generateKey(aesKeyGenParams,true,[`encrypt`])
,exportKey=await crypto.subtle.exportKey(format,key),encrypted=await crypto.subtle.encrypt(aesCbcParams,key,encoder.encode(string))
,signKey=await crypto.subtle.generateKey(hmacKeyParams,true,[`sign`])
,exportSignKey=await crypto.subtle.exportKey(signFormat,signKey)
,sign=await crypto.subtle.sign(signAlgorithm,signKey,encrypted)
console.log(algorithm.name)
console.log(await crypto.subtle.verify(signAlgorithm,await crypto.subtle.importKey(signFormat,exportSignKey,hmacKeyParams,false,[`verify`]),sign,encrypted))//true
console.log(decoder.decode(await crypto.subtle.decrypt(aesCbcParams,await crypto.subtle.importKey(format,exportKey,algorithm,false,[`decrypt`]),encrypted)))//hello world
}
,aesGCM=async(v,keyLength,hashParams)=>{
const algorithm={name:`AES-GCM`},signAlgorithm=`HMAC`,format=`raw`,signFormat=`raw`
,aesKeyGenParams=Object.assign({},algorithm,{length:keyLength})
,aesGcmParams=Object.assign({},algorithm,{iv:v})
,hmacKeyParams=Object.assign({},{name:signAlgorithm},hashParams)
,key=await crypto.subtle.generateKey(aesKeyGenParams,true,[`encrypt`])
,exportKey=await crypto.subtle.exportKey(format,key),encrypted=await crypto.subtle.encrypt(aesGcmParams,key,encoder.encode(string))
,signKey=await crypto.subtle.generateKey(hmacKeyParams,true,[`sign`])
,exportSignKey=await crypto.subtle.exportKey(signFormat,signKey)
,sign=await crypto.subtle.sign(signAlgorithm,signKey,encrypted)
console.log(algorithm.name)
console.log(await crypto.subtle.verify(signAlgorithm,await crypto.subtle.importKey(signFormat,exportSignKey,hmacKeyParams,false,[`verify`]),sign,encrypted))//true
console.log(decoder.decode(await crypto.subtle.decrypt(aesGcmParams,await crypto.subtle.importKey(format,exportKey,algorithm,false,[`decrypt`]),encrypted)))//hello world
}
,rsaOAEP=async(modulusLength,params,hashParams)=>{
const algorithm={name:`RSA-OAEP`},signAlgorithm=`HMAC`,format=`pkcs8`,signFormat=`raw`
,rsaHashedKeyGenParams=Object.assign({},algorithm,params,{modulusLength:modulusLength,publicExponent:new Uint8Array([0x01,0x00,0x01])})
,rsaHashedImportParams=Object.assign({},algorithm,params)
,hmacKeyParams=Object.assign({},{name:signAlgorithm},hashParams)
,keys=await crypto.subtle.generateKey(rsaHashedKeyGenParams,true,[`encrypt`,`decrypt`])
,exportKey=await crypto.subtle.exportKey(format,keys.privateKey),encrypted=await crypto.subtle.encrypt(algorithm,keys.publicKey,encoder.encode(string))
,signKey=await crypto.subtle.generateKey(hmacKeyParams,true,[`sign`])
,exportSignKey=await crypto.subtle.exportKey(signFormat,signKey)
,sign=await crypto.subtle.sign(signAlgorithm,signKey,encrypted)
console.log(algorithm.name)
console.log(await crypto.subtle.verify(signAlgorithm,await crypto.subtle.importKey(signFormat,exportSignKey,hmacKeyParams,false,[`verify`]),sign,encrypted))//true
console.log(decoder.decode(await crypto.subtle.decrypt(algorithm,await crypto.subtle.importKey(format,exportKey,rsaHashedImportParams,false,[`decrypt`]),encrypted)))//hello world
}
(async()=>{
const v=crypto.getRandomValues(new Uint8Array(16))
,keyLength=128//or 256
console.log(string)//hello world
await aesCTR(v,keyLength,64,{hash:`SHA-256`})
await aesCBC(v,keyLength,{hash:`SHA-256`})
await aesGCM(v,keyLength,{hash:`SHA-256`})
await rsaOAEP(2048,{hash:`SHA-256`},{hash:`SHA-256`})
})()
}</script></head></html>
WebGL, WebGL2, WebGPU(data uri)
code
<!doctype html>
<head>
<style>
body{background-color:#ffffffff;color:#000000ff}
@media(prefers-color-scheme:dark){body{background-color:#000000ff;color:#ffffffff}}
</style>
<style>
html{
*{margin:0;padding:0}
>body{
*{font-family:monospace;box-sizing:border-box;overflow-wrap:anywhere}
>:nth-child(1){
>dl>dd>canvas{width:100%;aspect-ratio:1}
display:grid;grid-template-columns:1fr 1fr 1fr
}
>:nth-child(2){
>dd{margin-left:.5rem}
display:grid;grid-template-columns:auto 1fr
}
}
}
</style>
<script>
WebGLRenderingContext.prototype.toDraw=function(p,is,mode,color){
const vertexShaderSrc=`precision highp float;attribute vec3 p;uniform vec4 q0;uniform vec4 q1;vec3 c(vec3 p,vec4 q){return p+2.0*cross(q.xyz,cross(q.xyz,p)+q.w*p);}void main(){gl_Position=vec4(c(c(p,q0),q1)+vec3(0,0,1.0),2.0);}`
,fragmentShaderSrc=`precision highp float;void main(){gl_FragColor=vec4(${color.join(`,`)});}`
,program=(()=>{
const createShader=(type,src)=>{
const shader=this.createShader(type)
this.shaderSource(shader,src)
this.compileShader(shader)
return shader
}
const program=this.createProgram()
this.attachShader(program,createShader(this.VERTEX_SHADER,vertexShaderSrc))
this.attachShader(program,createShader(this.FRAGMENT_SHADER,fragmentShaderSrc))
this.linkProgram(program)
return program
})()
,q0Location=this.getUniformLocation(program,`q0`)
,q1Location=this.getUniformLocation(program,`q1`)
this.clearColor(0,0,0,0)
this.useProgram(program)
this.enableVertexAttribArray(0)
this.bindBuffer(this.ARRAY_BUFFER,this.createBuffer())
this.bufferData(this.ARRAY_BUFFER,p,this.STATIC_DRAW)
this.bindBuffer(this.ELEMENT_ARRAY_BUFFER,this.createBuffer())
this.bufferData(this.ELEMENT_ARRAY_BUFFER,is,this.STATIC_DRAW)
this.vertexAttribPointer(0,3,this.FLOAT,false,0,0)
return(q0,q1)=>{
this.clear(this.COLOR_BUFFER_BIT|this.DEPTH_BUFFER_BIT)
this.uniform4f(q0Location,...q0)
this.uniform4f(q1Location,...q1)
this.drawElements(mode,is.length,this.UNSIGNED_SHORT,0)
}
}
WebGL2RenderingContext.prototype.toDraw=function(p,is,mode,color){
const vertexShaderSrc=`#version 300 es\nprecision highp float;in vec3 p;layout(std140)uniform q{vec4 q0;vec4 q1;};vec3 c(vec3 p,vec4 q){return p+2.0*cross(q.xyz,cross(q.xyz,p)+q.w*p);}void main(){gl_Position=vec4(c(c(p,q0),q1)+vec3(0,0,1.0),2.0);}`
,fragmentShaderSrc=`#version 300 es\nprecision highp float;out vec4 c;void main(){c=vec4(${color.join(`,`)});}`
,program=(()=>{
const createShader=(type,src)=>{
const shader=this.createShader(type)
this.shaderSource(shader,src)
this.compileShader(shader)
return shader
}
const program=this.createProgram()
this.attachShader(program,createShader(this.VERTEX_SHADER,vertexShaderSrc))
this.attachShader(program,createShader(this.FRAGMENT_SHADER,fragmentShaderSrc))
this.linkProgram(program)
return program
})()
,uniformBuffer=this.createBuffer()
this.clearColor(0,0,0,0)
this.useProgram(program)
this.enableVertexAttribArray(0)
this.bindBuffer(this.ARRAY_BUFFER,this.createBuffer())
this.bufferData(this.ARRAY_BUFFER,p,this.STATIC_DRAW)
this.uniformBlockBinding(program,0,0)
this.bindBuffer(this.UNIFORM_BUFFER,uniformBuffer)
this.bindBufferBase(this.UNIFORM_BUFFER,0,uniformBuffer)
this.bindBuffer(this.ELEMENT_ARRAY_BUFFER,this.createBuffer())
this.bufferData(this.ELEMENT_ARRAY_BUFFER,is,this.STATIC_DRAW)
this.vertexAttribPointer(0,3,this.FLOAT,false,0,0)
return(q0,q1)=>{
this.clear(this.COLOR_BUFFER_BIT|this.DEPTH_BUFFER_BIT)
const q=new Float32Array(q0.length+q1.length)
q.set(q0)
q.set(q1,q0.length)
this.bufferData(this.UNIFORM_BUFFER,q,this.STATIC_DRAW)
this.drawElements(mode,is.length,this.UNSIGNED_SHORT,0)
}
}
if(navigator.gpu)GPUCanvasContext.prototype.toDraw=function(device,p,is,topology,color){
const createBuffer=(usage,src)=>{
const buffer=device.createBuffer({usage:usage,size:src.byteLength,mappedAtCreation:true})
new src.constructor(buffer.getMappedRange()).set(src)
buffer.unmap()
return buffer
}
,layout=device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{}}]})
,vertexShaderSrc=`struct Q{q0:vec4f,q1:vec4f}@binding(0)@group(0)var<uniform>q:Q;fn c(p:vec3f,q:vec4f)->vec3f{return p+2.0*cross(q.xyz,cross(q.xyz,p)+q.w*p);}@vertex fn main(@location(0)p:vec3f)->@builtin(position)vec4f{return vec4f(c(c(p,q.q0),q.q1)+vec3f(0,0,1.0),2.0);}`
,fragmentShaderSrc=`@fragment fn main()->@location(0)vec4f{return vec4f(${color.join(`,`)});}`
,format=navigator.gpu.getPreferredCanvasFormat()
,pipeline=device.createRenderPipeline({
layout:device.createPipelineLayout({bindGroupLayouts:[layout]})
,primitive:{topology:topology}
,vertex:{buffers:[{attributes:[{format:`float32x3`,offset:0,shaderLocation:0}],arrayStride:12}],module:device.createShaderModule({code:vertexShaderSrc})}
,fragment:{targets:[{format:format}],module:device.createShaderModule({code:fragmentShaderSrc})}
})
,encoder=device.createRenderBundleEncoder({colorFormats:[format]})
,uniformBuffer=device.createBuffer({usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST,size:32})
,descriptor={colorAttachments:[{loadOp:`clear`,storeOp:`store`,clearValue:[0,0,0,0]}]}
this.configure({device:device,format:format,alphaMode:`premultiplied`})
encoder.setPipeline(pipeline)
encoder.setVertexBuffer(0,createBuffer(GPUBufferUsage.VERTEX,p))
encoder.setBindGroup(0,device.createBindGroup({entries:[{binding:0,resource:{buffer:uniformBuffer}}],layout:layout}))
encoder.setIndexBuffer(createBuffer(GPUBufferUsage.INDEX,is),`uint16`)
encoder.drawIndexed(is.length)
const bundle=encoder.finish()
return(q0,q1)=>{
const q=new Float32Array(q0.length+q1.length)
q.set(q0)
q.set(q1,q0.length)
device.queue.writeBuffer(uniformBuffer,0,q)
descriptor.colorAttachments[0].view=this.getCurrentTexture().createView()
const encoder=device.createCommandEncoder(),pass=encoder.beginRenderPass(descriptor)
pass.executeBundles([bundle])
pass.end()
device.queue.submit([encoder.finish()])
}
}
onload=async()=>{
const setPointerEvent=(e,c)=>{
let clientX,clientY
e.addEventListener(`pointerup`,()=>{
clientX=clientY=null
c(new Float32Array([0,0,0,1]),new Float32Array([0,0,0,1]))
})
e.addEventListener(`pointerdown`,()=>{
clientX=event.clientX
clientY=event.clientY
})
e.addEventListener(`pointermove`,()=>{
if(!clientX&&!clientY)return
let x,y
const v=Number(document.querySelector(`body>dl>dd>input[type=number]`).value)
x=(event.clientX-clientX)*v/2
y=(event.clientY-clientY)*v/2
x=new Float32Array([0,Math.sin(x),0,Math.cos(x)])
y=new Float32Array([Math.sin(y),0,0,Math.cos(y)])
Number(document.querySelector(`body>dl>dd>select`).value)?c(x,y):c(y,x)
})
}
,[webGLCanvas,webGL2Canvas,webGPUCanvas]=document.querySelectorAll(`body>:nth-child(1)>dl>dd>canvas`)
,[webGLContext,webGL2Context]=[webGLCanvas.getContext(`webgl`),webGL2Canvas.getContext(`webgl2`)]
,p=new Float32Array([
[
1,1,1
,-1,-1,-1
,1,-1,1
,-1,1,-1
,-1,1,1
,1,-1,-1
,1,1,-1
,-1,-1,1
].map(v=>v/2)
,[
0,1,0
,0,-1,0
,1,0,0
,-1,0,0
,0,0,1
,0,0,-1
]
].flat())
,is=new Uint16Array([
[
0,2,2,7,0,4,4,3,0,6,6,5
,1,3,3,6,1,5,5,2,1,7,7,4
]
,[
0,2,2,4,4,1
,1,5,5,3,3,0
,0,4,4,3,3,1
,1,2,2,5,5,0
].map(v=>8+v)
].flat())
,cs=[webGLContext.toDraw(p,is,1,[1,0,0,1]),webGL2Context.toDraw(p,is,1,[0,1,0,1])]
,identity=new Float32Array([0,0,0,1])
if(navigator.gpu){
const adapter=await navigator.gpu.requestAdapter()
if(adapter){
const device=await adapter.requestDevice()
if(device)cs.push(webGPUCanvas.getContext(`webgpu`).toDraw(device,p,is,`line-list`,[0,0,1,1]))
else webGPUCanvas.parentElement.textContent=`the device request failed.`
}else webGPUCanvas.parentElement.textContent=`the adapter request failed.`
}else webGPUCanvas.parentElement.textContent=`available in secure contexts.`
setPointerEvent(document.body,(q0,q1)=>cs.forEach(c=>c(q0,q1)))
let size
onresize=()=>{
if(webGLCanvas.clientWidth===size)return
size=webGLCanvas.clientWidth
webGPUCanvas.height=webGPUCanvas.width=webGL2Canvas.height=webGL2Canvas.width=webGLCanvas.height=webGLCanvas.width=size
webGLContext.viewport(0,0,size,size)
webGL2Context.viewport(0,0,size,size)
cs.forEach(c=>c(identity,identity))
}
onresize()
}
</script>
</head>
<body>
<dl>
<dl><dt>WebGL</dt><dd><canvas></canvas></dd></dl>
<dl><dt>WebGL2</dt><dd><canvas></canvas></dd></dl>
<dl><dt>WebGPU</dt><dd><canvas></canvas></dd></dl>
</dl>
<dl>
<dt>sensitivity</dt><dd><input type='number' step='.01' min='0' value='.05'></dd>
<dt>order</dt><dd><select><option value='0'>false</option><option value='1'>true</option></select></dd>
</dl>
</body>
</html>