├── .eslintrc.js ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── package.json ├── scripts └── combine-types.ts ├── src ├── arithmetic.ts ├── base.ts ├── functions.ts ├── index.ts ├── vecArithmetic.ts ├── vecBase.ts └── vecFunctions.ts ├── test ├── advanced_plane │ ├── index.html │ └── test.js ├── simple-wiggle │ ├── index.html │ └── test.js ├── sine_plane │ ├── index.html │ └── test.js ├── sinenoise_plane │ ├── index.html │ └── test.js └── sphere │ ├── index.html │ └── test.js ├── tsconfig.json ├── webpack.config.js └── yarn.lock /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | extends: [ 4 | 'plugin:@typescript-eslint/recommended', 5 | 'prettier/@typescript-eslint', 6 | 'plugin:prettier/recommended', 7 | ], 8 | parserOptions: { 9 | sourceType: 'module', 10 | }, 11 | ecmaFeatures: { 12 | jsx: true, 13 | }, 14 | rules: { 15 | // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs 16 | 'no-unused-vars': 'off', 17 | '@typescript-eslint/no-unused-vars': [1, { argsIgnorePattern: '^_' }], 18 | '@typescript-eslint/no-inferrable-types': 'off', 19 | '@typescript-eslint/no-explicit-any': 'off', 20 | '@typescript-eslint/no-non-null-assertion': 'off', 21 | '@typescript-eslint/explicit-member-accessibility': 'off', 22 | '@typescript-eslint/ban-ts-ignore': 'off', 23 | '@typescript-eslint/explicit-function-return-type': 'off', 24 | '@typescript-eslint/camelcase': 'off', 25 | 'react/prop-types': 'off', 26 | '@typescript-eslint/ban-ts-comment': 'off', 27 | '@typescript-eslint/explicit-module-boundary-types': 'off', 28 | '@typescript-eslint/no-empty-function': 'off', 29 | '@typescript-eslint/no-empty-interface': 'off', 30 | }, 31 | } 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Dave Pagurek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # glsl-autodiff 2 | Tired of doing math to get normals in your vertex shader? Same. Use this library to write your function once and generate derivatives automatically! 3 | 4 | - Demo 5 | - Starter Code 6 | - Why? 7 | - API Usage 8 | - Inputs and Outputs 9 | - Operations 10 | - Additional Settings 11 | - Importing in JS/TS Builds 12 | - Importing in the Browser 13 | - Contributing 14 | 15 | ## Demo 16 | ![airplane-small](https://user-images.githubusercontent.com/5315059/129101559-4f394a4c-ea3d-489f-9796-cff224aa277d.gif) 17 | 18 | Live version in the p5 editor 19 | 20 | ### Starter Code 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
Autodiff + Sphere mapped lightingAutodiff + Sphere mapped lighting + bump mapping
P5 Editor templateP5 Editor template
CodePen templateCodePen template
36 | 37 | ## Why? 38 | 39 | Sometimes, I want to displace mesh vertices in a vertex shader. After doing this, the normals of a surface should change: 40 | 41 | ![image](https://user-images.githubusercontent.com/5315059/129100445-7f48da08-df0f-4fd8-a5c5-16e169197ce4.png) 42 | 43 | However, per-vertex normals don't automatically update! Manual updating of vertex normals requires you to take the derivative of your displacement function. This library automates that process so that it takes less time and is less prone to user error. If you're interested, read a more in-depth blog post on why this is necessary and how it works. 44 | 45 | ## API Usage 46 | 47 | This exposes a `gen` function that generates GLSL that you can splice into your shader code. Inside a call to `gen()`, you provide a callback that takes in `ad`, the AutoDiff engine, and uses it to build shader code. We build shaders by essentially creating a graph of operations that we pass inputs through to arrive at an output. Every function call creates an object representing such an operation. Once we have a graph, we can automatically compute derivatives using it! 48 | 49 | The AutoDiff engine's methods are designed to look similar to how you would normally write a shader, but using method chaining instead of operator symbols, similar to how p5's Vector class works. It looks something like this in action: 50 | ```js 51 | import { gen } from `@davepagurek/glsl-autodiff' 52 | 53 | const vert = ` 54 | void main(void) { 55 | vec4 objSpacePosition = vec4(aPosition, 1.0); 56 | 57 | float x = objSpacePosition.x; 58 | float y = objSpacePosition.y; 59 | ${gen((ad) => { 60 | const x = ad.param('x') 61 | const y = ad.param('y') 62 | const time = ad.param('time') 63 | const speedX = 1.5 64 | const speedY = 2.8 65 | 66 | let offset = ad.val(0) 67 | for (let i = 0; i < 3; i++) { 68 | offset = offset.add(ad.sin( 69 | ad.sum( 70 | offset.mult(0.5).add(x.mult(speedX)).add(y.mult(speedY)), 71 | time.mult(0.002), 72 | ) 73 | )) 74 | } 75 | offset = offset.mult(0.1) 76 | offset.output('z') 77 | offset.outputDeriv('dzdx', x) 78 | offset.outputDeriv('dzdy', y) 79 | })} 80 | objSpacePosition.z = z; 81 | vec3 slopeX = vec3(1.0, 0.0, dzdx); 82 | vec3 slopeY = vec3(0.0, 1.0, dzdy); 83 | vNormal = uNormalMatrix * normalize(cross(slopeX, slopeY)); 84 | 85 | vec4 worldSpacePosition = uModelViewMatrix * objSpacePosition; 86 | gl_Position = uProjectionMatrix * worldSpacePosition; 87 | } 88 | ` 89 | ``` 90 | 91 | ### Inputs and Outputs 92 | 93 | **Parameters** are variables that you create outside of AutoDiff but that you want to reference inside AutoDiff. Depending on their variable type, use one of the following methods to create them: 94 | 95 | ```typescript 96 | interface AutoDiff { 97 | param(name: string): Param 98 | vec2Param: (name: string) => VecParam 99 | vec3Param: (name: string) => VecParam 100 | vec4Param: (name: string) => VecParam 101 | } 102 | ``` 103 | 104 | **Outputs** are used to store computation results from within AutoDiff into names that are accessible outside AutoDiff. You can also output the derivative of a computation with respect to an input parameter. 105 | 106 | ```typescript 107 | interface Op { 108 | output(name: string); 109 | outputDeriv(name: string, param: Param); 110 | } 111 | ``` 112 | 113 | As an example, we can use `param` to reference a uniform, do some math with it, and output the result: 114 | ```js 115 | const vert = ` 116 | // A uniform we want to reference 117 | uniform vec3 position; 118 | 119 | void main(void) { 120 | ${AutoDiff.gen((ad) => { 121 | // Get a computation graph node representing the uniform 122 | const position = ad.vec3Param('position') 123 | 124 | // Do stuff with it 125 | const offset = ad.sum(position.x(), position.y(), position.z()) 126 | 127 | // Output it so the rest of the shader can reference it 128 | offset.output('offset') 129 | })} 130 | vec3 worldSpacePosition = position; 131 | worldSpacePosition.z += offset; // Use offset, an output, outside of AutoDiff 132 | gl_Position = uProjectionMatrix * vec4(worldSpacePosition, 1.0); 133 | } 134 | ` 135 | ``` 136 | 137 | ### Operations 138 | 139 | Given any scalar graph node (`Op`), use any of the following methods to generate a new node corresponding to the GLSL operation of the same name: 140 | ```typescript 141 | interface Op { 142 | neg(): Op; // Multiply by -1 143 | add(...params: Input[]): Op; 144 | sub(val: Input): Op; 145 | mult(...params: Input[]): Op; 146 | div(param: Input): Op; 147 | pow(param: Input): Op; 148 | sqrt(): Op; 149 | sin(): Op; 150 | cos(): Op; 151 | tan(): Op; 152 | mix(b: Input, amt: Input): Op; 153 | clamp(min: Input, max: Input): Op; 154 | min(...params: Input[]): Op; 155 | max(...params: Input[]): Op; 156 | ifElse(thenOp: Input, elseOp: Input): Op; // Ternary with the receiving Op being the condition 157 | vecIfElse(thenOp: VectorOp, elseOp: VectorOp): VectorOp; // Ternary but where the if/else values are vectors 158 | } 159 | ``` 160 | 161 | Note that an `Input` is either another node, or a number literal. 162 | 163 | Given a vector graph node (`VectorOp`, which extends `Op`), use any of the following methods to again generate a new node with the computation result: 164 | ```typescript 165 | interface VectorOp { 166 | neg(): VectorOp; 167 | add(...params: VectorOp[]): VectorOp; 168 | scale(k: Input): VectorOp; // When multiplying by a scalar 169 | mult(...params: VectorOp[]): VectorOp; // When multiplying by another vector 170 | mix(other: VectorOp, amt: Input): VectorOp; 171 | clamp(min: VectorOp, max: VectorOp): VectorOp; 172 | min(...params: VectorOp[]): VectorOp; 173 | max(...params: VectorOp[]): VectorOp; 174 | dot(other: VectorOp): Op; 175 | length(): Op; 176 | dist(other: VectorOp): Op; 177 | } 178 | ``` 179 | 180 | You can also construct nodes directly from the AutoDiff engine passed to you in the `gen` callback: 181 | ```typescript 182 | interface AutoDiff { 183 | // Create new values 184 | val: (n: number) => Op; 185 | vec2: (x: Input, y: Input) => Vec; 186 | vec3: (x: Input, y: Input, z: Input) => Vec; 187 | vec4: (x: Input, y: Input, z: Input, w: Input) => Vec; 188 | 189 | // Create a new operation with scalar inputs 190 | sum: (...params: Input[]) => any; 191 | prod: (...params: Input[]) => any; 192 | sqrt: (param: Input) => any; 193 | sin: (input: Input) => any; 194 | cos: (input: Input) => any; 195 | tan: (input: Input) => any; 196 | mix: (a: Input, b: Input, amt: Input) => any; 197 | clamp: (val: Input, min: Input, max: Input) => any; 198 | min: (...params: Input[]) => any; 199 | max: (...params: Input[]) => any; 200 | ifElse: (ifOp: Input, thenOp: Input, elseOp: Input) => any; 201 | 202 | // Create a new operation with vector inputs 203 | vecSum: (...params: VectorOp[]) => VectorOp; 204 | vecProd: (...params: VectorOp[]) => VectorOp; 205 | vecMix: (a: VectorOp, b: VectorOp, amt: Input) => VectorOp; 206 | vecClamp: (val: VectorOp, min: VectorOp, max: VectorOp) => VectorOp; 207 | vecMin: (...params: VectorOp[]) => VectorOp; 208 | vecMax: (...params: VectorOp[]) => VectorOp; 209 | dot: (a: VectorOp, b: VectorOp) => Op; 210 | length: (val: VectorOp) => Op; 211 | dist: (a: VectorOp, b: VectorOp) => Op; 212 | } 213 | ``` 214 | 215 | ### Additional settings 216 | 217 | On some very rare occasions, you write code that Just Works™! For the other 99% of the time, AutoDiff includes debug options that you can change by passing an additional settings object into the `gen` function: 218 | 219 | ```typescript 220 | gen: ( 221 | cb: (ad: AD) => void, 222 | settings?: Partial, 223 | ) => string; 224 | 225 | type ADSettings = { 226 | maxDepthPerVariable: number; 227 | debug: boolean; 228 | }; 229 | ``` 230 | 231 | When you set `debug: true`, each line in the outputted GLSL that comes directly from an code you wrote gets a comment referencing where it came from: 232 | 233 | 234 | 237 | 238 | 270 | 298 | 299 |
Input 235 | Output 236 |
239 |
const vert = `
240 | void main(void) {
241 |   vec4 objSpacePosition = vec4(aPosition, 1.0);
242 |   float origZ = objSpacePosition.z;
243 |   float x = objSpacePosition.x;
244 |   float y = objSpacePosition.y;
245 |   ${AutoDiff.gen((ad) => {
246 |     const x = ad.param('x')
247 |     const y = ad.param('y')
248 |     const time = ad.param('time')
249 |     const speedX = 1.5
250 |     const speedY = 2.8
251 | 
252 |     let offset = ad.val(0)
253 |     for (let i = 0; i < 3; i++) {
254 |       offset = offset.add(ad.sin(
255 |         ad.sum(
256 |           offset.mult(0.5).add(x.mult(speedX)).add(y.mult(speedY)),
257 |           time.mult(0.002),
258 |         )
259 |       ))
260 |     }
261 |     offset = offset.mult(0.1)
262 |     offset.output('z')
263 |   }, { debug: true, maxDepthPerVariable: 4 })}
264 |   objSpacePosition.z += z;
265 |   vec4 worldSpacePosition = uModelViewMatrix * objSpacePosition;
266 |   gl_Position = uProjectionMatrix * worldSpacePosition;
267 | }
268 | `
269 |
271 |
void main(void) {
272 |   vec4 objSpacePosition = vec4(aPosition, 1.0);
273 |   float origZ = objSpacePosition.z;
274 |   float x = objSpacePosition.x;
275 |   float y = objSpacePosition.y;
276 |   
277 |   // From vert<@file:///Users/dpagurek/Documents/Projects/glsl-autodiff/test/sine_plane/test.js:31:12
278 |   float _glslad_v14=(((0.0000\*0.5000)+(x\*1.5000))+(y\*2.8000))+(time\*0.0020);
279 | 
280 |   // From vert<@file:///Users/dpagurek/Documents/Projects/glsl-autodiff/test/sine_plane/test.js:30:23
281 |   float _glslad_v16=0.0000+(sin(_glslad_v14));
282 | 
283 |   // From vert<@file:///Users/dpagurek/Documents/Projects/glsl-autodiff/test/sine_plane/test.js:31:12
284 |   float _glslad_v27=(((_glslad_v16\*0.5000)+(x\*1.5000))+(y\*2.8000))+(time\*0.0020);
285 | 
286 |   // From vert<@file:///Users/dpagurek/Documents/Projects/glsl-autodiff/test/sine_plane/test.js:30:23
287 |   float _glslad_v29=_glslad_v16+(sin(_glslad_v27));
288 | 
289 |   // From vert<@file:///Users/dpagurek/Documents/Projects/glsl-autodiff/test/sine_plane/test.js:31:12
290 |   float _glslad_v40=(((_glslad_v29\*0.5000)+(x\*1.5000))+(y\*2.8000))+(time\*0.0020);
291 |   float z=((_glslad_v29+(sin(_glslad_v40)))\*0.1000);
292 | 
293 |   objSpacePosition.z += z;
294 |   vec4 worldSpacePosition = uModelViewMatrix \* objSpacePosition;
295 |   gl_Position = uProjectionMatrix \* worldSpacePosition;
296 | }
297 |
300 | 301 | Sometimes too much or too little ends up on one line, so you can also supply `maxDepthPerVariable` to supply a maximum number of nested operations before creating an intermediate variable. If unspecified, we use `maxDepthPerVariable: 8`. To condense into as few lines as possible, use `Infinity`. To make every operation its own variable, use 1. 302 | 303 | ### Importing in JS/TS builds 304 | 305 | Add this library to your project: 306 | ``` 307 | yarn add @davepagurek/glsl-autodiff 308 | ``` 309 | 310 | Then, import the `gen` method: 311 | ```typescript 312 | import { gen } from '@davepagurek/glsl-autodiff' 313 | 314 | const myShader = ` 315 | // some shader code here 316 | ${gen((ad) => { 317 | // Use autodiff here 318 | })} 319 | ` 320 | ``` 321 | 322 | ### Importing in the Browser 323 | 324 | Download the library from the Github releases tab and add the library to your HTML file: 325 | ```html 326 | 327 | ``` 328 | 329 | Then, use the global `AutoDiff` variable which includes the `gen` function: 330 | ```js 331 | const myShader = ` 332 | // some shader code here 333 | ${AutoDiff.gen((ad) => { 334 | // Use autodiff here 335 | })} 336 | ` 337 | ``` 338 | 339 | ## Contributing 340 | 341 | Want to help out? There are a number of things I'd like to get done at some point that are written down for posterity in the Issues tab that I'd love help on! 342 | 343 | Setting up the repo: 344 | 345 | ``` 346 | git clone git@github.com:davepagurek/glsl-autodiff.git 347 | cd glsl-autodiff 348 | yarn install 349 | ``` 350 | 351 | Compiling `build/autodiff.js` and `build/autodiff.d.ts`: 352 | ``` 353 | yarn build 354 | ``` 355 | 356 | Pushing all compiled code to Github Pages for demos (if you are me or have write permissions): 357 | ``` 358 | yarn deploy 359 | ``` 360 | 361 | Publishing a new version to NPM: 362 | ``` 363 | yarn publish 364 | ``` 365 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@davepagurek/glsl-autodiff", 3 | "version": "0.0.20", 4 | "main": "build/autodiff.js", 5 | "author": "Dave Pagurek ", 6 | "license": "MIT", 7 | "types": "build/autodiff.d.ts", 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/davepagurek/glsl-autodiff.git" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/davepagurek/glsl-autodiff/issues" 14 | }, 15 | "homepage": "https://github.com/davepagurek/glsl-autodiff", 16 | "dependencies": { 17 | "lodash": "^4.17.21" 18 | }, 19 | "devDependencies": { 20 | "@types/node": "^15.12.5", 21 | "gh-pages": "^3.2.3", 22 | "ts-loader": "^9.2.3", 23 | "ts-node": "^10.0.0", 24 | "typescript": "^4.3.4", 25 | "webpack": "^5.41.1", 26 | "webpack-cli": "^4.7.2" 27 | }, 28 | "scripts": { 29 | "build": "yarn generate:js && yarn generate:types", 30 | "generate:js": "yarn run webpack", 31 | "generate:types": "yarn run ts-node scripts/combine-types.ts", 32 | "deploy": "yarn build && yarn run gh-pages -d .", 33 | "publish": "npm publish --access public" 34 | }, 35 | "files": [ 36 | "build" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /scripts/combine-types.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import path from 'path' 3 | 4 | const outFile = 'autodiff.d.ts' 5 | const buildDirectory = path.resolve( 6 | __dirname, 7 | '../build', 8 | ) 9 | const typeFiles = fs 10 | .readdirSync(buildDirectory, { withFileTypes: true }) 11 | .filter((dirEnt) => dirEnt.isFile()) 12 | .filter(({ name }) => name.endsWith('.d.ts')) 13 | .filter(({ name }) => name !== outFile) 14 | 15 | let combined = '' 16 | typeFiles.forEach(({ name }) => { 17 | const types = fs.readFileSync(path.resolve(buildDirectory, name), 'utf8') 18 | 19 | // Remove imports for now 20 | combined += types 21 | .replace(/^import.*$/mg, '') 22 | .replace(/import\(".\/[^"]+"\)\./g, '') 23 | .replace(/declare module '[^']+' \{\n([^}]+)\}/mg, 'export $1') 24 | }) 25 | fs.writeFileSync(path.resolve(buildDirectory, outFile), combined) 26 | -------------------------------------------------------------------------------- /src/arithmetic.ts: -------------------------------------------------------------------------------- 1 | import { Input, Op, Param, ADBase, ADConstructor, UserInput } from './base' 2 | 3 | export class Neg extends Op { 4 | definition() { 5 | return `-${this.dependsOn[0].ref()}` 6 | } 7 | derivative(param: Param) { 8 | return '-' + this.dependsOn[0].derivRef(param) 9 | } 10 | } 11 | 12 | export class Sum extends Op { 13 | definition() { 14 | return this.dependsOn.map((op) => op.ref()).join('+') 15 | } 16 | derivative(param: Param) { 17 | return this.dependsOn.map((op) => op.derivRef(param)).join('+') 18 | } 19 | } 20 | 21 | export class Mult extends Op { 22 | definition() { 23 | return this.dependsOn.map((op) => op.ref()).join('*') 24 | } 25 | derivative(param: Param) { 26 | const [f, g] = this.dependsOn 27 | const fIsConst = f.isConst(param) 28 | const gIsConst = g.isConst(param) 29 | if (fIsConst && !gIsConst) { 30 | return `${f.ref()}*${g.derivRef(param)}` 31 | } else if (!fIsConst && gIsConst) { 32 | return `${g.ref()}*${f.derivRef(param)}` 33 | } else { 34 | return `${f.ref()}*${g.derivRef(param)}+${g.ref()}*${f.derivRef(param)}` 35 | } 36 | } 37 | } 38 | 39 | export class Div extends Op { 40 | definition() { 41 | return this.dependsOn.map((op) => op.ref()).join('/') 42 | } 43 | derivative(param: Param) { 44 | const [f, g] = this.dependsOn 45 | return `(${f.derivRef(param)}*${g.ref()}-${g.derivRef(param)}*${f.ref()})/(${g.ref()}*${g.ref()})` 46 | } 47 | } 48 | 49 | export class Pow extends Op { 50 | definition() { 51 | return `pow(${this.dependsOn[0].ref()},${this.dependsOn[1].ref()})` 52 | } 53 | derivative(param: Param) { 54 | const [a, b] = this.dependsOn 55 | if (b.isConst()) { 56 | return `${b.ref()}*pow(${a.ref()},${b.ref()}-1.0)*${a.derivRef(param)}` 57 | } else if (a.isConst()) { 58 | return `pow(${a.ref()},${b.ref()})*log(${a.ref()})*${b.derivRef(param)}` 59 | } else { 60 | // f = a^b 61 | // ln(f) = ln(a^b) ln() both sides 62 | // ln(f) = b*ln(a) logarithm rules 63 | // e^(lnf) = e^(b*ln(a)) exp() both sides 64 | // f = e^(b*ln(a)) simplify 65 | // d/dx f = d/dx e^(b*ln(a)) differentiate both sides 66 | // d/dx f = e^(b*ln(a)) * d/dx b*ln(a) derivative of e^u 67 | // d/dx f = a^b * d/dx b*ln(a) exponential rules 68 | // d/dx f = a^b * (b*(1/a * da/dx) + ln(a)*(db/dx)) product rule 69 | // t1 t2 t3 70 | const t1 = `pow(${a.ref()},${b.ref()})` 71 | const t2 = `${b.ref()}*(1.0/${a.ref()}*${a.derivRef(param)})` 72 | const t3 = `log(${a.ref()})*${b.derivRef(param)}` 73 | return `${t1}*(${t2}+${t3})` 74 | } 75 | } 76 | } 77 | 78 | declare module './base' { 79 | interface Op { 80 | neg(): Op 81 | add(...params: Input[]): Op 82 | sub(val: Input): Op 83 | mult(...params: Input[]): Op 84 | div(param: Input): Op 85 | pow(param: Input): Op 86 | sqrt(): Op 87 | } 88 | } 89 | 90 | Op.prototype.neg = UserInput(function() { 91 | return new Neg(this.ad, this) 92 | }) 93 | Op.prototype.add = UserInput(function(...params: Input[]) { 94 | if (params.length === 0) { 95 | throw new Error(`add() called with too few arguments: ${params}`) 96 | } else { 97 | return new Sum(this.ad, this, ...this.ad.convertVals(params)) 98 | } 99 | }) 100 | Op.prototype.sub = UserInput(function(val: Input) { 101 | return this.add(this.ad.convertVal(val).neg()) 102 | }) 103 | Op.prototype.mult = UserInput(function(...params: Input[]) { 104 | if (params.length === 0) { 105 | throw new Error(`mult() called with too few arguments: ${params}`) 106 | } else if (params.length === 1) { 107 | return new Mult(this.ad, this, this.ad.convertVal(params[0])) 108 | } else { 109 | return this.mult(params[0]).mult(...params.slice(1)) 110 | } 111 | }) 112 | Op.prototype.div = UserInput(function(param: Input) { 113 | return new Div(this.ad, this, this.ad.convertVal(param)) 114 | }) 115 | Op.prototype.pow = UserInput(function(param: Input) { 116 | return new Pow(this.ad, this, this.ad.convertVal(param)) 117 | }) 118 | Op.prototype.sqrt = UserInput(function() { return this.pow(0.5) }) 119 | 120 | export function WithArithmetic(Base: T) { 121 | class AutoDiff extends Base { 122 | sum = UserInput(function(...params: Input[]) { 123 | if (params.length === 0) { 124 | throw new Error(`sum() called with too few arguments: ${params}`) 125 | } else { 126 | const first = this.convertVal(params[0]) 127 | if (params.length > 1) { 128 | return first.add(...params.slice(1)) 129 | } else { 130 | return first 131 | } 132 | } 133 | }) 134 | prod = UserInput(function(...params: Input[]) { 135 | if (params.length === 0) { 136 | throw new Error(`prod() called with too few arguments: ${params}`) 137 | } else { 138 | const first = this.convertVal(params[0]) 139 | if (params.length > 1) { 140 | return first.mult(...params.slice(1)) 141 | } else { 142 | return first 143 | } 144 | } 145 | }) 146 | sqrt = UserInput(function(param: Input) { 147 | return this.convertVal(param).sqrt() 148 | }) 149 | } 150 | return AutoDiff 151 | } 152 | -------------------------------------------------------------------------------- /src/base.ts: -------------------------------------------------------------------------------- 1 | export type Input = Op | number 2 | 3 | export interface ADBase { 4 | getNextID(): number 5 | val(n: number): Value 6 | registerParam(param: Op, name: string) 7 | param(name: string): Param 8 | convertVal(param: Input): Op 9 | convertVals(params: Input[]): Op[] 10 | output(name: string, op: Op): ADBase 11 | outputDeriv(name: string, param: Param | string, op: Op): ADBase 12 | settings: ADSettings 13 | } 14 | 15 | export type ADSettings = { 16 | maxDepthPerVariable: number 17 | debug: boolean 18 | } 19 | 20 | export type ADConstructor = new (...args: any[]) => ADBase 21 | 22 | // https://stackoverflow.com/a/27074218 23 | export const getStack = () => { 24 | const e = new Error() 25 | if (!e.stack) try { 26 | // IE requires the Error to actually be throw or else the Error's 'stack' 27 | // property is undefined. 28 | throw e 29 | } catch (e) { 30 | if (!e.stack) { 31 | return [] // IE < 10, likely 32 | } 33 | } 34 | const frameRE = /:(\d+):(?:\d+)[^\d]*$/ 35 | const stack = e.stack?.toString().split(/\r\n|\n/).filter((line) => line.match(frameRE)) ?? [] 36 | return stack 37 | } 38 | 39 | // If we know a function will be called directly by the user, wrap it with 40 | // this so we can add extra debug info 41 | export function UserInput Op>(fn: T): T { 42 | return function(...args: any[]) { 43 | const op = fn.apply(this, args) 44 | 45 | if (op.ad.settings.debug) { 46 | const stack = getStack() 47 | op.srcLine = stack[2] ?? '' 48 | } 49 | return op 50 | } as T 51 | } 52 | 53 | export abstract class Op { 54 | public ad: ADBase 55 | public id: number 56 | public dependsOn: Op[] 57 | public usedIn: Op[] = [] 58 | public srcLine: string = '' 59 | public internalDerivatives: { op: Op, param: Param }[] = [] 60 | 61 | constructor(ad: ADBase, ...params: Op[]) { 62 | this.ad = ad 63 | this.id = ad.getNextID() 64 | this.dependsOn = params 65 | for (const param of params) { 66 | param.usedIn.push(this) 67 | } 68 | } 69 | 70 | public scalar() { return true } 71 | 72 | public size() { return 1 } 73 | 74 | public glslType() { 75 | if (this.scalar()) { 76 | return 'float' 77 | } else { 78 | return `vec${this.size()}` 79 | } 80 | } 81 | 82 | public depth() { 83 | // Force usage of a temp variable if used in multiple spots 84 | if (this.usedIn.length > 1) return 1 85 | 86 | const depDepth = Math.max(0, ...this.dependsOn.map((op) => op.depth())) 87 | const depth = depDepth + 1 88 | 89 | if (depth > this.ad.settings.maxDepthPerVariable) { 90 | return 1 91 | } else { 92 | return depth 93 | } 94 | } 95 | 96 | public useTempVar() { 97 | return this.depth() === 1 98 | } 99 | 100 | public ref(): string { 101 | if (this.useTempVar()) { 102 | return `_glslad_v${this.id}` 103 | } else { 104 | return `(${this.definition()})` 105 | } 106 | } 107 | 108 | public zeroDerivative() { 109 | return '0.0' 110 | } 111 | 112 | public derivRef(param: Param): string { 113 | if (this.isConst(param)) { 114 | return this.zeroDerivative() 115 | } else if (this.useTempVar()) { 116 | return `_glslad_dv${this.id}_d${param.safeName()}` 117 | } else { 118 | return `(${this.derivative(param)})` 119 | } 120 | } 121 | 122 | public initializer(): string { 123 | if (this.useTempVar()) { 124 | let line = `${this.glslType()} ${this.ref()}=${this.definition()};` 125 | if (this.ad.settings.debug && this.srcLine) { 126 | line = `\n// From ${this.srcLine}\n` + line 127 | } 128 | line += '\n' 129 | return line 130 | } else { 131 | return '' 132 | } 133 | } 134 | 135 | public derivInitializer(param: Param): string { 136 | if (this.isConst(param) || !this.useTempVar()) { 137 | return '' 138 | } else { 139 | return `${this.glslType()} ${this.derivRef(param)}=${this.derivative(param)};\n` 140 | } 141 | } 142 | 143 | public isConst(param?: Param): boolean { 144 | return this.dependsOn.every((op) => op.isConst(param)) 145 | } 146 | 147 | public outputDependencies({ deps, derivDeps }: { deps: Set; derivDeps: Map> }): string { 148 | let code = '' 149 | for (const op of this.dependsOn) { 150 | if (!deps.has(op)) { 151 | deps.add(op) 152 | code += op.outputDependencies({ deps, derivDeps }) 153 | code += op.initializer() 154 | } 155 | } 156 | 157 | for (const { param, op } of this.internalDerivatives) { 158 | if (!derivDeps.get(param)?.has(op)) { 159 | const paramDerivDeps = derivDeps.get(param) ?? new Set() 160 | paramDerivDeps.add(op) 161 | derivDeps.set(param, paramDerivDeps) 162 | code += op.outputDerivDependencies(param, { deps, derivDeps }) 163 | code += op.derivInitializer(param) 164 | } 165 | } 166 | 167 | return code 168 | } 169 | 170 | public outputDerivDependencies(param: Param, { deps, derivDeps }: { deps: Set; derivDeps: Map> }): string { 171 | if (this.isConst()) return '' 172 | let code = '' 173 | for (const op of this.dependsOn) { 174 | if (!deps.has(op)) { 175 | deps.add(op) 176 | code += op.outputDependencies({ deps, derivDeps }) 177 | code += op.initializer() 178 | } 179 | 180 | if (!derivDeps.get(param)?.has(op) && !op.isConst(param)) { 181 | const paramDerivDeps = derivDeps.get(param) ?? new Set() 182 | paramDerivDeps.add(op) 183 | derivDeps.set(param, paramDerivDeps) 184 | code += op.outputDerivDependencies(param, { deps, derivDeps }) 185 | code += op.derivInitializer(param) 186 | } 187 | } 188 | 189 | for (const { param, op } of this.internalDerivatives) { 190 | if (!derivDeps.get(param)?.has(op)) { 191 | const paramDerivDeps = derivDeps.get(param) ?? new Set() 192 | paramDerivDeps.add(op) 193 | derivDeps.set(param, paramDerivDeps) 194 | code += op.outputDependencies({ deps, derivDeps }) 195 | code += op.derivInitializer(param) 196 | } 197 | } 198 | 199 | return code 200 | } 201 | 202 | public output(name: string) { return this.ad.output(name, this) } 203 | public outputDeriv(name: string, param: Param | string) { return this.ad.outputDeriv(name, param, this) } 204 | 205 | public abstract definition(): string 206 | public abstract derivative(param: Param): string 207 | } 208 | 209 | export abstract class BooleanOp extends Op { 210 | abstract operator(): string 211 | definition() { 212 | return this.dependsOn.map((op) => op.ref()).join(this.operator()) 213 | } 214 | derivative(): string { 215 | throw new Error('unimplemented') 216 | } 217 | isConst() { 218 | // They might not actually be constant, but we don't have derivatives 219 | // for these so we just treat them like they are 220 | return true; 221 | } 222 | glslType() { 223 | return 'bool' 224 | } 225 | } 226 | 227 | export class EqOp extends BooleanOp { 228 | operator() { 229 | return '==' 230 | } 231 | } 232 | 233 | export class NeOp extends BooleanOp { 234 | operator() { 235 | return '!=' 236 | } 237 | } 238 | 239 | export class LtOp extends BooleanOp { 240 | operator() { 241 | return '<' 242 | } 243 | } 244 | 245 | export class LeOp extends BooleanOp { 246 | operator() { 247 | return '<=' 248 | } 249 | } 250 | 251 | export class GtOp extends BooleanOp { 252 | operator() { 253 | return '>' 254 | } 255 | } 256 | 257 | export class GeOp extends BooleanOp { 258 | operator() { 259 | return '>=' 260 | } 261 | } 262 | 263 | export class NotOp extends BooleanOp { 264 | operator() { 265 | return '!' 266 | } 267 | definition() { 268 | return this.operator() + this.dependsOn[0].ref() 269 | } 270 | } 271 | 272 | export class AndOp extends BooleanOp { 273 | operator() { 274 | return '&&' 275 | } 276 | } 277 | 278 | export class OrOp extends BooleanOp { 279 | operator() { 280 | return '||' 281 | } 282 | } 283 | 284 | export abstract class OpLiteral extends Op { 285 | public override initializer() { return '' } 286 | public override derivInitializer() { return '' } 287 | public override ref() { return this.definition() } 288 | public override derivRef(param: Param) { return this.derivative(param) } 289 | } 290 | 291 | export class Value extends OpLiteral { 292 | private val: number 293 | 294 | constructor(ad: ADBase, val: number) { 295 | super(ad) 296 | this.val = val 297 | } 298 | 299 | isConst() { return true } 300 | definition() { 301 | const str = `${this.val.toFixed(4)}` 302 | return this.val < 0 ? `(${str})` : str 303 | } 304 | derivative() { return '0.0' } 305 | } 306 | 307 | export class Param extends OpLiteral { 308 | public name: string 309 | 310 | constructor(ad: ADBase, name: string, ...dependsOn: Op[]) { 311 | super(ad, ...dependsOn) 312 | this.name = name 313 | this.ad.registerParam(this, name) 314 | } 315 | 316 | safeName() { 317 | // A version of the name that can be used in temp variable 318 | // names 319 | return this.name.split('').map((c) => { 320 | if (c.match(/[\w\d]/)) { 321 | return c 322 | } else { 323 | return '_' 324 | } 325 | }).join('') + this.id // Add id to ensure uniqueness 326 | } 327 | 328 | isConst(param?: Param) { 329 | if (param) { 330 | return param !== this 331 | } else { 332 | return false 333 | } 334 | } 335 | definition() { return this.name } 336 | derivative(param: Param) { 337 | if (param === this) { 338 | return '1.0' 339 | } else { 340 | return '0.0' 341 | } 342 | } 343 | } 344 | -------------------------------------------------------------------------------- /src/functions.ts: -------------------------------------------------------------------------------- 1 | import { Input, Op, Param, ADBase, ADConstructor, UserInput } from './base' 2 | 3 | export class Sin extends Op { 4 | definition() { 5 | return `sin(${this.dependsOn[0].ref()})` 6 | } 7 | derivative(param: Param) { 8 | return `cos(${this.dependsOn[0].ref()})*${this.dependsOn[0].derivRef(param)}` 9 | } 10 | } 11 | 12 | export class Cos extends Op { 13 | definition() { 14 | return `cos(${this.dependsOn[0].ref()})` 15 | } 16 | derivative(param: Param) { 17 | return `-sin(${this.dependsOn[0].ref()})*${this.dependsOn[0].derivRef(param)}` 18 | } 19 | } 20 | 21 | export class Mix extends Op { 22 | definition() { 23 | return `mix(${this.dependsOn.map((op) => op.ref()).join(',')})` 24 | } 25 | derivative(param: Param) { 26 | const [a, b, mix] = this.dependsOn 27 | const aDeriv = `(1.0-${a.ref()})*${mix.derivRef(param)}+(-${a.derivRef(param)})*${mix.ref()}` 28 | const bDeriv = `${b.ref()}*${mix.derivRef(param)}+${b.derivRef(param)}*${mix.ref()}` 29 | return `${aDeriv}+${bDeriv}` 30 | } 31 | } 32 | 33 | export class Clamp extends Op { 34 | definition() { 35 | return `clamp(${this.dependsOn.map((op) => op.ref()).join(',')})` 36 | } 37 | derivative(param: Param) { 38 | const [v, min, max] = this.dependsOn 39 | return `${v.ref()}<${min.ref()} ? 0.0 : (${v.ref()}>${max.ref()} ? 0.0 : ${v.derivRef(param)})` 40 | } 41 | } 42 | 43 | export class Min extends Op { 44 | definition() { 45 | return `min(${this.dependsOn.map((op) => op.ref()).join(',')})` 46 | } 47 | derivative(param: Param) { 48 | const [a, b] = this.dependsOn 49 | return `${a.ref()}<${b.ref()} ? ${a.derivRef(param)} : ${b.derivRef(param)}` 50 | } 51 | } 52 | 53 | export class Max extends Op { 54 | definition() { 55 | return `max(${this.dependsOn.map((op) => op.ref()).join(',')})` 56 | } 57 | derivative(param: Param) { 58 | const [a, b] = this.dependsOn 59 | return `${a.ref()}>${b.ref()} ? ${a.derivRef(param)} : ${b.derivRef(param)}` 60 | } 61 | } 62 | 63 | export class IfElse extends Op { 64 | definition() { 65 | const [condition, thenOp, elseOp] = this.dependsOn 66 | return `${condition.ref()}?${thenOp.ref()}:${elseOp.ref()}` 67 | } 68 | derivative(param: Param) { 69 | const [condition, thenOp, elseOp] = this.dependsOn 70 | return `${condition.ref()}?${thenOp.derivRef(param)}:${elseOp.derivRef(param)}` 71 | } 72 | } 73 | 74 | export class Abs extends Op { 75 | definition() { 76 | return `abs(${this.dependsOn[0].ref()})` 77 | } 78 | derivative(param: Param) { 79 | return '0.0' 80 | } 81 | } 82 | 83 | declare module './base' { 84 | interface Op { 85 | sin(): Op 86 | cos(): Op 87 | tan(): Op 88 | mix(b: Input, amt: Input): Op 89 | clamp(min: Input, max: Input): Op 90 | min(...params: Input[]): Op 91 | max(...params: Input[]): Op 92 | ifElse(thenOp: Input, elseOp: Input): Op 93 | } 94 | } 95 | 96 | Op.prototype.sin = UserInput(function() { 97 | return new Sin(this.ad, this) 98 | }) 99 | Op.prototype.cos = UserInput(function() { 100 | return new Cos(this.ad, this) 101 | }) 102 | Op.prototype.tan = UserInput(function() { 103 | // TODO make this its own class to optimize it 104 | return this.sin().div(this.cos()) 105 | }) 106 | Op.prototype.mix = UserInput(function(b: Input, amt: Input) { 107 | return new Mix(this.ad, this, this.ad.convertVal(b), this.ad.convertVal(amt)) 108 | }) 109 | Op.prototype.clamp = UserInput(function(min: Input, max: Input) { 110 | return new Clamp(this.ad, this, this.ad.convertVal(min), this.ad.convertVal(max)) 111 | }) 112 | Op.prototype.min = UserInput(function(...params: Input[]) { 113 | return params.reduce( 114 | (acc, next) => new Min(this.ad, acc, this.ad.convertVal(next)), 115 | this, 116 | ) 117 | }) 118 | Op.prototype.max = UserInput(function(...params: Input[]) { 119 | return params.reduce( 120 | (acc, next) => new Max(this.ad, acc, this.ad.convertVal(next)), 121 | this, 122 | ) 123 | }) 124 | Op.prototype.ifElse = UserInput(function(thenOp: Input, elseOp: Input) { 125 | return new IfElse(this.ad, this, this.ad.convertVal(thenOp), this.ad.convertVal(elseOp)) 126 | }) 127 | 128 | export function WithFunctions(Base: T) { 129 | class AutoDiff extends Base { 130 | sin = UserInput(function(input: Input) { 131 | return this.convertVal(input).sin() 132 | }) 133 | cos = UserInput(function(input: Input) { 134 | return this.convertVal(input).cos() 135 | }) 136 | tan = UserInput(function(input: Input) { 137 | return this.convertVal(input).tan() 138 | }) 139 | mix = UserInput(function(a: Input, b: Input, amt: Input) { 140 | return this.convertVal(a).mix(b, amt) 141 | }) 142 | clamp = UserInput(function(val: Input, min: Input, max: Input) { 143 | return this.convertVal(val).clamp(min, max) 144 | }) 145 | min = UserInput(function(...params: Input[]) { 146 | if (params.length === 0) { 147 | throw new Error(`No arguments passed to min()!`) 148 | } else { 149 | const first = this.convertVal(params[0]) 150 | if (params.length > 1) { 151 | return first.min(...params.slice(1)) 152 | } else { 153 | return first 154 | } 155 | } 156 | }) 157 | max = UserInput(function(...params: Input[]) { 158 | if (params.length === 0) { 159 | throw new Error(`No arguments passed to min()!`) 160 | } else { 161 | const first = this.convertVal(params[0]) 162 | if (params.length > 1) { 163 | return first.max(...params.slice(1)) 164 | } else { 165 | return first 166 | } 167 | } 168 | }) 169 | ifElse = UserInput(function(ifOp: Input, thenOp: Input, elseOp: Input) { 170 | return this.convertVal(ifOp).ifElse(thenOp, elseOp) 171 | }) 172 | } 173 | return AutoDiff 174 | } 175 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { ADSettings, Input, Param, Op, Value, ADBase, UserInput } from './base' 2 | import { WithArithmetic } from './arithmetic' 3 | import { WithFunctions } from './functions' 4 | import { WithVecBase } from './vecBase' 5 | import { WithVecArithmetic } from './vecArithmetic' 6 | import { WithVecFunctions } from './vecFunctions' 7 | 8 | class AutoDiffImpl implements ADBase { 9 | protected nextID = 0 10 | public getNextID(): number { 11 | const id = this.nextID 12 | this.nextID++ 13 | return id 14 | } 15 | 16 | public settings: ADSettings = { 17 | maxDepthPerVariable: 8, 18 | debug: false, 19 | } 20 | 21 | protected params: { [key: string]: Param } = {} 22 | protected outputs: { [key: string]: Op } = {} 23 | protected derivOutputs: { [param: string]: { [key: string]: Op } } = {} 24 | 25 | public val = UserInput(function(n: number) { return new Value(this, n) }) 26 | public registerParam(param, name) { 27 | this.params[name] = param 28 | } 29 | public param = UserInput(function(name: string) { 30 | return new Param(this, name) 31 | }) 32 | 33 | public convertVal(param: Input): Op { 34 | if (param instanceof Op) { 35 | return param 36 | } else { 37 | return this.val(param) 38 | } 39 | } 40 | public convertVals(params: Input[]): Op[] { 41 | return params.map((param) => this.convertVal(param)) 42 | } 43 | 44 | public output(name: string, op: Op) { 45 | this.outputs[name] = op 46 | return this 47 | } 48 | 49 | public outputDeriv(name: string, param: Param | string, op: Op) { 50 | const paramName = typeof param === 'string' ? param : param.name 51 | this.derivOutputs[paramName] = this.derivOutputs[paramName] || {} 52 | this.derivOutputs[paramName][name] = op 53 | return this 54 | } 55 | 56 | public gen(): string { 57 | let code = '' 58 | 59 | // Add initializers for outputs 60 | const deps = new Set() 61 | const derivDeps = new Map>() 62 | 63 | for (const name in this.outputs) { 64 | code += this.outputs[name].outputDependencies({ deps, derivDeps }) 65 | code += this.outputs[name].initializer() 66 | deps.add(this.outputs[name]) 67 | code += `${this.outputs[name].glslType()} ${name}=${this.outputs[name].ref()};\n` 68 | } 69 | for (const param in this.derivOutputs) { 70 | const paramOp = this.params[param] 71 | for (const name in this.derivOutputs[param]) { 72 | code += this.derivOutputs[param][name].outputDerivDependencies(paramOp, { deps, derivDeps }) 73 | code += this.derivOutputs[param][name].derivInitializer(paramOp) 74 | code += `${this.derivOutputs[param][name].glslType()} ${name}=${this.derivOutputs[param][name].derivRef(paramOp)};\n` 75 | const paramDerivDeps = derivDeps.get(paramOp) ?? new Set() 76 | paramDerivDeps.add(this.derivOutputs[param][name]) 77 | derivDeps.set(paramOp, paramDerivDeps) 78 | } 79 | } 80 | 81 | return code 82 | } 83 | } 84 | 85 | // TODO figure out a better way of writing this that Typescript can still infer the type of 86 | const ExtendedAD = WithVecFunctions(WithVecArithmetic(WithVecBase(WithFunctions(WithArithmetic(AutoDiffImpl))))) 87 | type GetType = T extends new (...args: any[]) => infer V ? V : never 88 | export type AD = GetType 89 | 90 | export const gen = (cb: (ad: AD) => void, settings: Partial = {}): string => { 91 | const ad = new ExtendedAD() 92 | for (const setting in settings) { 93 | ad.settings[setting] = settings[setting] 94 | } 95 | cb(ad) 96 | return ad.gen() 97 | } 98 | -------------------------------------------------------------------------------- /src/vecArithmetic.ts: -------------------------------------------------------------------------------- 1 | import { Input, Param, ADBase, ADConstructor, UserInput } from './base' 2 | import { VectorOp, WithVecDependencies } from './vecBase' 3 | 4 | export class VecNeg extends WithVecDependencies { 5 | definition() { 6 | return `-${this.dependsOn[0].ref()}` 7 | } 8 | derivative(param: Param) { 9 | return '-' + this.dependsOn[0].derivRef(param) 10 | } 11 | } 12 | 13 | export class VecSum extends WithVecDependencies { 14 | definition() { 15 | return this.dependsOn.map((op) => op.ref()).join('+') 16 | } 17 | derivative(param: Param) { 18 | return this.dependsOn.map((op) => op.derivRef(param)).join('+') 19 | } 20 | } 21 | 22 | export class VecScale extends WithVecDependencies { 23 | definition() { 24 | return this.dependsOn.map((op) => op.ref()).join('*') 25 | } 26 | derivative(param: Param) { 27 | const [f, g] = this.dependsOn 28 | return `${f.ref()}*${g.derivRef(param)}+${g.ref()}*${f.derivRef(param)}` 29 | } 30 | } 31 | 32 | export class VecMult extends WithVecDependencies { 33 | definition() { 34 | return this.dependsOn.map((op) => op.ref()).join('*') 35 | } 36 | derivative(param: Param) { 37 | const [f, g] = this.dependsOn 38 | // Multiplying two vectors in glsl does elementwise multiplication 39 | return `${f.ref()}*${g.derivRef(param)}+${g.ref()}*${f.derivRef(param)}` 40 | } 41 | } 42 | 43 | declare module './vecBase' { 44 | interface VectorOp { 45 | neg(): VectorOp 46 | add(...params: VectorOp[]): VectorOp 47 | scale(k: Input): VectorOp 48 | mult(...params: VectorOp[]): VectorOp 49 | } 50 | } 51 | VectorOp.prototype.neg = UserInput(function() { 52 | return new VecNeg(this.ad, this) 53 | }) 54 | VectorOp.prototype.add = UserInput(function(...params: VectorOp[]) { 55 | return new VecSum(this.ad, this, ...params) 56 | }) 57 | VectorOp.prototype.scale = UserInput(function(k: Input) { 58 | return new VecScale(this.ad, this, this.ad.convertVal(k)) 59 | }) 60 | VectorOp.prototype.mult = UserInput(function(...params: VectorOp[]) { 61 | if (params.length === 0) { 62 | throw new Error(`mult() called with too few arguments: ${params}`) 63 | } else if (params.length === 1) { 64 | return new VecMult(this.ad, this, params[0]) 65 | } else { 66 | return this.mult(params[0]).mult(...params.slice(1)) 67 | } 68 | }) 69 | 70 | export function WithVecArithmetic(Base: T) { 71 | class AutoDiff extends Base { 72 | vecSum = UserInput(function(...params: VectorOp[]) { 73 | if (params.length === 0) { 74 | throw new Error('No arguments passed to vecSum()!') 75 | } else if (params.length === 1) { 76 | return params[0] 77 | } else { 78 | return params[0].add(...params.slice(1)) 79 | } 80 | }) 81 | vecProd = UserInput(function(...params: VectorOp[]) { 82 | return params.reduce((acc, next) => acc.mult(next)) 83 | }) 84 | } 85 | return AutoDiff 86 | } 87 | -------------------------------------------------------------------------------- /src/vecBase.ts: -------------------------------------------------------------------------------- 1 | import { Op, OpLiteral, ADBase, Param, Input, ADConstructor, UserInput, EqOp } from './base' 2 | 3 | export interface VecOp extends Op { 4 | x(): Op 5 | y(): Op 6 | z(): Op 7 | w(): Op 8 | definition(): string 9 | derivative(param: Param): string 10 | size(): number 11 | } 12 | 13 | export class VecElementRef extends Op { 14 | public prop: string 15 | 16 | constructor(ad: ADBase, prop: string, vec: VecOp) { 17 | super(ad, vec) 18 | this.prop = prop 19 | } 20 | 21 | definition() { return `${this.dependsOn[0].ref()}.${this.prop}` } 22 | derivative(param: Param) { return `${this.dependsOn[0].derivRef(param)}.${this.prop}` } 23 | } 24 | 25 | export class VecParamElementRef extends Param { 26 | public prop: string 27 | public name: string 28 | 29 | constructor(ad: ADBase, prop: string, vec: VecOp) { 30 | super(ad, `_glslad_r${vec.id}_${prop}`, vec) 31 | this.prop = prop 32 | this.name = `_glslad_r${vec.id}_${prop}` 33 | this.ad.registerParam(this, this.name) 34 | } 35 | 36 | public isConst(param?: Param) { 37 | if (param) { 38 | return param !== this 39 | } else { 40 | return false 41 | } 42 | } 43 | 44 | definition() { return `${this.dependsOn[0].ref()}.${this.prop}` } 45 | derivative(param: Param) { 46 | if (param === this) { 47 | return '1.0' 48 | } else { 49 | return '0.0' 50 | } 51 | } 52 | } 53 | 54 | export function Cache(target: Object, propertyKey: string, descriptor: PropertyDescriptor) { 55 | const originalMethod = descriptor.value 56 | let created = false 57 | const cache = new Map() 58 | descriptor.value = function(...args: any[]) { 59 | let cached = cache.get(this) 60 | if (!cached) { 61 | cached = originalMethod.apply(this, ...args) 62 | cache.set(this, cached) 63 | } 64 | return cached 65 | } 66 | return descriptor 67 | } 68 | 69 | 70 | 71 | export abstract class VectorOp extends Op { 72 | scalar() { return false } 73 | 74 | abstract size(): number 75 | 76 | @Cache 77 | public x(): Op { return new VecElementRef(this.ad, 'x', this) } 78 | 79 | @Cache 80 | public y(): Op { return new VecElementRef(this.ad, 'y', this) } 81 | 82 | @Cache 83 | public z(): Op { return new VecElementRef(this.ad, 'z', this) } 84 | 85 | @Cache 86 | public w(): Op { return new VecElementRef(this.ad, 'w', this) } 87 | 88 | public getVecElementRef(el: string) { 89 | if (el === 'x') { 90 | return this.x() 91 | } else if (el === 'y') { 92 | return this.y() 93 | } else if (el === 'z') { 94 | return this.z() 95 | } else if (el === 'w') { 96 | return this.w() 97 | } else { 98 | throw new Error(`Can't get element ref ${el}`) 99 | } 100 | } 101 | 102 | public glslType() { 103 | return `vec${this.size()}` 104 | } 105 | 106 | zeroDerivative() { 107 | return `${this.glslType()}(0.0)` 108 | } 109 | 110 | public u() { return this.x() } 111 | public v() { return this.y() } 112 | public r() { return this.x() } 113 | public g() { return this.y() } 114 | public b() { return this.z() } 115 | public a() { return this.w() } 116 | // I really wish I could just do a loop but I also want TS to statically type this, 117 | // so instead I just found permutations of all combinations and generated code to 118 | // paste in. 119 | // TODO make these refs instead of new vectors 120 | xyzw() { return new Vec(this.ad, this.x(), this.y(), this.z(), this.w()) } 121 | xywz() { return new Vec(this.ad, this.x(), this.y(), this.w(), this.z()) } 122 | xzyw() { return new Vec(this.ad, this.x(), this.z(), this.y(), this.w()) } 123 | xzwy() { return new Vec(this.ad, this.x(), this.z(), this.w(), this.y()) } 124 | xwyz() { return new Vec(this.ad, this.x(), this.w(), this.y(), this.z()) } 125 | xwzy() { return new Vec(this.ad, this.x(), this.w(), this.z(), this.y()) } 126 | yxzw() { return new Vec(this.ad, this.y(), this.x(), this.z(), this.w()) } 127 | yxwz() { return new Vec(this.ad, this.y(), this.x(), this.w(), this.z()) } 128 | yzxw() { return new Vec(this.ad, this.y(), this.z(), this.x(), this.w()) } 129 | yzwx() { return new Vec(this.ad, this.y(), this.z(), this.w(), this.x()) } 130 | ywxz() { return new Vec(this.ad, this.y(), this.w(), this.x(), this.z()) } 131 | ywzx() { return new Vec(this.ad, this.y(), this.w(), this.z(), this.x()) } 132 | zxyw() { return new Vec(this.ad, this.z(), this.x(), this.y(), this.w()) } 133 | zxwy() { return new Vec(this.ad, this.z(), this.x(), this.w(), this.y()) } 134 | zyxw() { return new Vec(this.ad, this.z(), this.y(), this.x(), this.w()) } 135 | zywx() { return new Vec(this.ad, this.z(), this.y(), this.w(), this.x()) } 136 | zwxy() { return new Vec(this.ad, this.z(), this.w(), this.x(), this.y()) } 137 | zwyx() { return new Vec(this.ad, this.z(), this.w(), this.y(), this.x()) } 138 | wxyz() { return new Vec(this.ad, this.w(), this.x(), this.y(), this.z()) } 139 | wxzy() { return new Vec(this.ad, this.w(), this.x(), this.z(), this.y()) } 140 | wyxz() { return new Vec(this.ad, this.w(), this.y(), this.x(), this.z()) } 141 | wyzx() { return new Vec(this.ad, this.w(), this.y(), this.z(), this.x()) } 142 | wzxy() { return new Vec(this.ad, this.w(), this.z(), this.x(), this.y()) } 143 | wzyx() { return new Vec(this.ad, this.w(), this.z(), this.y(), this.x()) } 144 | xyz() { return new Vec(this.ad, this.x(), this.y(), this.z()) } 145 | xzy() { return new Vec(this.ad, this.x(), this.z(), this.y()) } 146 | yxz() { return new Vec(this.ad, this.y(), this.x(), this.z()) } 147 | yzx() { return new Vec(this.ad, this.y(), this.z(), this.x()) } 148 | zxy() { return new Vec(this.ad, this.z(), this.x(), this.y()) } 149 | zyx() { return new Vec(this.ad, this.z(), this.y(), this.x()) } 150 | xyw() { return new Vec(this.ad, this.x(), this.y(), this.w()) } 151 | xwy() { return new Vec(this.ad, this.x(), this.w(), this.y()) } 152 | yxw() { return new Vec(this.ad, this.y(), this.x(), this.w()) } 153 | ywx() { return new Vec(this.ad, this.y(), this.w(), this.x()) } 154 | wxy() { return new Vec(this.ad, this.w(), this.x(), this.y()) } 155 | wyx() { return new Vec(this.ad, this.w(), this.y(), this.x()) } 156 | xy() { return new Vec(this.ad, this.x(), this.y()) } 157 | yx() { return new Vec(this.ad, this.y(), this.x()) } 158 | xzw() { return new Vec(this.ad, this.x(), this.z(), this.w()) } 159 | xwz() { return new Vec(this.ad, this.x(), this.w(), this.z()) } 160 | zxw() { return new Vec(this.ad, this.z(), this.x(), this.w()) } 161 | zwx() { return new Vec(this.ad, this.z(), this.w(), this.x()) } 162 | wxz() { return new Vec(this.ad, this.w(), this.x(), this.z()) } 163 | wzx() { return new Vec(this.ad, this.w(), this.z(), this.x()) } 164 | xz() { return new Vec(this.ad, this.x(), this.z()) } 165 | zx() { return new Vec(this.ad, this.z(), this.x()) } 166 | xw() { return new Vec(this.ad, this.x(), this.w()) } 167 | wx() { return new Vec(this.ad, this.w(), this.x()) } 168 | yzw() { return new Vec(this.ad, this.y(), this.z(), this.w()) } 169 | ywz() { return new Vec(this.ad, this.y(), this.w(), this.z()) } 170 | zyw() { return new Vec(this.ad, this.z(), this.y(), this.w()) } 171 | zwy() { return new Vec(this.ad, this.z(), this.w(), this.y()) } 172 | wyz() { return new Vec(this.ad, this.w(), this.y(), this.z()) } 173 | wzy() { return new Vec(this.ad, this.w(), this.z(), this.y()) } 174 | yz() { return new Vec(this.ad, this.y(), this.z()) } 175 | zy() { return new Vec(this.ad, this.z(), this.y()) } 176 | yw() { return new Vec(this.ad, this.y(), this.w()) } 177 | wy() { return new Vec(this.ad, this.w(), this.y()) } 178 | zw() { return new Vec(this.ad, this.z(), this.w()) } 179 | wz() { return new Vec(this.ad, this.w(), this.z()) } 180 | rgba() { return new Vec(this.ad, this.r(), this.g(), this.b(), this.a()) } 181 | rgab() { return new Vec(this.ad, this.r(), this.g(), this.a(), this.b()) } 182 | rbga() { return new Vec(this.ad, this.r(), this.b(), this.g(), this.a()) } 183 | rbag() { return new Vec(this.ad, this.r(), this.b(), this.a(), this.g()) } 184 | ragb() { return new Vec(this.ad, this.r(), this.a(), this.g(), this.b()) } 185 | rabg() { return new Vec(this.ad, this.r(), this.a(), this.b(), this.g()) } 186 | grba() { return new Vec(this.ad, this.g(), this.r(), this.b(), this.a()) } 187 | grab() { return new Vec(this.ad, this.g(), this.r(), this.a(), this.b()) } 188 | gbra() { return new Vec(this.ad, this.g(), this.b(), this.r(), this.a()) } 189 | gbar() { return new Vec(this.ad, this.g(), this.b(), this.a(), this.r()) } 190 | garb() { return new Vec(this.ad, this.g(), this.a(), this.r(), this.b()) } 191 | gabr() { return new Vec(this.ad, this.g(), this.a(), this.b(), this.r()) } 192 | brga() { return new Vec(this.ad, this.b(), this.r(), this.g(), this.a()) } 193 | brag() { return new Vec(this.ad, this.b(), this.r(), this.a(), this.g()) } 194 | bgra() { return new Vec(this.ad, this.b(), this.g(), this.r(), this.a()) } 195 | bgar() { return new Vec(this.ad, this.b(), this.g(), this.a(), this.r()) } 196 | barg() { return new Vec(this.ad, this.b(), this.a(), this.r(), this.g()) } 197 | bagr() { return new Vec(this.ad, this.b(), this.a(), this.g(), this.r()) } 198 | argb() { return new Vec(this.ad, this.a(), this.r(), this.g(), this.b()) } 199 | arbg() { return new Vec(this.ad, this.a(), this.r(), this.b(), this.g()) } 200 | agrb() { return new Vec(this.ad, this.a(), this.g(), this.r(), this.b()) } 201 | agbr() { return new Vec(this.ad, this.a(), this.g(), this.b(), this.r()) } 202 | abrg() { return new Vec(this.ad, this.a(), this.b(), this.r(), this.g()) } 203 | abgr() { return new Vec(this.ad, this.a(), this.b(), this.g(), this.r()) } 204 | rgb() { return new Vec(this.ad, this.r(), this.g(), this.b()) } 205 | rbg() { return new Vec(this.ad, this.r(), this.b(), this.g()) } 206 | grb() { return new Vec(this.ad, this.g(), this.r(), this.b()) } 207 | gbr() { return new Vec(this.ad, this.g(), this.b(), this.r()) } 208 | brg() { return new Vec(this.ad, this.b(), this.r(), this.g()) } 209 | bgr() { return new Vec(this.ad, this.b(), this.g(), this.r()) } 210 | rga() { return new Vec(this.ad, this.r(), this.g(), this.a()) } 211 | rag() { return new Vec(this.ad, this.r(), this.a(), this.g()) } 212 | gra() { return new Vec(this.ad, this.g(), this.r(), this.a()) } 213 | gar() { return new Vec(this.ad, this.g(), this.a(), this.r()) } 214 | arg() { return new Vec(this.ad, this.a(), this.r(), this.g()) } 215 | agr() { return new Vec(this.ad, this.a(), this.g(), this.r()) } 216 | rg() { return new Vec(this.ad, this.r(), this.g()) } 217 | gr() { return new Vec(this.ad, this.g(), this.r()) } 218 | rba() { return new Vec(this.ad, this.r(), this.b(), this.a()) } 219 | rab() { return new Vec(this.ad, this.r(), this.a(), this.b()) } 220 | bra() { return new Vec(this.ad, this.b(), this.r(), this.a()) } 221 | bar() { return new Vec(this.ad, this.b(), this.a(), this.r()) } 222 | arb() { return new Vec(this.ad, this.a(), this.r(), this.b()) } 223 | abr() { return new Vec(this.ad, this.a(), this.b(), this.r()) } 224 | rb() { return new Vec(this.ad, this.r(), this.b()) } 225 | br() { return new Vec(this.ad, this.b(), this.r()) } 226 | ra() { return new Vec(this.ad, this.r(), this.a()) } 227 | ar() { return new Vec(this.ad, this.a(), this.r()) } 228 | gba() { return new Vec(this.ad, this.g(), this.b(), this.a()) } 229 | gab() { return new Vec(this.ad, this.g(), this.a(), this.b()) } 230 | bga() { return new Vec(this.ad, this.b(), this.g(), this.a()) } 231 | bag() { return new Vec(this.ad, this.b(), this.a(), this.g()) } 232 | agb() { return new Vec(this.ad, this.a(), this.g(), this.b()) } 233 | abg() { return new Vec(this.ad, this.a(), this.b(), this.g()) } 234 | gb() { return new Vec(this.ad, this.g(), this.b()) } 235 | bg() { return new Vec(this.ad, this.b(), this.g()) } 236 | ga() { return new Vec(this.ad, this.g(), this.a()) } 237 | ag() { return new Vec(this.ad, this.a(), this.g()) } 238 | ba() { return new Vec(this.ad, this.b(), this.a()) } 239 | ab() { return new Vec(this.ad, this.a(), this.b()) } 240 | uv() { return new Vec(this.ad, this.u(), this.v()) } 241 | vu() { return new Vec(this.ad, this.v(), this.u()) } 242 | } 243 | 244 | export abstract class WithVecDependencies extends VectorOp { 245 | public get vecDependsOn() { 246 | return this.dependsOn as VecOp[] 247 | } 248 | 249 | public size() { 250 | return this.vecDependsOn[0].size() 251 | } 252 | } 253 | 254 | export abstract class ScalarWithVecDependencies extends Op { 255 | public get vecDependsOn() { 256 | return this.dependsOn as VecOp[] 257 | } 258 | 259 | public size() { 260 | return this.vecDependsOn[0].size() 261 | } 262 | } 263 | 264 | export class OffsetJacobian extends WithVecDependencies { 265 | constructor(ad, ...args) { 266 | super(ad, ...args) 267 | this.internalDerivatives.push( 268 | { op: this.offset(), param: this.position().x() }, 269 | { op: this.offset(), param: this.position().y() }, 270 | { op: this.offset(), param: this.position().z() }, 271 | ) 272 | for (const { op } of this.internalDerivatives) { 273 | op.usedIn.push(this) 274 | } 275 | } 276 | 277 | public size(): number { 278 | return 3 279 | } 280 | 281 | private position() { 282 | return this.dependsOn[0] as VecParam 283 | } 284 | 285 | private offset() { 286 | return this.dependsOn[1] as VectorOp 287 | } 288 | 289 | glslType() { 290 | return 'mat3' 291 | } 292 | 293 | definition() { 294 | const dodx = this.offset().derivRef(this.position().x()) 295 | const dody = this.offset().derivRef(this.position().y()) 296 | const dodz = this.offset().derivRef(this.position().z()) 297 | return `mat3(${dodx},${dody},${dodz})` 298 | } 299 | derivative(_param: Param): string { 300 | throw new Error('Unimplemented') 301 | } 302 | 303 | public dot(vec3: VectorOp) { 304 | return new Mat3Dot(this.ad, this, vec3) 305 | } 306 | } 307 | 308 | export class Mat3Dot extends VectorOp { 309 | public size() { 310 | return 3 311 | } 312 | 313 | private mat3() { 314 | return this.dependsOn[0] as OffsetJacobian 315 | } 316 | 317 | private vec3() { 318 | return this.dependsOn[1] as VectorOp 319 | } 320 | 321 | definition() { 322 | return `${this.mat3().ref()}*${this.vec3().ref()}` 323 | } 324 | derivative(_param: Param): string { 325 | throw new Error('Unimplemented') 326 | } 327 | } 328 | 329 | export class Vec extends VectorOp { 330 | public size(): number { 331 | return this.dependsOn.length 332 | } 333 | 334 | definition() { 335 | return `vec${this.size()}(${this.dependsOn.map((op) => op.ref()).join(',')})` 336 | } 337 | derivative(param: Param) { 338 | return `vec${this.size()}(${this.dependsOn.map((op) => op.derivRef(param)).join(',')})` 339 | } 340 | 341 | public x() { return this.dependsOn[0] } 342 | public y() { return this.dependsOn[1] } 343 | public z() { return this.dependsOn[2] } 344 | public w() { return this.dependsOn[3] } 345 | } 346 | 347 | export class VecParam extends VectorOp { 348 | private name: string 349 | private _size: number 350 | public size() { return this._size } 351 | 352 | constructor(ad: ADBase, name: string, size: number) { 353 | super(ad) 354 | this.name = name 355 | this._size = size 356 | } 357 | 358 | @Cache 359 | public x() { return new VecParamElementRef(this.ad, 'x', this) } 360 | 361 | @Cache 362 | public y() { return new VecParamElementRef(this.ad, 'y', this) } 363 | 364 | @Cache 365 | public z() { return new VecParamElementRef(this.ad, 'z', this) } 366 | 367 | @Cache 368 | public w() { return new VecParamElementRef(this.ad, 'w', this) } 369 | 370 | private getElems() { 371 | return 'xyzw' 372 | .split('') 373 | .slice(0, this.size()) 374 | .map((el) => this.getVecElementRef(el)) 375 | } 376 | 377 | definition() { return this.name } 378 | derivative(param: Param) { 379 | return `vec${this.size()}(${this.getElems().map((el) => el.derivRef(param)).join(',')})` 380 | } 381 | 382 | public isConst(param?: Param) { 383 | if (param) { 384 | return param !== this.x() && param !== this.y() && param !== this.z() 385 | } else { 386 | return false 387 | } 388 | } 389 | 390 | public override initializer() { return '' } 391 | public override ref() { return this.definition() } 392 | public override derivInitializer(param: Param) { 393 | if (this.isConst(param) || !this.useTempVar()) { 394 | return '' 395 | } else { 396 | return `vec${this.size()} ${this.derivRef(param)}=${this.derivative(param)};\n` 397 | } 398 | } 399 | } 400 | 401 | export function WithVecBase(Base: T) { 402 | class AutoDiff extends Base { 403 | vec2Param = UserInput(function(name: string) { 404 | return new VecParam(this, name, 2) 405 | }) 406 | vec3Param = UserInput(function(name: string) { 407 | return new VecParam(this, name, 3) 408 | }) 409 | vec4Param = UserInput(function(name: string) { 410 | return new VecParam(this, name, 4) 411 | }) 412 | vec2 = UserInput(function(x: Input, y: Input) { 413 | return new Vec(this, this.convertVal(x), this.convertVal(y)) 414 | }) 415 | vec3 = UserInput(function(x: Input, y: Input, z: Input) { 416 | return new Vec(this, ...this.convertVals([x, y, z])) 417 | }) 418 | vec4 = UserInput(function(x: Input, y: Input, z: Input, w: Input) { 419 | return new Vec(this, ...this.convertVals([x, y, z, w])) 420 | }) 421 | } 422 | return AutoDiff 423 | } 424 | -------------------------------------------------------------------------------- /src/vecFunctions.ts: -------------------------------------------------------------------------------- 1 | import { Input, Op, Param, ADBase, ADConstructor, UserInput, EqOp, AndOp, Value, LtOp } from './base' 2 | import { Vec, VecParam, VectorOp, WithVecDependencies, ScalarWithVecDependencies, OffsetJacobian } from './vecBase' 3 | import { VecMult, VecSum } from './vecArithmetic' 4 | import { Abs } from './functions' 5 | import { Mult } from './arithmetic' 6 | 7 | export class VecMix extends WithVecDependencies { 8 | definition() { 9 | return `mix(${this.dependsOn.map((op) => op.ref()).join(',')})` 10 | } 11 | derivative(param: Param) { 12 | const [a, b, mix] = this.dependsOn 13 | const aDeriv = `(1.0-${a.ref()})*${mix.derivRef(param)}+(-${a.derivRef(param)})*${mix.ref()}` 14 | const bDeriv = `${b.ref()}*${mix.derivRef(param)}+${b.derivRef(param)}*${mix.ref()}` 15 | return `${aDeriv}+${bDeriv}` 16 | } 17 | } 18 | 19 | export class VecClamp extends WithVecDependencies { 20 | definition() { 21 | return `clamp(${this.dependsOn.map((op) => op.ref()).join(',')})` 22 | } 23 | derivative(param: Param) { 24 | // Get an expression for the derivative of just one element in the vector 25 | const elemClamp = (v, min, max) => `${v.ref()}<${min.ref()} ? 0.0 : (${v.ref()}>${max.ref()} ? 0.0 : ${v.derivRef(param)})` 26 | 27 | // Get refs for each element of each parameter 28 | const toRefs = (vec) => 'xyzw'.split('').slice(0, vec.size()).map((el) => vec.getVecElementRef(el)) 29 | const [vecC, vecMin, vecMax] = this.vecDependsOn.map(toRefs) 30 | 31 | // Construct a vector out of the elementwise derivatives 32 | const innerDef = Array(this.size()).fill(0).map((_, i) => elemClamp(vecC[i], vecMin[i], vecMax[i])).join(',') 33 | return `vec${this.size()}(${innerDef})` 34 | } 35 | } 36 | 37 | export class VecMin extends WithVecDependencies { 38 | definition() { 39 | return `min(${this.dependsOn.map((op) => op.ref()).join(',')})` 40 | } 41 | derivative(param: Param) { 42 | // Get an expression for the derivative of just one element in the vector 43 | const elemMin = (a, b) => `${a.ref()}<${b.ref()} ? ${a.derivRef(param)} : ${b.derivRef(param)}` 44 | 45 | // Get refs for each element of each parameter 46 | const toRefs = (vec) => 'xyzw'.split('').slice(0, vec.size()).map((el) => vec.getVecElementRef(el)) 47 | const [vecA, vecB] = this.vecDependsOn.map(toRefs) 48 | 49 | // Construct a vector out of the elementwise derivatives 50 | const innerDef = Array(this.size()).fill(0).map((_, i) => elemMin(vecA[i], vecB[i])).join(',') 51 | return `vec${this.size()}(${innerDef})` 52 | } 53 | } 54 | 55 | export class VecMax extends WithVecDependencies { 56 | definition() { 57 | return `max(${this.dependsOn.map((op) => op.ref()).join(',')})` 58 | } 59 | derivative(param: Param) { 60 | // Get an expression for the derivative of just one element in the vector 61 | const elemMax = (a, b) => `${a.ref()}>${b.ref()} ? ${a.derivRef(param)} : ${b.derivRef(param)}` 62 | 63 | // Get refs for each element of each parameter 64 | const toRefs = (vec) => 'xyzw'.split('').slice(0, vec.size()).map((el) => vec.getVecElementRef(el)) 65 | const [vecA, vecB] = this.vecDependsOn.map(toRefs) 66 | 67 | // Construct a vector out of the elementwise derivatives 68 | const innerDef = Array(this.size()).fill(0).map((_, i) => elemMax(vecA[i], vecB[i])).join(',') 69 | return `vec${this.size()}(${innerDef})` 70 | } 71 | } 72 | 73 | export class VecIfElse extends WithVecDependencies { 74 | override size() { 75 | return this.vecDependsOn[1].size() 76 | } 77 | definition() { 78 | const [condition, thenOp, elseOp] = this.dependsOn 79 | return `${condition.ref()}?${thenOp.ref()}:${elseOp.ref()}` 80 | } 81 | derivative(param: Param) { 82 | const [condition, thenOp, elseOp] = this.dependsOn 83 | return `${condition.ref()}?${thenOp.derivRef(param)}:${elseOp.derivRef(param)}` 84 | } 85 | } 86 | 87 | export class VecNormalize extends WithVecDependencies { 88 | override size() { 89 | return this.vecDependsOn[0].size() 90 | } 91 | definition() { 92 | const [input] = this.dependsOn 93 | return `normalize(${input.ref()})` 94 | } 95 | derivative(param: Param): string { 96 | throw new Error('unimplemented') 97 | } 98 | } 99 | 100 | export class VecAbs extends WithVecDependencies { 101 | override size() { 102 | return this.vecDependsOn[0].size() 103 | } 104 | definition() { 105 | const [input] = this.dependsOn 106 | return `abs(${input.ref()})}` 107 | } 108 | derivative(param: Param): string { 109 | return '0.0' 110 | } 111 | } 112 | 113 | export class Dot extends ScalarWithVecDependencies { 114 | definition() { 115 | return `dot(${this.dependsOn.map((v) => v.ref()).join(',')})` 116 | } 117 | derivative(param: Param) { 118 | const [f, g] = this.vecDependsOn 119 | return 'xyzw' 120 | .split('') 121 | .slice(0, this.size()) 122 | .map((el) => `${f.ref()}.${el}*${g.derivRef(param)}.${el}+${g.ref()}.${el}*${f.derivRef(param)}.${el}`) 123 | .join('+') 124 | } 125 | } 126 | 127 | export class Length extends ScalarWithVecDependencies { 128 | override scalar() { return true } 129 | definition() { return `length(${this.dependsOn[0].ref()})` } 130 | derivative(param: Param) { 131 | const outerDeriv = `0.5/length(${this.dependsOn[0].ref()})` 132 | const innerDeriv = 'xyzw' 133 | .split('') 134 | .slice(0, this.size()) 135 | .map((el) => `2.0*${this.dependsOn[0].ref()}.${el}*${this.dependsOn[0].derivRef(param)}.${el}`) 136 | .join('+') 137 | return `${outerDeriv}*${innerDeriv}` 138 | } 139 | } 140 | 141 | export class Dist extends ScalarWithVecDependencies { 142 | definition() { return `distance(${this.dependsOn.map((v) => v.ref()).join(',')})` } 143 | derivative(param: Param) { 144 | const outerDeriv = `0.5/distance(${this.dependsOn.map((v) => v.ref()).join(',')})` 145 | const innerDeriv = 'xyzw' 146 | .split('') 147 | .slice(0, this.size()) 148 | .map((el) => { 149 | const diff = this.dependsOn.map((v) => v.ref()).join('-') 150 | const derivDiff = this.dependsOn.map((v) => v.derivRef(param)).join('-') 151 | return `2.0*(${diff}).${el}*(${derivDiff}).${el}` 152 | }) 153 | .join('+') 154 | return `${outerDeriv}*${innerDeriv}` 155 | } 156 | } 157 | 158 | export class Cross extends WithVecDependencies { 159 | override size() { 160 | return this.vecDependsOn[0].size() 161 | } 162 | definition() { 163 | const [a, b] = this.dependsOn 164 | return `cross(${a.ref()},${b.ref()})` 165 | } 166 | derivative(param: Param): string { 167 | throw new Error('unimplemented') 168 | } 169 | } 170 | 171 | export class Normalize extends WithVecDependencies { 172 | override size() { 173 | return this.vecDependsOn[0].size() 174 | } 175 | definition() { 176 | const [a, b] = this.dependsOn 177 | return `normalize(${a.ref()}})` 178 | } 179 | derivative(param: Param): string { 180 | throw new Error('unimplemented') 181 | } 182 | } 183 | 184 | declare module './vecBase' { 185 | interface VectorOp { 186 | mix(other: VectorOp, amt: Input): VectorOp 187 | clamp(min: VectorOp, max: VectorOp): VectorOp 188 | min(...params: VectorOp[]): VectorOp 189 | max(...params: VectorOp[]): VectorOp 190 | dot(other: VectorOp): Op 191 | length(): Op 192 | dist(other: VectorOp): Op 193 | adjustNormal(normal: VecParam, position: VecParam): VectorOp 194 | } 195 | } 196 | declare module './base' { 197 | interface Op { 198 | vecIfElse(thenOp: VectorOp, elseOp: VectorOp): VectorOp 199 | } 200 | } 201 | 202 | VectorOp.prototype.mix = UserInput(function(other: VectorOp, amt: Input) { 203 | return new VecMix(this.ad, this, other, this.ad.convertVal(amt)) 204 | }) 205 | VectorOp.prototype.clamp = UserInput(function(min: VectorOp, max: VectorOp) { 206 | return new VecClamp(this.ad, this, min, max) 207 | }) 208 | VectorOp.prototype.min = UserInput(function(...params: VectorOp[]) { 209 | return params.reduce( 210 | (acc, next) => new VecMin(this.ad, acc, next), 211 | this, 212 | ) 213 | }) 214 | VectorOp.prototype.max = UserInput(function(...params: VectorOp[]) { 215 | return params.reduce( 216 | (acc, next) => new VecMax(this.ad, acc, next), 217 | this, 218 | ) 219 | }) 220 | VectorOp.prototype.dot = UserInput(function(other: VectorOp) { 221 | return new Dot(this.ad, this, other) 222 | }) 223 | VectorOp.prototype.length = UserInput(function() { 224 | return new Length(this.ad, this) 225 | }) 226 | VectorOp.prototype.dist = UserInput(function(other: VectorOp) { 227 | return new Dist(this.ad, this, other) 228 | }) 229 | Op.prototype.vecIfElse = UserInput(function(thenOp: VectorOp, elseOp: VectorOp) { 230 | return new VecIfElse(this.ad, this, thenOp, elseOp) 231 | }) 232 | VectorOp.prototype.adjustNormal = function(normal: VecParam, position: VecParam) { 233 | const x = new Vec(this.ad, ...this.ad.convertVals([1, 0, 0])) 234 | const y = new Vec(this.ad, ...this.ad.convertVals([0, 1, 0])) 235 | const yEq0 = new EqOp(this.ad, normal.y(), new Value(this.ad, 0)) 236 | const zEq0 = new EqOp(this.ad, normal.z(), new Value(this.ad, 0)) 237 | const normalIsX = new AndOp(this.ad, yEq0, zEq0) 238 | const other = normalIsX.vecIfElse(y, x) 239 | const v = new VecNormalize(this.ad, new Cross(this.ad, other, normal)) 240 | const u = new Cross(this.ad, v, normal) 241 | const jacobian = new OffsetJacobian(this.ad, position, this) 242 | const dodu = new VecMult(this.ad, jacobian, u) 243 | const dodv = new VecMult(this.ad, jacobian, v) 244 | return new VecNormalize(this.ad, new Cross( 245 | this.ad, 246 | new VecSum(this.ad, u, dodu), 247 | new VecSum(this.ad, v, dodv), 248 | )) 249 | } 250 | 251 | export function WithVecFunctions(Base: T) { 252 | class AutoDiff extends Base { 253 | vecMix = UserInput(function(a: VectorOp, b: VectorOp, amt: Input) { 254 | return a.mix(b, amt) 255 | }) 256 | vecClamp = UserInput(function(val: VectorOp, min: VectorOp, max: VectorOp) { 257 | return val.clamp(min, max) 258 | }) 259 | vecMin = UserInput(function(...params: VectorOp[]) { 260 | if (params.length === 0) { 261 | throw new Error(`No arguments passed to vecMin()!`) 262 | } else { 263 | return params.reduce((acc, next) => acc.min(next)) 264 | } 265 | }) 266 | vecMax = UserInput(function(...params: VectorOp[]) { 267 | if (params.length === 0) { 268 | throw new Error(`No arguments passed to vecMax()!`) 269 | } else { 270 | return params.reduce((acc, next) => acc.max(next)) 271 | } 272 | }) 273 | dot = UserInput(function(a: VectorOp, b: VectorOp) { 274 | return a.dot(b) 275 | }) 276 | length = UserInput(function(val: VectorOp) { 277 | return val.length() 278 | }) 279 | dist = UserInput(function(a: VectorOp, b: VectorOp) { 280 | return a.dist(b) 281 | }) 282 | } 283 | return AutoDiff 284 | } 285 | -------------------------------------------------------------------------------- /test/advanced_plane/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | glsl-autodiff test 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/advanced_plane/test.js: -------------------------------------------------------------------------------- 1 | const vert = ` 2 | attribute vec3 aPosition; 3 | attribute vec3 aNormal; 4 | attribute vec2 aTexCoord; 5 | 6 | uniform mat4 uModelViewMatrix; 7 | uniform mat4 uProjectionMatrix; 8 | uniform mat3 uNormalMatrix; 9 | 10 | uniform float time; 11 | 12 | varying vec2 vTexCoord; 13 | varying vec3 vNormal; 14 | varying vec3 vPosition; 15 | 16 | void main(void) { 17 | vec4 objSpacePosition = vec4(aPosition, 1.0); 18 | float origZ = objSpacePosition.z; 19 | ${AutoDiff.gen((ad) => { 20 | const aTexCoord = ad.vec2Param('aTexCoord') 21 | const time = ad.param('time') 22 | 23 | const displace_sin = (vec, magnitude, t, waviness, angle) => { 24 | const cos_angle = ad.cos(angle) 25 | const sin_angle = ad.sin(angle) 26 | const dist = vec.dot(ad.vec2(cos_angle, sin_angle)) 27 | return magnitude.mult(ad.sin(t.add(dist.mult(waviness)))) 28 | } 29 | 30 | const displace_rad = (vec, magnitude, t, waviness, center) => { 31 | const dist = vec.dist(center) 32 | const timeScaledDist = t.add(dist.mult(waviness)) 33 | 34 | return magnitude.mult( 35 | ad.sum( 36 | ad.sin(timeScaledDist.mult(6)), 37 | ad.sin(timeScaledDist), 38 | -1 39 | ).max(0).pow(2), 40 | ) 41 | } 42 | 43 | let offset = ad.val(0) 44 | offset = offset.add(displace_sin(aTexCoord, ad.sin(time).mult(0.5), time.mult(5), ad.val(5), ad.val(2*Math.PI/8))) 45 | offset = offset.add(displace_sin(aTexCoord, ad.sin(time.add(10)).add(5).mult(0.15), time.mult(5).add(50), ad.val(10), ad.val(2*Math.PI*0.4))) 46 | offset = offset.sub(displace_rad(aTexCoord, ad.sin(time).add(1), time.mult(1.5).add(8), ad.val(4), ad.vec2(-0.5, -0.5))) 47 | offset = offset.mult(0.08) 48 | 49 | offset.output('z') 50 | offset.outputDeriv('dzdx', aTexCoord.x()) 51 | offset.outputDeriv('dzdy', aTexCoord.y()) 52 | })} 53 | objSpacePosition.z += z; 54 | vec3 slopeX = vec3(1.0, 0.0, dzdx); 55 | vec3 slopeY = vec3(0.0, 1.0, dzdy); 56 | vec4 worldSpacePosition = uModelViewMatrix * objSpacePosition; 57 | gl_Position = uProjectionMatrix * worldSpacePosition; 58 | vTexCoord = aTexCoord; 59 | vPosition = worldSpacePosition.xyz; 60 | vNormal = uNormalMatrix * normalize(cross(slopeX, slopeY)); 61 | } 62 | ` 63 | console.log(vert) 64 | 65 | const frag = ` 66 | precision mediump float; 67 | const int MAX_LIGHTS = 3; 68 | 69 | varying vec2 vTexCoord; 70 | varying vec3 vNormal; 71 | varying vec3 vPosition; 72 | 73 | uniform sampler2D img; 74 | uniform int numLights; 75 | uniform vec3 lightPositions[MAX_LIGHTS]; 76 | uniform vec3 lightColors[MAX_LIGHTS]; 77 | uniform float lightStrengths[MAX_LIGHTS]; 78 | uniform vec3 ambientLight; 79 | uniform float materialShininess; 80 | 81 | void main(void) { 82 | vec3 materialColor = texture2D(img, vTexCoord).rgb; 83 | vec3 normal = normalize(vNormal); 84 | vec3 color = vec3(0.0, 0.0, 0.0); 85 | for (int i = 0; i < MAX_LIGHTS; i++) { 86 | if (i >= numLights) break; 87 | vec3 lightPosition = lightPositions[i]; 88 | float distanceSquared = 0.0; /*0.00015*dot( 89 | lightPosition - vPosition, 90 | lightPosition - vPosition);*/ 91 | vec3 lightDir = normalize(lightPosition - vPosition); 92 | float lambertian = max(dot(lightDir, normal), 0.0); 93 | color += lambertian * materialColor * lightColors[i] * 94 | lightStrengths[i] / (1.0 + distanceSquared); 95 | vec3 viewDir = normalize(-vPosition); 96 | float spec = pow( 97 | max(dot(viewDir, reflect(-lightDir, normal)), 0.0), 98 | materialShininess); 99 | color += spec * lightStrengths[i] * lightColors[i] / 100 | (1.0 + distanceSquared); 101 | } 102 | color += ambientLight * materialColor; 103 | gl_FragColor = vec4(color, 1.0); 104 | } 105 | ` 106 | 107 | let distortShader 108 | let texture 109 | function setup() { 110 | createCanvas(800, 600, WEBGL) 111 | distortShader = createShader(vert, frag) 112 | texture = createGraphics(500, 500) 113 | } 114 | 115 | const lights = [{ 116 | position: [200, 50, -100], 117 | color: [1, 1, 1], 118 | strength: 0.5, 119 | }, 120 | { 121 | position: [-200, -50, -100], 122 | color: [1, 1, 1], 123 | strength: 0.5, 124 | }, 125 | ]; 126 | 127 | function draw() { 128 | texture.background(255, 0, 0) 129 | texture.fill(255) 130 | texture.noStroke() 131 | texture.textSize(70) 132 | texture.textAlign(CENTER, CENTER) 133 | texture.text('hello, world', texture.width / 2, texture.height / 2) 134 | 135 | background(0) 136 | 137 | const shininess = 1000 138 | const ambient = [0.2, 0.2, 0.2] 139 | 140 | orbitControl() 141 | noStroke() 142 | shader(distortShader) 143 | distortShader.setUniform('img', texture) 144 | distortShader.setUniform('lightPositions', lights.map(l => l.position).flat()) 145 | distortShader.setUniform('lightColors', lights.map(l => l.color).flat()) 146 | distortShader.setUniform('lightStrengths', lights.map(l => l.strength).flat()) 147 | distortShader.setUniform('numLights', lights.length) 148 | distortShader.setUniform('ambientLight', ambient) 149 | distortShader.setUniform('materialShininess', shininess) 150 | distortShader.setUniform('time', frameCount*.005) 151 | push() 152 | const r = 200 153 | scale(r) 154 | plane(1, 1, 40, 40) 155 | pop() 156 | } 157 | -------------------------------------------------------------------------------- /test/simple-wiggle/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | glsl-autodiff test 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/simple-wiggle/test.js: -------------------------------------------------------------------------------- 1 | const vert = ` 2 | attribute vec3 aPosition; 3 | attribute vec3 aNormal; 4 | attribute vec2 aTexCoord; 5 | 6 | uniform mat4 uModelViewMatrix; 7 | uniform mat4 uProjectionMatrix; 8 | uniform mat3 uNormalMatrix; 9 | 10 | uniform float time; 11 | 12 | varying vec2 vTexCoord; 13 | varying vec3 vNormal; 14 | varying vec3 vPosition; 15 | 16 | void main(void) { 17 | vec4 objSpacePosition = vec4(aPosition, 1.0); 18 | float origZ = objSpacePosition.z; 19 | ${AutoDiff.gen((ad) => { 20 | const pos = ad.vec3Param('objSpacePosition') 21 | const y = pos.y() 22 | const time = ad.param('time') 23 | 24 | offset = ad.vec3(time.mult(0.005).add(y.mult(2)).sin().mult(0.5), 0, 0) 25 | offset.output('offset') 26 | offset.adjustNormal(ad.vec3Param('aNormal'), pos).output('normal') 27 | //offset.output('z') 28 | //offset.outputDeriv('dzdx', x) 29 | //offset.outputDeriv('dzdy', y) 30 | }, { debug: true, maxDepthPerVariable: 8 })} 31 | objSpacePosition.xyz += offset; 32 | //vec3 slopeX = vec3(1.0, 0.0, dzdx); 33 | //vec3 slopeY = vec3(0.0, 1.0, dzdy); 34 | vec4 worldSpacePosition = uModelViewMatrix * objSpacePosition; 35 | gl_Position = uProjectionMatrix * worldSpacePosition; 36 | vTexCoord = aTexCoord; 37 | vPosition = worldSpacePosition.xyz; 38 | //vNormal = uNormalMatrix * aNormal; 39 | //normal=cross(_glslad_v66,_glslad_v65); 40 | //normal=_glslad_v66; 41 | vNormal = uNormalMatrix * normal; 42 | } 43 | ` 44 | console.log(vert) 45 | 46 | const frag = ` 47 | precision mediump float; 48 | const int MAX_LIGHTS = 3; 49 | 50 | varying vec2 vTexCoord; 51 | varying vec3 vNormal; 52 | varying vec3 vPosition; 53 | 54 | uniform sampler2D img; 55 | uniform int numLights; 56 | uniform vec3 lightPositions[MAX_LIGHTS]; 57 | uniform vec3 lightColors[MAX_LIGHTS]; 58 | uniform float lightStrengths[MAX_LIGHTS]; 59 | uniform vec3 ambientLight; 60 | uniform float materialShininess; 61 | 62 | void main(void) { 63 | vec3 materialColor = texture2D(img, vTexCoord).rgb; 64 | vec3 normal = normalize(vNormal); 65 | gl_FragColor = vec4(abs(normal), 1.); return; 66 | //gl_FragColor = length(vNormal) * vec4(1.); return; 67 | vec3 color = vec3(0.0, 0.0, 0.0); 68 | for (int i = 0; i < MAX_LIGHTS; i++) { 69 | if (i >= numLights) break; 70 | vec3 lightPosition = lightPositions[i]; 71 | float distanceSquared = 0.0; /*0.00015*dot( 72 | lightPosition - vPosition, 73 | lightPosition - vPosition);*/ 74 | vec3 lightDir = normalize(lightPosition - vPosition); 75 | float lambertian = max(dot(lightDir, normal), 0.0); 76 | color += lambertian * materialColor * lightColors[i] * 77 | lightStrengths[i] / (1.0 + distanceSquared); 78 | vec3 viewDir = normalize(-vPosition); 79 | float spec = pow( 80 | max(dot(viewDir, reflect(-lightDir, normal)), 0.0), 81 | materialShininess); 82 | color += spec * lightStrengths[i] * lightColors[i] / 83 | (1.0 + distanceSquared); 84 | } 85 | color += ambientLight * materialColor; 86 | gl_FragColor = vec4(color, 1.0); 87 | } 88 | ` 89 | 90 | let distortShader 91 | let texture 92 | function setup() { 93 | createCanvas(800, 600, WEBGL) 94 | distortShader = createShader(vert, frag) 95 | texture = createGraphics(500, 500) 96 | } 97 | 98 | const lights = [{ 99 | position: [200, 50, -100], 100 | color: [1, 1, 1], 101 | strength: 0.5, 102 | }, 103 | { 104 | position: [-200, -50, -100], 105 | color: [1, 1, 1], 106 | strength: 0.5, 107 | }, 108 | ]; 109 | 110 | function draw() { 111 | texture.background(255, 0, 0) 112 | texture.fill(255) 113 | texture.noStroke() 114 | texture.textSize(70) 115 | texture.textAlign(CENTER, CENTER) 116 | texture.text('hello, world', texture.width / 2, texture.height / 2) 117 | 118 | background(0) 119 | 120 | const shininess = 1000 121 | const ambient = [0.2, 0.2, 0.2] 122 | 123 | orbitControl() 124 | noStroke() 125 | shader(distortShader) 126 | distortShader.setUniform('img', texture) 127 | distortShader.setUniform('lightPositions', lights.map(l => l.position).flat()) 128 | distortShader.setUniform('lightColors', lights.map(l => l.color).flat()) 129 | distortShader.setUniform('lightStrengths', lights.map(l => l.strength).flat()) 130 | distortShader.setUniform('numLights', lights.length) 131 | distortShader.setUniform('ambientLight', ambient) 132 | distortShader.setUniform('materialShininess', shininess) 133 | distortShader.setUniform('time', millis()) 134 | push() 135 | sphere(200, 60, 30) 136 | pop() 137 | } 138 | -------------------------------------------------------------------------------- /test/sine_plane/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | glsl-autodiff test 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/sine_plane/test.js: -------------------------------------------------------------------------------- 1 | const vert = ` 2 | attribute vec3 aPosition; 3 | attribute vec3 aNormal; 4 | attribute vec2 aTexCoord; 5 | 6 | uniform mat4 uModelViewMatrix; 7 | uniform mat4 uProjectionMatrix; 8 | uniform mat3 uNormalMatrix; 9 | 10 | uniform float time; 11 | 12 | varying vec2 vTexCoord; 13 | varying vec3 vNormal; 14 | varying vec3 vPosition; 15 | 16 | void main(void) { 17 | vec4 objSpacePosition = vec4(aPosition, 1.0); 18 | float origZ = objSpacePosition.z; 19 | float x = objSpacePosition.x; 20 | float y = objSpacePosition.y; 21 | ${AutoDiff.gen((ad) => { 22 | const x = ad.param('x') 23 | const y = ad.param('y') 24 | const time = ad.param('time') 25 | const speedX = 1.5 26 | const speedY = 2.8 27 | 28 | let offset = ad.val(0) 29 | for (let i = 0; i < 3; i++) { 30 | offset = offset.add(ad.sin( 31 | ad.sum( 32 | offset.mult(0.5).add(x.mult(speedX)).add(y.mult(speedY)), 33 | time.mult(0.002), 34 | ) 35 | )) 36 | } 37 | offset = offset.mult(0.1) 38 | offset.output('z') 39 | offset.outputDeriv('dzdx', x) 40 | offset.outputDeriv('dzdy', y) 41 | }, { debug: true, maxDepthPerVariable: 4 })} 42 | objSpacePosition.z += z; 43 | vec3 slopeX = vec3(1.0, 0.0, dzdx); 44 | vec3 slopeY = vec3(0.0, 1.0, dzdy); 45 | vec4 worldSpacePosition = uModelViewMatrix * objSpacePosition; 46 | gl_Position = uProjectionMatrix * worldSpacePosition; 47 | vTexCoord = aTexCoord; 48 | vPosition = worldSpacePosition.xyz; 49 | vNormal = uNormalMatrix * normalize(cross(slopeX, slopeY)); 50 | } 51 | ` 52 | console.log(vert) 53 | 54 | const frag = ` 55 | precision mediump float; 56 | const int MAX_LIGHTS = 3; 57 | 58 | varying vec2 vTexCoord; 59 | varying vec3 vNormal; 60 | varying vec3 vPosition; 61 | 62 | uniform sampler2D img; 63 | uniform int numLights; 64 | uniform vec3 lightPositions[MAX_LIGHTS]; 65 | uniform vec3 lightColors[MAX_LIGHTS]; 66 | uniform float lightStrengths[MAX_LIGHTS]; 67 | uniform vec3 ambientLight; 68 | uniform float materialShininess; 69 | 70 | void main(void) { 71 | vec3 materialColor = texture2D(img, vTexCoord).rgb; 72 | vec3 normal = normalize(vNormal); 73 | vec3 color = vec3(0.0, 0.0, 0.0); 74 | for (int i = 0; i < MAX_LIGHTS; i++) { 75 | if (i >= numLights) break; 76 | vec3 lightPosition = lightPositions[i]; 77 | float distanceSquared = 0.0; /*0.00015*dot( 78 | lightPosition - vPosition, 79 | lightPosition - vPosition);*/ 80 | vec3 lightDir = normalize(lightPosition - vPosition); 81 | float lambertian = max(dot(lightDir, normal), 0.0); 82 | color += lambertian * materialColor * lightColors[i] * 83 | lightStrengths[i] / (1.0 + distanceSquared); 84 | vec3 viewDir = normalize(-vPosition); 85 | float spec = pow( 86 | max(dot(viewDir, reflect(-lightDir, normal)), 0.0), 87 | materialShininess); 88 | color += spec * lightStrengths[i] * lightColors[i] / 89 | (1.0 + distanceSquared); 90 | } 91 | color += ambientLight * materialColor; 92 | gl_FragColor = vec4(color, 1.0); 93 | } 94 | ` 95 | 96 | let distortShader 97 | let texture 98 | function setup() { 99 | createCanvas(800, 600, WEBGL) 100 | distortShader = createShader(vert, frag) 101 | texture = createGraphics(500, 500) 102 | } 103 | 104 | const lights = [{ 105 | position: [200, 50, -100], 106 | color: [1, 1, 1], 107 | strength: 0.5, 108 | }, 109 | { 110 | position: [-200, -50, -100], 111 | color: [1, 1, 1], 112 | strength: 0.5, 113 | }, 114 | ]; 115 | 116 | function draw() { 117 | texture.background(255, 0, 0) 118 | texture.fill(255) 119 | texture.noStroke() 120 | texture.textSize(70) 121 | texture.textAlign(CENTER, CENTER) 122 | texture.text('hello, world', texture.width / 2, texture.height / 2) 123 | 124 | background(0) 125 | 126 | const shininess = 1000 127 | const ambient = [0.2, 0.2, 0.2] 128 | 129 | orbitControl() 130 | noStroke() 131 | shader(distortShader) 132 | distortShader.setUniform('img', texture) 133 | distortShader.setUniform('lightPositions', lights.map(l => l.position).flat()) 134 | distortShader.setUniform('lightColors', lights.map(l => l.color).flat()) 135 | distortShader.setUniform('lightStrengths', lights.map(l => l.strength).flat()) 136 | distortShader.setUniform('numLights', lights.length) 137 | distortShader.setUniform('ambientLight', ambient) 138 | distortShader.setUniform('materialShininess', shininess) 139 | distortShader.setUniform('time', millis()) 140 | push() 141 | const r = 200 142 | scale(r) 143 | plane(1, 1, 20, 20) 144 | pop() 145 | } 146 | -------------------------------------------------------------------------------- /test/sinenoise_plane/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | glsl-autodiff test 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/sinenoise_plane/test.js: -------------------------------------------------------------------------------- 1 | const vert = ` 2 | //standard vertex shader 3 | #ifdef GL_ES 4 | precision mediump float; 5 | #endif 6 | 7 | // attributes, in 8 | attribute vec3 aPosition; 9 | attribute vec3 aNormal; 10 | attribute vec2 aTexCoord; 11 | attribute vec4 aVertexColor; 12 | 13 | // attributes, out 14 | varying vec2 vTexCoord; 15 | varying vec3 vNormal; 16 | varying vec3 vPosition; 17 | 18 | uniform float time; 19 | uniform float wind; 20 | uniform float anchor; 21 | uniform float height; 22 | 23 | // matrices 24 | uniform mat4 uModelViewMatrix; 25 | uniform mat4 uProjectionMatrix; 26 | uniform mat3 uNormalMatrix; 27 | 28 | 29 | /*float sinnoise(vec2 u ){ 30 | vec2 zoom = vec2(4.0,4.0); 31 | vec2 offset = vec2(10.,1.); 32 | vec2 cumul = u*zoom+offset; 33 | float a_x = 0.4; 34 | float a_y = 0.4; 35 | for(int i=1; i< 4; i++){ 36 | float float_i = float(i); 37 | cumul.x+= a_x*sin(float_i*cumul.y+time); 38 | cumul.y+= a_y*cos(float_i*cumul.x+time); 39 | }; 40 | 41 | float r = sin(cumul.x*cumul.y)*.5+.5; 42 | r = smoothstep(-0.5,1.5,r); 43 | return r; 44 | 45 | }*/ 46 | 47 | void main() { 48 | vec3 pos = aPosition; 49 | vec3 inputNorm = aNormal; 50 | float var_height = height; 51 | 52 | float var_anchor = -pos.x; 53 | if(anchor == 1.) var_anchor = -pos.y; 54 | if(anchor == 2.) var_anchor = pos.x; 55 | if(anchor == 3.) var_anchor = pos.y; 56 | 57 | ${AutoDiff.gen((ad) => { 58 | const pos = ad.vec2Param('pos.xy') 59 | const time = ad.param('time') 60 | const var_anchor = ad.param('var_anchor') 61 | const var_height = ad.param('var_height') 62 | const wind = ad.param('wind') 63 | 64 | const smoothstep = (edge0, edge1, x) => { 65 | const t = x.sub(edge0).div(edge1.sub(edge0)).clamp(0, 1) 66 | return t.mult(t).mult(t.mult(-2).add(3)) 67 | } 68 | 69 | const sinnoise = (u) => { 70 | const zoom = ad.vec2(4, 4) 71 | const offset = ad.vec2(10, 1) 72 | let cumul = u.mult(zoom).add(offset) 73 | const a = ad.vec2(0.4, 0.4) 74 | for (let i = 1; i < 4; i++) { 75 | cumul = cumul.add( 76 | ad 77 | .vec2( 78 | ad.sin(ad.val(i).mult(cumul.y()).add(time)), 79 | ad.sin(ad.val(i).mult(cumul.x()).add(time)), 80 | ) 81 | .mult(a), 82 | ) 83 | } 84 | 85 | const r = ad.sin(cumul.x().mult(cumul.y())).mult(0.5).add(0.5) 86 | return smoothstep(ad.val(-0.5), ad.val(1.5), r) 87 | } 88 | 89 | const sn = sinnoise(pos.neg().scale(0.1)) 90 | const z = sn.mult(var_anchor.mult(2).sub(1)).mult(var_height).mult(wind) 91 | z.output('z') 92 | z.outputDeriv('dzdx', pos.x()) 93 | z.outputDeriv('dzdy', pos.y()) 94 | })} 95 | 96 | //float sn = sinnoise(-pos.xy*.10); 97 | //pos.z = sn * (var_anchor*2.-1.) * var_height * wind; 98 | pos.z = z; 99 | vec3 slopeX = vec3(1.0, 0.0, dzdx); 100 | vec3 slopeY = vec3(0.0, 1.0, dzdy); 101 | vNormal = uNormalMatrix * normalize(cross(slopeX, slopeY)); 102 | 103 | gl_Position = uProjectionMatrix * 104 | uModelViewMatrix * 105 | vec4(pos, 1.0); 106 | 107 | vPosition = pos; 108 | vTexCoord = aTexCoord; 109 | 110 | } 111 | ` 112 | console.log(vert) 113 | 114 | const frag = ` 115 | precision mediump float; 116 | const int MAX_LIGHTS = 3; 117 | 118 | varying vec2 vTexCoord; 119 | varying vec3 vNormal; 120 | varying vec3 vPosition; 121 | 122 | uniform sampler2D img; 123 | uniform int numLights; 124 | uniform vec3 lightPositions[MAX_LIGHTS]; 125 | uniform vec3 lightColors[MAX_LIGHTS]; 126 | uniform float lightStrengths[MAX_LIGHTS]; 127 | uniform vec3 ambientLight; 128 | uniform float materialShininess; 129 | 130 | void main() { 131 | 132 | vec3 materialColor = texture2D(img, vTexCoord).rgb; 133 | vec3 normal = normalize(vNormal); 134 | vec3 color = vec3(0.0, 0.0, 0.0); 135 | for (int i = 0; i < MAX_LIGHTS; i++) { 136 | if (i >= numLights) break; 137 | vec3 toLightNormal = normal; 138 | vec3 lightPosition = lightPositions[i]; 139 | float distanceSquared = 0.0; /*0.00015*dot( 140 | lightPosition - vPosition, 141 | lightPosition - vPosition);*/ 142 | vec3 lightDir = normalize(lightPosition - vPosition); 143 | if (dot(lightDir, toLightNormal) < 0.0) { 144 | toLightNormal *= -1.0; 145 | } 146 | float lambertian = max(dot(lightDir, toLightNormal), 0.0); 147 | color += lambertian * materialColor * lightColors[i] * 148 | lightStrengths[i] / (1.0 + distanceSquared); 149 | vec3 viewDir = normalize(-vPosition); 150 | float spec = pow( 151 | max(dot(viewDir, reflect(-lightDir, toLightNormal)), 0.0), 152 | materialShininess); 153 | color += spec * lightStrengths[i] * lightColors[i] / 154 | (1.0 + distanceSquared); 155 | } 156 | color += ambientLight * materialColor; 157 | gl_FragColor = vec4(color, 1.0); 158 | //gl_FragColor = vec4(normal, 1.0); 159 | } 160 | ` 161 | 162 | let distortShader 163 | let texture 164 | function setup() { 165 | createCanvas(800, 600, WEBGL) 166 | distortShader = createShader(vert, frag) 167 | texture = createGraphics(500, 500) 168 | } 169 | 170 | const lights = [{ 171 | position: [200, 50, -100], 172 | color: [1, 1, 1], 173 | strength: 0.5, 174 | }, 175 | { 176 | position: [-200, -50, -100], 177 | color: [1, 1, 1], 178 | strength: 0.5, 179 | }, 180 | ]; 181 | 182 | function draw() { 183 | texture.background(255, 0, 0) 184 | texture.fill(255) 185 | texture.noStroke() 186 | texture.textSize(70) 187 | texture.textAlign(CENTER, CENTER) 188 | texture.text('hello, world', texture.width / 2, texture.height / 2) 189 | 190 | background(0) 191 | 192 | const shininess = 1000 193 | const ambient = [0.2, 0.2, 0.2] 194 | 195 | orbitControl() 196 | noStroke() 197 | shader(distortShader) 198 | distortShader.setUniform('height', 0.4) 199 | distortShader.setUniform('wind', 1) 200 | distortShader.setUniform('anchor', 0) 201 | distortShader.setUniform('time', frameCount*.005) 202 | distortShader.setUniform('img', texture) 203 | distortShader.setUniform('lightPositions', lights.map(l => l.position).flat()) 204 | distortShader.setUniform('lightColors', lights.map(l => l.color).flat()) 205 | distortShader.setUniform('lightStrengths', lights.map(l => l.strength).flat()) 206 | distortShader.setUniform('numLights', lights.length) 207 | distortShader.setUniform('ambientLight', ambient) 208 | distortShader.setUniform('materialShininess', shininess) 209 | push() 210 | const r = 200 211 | scale(r) 212 | plane(1, 1, 40, 40) 213 | pop() 214 | } 215 | -------------------------------------------------------------------------------- /test/sphere/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | glsl-autodiff test 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/sphere/test.js: -------------------------------------------------------------------------------- 1 | const vert = ` 2 | attribute vec3 aPosition; 3 | attribute vec3 aNormal; 4 | attribute vec2 aTexCoord; 5 | 6 | uniform mat4 uModelViewMatrix; 7 | uniform mat4 uProjectionMatrix; 8 | uniform mat3 uNormalMatrix; 9 | 10 | uniform float time; 11 | 12 | varying vec2 vTexCoord; 13 | varying vec3 vNormal; 14 | varying vec3 vPosition; 15 | 16 | void main(void) { 17 | vec4 objSpacePosition = vec4(aPosition, 1.0); 18 | float origZ = objSpacePosition.z; 19 | ${AutoDiff.gen((ad) => { 20 | const pos = ad.vec3Param('objSpacePosition') 21 | const x = pos.x() 22 | const y = pos.y() 23 | const time = ad.param('time') 24 | const speedX = 1.5 25 | const speedY = 2.8 26 | 27 | let offset = ad.val(0) 28 | for (let i = 0; i < 3; i++) { 29 | offset = offset.add(ad.sin( 30 | ad.sum( 31 | offset.mult(0.5).add(x.mult(speedX)).add(y.mult(speedY)), 32 | time.mult(0.002), 33 | ) 34 | )) 35 | } 36 | offset = offset.mult(0.1) 37 | offset = ad.vec3(0, 0, offset) 38 | offset.output('offset') 39 | offset.adjustNormal(ad.vec3Param('aNormal'), pos).output('normal') 40 | //offset.output('z') 41 | //offset.outputDeriv('dzdx', x) 42 | //offset.outputDeriv('dzdy', y) 43 | }, { debug: true, maxDepthPerVariable: 4 })} 44 | objSpacePosition.xyz += offset; 45 | //vec3 slopeX = vec3(1.0, 0.0, dzdx); 46 | //vec3 slopeY = vec3(0.0, 1.0, dzdy); 47 | vec4 worldSpacePosition = uModelViewMatrix * objSpacePosition; 48 | gl_Position = uProjectionMatrix * worldSpacePosition; 49 | vTexCoord = aTexCoord; 50 | vPosition = worldSpacePosition.xyz; 51 | //vNormal = uNormalMatrix * aNormal; 52 | //normal=cross(_glslad_v66,_glslad_v65); 53 | //normal=_glslad_v66; 54 | vNormal = uNormalMatrix * normal; 55 | } 56 | ` 57 | console.log(vert) 58 | 59 | const frag = ` 60 | precision mediump float; 61 | const int MAX_LIGHTS = 3; 62 | 63 | varying vec2 vTexCoord; 64 | varying vec3 vNormal; 65 | varying vec3 vPosition; 66 | 67 | uniform sampler2D img; 68 | uniform int numLights; 69 | uniform vec3 lightPositions[MAX_LIGHTS]; 70 | uniform vec3 lightColors[MAX_LIGHTS]; 71 | uniform float lightStrengths[MAX_LIGHTS]; 72 | uniform vec3 ambientLight; 73 | uniform float materialShininess; 74 | 75 | void main(void) { 76 | vec3 materialColor = texture2D(img, vTexCoord).rgb; 77 | vec3 normal = normalize(vNormal); 78 | gl_FragColor = vec4(abs(normal), 1.); return; 79 | //gl_FragColor = length(vNormal) * vec4(1.); return; 80 | vec3 color = vec3(0.0, 0.0, 0.0); 81 | for (int i = 0; i < MAX_LIGHTS; i++) { 82 | if (i >= numLights) break; 83 | vec3 lightPosition = lightPositions[i]; 84 | float distanceSquared = 0.0; /*0.00015*dot( 85 | lightPosition - vPosition, 86 | lightPosition - vPosition);*/ 87 | vec3 lightDir = normalize(lightPosition - vPosition); 88 | float lambertian = max(dot(lightDir, normal), 0.0); 89 | color += lambertian * materialColor * lightColors[i] * 90 | lightStrengths[i] / (1.0 + distanceSquared); 91 | vec3 viewDir = normalize(-vPosition); 92 | float spec = pow( 93 | max(dot(viewDir, reflect(-lightDir, normal)), 0.0), 94 | materialShininess); 95 | color += spec * lightStrengths[i] * lightColors[i] / 96 | (1.0 + distanceSquared); 97 | } 98 | color += ambientLight * materialColor; 99 | gl_FragColor = vec4(color, 1.0); 100 | } 101 | ` 102 | 103 | let distortShader 104 | let texture 105 | function setup() { 106 | createCanvas(800, 600, WEBGL) 107 | distortShader = createShader(vert, frag) 108 | texture = createGraphics(500, 500) 109 | } 110 | 111 | const lights = [{ 112 | position: [200, 50, -100], 113 | color: [1, 1, 1], 114 | strength: 0.5, 115 | }, 116 | { 117 | position: [-200, -50, -100], 118 | color: [1, 1, 1], 119 | strength: 0.5, 120 | }, 121 | ]; 122 | 123 | function draw() { 124 | texture.background(255, 0, 0) 125 | texture.fill(255) 126 | texture.noStroke() 127 | texture.textSize(70) 128 | texture.textAlign(CENTER, CENTER) 129 | texture.text('hello, world', texture.width / 2, texture.height / 2) 130 | 131 | background(0) 132 | 133 | const shininess = 1000 134 | const ambient = [0.2, 0.2, 0.2] 135 | 136 | orbitControl() 137 | noStroke() 138 | shader(distortShader) 139 | distortShader.setUniform('img', texture) 140 | distortShader.setUniform('lightPositions', lights.map(l => l.position).flat()) 141 | distortShader.setUniform('lightColors', lights.map(l => l.color).flat()) 142 | distortShader.setUniform('lightStrengths', lights.map(l => l.strength).flat()) 143 | distortShader.setUniform('numLights', lights.length) 144 | distortShader.setUniform('ambientLight', ambient) 145 | distortShader.setUniform('materialShininess', shininess) 146 | distortShader.setUniform('time', millis()) 147 | push() 148 | sphere(200, 60, 30) 149 | pop() 150 | } 151 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["es2015", "dom"], 4 | "outDir": "build", 5 | "allowJs": true, 6 | "experimentalDecorators": true, 7 | "emitDecoratorMetadata": true, 8 | "noImplicitAny": false, 9 | "downlevelIteration": true, 10 | "module": "commonjs", 11 | "strictPropertyInitialization": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "esModuleInterop": true, 14 | "moduleResolution": "node", 15 | "removeComments": true, 16 | "target": "es6", 17 | "sourceMap": true, 18 | "strictNullChecks": true, 19 | "downlevelIteration": true, 20 | "declaration": true 21 | }, 22 | "include": ["./src"], 23 | "exclude": [ 24 | "node_modules", 25 | "*/node_modules" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = (env, argv) => { 4 | const mode = argv.mode ?? 'production' 5 | const config = { 6 | context: path.resolve(__dirname, 'src'), 7 | entry: './index.ts', 8 | mode, 9 | module: { 10 | rules: [{ 11 | test: /\.tsx?$/, 12 | use: 'ts-loader', 13 | exclude: /node_modules/ 14 | }] 15 | }, 16 | output: { 17 | filename: 'autodiff.js', 18 | path: path.resolve(__dirname, 'build'), 19 | libraryTarget: 'umd', 20 | library: 'AutoDiff', 21 | }, 22 | resolve: { 23 | extensions: ['.tsx', '.ts', '.jsx', '.js'] 24 | }, 25 | } 26 | 27 | if (mode === 'development') { 28 | config.devtool = 'inline-source-map' 29 | } 30 | 31 | return config 32 | }; 33 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@discoveryjs/json-ext@^0.5.0": 6 | version "0.5.3" 7 | resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz#90420f9f9c6d3987f176a19a7d8e764271a2f55d" 8 | integrity sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g== 9 | 10 | "@tsconfig/node10@^1.0.7": 11 | version "1.0.8" 12 | resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" 13 | integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== 14 | 15 | "@tsconfig/node12@^1.0.7": 16 | version "1.0.9" 17 | resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" 18 | integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== 19 | 20 | "@tsconfig/node14@^1.0.0": 21 | version "1.0.1" 22 | resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" 23 | integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== 24 | 25 | "@tsconfig/node16@^1.0.1": 26 | version "1.0.1" 27 | resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.1.tgz#a6ca6a9a0ff366af433f42f5f0e124794ff6b8f1" 28 | integrity sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA== 29 | 30 | "@types/eslint-scope@^3.7.0": 31 | version "3.7.0" 32 | resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.0.tgz#4792816e31119ebd506902a482caec4951fabd86" 33 | integrity sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw== 34 | dependencies: 35 | "@types/eslint" "*" 36 | "@types/estree" "*" 37 | 38 | "@types/eslint@*": 39 | version "7.2.13" 40 | resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.13.tgz#e0ca7219ba5ded402062ad6f926d491ebb29dd53" 41 | integrity sha512-LKmQCWAlnVHvvXq4oasNUMTJJb2GwSyTY8+1C7OH5ILR8mPLaljv1jxL1bXW3xB3jFbQxTKxJAvI8PyjB09aBg== 42 | dependencies: 43 | "@types/estree" "*" 44 | "@types/json-schema" "*" 45 | 46 | "@types/estree@*", "@types/estree@^0.0.48": 47 | version "0.0.48" 48 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.48.tgz#18dc8091b285df90db2f25aa7d906cfc394b7f74" 49 | integrity sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew== 50 | 51 | "@types/json-schema@*", "@types/json-schema@^7.0.6": 52 | version "7.0.7" 53 | resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" 54 | integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== 55 | 56 | "@types/node@*", "@types/node@^15.12.5": 57 | version "15.12.5" 58 | resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.5.tgz#9a78318a45d75c9523d2396131bd3cca54b2d185" 59 | integrity sha512-se3yX7UHv5Bscf8f1ERKvQOD6sTyycH3hdaoozvaLxgUiY5lIGEeH37AD0G0Qi9kPqihPn0HOfd2yaIEN9VwEg== 60 | 61 | "@webassemblyjs/ast@1.11.0": 62 | version "1.11.0" 63 | resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.0.tgz#a5aa679efdc9e51707a4207139da57920555961f" 64 | integrity sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg== 65 | dependencies: 66 | "@webassemblyjs/helper-numbers" "1.11.0" 67 | "@webassemblyjs/helper-wasm-bytecode" "1.11.0" 68 | 69 | "@webassemblyjs/floating-point-hex-parser@1.11.0": 70 | version "1.11.0" 71 | resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz#34d62052f453cd43101d72eab4966a022587947c" 72 | integrity sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA== 73 | 74 | "@webassemblyjs/helper-api-error@1.11.0": 75 | version "1.11.0" 76 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz#aaea8fb3b923f4aaa9b512ff541b013ffb68d2d4" 77 | integrity sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w== 78 | 79 | "@webassemblyjs/helper-buffer@1.11.0": 80 | version "1.11.0" 81 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz#d026c25d175e388a7dbda9694e91e743cbe9b642" 82 | integrity sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA== 83 | 84 | "@webassemblyjs/helper-numbers@1.11.0": 85 | version "1.11.0" 86 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz#7ab04172d54e312cc6ea4286d7d9fa27c88cd4f9" 87 | integrity sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ== 88 | dependencies: 89 | "@webassemblyjs/floating-point-hex-parser" "1.11.0" 90 | "@webassemblyjs/helper-api-error" "1.11.0" 91 | "@xtuc/long" "4.2.2" 92 | 93 | "@webassemblyjs/helper-wasm-bytecode@1.11.0": 94 | version "1.11.0" 95 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz#85fdcda4129902fe86f81abf7e7236953ec5a4e1" 96 | integrity sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA== 97 | 98 | "@webassemblyjs/helper-wasm-section@1.11.0": 99 | version "1.11.0" 100 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz#9ce2cc89300262509c801b4af113d1ca25c1a75b" 101 | integrity sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew== 102 | dependencies: 103 | "@webassemblyjs/ast" "1.11.0" 104 | "@webassemblyjs/helper-buffer" "1.11.0" 105 | "@webassemblyjs/helper-wasm-bytecode" "1.11.0" 106 | "@webassemblyjs/wasm-gen" "1.11.0" 107 | 108 | "@webassemblyjs/ieee754@1.11.0": 109 | version "1.11.0" 110 | resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz#46975d583f9828f5d094ac210e219441c4e6f5cf" 111 | integrity sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA== 112 | dependencies: 113 | "@xtuc/ieee754" "^1.2.0" 114 | 115 | "@webassemblyjs/leb128@1.11.0": 116 | version "1.11.0" 117 | resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.0.tgz#f7353de1df38aa201cba9fb88b43f41f75ff403b" 118 | integrity sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g== 119 | dependencies: 120 | "@xtuc/long" "4.2.2" 121 | 122 | "@webassemblyjs/utf8@1.11.0": 123 | version "1.11.0" 124 | resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.0.tgz#86e48f959cf49e0e5091f069a709b862f5a2cadf" 125 | integrity sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw== 126 | 127 | "@webassemblyjs/wasm-edit@1.11.0": 128 | version "1.11.0" 129 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz#ee4a5c9f677046a210542ae63897094c2027cb78" 130 | integrity sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ== 131 | dependencies: 132 | "@webassemblyjs/ast" "1.11.0" 133 | "@webassemblyjs/helper-buffer" "1.11.0" 134 | "@webassemblyjs/helper-wasm-bytecode" "1.11.0" 135 | "@webassemblyjs/helper-wasm-section" "1.11.0" 136 | "@webassemblyjs/wasm-gen" "1.11.0" 137 | "@webassemblyjs/wasm-opt" "1.11.0" 138 | "@webassemblyjs/wasm-parser" "1.11.0" 139 | "@webassemblyjs/wast-printer" "1.11.0" 140 | 141 | "@webassemblyjs/wasm-gen@1.11.0": 142 | version "1.11.0" 143 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz#3cdb35e70082d42a35166988dda64f24ceb97abe" 144 | integrity sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ== 145 | dependencies: 146 | "@webassemblyjs/ast" "1.11.0" 147 | "@webassemblyjs/helper-wasm-bytecode" "1.11.0" 148 | "@webassemblyjs/ieee754" "1.11.0" 149 | "@webassemblyjs/leb128" "1.11.0" 150 | "@webassemblyjs/utf8" "1.11.0" 151 | 152 | "@webassemblyjs/wasm-opt@1.11.0": 153 | version "1.11.0" 154 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz#1638ae188137f4bb031f568a413cd24d32f92978" 155 | integrity sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg== 156 | dependencies: 157 | "@webassemblyjs/ast" "1.11.0" 158 | "@webassemblyjs/helper-buffer" "1.11.0" 159 | "@webassemblyjs/wasm-gen" "1.11.0" 160 | "@webassemblyjs/wasm-parser" "1.11.0" 161 | 162 | "@webassemblyjs/wasm-parser@1.11.0": 163 | version "1.11.0" 164 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz#3e680b8830d5b13d1ec86cc42f38f3d4a7700754" 165 | integrity sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw== 166 | dependencies: 167 | "@webassemblyjs/ast" "1.11.0" 168 | "@webassemblyjs/helper-api-error" "1.11.0" 169 | "@webassemblyjs/helper-wasm-bytecode" "1.11.0" 170 | "@webassemblyjs/ieee754" "1.11.0" 171 | "@webassemblyjs/leb128" "1.11.0" 172 | "@webassemblyjs/utf8" "1.11.0" 173 | 174 | "@webassemblyjs/wast-printer@1.11.0": 175 | version "1.11.0" 176 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz#680d1f6a5365d6d401974a8e949e05474e1fab7e" 177 | integrity sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ== 178 | dependencies: 179 | "@webassemblyjs/ast" "1.11.0" 180 | "@xtuc/long" "4.2.2" 181 | 182 | "@webpack-cli/configtest@^1.0.4": 183 | version "1.0.4" 184 | resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.0.4.tgz#f03ce6311c0883a83d04569e2c03c6238316d2aa" 185 | integrity sha512-cs3XLy+UcxiP6bj0A6u7MLLuwdXJ1c3Dtc0RkKg+wiI1g/Ti1om8+/2hc2A2B60NbBNAbMgyBMHvyymWm/j4wQ== 186 | 187 | "@webpack-cli/info@^1.3.0": 188 | version "1.3.0" 189 | resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.3.0.tgz#9d78a31101a960997a4acd41ffd9b9300627fe2b" 190 | integrity sha512-ASiVB3t9LOKHs5DyVUcxpraBXDOKubYu/ihHhU+t1UPpxsivg6Od2E2qU4gJCekfEddzRBzHhzA/Acyw/mlK/w== 191 | dependencies: 192 | envinfo "^7.7.3" 193 | 194 | "@webpack-cli/serve@^1.5.1": 195 | version "1.5.1" 196 | resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.5.1.tgz#b5fde2f0f79c1e120307c415a4c1d5eb15a6f278" 197 | integrity sha512-4vSVUiOPJLmr45S8rMGy7WDvpWxfFxfP/Qx/cxZFCfvoypTYpPPL1X8VIZMe0WTA+Jr7blUxwUSEZNkjoMTgSw== 198 | 199 | "@xtuc/ieee754@^1.2.0": 200 | version "1.2.0" 201 | resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" 202 | integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== 203 | 204 | "@xtuc/long@4.2.2": 205 | version "4.2.2" 206 | resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" 207 | integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== 208 | 209 | acorn@^8.2.1: 210 | version "8.4.1" 211 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.4.1.tgz#56c36251fc7cabc7096adc18f05afe814321a28c" 212 | integrity sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA== 213 | 214 | ajv-keywords@^3.5.2: 215 | version "3.5.2" 216 | resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" 217 | integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== 218 | 219 | ajv@^6.12.5: 220 | version "6.12.6" 221 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 222 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 223 | dependencies: 224 | fast-deep-equal "^3.1.1" 225 | fast-json-stable-stringify "^2.0.0" 226 | json-schema-traverse "^0.4.1" 227 | uri-js "^4.2.2" 228 | 229 | ansi-styles@^4.1.0: 230 | version "4.3.0" 231 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 232 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 233 | dependencies: 234 | color-convert "^2.0.1" 235 | 236 | arg@^4.1.0: 237 | version "4.1.3" 238 | resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" 239 | integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== 240 | 241 | array-union@^1.0.1: 242 | version "1.0.2" 243 | resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" 244 | integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= 245 | dependencies: 246 | array-uniq "^1.0.1" 247 | 248 | array-uniq@^1.0.1: 249 | version "1.0.3" 250 | resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" 251 | integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= 252 | 253 | async@^2.6.1: 254 | version "2.6.3" 255 | resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" 256 | integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== 257 | dependencies: 258 | lodash "^4.17.14" 259 | 260 | balanced-match@^1.0.0: 261 | version "1.0.2" 262 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 263 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 264 | 265 | brace-expansion@^1.1.7: 266 | version "1.1.11" 267 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 268 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 269 | dependencies: 270 | balanced-match "^1.0.0" 271 | concat-map "0.0.1" 272 | 273 | braces@^3.0.1: 274 | version "3.0.2" 275 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 276 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 277 | dependencies: 278 | fill-range "^7.0.1" 279 | 280 | browserslist@^4.14.5: 281 | version "4.16.6" 282 | resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" 283 | integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== 284 | dependencies: 285 | caniuse-lite "^1.0.30001219" 286 | colorette "^1.2.2" 287 | electron-to-chromium "^1.3.723" 288 | escalade "^3.1.1" 289 | node-releases "^1.1.71" 290 | 291 | buffer-from@^1.0.0: 292 | version "1.1.1" 293 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" 294 | integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== 295 | 296 | caniuse-lite@^1.0.30001219: 297 | version "1.0.30001241" 298 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001241.tgz#cd3fae47eb3d7691692b406568d7a3e5b23c7598" 299 | integrity sha512-1uoSZ1Pq1VpH0WerIMqwptXHNNGfdl7d1cJUFs80CwQ/lVzdhTvsFZCeNFslze7AjsQnb4C85tzclPa1VShbeQ== 300 | 301 | chalk@^4.1.0: 302 | version "4.1.1" 303 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad" 304 | integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== 305 | dependencies: 306 | ansi-styles "^4.1.0" 307 | supports-color "^7.1.0" 308 | 309 | chrome-trace-event@^1.0.2: 310 | version "1.0.3" 311 | resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" 312 | integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== 313 | 314 | clone-deep@^4.0.1: 315 | version "4.0.1" 316 | resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" 317 | integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== 318 | dependencies: 319 | is-plain-object "^2.0.4" 320 | kind-of "^6.0.2" 321 | shallow-clone "^3.0.0" 322 | 323 | color-convert@^2.0.1: 324 | version "2.0.1" 325 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 326 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 327 | dependencies: 328 | color-name "~1.1.4" 329 | 330 | color-name@~1.1.4: 331 | version "1.1.4" 332 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 333 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 334 | 335 | colorette@^1.2.1, colorette@^1.2.2: 336 | version "1.2.2" 337 | resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" 338 | integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== 339 | 340 | commander@^2.18.0, commander@^2.20.0: 341 | version "2.20.3" 342 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 343 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 344 | 345 | commander@^7.0.0: 346 | version "7.2.0" 347 | resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" 348 | integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== 349 | 350 | commondir@^1.0.1: 351 | version "1.0.1" 352 | resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" 353 | integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= 354 | 355 | concat-map@0.0.1: 356 | version "0.0.1" 357 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 358 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 359 | 360 | create-require@^1.1.0: 361 | version "1.1.1" 362 | resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" 363 | integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== 364 | 365 | cross-spawn@^7.0.3: 366 | version "7.0.3" 367 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" 368 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 369 | dependencies: 370 | path-key "^3.1.0" 371 | shebang-command "^2.0.0" 372 | which "^2.0.1" 373 | 374 | diff@^4.0.1: 375 | version "4.0.2" 376 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" 377 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 378 | 379 | electron-to-chromium@^1.3.723: 380 | version "1.3.762" 381 | resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.762.tgz#3fa4e3bcbda539b50e3aa23041627063a5cffe61" 382 | integrity sha512-LehWjRpfPcK8F1Lf/NZoAwWLWnjJVo0SZeQ9j/tvnBWYcT99qDqgo4raAfS2oTKZjPrR/jxruh85DGgDUmywEA== 383 | 384 | email-addresses@^3.0.1: 385 | version "3.1.0" 386 | resolved "https://registry.yarnpkg.com/email-addresses/-/email-addresses-3.1.0.tgz#cabf7e085cbdb63008a70319a74e6136188812fb" 387 | integrity sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg== 388 | 389 | enhanced-resolve@^5.0.0, enhanced-resolve@^5.8.0: 390 | version "5.8.2" 391 | resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz#15ddc779345cbb73e97c611cd00c01c1e7bf4d8b" 392 | integrity sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA== 393 | dependencies: 394 | graceful-fs "^4.2.4" 395 | tapable "^2.2.0" 396 | 397 | envinfo@^7.7.3: 398 | version "7.8.1" 399 | resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" 400 | integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== 401 | 402 | es-module-lexer@^0.6.0: 403 | version "0.6.0" 404 | resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.6.0.tgz#e72ab05b7412e62b9be37c37a09bdb6000d706f0" 405 | integrity sha512-f8kcHX1ArhllUtb/wVSyvygoKCznIjnxhLxy7TCvIiMdT7fL4ZDTIKaadMe6eLvOXg6Wk02UeoFgUoZ2EKZZUA== 406 | 407 | escalade@^3.1.1: 408 | version "3.1.1" 409 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 410 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 411 | 412 | escape-string-regexp@^1.0.2: 413 | version "1.0.5" 414 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 415 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 416 | 417 | eslint-scope@5.1.1: 418 | version "5.1.1" 419 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" 420 | integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== 421 | dependencies: 422 | esrecurse "^4.3.0" 423 | estraverse "^4.1.1" 424 | 425 | esrecurse@^4.3.0: 426 | version "4.3.0" 427 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" 428 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 429 | dependencies: 430 | estraverse "^5.2.0" 431 | 432 | estraverse@^4.1.1: 433 | version "4.3.0" 434 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" 435 | integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== 436 | 437 | estraverse@^5.2.0: 438 | version "5.2.0" 439 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" 440 | integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== 441 | 442 | events@^3.2.0: 443 | version "3.3.0" 444 | resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" 445 | integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== 446 | 447 | execa@^5.0.0: 448 | version "5.1.1" 449 | resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" 450 | integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== 451 | dependencies: 452 | cross-spawn "^7.0.3" 453 | get-stream "^6.0.0" 454 | human-signals "^2.1.0" 455 | is-stream "^2.0.0" 456 | merge-stream "^2.0.0" 457 | npm-run-path "^4.0.1" 458 | onetime "^5.1.2" 459 | signal-exit "^3.0.3" 460 | strip-final-newline "^2.0.0" 461 | 462 | fast-deep-equal@^3.1.1: 463 | version "3.1.3" 464 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 465 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 466 | 467 | fast-json-stable-stringify@^2.0.0: 468 | version "2.1.0" 469 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 470 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 471 | 472 | fastest-levenshtein@^1.0.12: 473 | version "1.0.12" 474 | resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" 475 | integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== 476 | 477 | filename-reserved-regex@^2.0.0: 478 | version "2.0.0" 479 | resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" 480 | integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik= 481 | 482 | filenamify@^4.3.0: 483 | version "4.3.0" 484 | resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-4.3.0.tgz#62391cb58f02b09971c9d4f9d63b3cf9aba03106" 485 | integrity sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg== 486 | dependencies: 487 | filename-reserved-regex "^2.0.0" 488 | strip-outer "^1.0.1" 489 | trim-repeated "^1.0.0" 490 | 491 | fill-range@^7.0.1: 492 | version "7.0.1" 493 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 494 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 495 | dependencies: 496 | to-regex-range "^5.0.1" 497 | 498 | find-cache-dir@^3.3.1: 499 | version "3.3.1" 500 | resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" 501 | integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== 502 | dependencies: 503 | commondir "^1.0.1" 504 | make-dir "^3.0.2" 505 | pkg-dir "^4.1.0" 506 | 507 | find-up@^4.0.0: 508 | version "4.1.0" 509 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 510 | integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 511 | dependencies: 512 | locate-path "^5.0.0" 513 | path-exists "^4.0.0" 514 | 515 | fs-extra@^8.1.0: 516 | version "8.1.0" 517 | resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" 518 | integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== 519 | dependencies: 520 | graceful-fs "^4.2.0" 521 | jsonfile "^4.0.0" 522 | universalify "^0.1.0" 523 | 524 | fs.realpath@^1.0.0: 525 | version "1.0.0" 526 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 527 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 528 | 529 | function-bind@^1.1.1: 530 | version "1.1.1" 531 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 532 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 533 | 534 | get-stream@^6.0.0: 535 | version "6.0.1" 536 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" 537 | integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== 538 | 539 | gh-pages@^3.2.3: 540 | version "3.2.3" 541 | resolved "https://registry.yarnpkg.com/gh-pages/-/gh-pages-3.2.3.tgz#897e5f15e111f42af57d21d430b83e5cdf29472c" 542 | integrity sha512-jA1PbapQ1jqzacECfjUaO9gV8uBgU6XNMV0oXLtfCX3haGLe5Atq8BxlrADhbD6/UdG9j6tZLWAkAybndOXTJg== 543 | dependencies: 544 | async "^2.6.1" 545 | commander "^2.18.0" 546 | email-addresses "^3.0.1" 547 | filenamify "^4.3.0" 548 | find-cache-dir "^3.3.1" 549 | fs-extra "^8.1.0" 550 | globby "^6.1.0" 551 | 552 | glob-to-regexp@^0.4.1: 553 | version "0.4.1" 554 | resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" 555 | integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== 556 | 557 | glob@^7.0.3: 558 | version "7.1.7" 559 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" 560 | integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== 561 | dependencies: 562 | fs.realpath "^1.0.0" 563 | inflight "^1.0.4" 564 | inherits "2" 565 | minimatch "^3.0.4" 566 | once "^1.3.0" 567 | path-is-absolute "^1.0.0" 568 | 569 | globby@^6.1.0: 570 | version "6.1.0" 571 | resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" 572 | integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= 573 | dependencies: 574 | array-union "^1.0.1" 575 | glob "^7.0.3" 576 | object-assign "^4.0.1" 577 | pify "^2.0.0" 578 | pinkie-promise "^2.0.0" 579 | 580 | graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: 581 | version "4.2.6" 582 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" 583 | integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== 584 | 585 | has-flag@^4.0.0: 586 | version "4.0.0" 587 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 588 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 589 | 590 | has@^1.0.3: 591 | version "1.0.3" 592 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 593 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 594 | dependencies: 595 | function-bind "^1.1.1" 596 | 597 | human-signals@^2.1.0: 598 | version "2.1.0" 599 | resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" 600 | integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== 601 | 602 | import-local@^3.0.2: 603 | version "3.0.2" 604 | resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" 605 | integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== 606 | dependencies: 607 | pkg-dir "^4.2.0" 608 | resolve-cwd "^3.0.0" 609 | 610 | inflight@^1.0.4: 611 | version "1.0.6" 612 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 613 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 614 | dependencies: 615 | once "^1.3.0" 616 | wrappy "1" 617 | 618 | inherits@2: 619 | version "2.0.4" 620 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 621 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 622 | 623 | interpret@^2.2.0: 624 | version "2.2.0" 625 | resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" 626 | integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== 627 | 628 | is-core-module@^2.2.0: 629 | version "2.4.0" 630 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1" 631 | integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A== 632 | dependencies: 633 | has "^1.0.3" 634 | 635 | is-number@^7.0.0: 636 | version "7.0.0" 637 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 638 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 639 | 640 | is-plain-object@^2.0.4: 641 | version "2.0.4" 642 | resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" 643 | integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== 644 | dependencies: 645 | isobject "^3.0.1" 646 | 647 | is-stream@^2.0.0: 648 | version "2.0.0" 649 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" 650 | integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== 651 | 652 | isexe@^2.0.0: 653 | version "2.0.0" 654 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 655 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 656 | 657 | isobject@^3.0.1: 658 | version "3.0.1" 659 | resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" 660 | integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= 661 | 662 | jest-worker@^27.0.2: 663 | version "27.0.6" 664 | resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.6.tgz#a5fdb1e14ad34eb228cfe162d9f729cdbfa28aed" 665 | integrity sha512-qupxcj/dRuA3xHPMUd40gr2EaAurFbkwzOh7wfPaeE9id7hyjURRQoqNfHifHK3XjJU6YJJUQKILGUnwGPEOCA== 666 | dependencies: 667 | "@types/node" "*" 668 | merge-stream "^2.0.0" 669 | supports-color "^8.0.0" 670 | 671 | json-parse-better-errors@^1.0.2: 672 | version "1.0.2" 673 | resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" 674 | integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== 675 | 676 | json-schema-traverse@^0.4.1: 677 | version "0.4.1" 678 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 679 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 680 | 681 | jsonfile@^4.0.0: 682 | version "4.0.0" 683 | resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" 684 | integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= 685 | optionalDependencies: 686 | graceful-fs "^4.1.6" 687 | 688 | kind-of@^6.0.2: 689 | version "6.0.3" 690 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" 691 | integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== 692 | 693 | loader-runner@^4.2.0: 694 | version "4.2.0" 695 | resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" 696 | integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== 697 | 698 | locate-path@^5.0.0: 699 | version "5.0.0" 700 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 701 | integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 702 | dependencies: 703 | p-locate "^4.1.0" 704 | 705 | lodash@^4.17.14, lodash@^4.17.21: 706 | version "4.17.21" 707 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 708 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 709 | 710 | lru-cache@^6.0.0: 711 | version "6.0.0" 712 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 713 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 714 | dependencies: 715 | yallist "^4.0.0" 716 | 717 | make-dir@^3.0.2: 718 | version "3.1.0" 719 | resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" 720 | integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== 721 | dependencies: 722 | semver "^6.0.0" 723 | 724 | make-error@^1.1.1: 725 | version "1.3.6" 726 | resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" 727 | integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== 728 | 729 | merge-stream@^2.0.0: 730 | version "2.0.0" 731 | resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" 732 | integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== 733 | 734 | micromatch@^4.0.0: 735 | version "4.0.4" 736 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" 737 | integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== 738 | dependencies: 739 | braces "^3.0.1" 740 | picomatch "^2.2.3" 741 | 742 | mime-db@1.48.0: 743 | version "1.48.0" 744 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d" 745 | integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ== 746 | 747 | mime-types@^2.1.27: 748 | version "2.1.31" 749 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b" 750 | integrity sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg== 751 | dependencies: 752 | mime-db "1.48.0" 753 | 754 | mimic-fn@^2.1.0: 755 | version "2.1.0" 756 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" 757 | integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== 758 | 759 | minimatch@^3.0.4: 760 | version "3.0.4" 761 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 762 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 763 | dependencies: 764 | brace-expansion "^1.1.7" 765 | 766 | neo-async@^2.6.2: 767 | version "2.6.2" 768 | resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" 769 | integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== 770 | 771 | node-releases@^1.1.71: 772 | version "1.1.73" 773 | resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20" 774 | integrity sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg== 775 | 776 | npm-run-path@^4.0.1: 777 | version "4.0.1" 778 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" 779 | integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== 780 | dependencies: 781 | path-key "^3.0.0" 782 | 783 | object-assign@^4.0.1: 784 | version "4.1.1" 785 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 786 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 787 | 788 | once@^1.3.0: 789 | version "1.4.0" 790 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 791 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 792 | dependencies: 793 | wrappy "1" 794 | 795 | onetime@^5.1.2: 796 | version "5.1.2" 797 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" 798 | integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== 799 | dependencies: 800 | mimic-fn "^2.1.0" 801 | 802 | p-limit@^2.2.0: 803 | version "2.3.0" 804 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" 805 | integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== 806 | dependencies: 807 | p-try "^2.0.0" 808 | 809 | p-limit@^3.1.0: 810 | version "3.1.0" 811 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 812 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 813 | dependencies: 814 | yocto-queue "^0.1.0" 815 | 816 | p-locate@^4.1.0: 817 | version "4.1.0" 818 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 819 | integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 820 | dependencies: 821 | p-limit "^2.2.0" 822 | 823 | p-try@^2.0.0: 824 | version "2.2.0" 825 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 826 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 827 | 828 | path-exists@^4.0.0: 829 | version "4.0.0" 830 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 831 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 832 | 833 | path-is-absolute@^1.0.0: 834 | version "1.0.1" 835 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 836 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 837 | 838 | path-key@^3.0.0, path-key@^3.1.0: 839 | version "3.1.1" 840 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 841 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 842 | 843 | path-parse@^1.0.6: 844 | version "1.0.7" 845 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 846 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 847 | 848 | picomatch@^2.2.3: 849 | version "2.3.0" 850 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" 851 | integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== 852 | 853 | pify@^2.0.0: 854 | version "2.3.0" 855 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 856 | integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= 857 | 858 | pinkie-promise@^2.0.0: 859 | version "2.0.1" 860 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 861 | integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= 862 | dependencies: 863 | pinkie "^2.0.0" 864 | 865 | pinkie@^2.0.0: 866 | version "2.0.4" 867 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 868 | integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= 869 | 870 | pkg-dir@^4.1.0, pkg-dir@^4.2.0: 871 | version "4.2.0" 872 | resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" 873 | integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== 874 | dependencies: 875 | find-up "^4.0.0" 876 | 877 | punycode@^2.1.0: 878 | version "2.1.1" 879 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 880 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 881 | 882 | randombytes@^2.1.0: 883 | version "2.1.0" 884 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 885 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 886 | dependencies: 887 | safe-buffer "^5.1.0" 888 | 889 | rechoir@^0.7.0: 890 | version "0.7.0" 891 | resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.0.tgz#32650fd52c21ab252aa5d65b19310441c7e03aca" 892 | integrity sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q== 893 | dependencies: 894 | resolve "^1.9.0" 895 | 896 | resolve-cwd@^3.0.0: 897 | version "3.0.0" 898 | resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" 899 | integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== 900 | dependencies: 901 | resolve-from "^5.0.0" 902 | 903 | resolve-from@^5.0.0: 904 | version "5.0.0" 905 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" 906 | integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== 907 | 908 | resolve@^1.9.0: 909 | version "1.20.0" 910 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" 911 | integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== 912 | dependencies: 913 | is-core-module "^2.2.0" 914 | path-parse "^1.0.6" 915 | 916 | safe-buffer@^5.1.0: 917 | version "5.2.1" 918 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 919 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 920 | 921 | schema-utils@^3.0.0: 922 | version "3.0.0" 923 | resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef" 924 | integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA== 925 | dependencies: 926 | "@types/json-schema" "^7.0.6" 927 | ajv "^6.12.5" 928 | ajv-keywords "^3.5.2" 929 | 930 | semver@^6.0.0: 931 | version "6.3.0" 932 | resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" 933 | integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== 934 | 935 | semver@^7.3.4: 936 | version "7.3.5" 937 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" 938 | integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== 939 | dependencies: 940 | lru-cache "^6.0.0" 941 | 942 | serialize-javascript@^6.0.0: 943 | version "6.0.0" 944 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" 945 | integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== 946 | dependencies: 947 | randombytes "^2.1.0" 948 | 949 | shallow-clone@^3.0.0: 950 | version "3.0.1" 951 | resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" 952 | integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== 953 | dependencies: 954 | kind-of "^6.0.2" 955 | 956 | shebang-command@^2.0.0: 957 | version "2.0.0" 958 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 959 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 960 | dependencies: 961 | shebang-regex "^3.0.0" 962 | 963 | shebang-regex@^3.0.0: 964 | version "3.0.0" 965 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 966 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 967 | 968 | signal-exit@^3.0.3: 969 | version "3.0.3" 970 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" 971 | integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== 972 | 973 | source-list-map@^2.0.1: 974 | version "2.0.1" 975 | resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" 976 | integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== 977 | 978 | source-map-support@^0.5.17, source-map-support@~0.5.19: 979 | version "0.5.19" 980 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" 981 | integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== 982 | dependencies: 983 | buffer-from "^1.0.0" 984 | source-map "^0.6.0" 985 | 986 | source-map@^0.6.0, source-map@^0.6.1: 987 | version "0.6.1" 988 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 989 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 990 | 991 | source-map@~0.7.2: 992 | version "0.7.3" 993 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" 994 | integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== 995 | 996 | strip-final-newline@^2.0.0: 997 | version "2.0.0" 998 | resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" 999 | integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== 1000 | 1001 | strip-outer@^1.0.1: 1002 | version "1.0.1" 1003 | resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" 1004 | integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== 1005 | dependencies: 1006 | escape-string-regexp "^1.0.2" 1007 | 1008 | supports-color@^7.1.0: 1009 | version "7.2.0" 1010 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1011 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1012 | dependencies: 1013 | has-flag "^4.0.0" 1014 | 1015 | supports-color@^8.0.0: 1016 | version "8.1.1" 1017 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 1018 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 1019 | dependencies: 1020 | has-flag "^4.0.0" 1021 | 1022 | tapable@^2.1.1, tapable@^2.2.0: 1023 | version "2.2.0" 1024 | resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.0.tgz#5c373d281d9c672848213d0e037d1c4165ab426b" 1025 | integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw== 1026 | 1027 | terser-webpack-plugin@^5.1.3: 1028 | version "5.1.4" 1029 | resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.1.4.tgz#c369cf8a47aa9922bd0d8a94fe3d3da11a7678a1" 1030 | integrity sha512-C2WkFwstHDhVEmsmlCxrXUtVklS+Ir1A7twrYzrDrQQOIMOaVAYykaoo/Aq1K0QRkMoY2hhvDQY1cm4jnIMFwA== 1031 | dependencies: 1032 | jest-worker "^27.0.2" 1033 | p-limit "^3.1.0" 1034 | schema-utils "^3.0.0" 1035 | serialize-javascript "^6.0.0" 1036 | source-map "^0.6.1" 1037 | terser "^5.7.0" 1038 | 1039 | terser@^5.7.0: 1040 | version "5.7.1" 1041 | resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.1.tgz#2dc7a61009b66bb638305cb2a824763b116bf784" 1042 | integrity sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg== 1043 | dependencies: 1044 | commander "^2.20.0" 1045 | source-map "~0.7.2" 1046 | source-map-support "~0.5.19" 1047 | 1048 | to-regex-range@^5.0.1: 1049 | version "5.0.1" 1050 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1051 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1052 | dependencies: 1053 | is-number "^7.0.0" 1054 | 1055 | trim-repeated@^1.0.0: 1056 | version "1.0.0" 1057 | resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" 1058 | integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE= 1059 | dependencies: 1060 | escape-string-regexp "^1.0.2" 1061 | 1062 | ts-loader@^9.2.3: 1063 | version "9.2.3" 1064 | resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.3.tgz#dc3b6362a4d4382493cd4f138d345f419656de68" 1065 | integrity sha512-sEyWiU3JMHBL55CIeC4iqJQadI0U70A5af0kvgbNLHVNz2ACztQg0j/9x10bjjIht8WfFYLKfn4L6tkZ+pu+8Q== 1066 | dependencies: 1067 | chalk "^4.1.0" 1068 | enhanced-resolve "^5.0.0" 1069 | micromatch "^4.0.0" 1070 | semver "^7.3.4" 1071 | 1072 | ts-node@^10.0.0: 1073 | version "10.0.0" 1074 | resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.0.0.tgz#05f10b9a716b0b624129ad44f0ea05dac84ba3be" 1075 | integrity sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg== 1076 | dependencies: 1077 | "@tsconfig/node10" "^1.0.7" 1078 | "@tsconfig/node12" "^1.0.7" 1079 | "@tsconfig/node14" "^1.0.0" 1080 | "@tsconfig/node16" "^1.0.1" 1081 | arg "^4.1.0" 1082 | create-require "^1.1.0" 1083 | diff "^4.0.1" 1084 | make-error "^1.1.1" 1085 | source-map-support "^0.5.17" 1086 | yn "3.1.1" 1087 | 1088 | typescript@^4.3.4: 1089 | version "4.3.4" 1090 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.4.tgz#3f85b986945bcf31071decdd96cf8bfa65f9dcbc" 1091 | integrity sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew== 1092 | 1093 | universalify@^0.1.0: 1094 | version "0.1.2" 1095 | resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" 1096 | integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== 1097 | 1098 | uri-js@^4.2.2: 1099 | version "4.4.1" 1100 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 1101 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 1102 | dependencies: 1103 | punycode "^2.1.0" 1104 | 1105 | v8-compile-cache@^2.2.0: 1106 | version "2.3.0" 1107 | resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" 1108 | integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== 1109 | 1110 | watchpack@^2.2.0: 1111 | version "2.2.0" 1112 | resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.2.0.tgz#47d78f5415fe550ecd740f99fe2882323a58b1ce" 1113 | integrity sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA== 1114 | dependencies: 1115 | glob-to-regexp "^0.4.1" 1116 | graceful-fs "^4.1.2" 1117 | 1118 | webpack-cli@^4.7.2: 1119 | version "4.7.2" 1120 | resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.7.2.tgz#a718db600de6d3906a4357e059ae584a89f4c1a5" 1121 | integrity sha512-mEoLmnmOIZQNiRl0ebnjzQ74Hk0iKS5SiEEnpq3dRezoyR3yPaeQZCMCe+db4524pj1Pd5ghZXjT41KLzIhSLw== 1122 | dependencies: 1123 | "@discoveryjs/json-ext" "^0.5.0" 1124 | "@webpack-cli/configtest" "^1.0.4" 1125 | "@webpack-cli/info" "^1.3.0" 1126 | "@webpack-cli/serve" "^1.5.1" 1127 | colorette "^1.2.1" 1128 | commander "^7.0.0" 1129 | execa "^5.0.0" 1130 | fastest-levenshtein "^1.0.12" 1131 | import-local "^3.0.2" 1132 | interpret "^2.2.0" 1133 | rechoir "^0.7.0" 1134 | v8-compile-cache "^2.2.0" 1135 | webpack-merge "^5.7.3" 1136 | 1137 | webpack-merge@^5.7.3: 1138 | version "5.8.0" 1139 | resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" 1140 | integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== 1141 | dependencies: 1142 | clone-deep "^4.0.1" 1143 | wildcard "^2.0.0" 1144 | 1145 | webpack-sources@^2.3.0: 1146 | version "2.3.0" 1147 | resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.0.tgz#9ed2de69b25143a4c18847586ad9eccb19278cfa" 1148 | integrity sha512-WyOdtwSvOML1kbgtXbTDnEW0jkJ7hZr/bDByIwszhWd/4XX1A3XMkrbFMsuH4+/MfLlZCUzlAdg4r7jaGKEIgQ== 1149 | dependencies: 1150 | source-list-map "^2.0.1" 1151 | source-map "^0.6.1" 1152 | 1153 | webpack@^5.41.1: 1154 | version "5.41.1" 1155 | resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.41.1.tgz#23fa1d82c95c222d3fc3163806b9a833fe52b253" 1156 | integrity sha512-AJZIIsqJ/MVTmegEq9Tlw5mk5EHdGiJbDdz9qP15vmUH+oxI1FdWcL0E9EO8K/zKaRPWqEs7G/OPxq1P61u5Ug== 1157 | dependencies: 1158 | "@types/eslint-scope" "^3.7.0" 1159 | "@types/estree" "^0.0.48" 1160 | "@webassemblyjs/ast" "1.11.0" 1161 | "@webassemblyjs/wasm-edit" "1.11.0" 1162 | "@webassemblyjs/wasm-parser" "1.11.0" 1163 | acorn "^8.2.1" 1164 | browserslist "^4.14.5" 1165 | chrome-trace-event "^1.0.2" 1166 | enhanced-resolve "^5.8.0" 1167 | es-module-lexer "^0.6.0" 1168 | eslint-scope "5.1.1" 1169 | events "^3.2.0" 1170 | glob-to-regexp "^0.4.1" 1171 | graceful-fs "^4.2.4" 1172 | json-parse-better-errors "^1.0.2" 1173 | loader-runner "^4.2.0" 1174 | mime-types "^2.1.27" 1175 | neo-async "^2.6.2" 1176 | schema-utils "^3.0.0" 1177 | tapable "^2.1.1" 1178 | terser-webpack-plugin "^5.1.3" 1179 | watchpack "^2.2.0" 1180 | webpack-sources "^2.3.0" 1181 | 1182 | which@^2.0.1: 1183 | version "2.0.2" 1184 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1185 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1186 | dependencies: 1187 | isexe "^2.0.0" 1188 | 1189 | wildcard@^2.0.0: 1190 | version "2.0.0" 1191 | resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" 1192 | integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== 1193 | 1194 | wrappy@1: 1195 | version "1.0.2" 1196 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1197 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1198 | 1199 | yallist@^4.0.0: 1200 | version "4.0.0" 1201 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 1202 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 1203 | 1204 | yn@3.1.1: 1205 | version "3.1.1" 1206 | resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" 1207 | integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== 1208 | 1209 | yocto-queue@^0.1.0: 1210 | version "0.1.0" 1211 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 1212 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 1213 | --------------------------------------------------------------------------------