@@ -4,8 +4,19 @@ import type { ShaderCode, ShaderFunction } from "./shaderCode.types";
4
4
import { ConnectionPointType } from "../../connection/connectionPointType.js" ;
5
5
import { BlockDisableStrategy } from "../../blockFoundation/disableableShaderBlock.js" ;
6
6
7
- const GetFunctionHeaderRegEx = / \S * \w + \s + ( \w + ) \s * \( ( .* ?) \) \s * \{ / g; // Matches a function's name and its parameters
8
- const GetDefineRegEx = / ^ \S * # d e f i n e \s + ( \w + ) .* $ / gm; // Matches a #define statement line, capturing its name
7
+ // Note: creating a global RegExp object is risky, because it holds state (e.g. lastIndex) that has to be
8
+ // cleared at the right time to ensure correctness, which is easy to forget to do.
9
+ // Instead, for regular expressions used in multiple places, we define the string and options once, and create
10
+ // a new RegExp object from them when needed, to ensure state isn't accidentally reused.
11
+
12
+ // Matches a function's name and its parameters
13
+ const GetFunctionHeaderRegExString = `\\S*\\w+\\s+(\\w+)\\s*\\((.*?)\\)\\s*\\{` ;
14
+ const GetFunctionHeaderRegExOptions = "g" ;
15
+
16
+ // Matches a #define statement line, capturing its name
17
+ const GetDefineRegExString = `^\\S*#define\\s+(\\w+).*$` ;
18
+ const GetDefineRegExOptions = "gm" ;
19
+
9
20
const ReservedSymbols = [ "main" ] ;
10
21
11
22
/**
@@ -161,11 +172,15 @@ export function parseFragmentShader(fragmentShader: string): FragmentShaderInfo
161
172
Logger . Log ( `Uniforms found: ${ JSON . stringify ( uniforms ) } ` ) ;
162
173
const consts = [ ...fragmentShader . matchAll ( / \S * c o n s t \s + \w * \s + ( \w * ) \s * = .* ; / g) ] . map ( ( match ) => match [ 1 ] ) ;
163
174
Logger . Log ( `Consts found: ${ JSON . stringify ( consts ) } ` ) ;
164
- const defineNames = [ ...fragmentShader . matchAll ( GetDefineRegEx ) ] . map ( ( match ) => match [ 1 ] ) ;
165
- Logger . Log ( `Defines found: ${ JSON . stringify ( defineNames ) } ` ) ;
166
- const functionNames = [ ...fragmentShaderWithNoFunctionBodies . matchAll ( GetFunctionHeaderRegEx ) ] . map (
175
+ const defineNames = [ ...fragmentShader . matchAll ( new RegExp ( GetDefineRegExString , GetDefineRegExOptions ) ) ] . map (
167
176
( match ) => match [ 1 ]
168
177
) ;
178
+ Logger . Log ( `Defines found: ${ JSON . stringify ( defineNames ) } ` ) ;
179
+ const functionNames = [
180
+ ...fragmentShaderWithNoFunctionBodies . matchAll (
181
+ new RegExp ( GetFunctionHeaderRegExString , GetFunctionHeaderRegExOptions )
182
+ ) ,
183
+ ] . map ( ( match ) => match [ 1 ] ) ;
169
184
Logger . Log ( `Functions found: ${ JSON . stringify ( functionNames ) } ` ) ;
170
185
171
186
// Decorate the uniforms, consts, defines, and functions
@@ -192,7 +207,9 @@ export function parseFragmentShader(fragmentShader: string): FragmentShaderInfo
192
207
const finalConsts = [ ...fragmentShaderWithRenamedSymbols . matchAll ( / ^ \s * ( c o n s t \s .* ) / gm) ] . map ( ( match ) => match [ 1 ] ) ;
193
208
194
209
// Extract all the defines
195
- const finalDefines = [ ...fragmentShaderWithRenamedSymbols . matchAll ( GetDefineRegEx ) ] . map ( ( match ) => match [ 0 ] ) ;
210
+ const finalDefines = [
211
+ ...fragmentShaderWithRenamedSymbols . matchAll ( new RegExp ( GetDefineRegExString , GetDefineRegExOptions ) ) ,
212
+ ] . map ( ( match ) => match [ 0 ] ) ;
196
213
197
214
// Find the main input
198
215
const mainInputs = [ ...fragmentShaderWithRenamedSymbols . matchAll ( / \S * u n i f o r m .* \s ( \w * ) ; \s * \/ \/ \s * m a i n / gm) ] . map (
@@ -248,10 +265,12 @@ function extractFunctions(fragment: string): {
248
265
let mainFunctionName : string | undefined ;
249
266
let pos = 0 ;
250
267
268
+ const getFunctionHeaderRegEx = new RegExp ( GetFunctionHeaderRegExString , GetFunctionHeaderRegExOptions ) ;
269
+
251
270
while ( pos < fragment . length ) {
252
271
// Match the next available function header in the fragment code
253
- GetFunctionHeaderRegEx . lastIndex = pos ;
254
- const match = GetFunctionHeaderRegEx . exec ( fragment ) ;
272
+ getFunctionHeaderRegEx . lastIndex = pos ;
273
+ const match = getFunctionHeaderRegEx . exec ( fragment ) ;
255
274
if ( ! match ) {
256
275
break ;
257
276
}
0 commit comments