4
4
*
5
5
* GPU Accelerated JavaScript
6
6
*
7
- * @version 2.4.3
8
- * @date Fri Dec 27 2019 16:33:11 GMT-0500 (Eastern Standard Time)
7
+ * @version 2.4.4
8
+ * @date Thu Jan 02 2020 12:26:36 GMT-0500 (Eastern Standard Time)
9
9
*
10
10
* @license MIT
11
11
* The MIT License
12
12
*
13
- * Copyright (c) 2019 gpu.js Team
13
+ * Copyright (c) 2020 gpu.js Team
14
14
*/ ( function ( f ) { if ( typeof exports === "object" && typeof module !== "undefined" ) { module . exports = f ( ) } else if ( typeof define === "function" && define . amd ) { define ( [ ] , f ) } else { var g ; if ( typeof window !== "undefined" ) { g = window } else if ( typeof global !== "undefined" ) { g = global } else if ( typeof self !== "undefined" ) { g = self } else { g = this } g . GPU = f ( ) } } ) ( function ( ) { var define , module , exports ; return ( function ( ) { function r ( e , n , t ) { function o ( i , f ) { if ( ! n [ i ] ) { if ( ! e [ i ] ) { var c = "function" == typeof require && require ; if ( ! f && c ) return c ( i , ! 0 ) ; if ( u ) return u ( i , ! 0 ) ; var a = new Error ( "Cannot find module '" + i + "'" ) ; throw a . code = "MODULE_NOT_FOUND" , a } var p = n [ i ] = { exports :{ } } ; e [ i ] [ 0 ] . call ( p . exports , function ( r ) { var n = e [ i ] [ 1 ] [ r ] ; return o ( n || r ) } , p , p . exports , r , e , n , t ) } return n [ i ] . exports } for ( var u = "function" == typeof require && require , i = 0 ; i < t . length ; i ++ ) o ( t [ i ] ) ; return o } return r } ) ( ) ( { 1 :[ function ( require , module , exports ) {
15
15
16
16
} , { } ] , 2 :[ function ( require , module , exports ) {
@@ -2596,12 +2596,12 @@ class FunctionNode {
2596
2596
this . functions = functions ;
2597
2597
for ( let i = 0 ; i < declarations . length ; i ++ ) {
2598
2598
const declaration = declarations [ i ] ;
2599
- const { ast, context, name, origin, forceInteger , assignable } = declaration ;
2599
+ const { ast, context, name, origin, inForLoopInit , inForLoopTest , assignable } = declaration ;
2600
2600
const { init } = ast ;
2601
2601
const dependencies = this . getDependencies ( init ) ;
2602
2602
let valueType = null ;
2603
2603
2604
- if ( forceInteger ) {
2604
+ if ( inForLoopInit && inForLoopTest ) {
2605
2605
valueType = 'Integer' ;
2606
2606
} else {
2607
2607
if ( init ) {
@@ -2626,6 +2626,8 @@ class FunctionNode {
2626
2626
}
2627
2627
this . declarations . push ( {
2628
2628
valueType,
2629
+ inForLoopInit,
2630
+ inForLoopTest,
2629
2631
dependencies,
2630
2632
isSafe : this . isSafeDependencies ( dependencies ) ,
2631
2633
ast,
@@ -3833,6 +3835,12 @@ function last(array) {
3833
3835
return array . length > 0 ? array [ array . length - 1 ] : null ;
3834
3836
}
3835
3837
3838
+ const states = {
3839
+ trackIdentifiers : 'trackIdentifiers' ,
3840
+ memberExpression : 'memberExpression' ,
3841
+ inForLoopInit : 'inForLoopInit'
3842
+ } ;
3843
+
3836
3844
class FunctionTracer {
3837
3845
constructor ( ast ) {
3838
3846
this . runningContexts = [ ] ;
@@ -3843,11 +3851,32 @@ class FunctionTracer {
3843
3851
this . identifiers = [ ] ;
3844
3852
this . functions = [ ] ;
3845
3853
this . returnStatements = [ ] ;
3846
- this . inLoopInit = false ;
3854
+ this . trackedIdentifiers = null ;
3855
+ this . states = [ ] ;
3847
3856
this . newFunctionContext ( ) ;
3848
3857
this . scan ( ast ) ;
3849
3858
}
3850
3859
3860
+ isState ( state ) {
3861
+ return this . states [ this . states . length - 1 ] === state ;
3862
+ }
3863
+
3864
+ hasState ( state ) {
3865
+ return this . states . indexOf ( state ) > - 1 ;
3866
+ }
3867
+
3868
+ pushState ( state ) {
3869
+ this . states . push ( state ) ;
3870
+ }
3871
+
3872
+ popState ( state ) {
3873
+ if ( this . isState ( state ) ) {
3874
+ this . states . pop ( ) ;
3875
+ } else {
3876
+ throw new Error ( `Cannot pop the non-active state "${ state } "` ) ;
3877
+ }
3878
+ }
3879
+
3851
3880
get currentFunctionContext ( ) {
3852
3881
return last ( this . functionContexts ) ;
3853
3882
}
@@ -3857,13 +3886,13 @@ class FunctionTracer {
3857
3886
}
3858
3887
3859
3888
newFunctionContext ( ) {
3860
- const newContext = { '@contextType' : 'var ' } ;
3889
+ const newContext = { '@contextType' : 'function ' } ;
3861
3890
this . contexts . push ( newContext ) ;
3862
3891
this . functionContexts . push ( newContext ) ;
3863
3892
}
3864
3893
3865
3894
newContext ( run ) {
3866
- const newContext = Object . assign ( { '@contextType' : 'var/ const/let' } , this . currentContext ) ;
3895
+ const newContext = Object . assign ( { '@contextType' : 'const/let' } , this . currentContext ) ;
3867
3896
this . contexts . push ( newContext ) ;
3868
3897
this . runningContexts . push ( newContext ) ;
3869
3898
run ( ) ;
@@ -3873,6 +3902,7 @@ class FunctionTracer {
3873
3902
newContext [ p ] = currentFunctionContext [ p ] ;
3874
3903
}
3875
3904
this . runningContexts . pop ( ) ;
3905
+ return newContext ;
3876
3906
}
3877
3907
3878
3908
useFunctionContext ( run ) {
@@ -3882,6 +3912,15 @@ class FunctionTracer {
3882
3912
this . runningContexts . pop ( ) ;
3883
3913
}
3884
3914
3915
+ getIdentifiers ( run ) {
3916
+ const trackedIdentifiers = this . trackedIdentifiers = [ ] ;
3917
+ this . pushState ( states . trackIdentifiers ) ;
3918
+ run ( ) ;
3919
+ this . trackedIdentifiers = null ;
3920
+ this . popState ( states . trackIdentifiers ) ;
3921
+ return trackedIdentifiers ;
3922
+ }
3923
+
3885
3924
scan ( ast ) {
3886
3925
if ( ! ast ) return ;
3887
3926
if ( Array . isArray ( ast ) ) {
@@ -3892,7 +3931,9 @@ class FunctionTracer {
3892
3931
}
3893
3932
switch ( ast . type ) {
3894
3933
case 'Program' :
3895
- this . scan ( ast . body ) ;
3934
+ this . useFunctionContext ( ( ) => {
3935
+ this . scan ( ast . body ) ;
3936
+ } ) ;
3896
3937
break ;
3897
3938
case 'BlockStatement' :
3898
3939
this . newContext ( ( ) => {
@@ -3925,13 +3966,15 @@ class FunctionTracer {
3925
3966
break ;
3926
3967
case 'VariableDeclarator' :
3927
3968
const { currentContext } = this ;
3969
+ const inForLoopInit = this . hasState ( states . inForLoopInit ) ;
3928
3970
const declaration = {
3929
3971
ast : ast ,
3930
3972
context : currentContext ,
3931
3973
name : ast . id . name ,
3932
3974
origin : 'declaration' ,
3933
- forceInteger : this . inLoopInit ,
3934
- assignable : currentContext === this . currentFunctionContext || ( ! this . inLoopInit && ! currentContext . hasOwnProperty ( ast . id . name ) ) ,
3975
+ inForLoopInit,
3976
+ inForLoopTest : null ,
3977
+ assignable : currentContext === this . currentFunctionContext || ( ! inForLoopInit && ! currentContext . hasOwnProperty ( ast . id . name ) ) ,
3935
3978
} ;
3936
3979
currentContext [ ast . id . name ] = declaration ;
3937
3980
this . declarations . push ( declaration ) ;
@@ -3952,16 +3995,30 @@ class FunctionTracer {
3952
3995
if ( ast . alternate ) this . scan ( ast . alternate ) ;
3953
3996
break ;
3954
3997
case 'ForStatement' :
3955
- this . newContext ( ( ) => {
3956
- this . inLoopInit = true ;
3998
+ let testIdentifiers ;
3999
+ const context = this . newContext ( ( ) => {
4000
+ testIdentifiers = this . getIdentifiers ( ( ) => {
4001
+ this . scan ( ast . test ) ;
4002
+ } ) ;
4003
+
4004
+ this . pushState ( states . inForLoopInit ) ;
3957
4005
this . scan ( ast . init ) ;
3958
- this . inLoopInit = false ;
3959
- this . scan ( ast . test ) ;
4006
+ this . popState ( states . inForLoopInit ) ;
4007
+
3960
4008
this . scan ( ast . update ) ;
3961
4009
this . newContext ( ( ) => {
3962
4010
this . scan ( ast . body ) ;
3963
4011
} ) ;
3964
4012
} ) ;
4013
+
4014
+ if ( testIdentifiers ) {
4015
+ for ( const p in context ) {
4016
+ if ( p === '@contextType' ) continue ;
4017
+ if ( testIdentifiers . indexOf ( p ) > - 1 ) {
4018
+ context [ p ] . inForLoopTest = true ;
4019
+ }
4020
+ }
4021
+ }
3965
4022
break ;
3966
4023
case 'DoWhileStatement' :
3967
4024
case 'WhileStatement' :
@@ -3971,6 +4028,9 @@ class FunctionTracer {
3971
4028
} ) ;
3972
4029
break ;
3973
4030
case 'Identifier' :
4031
+ if ( this . isState ( states . trackIdentifiers ) ) {
4032
+ this . trackedIdentifiers . push ( ast . name ) ;
4033
+ }
3974
4034
this . identifiers . push ( {
3975
4035
context : this . currentContext ,
3976
4036
ast,
@@ -3981,8 +4041,10 @@ class FunctionTracer {
3981
4041
this . scan ( ast . argument ) ;
3982
4042
break ;
3983
4043
case 'MemberExpression' :
4044
+ this . pushState ( states . memberExpression ) ;
3984
4045
this . scan ( ast . object ) ;
3985
4046
this . scan ( ast . property ) ;
4047
+ this . popState ( states . memberExpression ) ;
3986
4048
break ;
3987
4049
case 'ExpressionStatement' :
3988
4050
this . scan ( ast . expression ) ;
@@ -7489,7 +7551,11 @@ class WebGLFunctionNode extends FunctionNode {
7489
7551
const actualType = this . getType ( declaration . init ) ;
7490
7552
let type = inForLoopInit ? 'Integer' : actualType ;
7491
7553
if ( type === 'LiteralInteger' ) {
7492
- type = 'Number' ;
7554
+ if ( info . inForLoopInit && info . inForLoopTest ) {
7555
+ type = 'Integer' ;
7556
+ } else {
7557
+ type = 'Number' ;
7558
+ }
7493
7559
}
7494
7560
const markupType = typeMap [ type ] ;
7495
7561
if ( ! markupType ) {
@@ -7530,6 +7596,8 @@ class WebGLFunctionNode extends FunctionNode {
7530
7596
this . astGeneric ( init , declarationResult ) ;
7531
7597
declarationResult . push ( ')' ) ;
7532
7598
}
7599
+ } else if ( actualType === 'LiteralInteger' && type === 'Integer' ) {
7600
+ this . castLiteralToInteger ( init , declarationResult ) ;
7533
7601
} else {
7534
7602
this . astGeneric ( init , declarationResult ) ;
7535
7603
}
@@ -13031,7 +13099,8 @@ class GPU {
13031
13099
createKernelMap ( ) {
13032
13100
let fn ;
13033
13101
let settings ;
13034
- if ( typeof arguments [ arguments . length - 2 ] === 'function' ) {
13102
+ const argument2Type = typeof arguments [ arguments . length - 2 ] ;
13103
+ if ( argument2Type === 'function' || argument2Type === 'string' ) {
13035
13104
fn = arguments [ arguments . length - 2 ] ;
13036
13105
settings = arguments [ arguments . length - 1 ] ;
13037
13106
} else {
@@ -14339,6 +14408,14 @@ const utils = {
14339
14408
visualKernelB . canvas ,
14340
14409
visualKernelA . canvas ,
14341
14410
] ;
14411
+ } ,
14412
+
14413
+ getMinifySafeName : ( fn ) => {
14414
+ const ast = acorn . parse ( fn . toString ( ) ) ;
14415
+ if ( ! ast . body || ! ast . body [ 0 ] || ! ast . body [ 0 ] . expression || ! ast . body [ 0 ] . expression . body || ! ast . body [ 0 ] . expression . body . name ) {
14416
+ throw new Error ( 'Unrecognized function type. Please use `() => yourFunctionVariableHere`' ) ;
14417
+ }
14418
+ return ast . body [ 0 ] . expression . body . name ;
14342
14419
}
14343
14420
} ;
14344
14421
0 commit comments