@@ -4233,6 +4233,116 @@ suite('p5.Shader', function () {
42334233 } ) ;
42344234 } ) ;
42354235
4236+ test ( 'set() outside a hook block reports a scope error' , ( ) => {
4237+ myp5 . createCanvas ( 50 , 50 , myp5 . WEBGL ) ;
4238+
4239+ try {
4240+ myp5 . baseFilterShader ( ) . modify (
4241+ ( ) => {
4242+ myp5 . filterColor . begin ( ) ;
4243+ myp5 . filterColor . set ( [ 1 , 0 , 0 , 1 ] ) ;
4244+ myp5 . filterColor . end ( ) ;
4245+ myp5 . filterColor . set ( [ 0 , 1 , 0 , 1 ] ) ;
4246+ } ,
4247+ { myp5 }
4248+ ) ;
4249+ } catch {
4250+ /* expected */
4251+ }
4252+
4253+ const scopeCall = mockUserError . mock . calls . find (
4254+ call => call [ 0 ] === 'scope error' && call [ 1 ] . includes ( 'set()' )
4255+ ) ;
4256+ assert . isDefined ( scopeCall , 'scope error should have been called' ) ;
4257+ assert . include ( scopeCall [ 1 ] , 'filterColor.set()' ) ;
4258+ assert . notInclude ( scopeCall [ 1 ] , 'getColor' ) ;
4259+ } ) ;
4260+
4261+ test ( 'ending a value-returning hook without a value reports a scope error' , ( ) => {
4262+ myp5 . createCanvas ( 50 , 50 , myp5 . WEBGL ) ;
4263+
4264+ try {
4265+ myp5 . baseFilterShader ( ) . modify (
4266+ ( ) => {
4267+ myp5 . filterColor . begin ( ) ;
4268+ myp5 . filterColor . end ( ) ;
4269+ } ,
4270+ { myp5 }
4271+ ) ;
4272+ } catch {
4273+ /* expected */
4274+ }
4275+
4276+ const scopeCall = mockUserError . mock . calls . find (
4277+ call =>
4278+ call [ 0 ] === 'scope error' &&
4279+ call [ 1 ] . includes ( 'requires a value' )
4280+ ) ;
4281+ assert . isDefined ( scopeCall , 'scope error should have been called' ) ;
4282+ assert . include ( scopeCall [ 1 ] , 'filterColor requires a value' ) ;
4283+ assert . include (
4284+ scopeCall [ 1 ] ,
4285+ 'filterColor.set(value) before filterColor.end()'
4286+ ) ;
4287+ assert . notInclude ( scopeCall [ 1 ] , 'getColor' ) ;
4288+ } ) ;
4289+
4290+ test ( 'value-required error uses the hook\'s own public name' , ( ) => {
4291+ myp5 . createCanvas ( 50 , 50 , myp5 . WEBGL ) ;
4292+
4293+ try {
4294+ myp5 . baseMaterialShader ( ) . modify (
4295+ ( ) => {
4296+ myp5 . finalColor . begin ( ) ;
4297+ myp5 . finalColor . end ( ) ;
4298+ } ,
4299+ { myp5 }
4300+ ) ;
4301+ } catch {
4302+ /* expected */
4303+ }
4304+
4305+ const scopeCall = mockUserError . mock . calls . find (
4306+ call =>
4307+ call [ 0 ] === 'scope error' &&
4308+ call [ 1 ] . includes ( 'requires a value' )
4309+ ) ;
4310+ assert . isDefined ( scopeCall , 'scope error should have been called' ) ;
4311+ assert . include ( scopeCall [ 1 ] , 'finalColor requires a value' ) ;
4312+ assert . include (
4313+ scopeCall [ 1 ] ,
4314+ 'finalColor.set(value) before finalColor.end()'
4315+ ) ;
4316+ assert . notInclude ( scopeCall [ 1 ] , 'getFinalColor' ) ;
4317+ assert . notInclude ( scopeCall [ 1 ] , 'filterColor' ) ;
4318+ } ) ;
4319+
4320+ test ( 'missing end() reports a scope error' , ( ) => {
4321+ myp5 . createCanvas ( 50 , 50 , myp5 . WEBGL ) ;
4322+
4323+ try {
4324+ myp5 . baseFilterShader ( ) . modify (
4325+ ( ) => {
4326+ myp5 . filterColor . begin ( ) ;
4327+ myp5 . filterColor . set ( [ 1 , 0 , 0 , 1 ] ) ;
4328+ } ,
4329+ { myp5 }
4330+ ) ;
4331+ } catch {
4332+ /* expected */
4333+ }
4334+ const scopeCall = mockUserError . mock . calls . find (
4335+ call =>
4336+ call [ 0 ] === 'scope error' &&
4337+ call [ 1 ] . includes ( 'without a matching' )
4338+ ) ;
4339+ assert . isDefined ( scopeCall , 'scope error should have been called' ) ;
4340+ assert . include (
4341+ scopeCall [ 1 ] ,
4342+ 'filterColor.begin() was called without a matching filterColor.end()'
4343+ ) ;
4344+ } ) ;
4345+
42364346 test ( 'scope error uses unprefixed hook name' , ( ) => {
42374347 myp5 . createCanvas ( 50 , 50 , myp5 . WEBGL ) ;
42384348
0 commit comments