@@ -1969,6 +1969,44 @@ function createModel(response: Response, model: any): any {
1969
1969
return model ;
1970
1970
}
1971
1971
1972
+ const mightHaveStaticConstructor = /\bclass\b.*\bstatic\b/;
1973
+
1974
+ function getInferredFunctionApproximate(code: string): () => void {
1975
+ let slicedCode ;
1976
+ if ( code . startsWith ( 'Object.defineProperty(' ) ) {
1977
+ slicedCode = code . slice ( 'Object.defineProperty(' . length ) ;
1978
+ } else if (code.startsWith('(')) {
1979
+ slicedCode = code . slice ( 1 ) ;
1980
+ } else {
1981
+ slicedCode = code ;
1982
+ }
1983
+ if (slicedCode.startsWith('async function')) {
1984
+ const idx = slicedCode . indexOf ( '(' , 14 ) ;
1985
+ if ( idx !== - 1 ) {
1986
+ const name = slicedCode . slice ( 14 , idx ) . trim ( ) ;
1987
+ // eslint-disable-next-line no-eval
1988
+ return ( 0 , eval ) ( '({' + JSON . stringify ( name ) + ':async function(){}})' ) [
1989
+ name
1990
+ ] ;
1991
+ }
1992
+ } else if ( slicedCode . startsWith ( 'function ') ) {
1993
+ const idx = slicedCode . indexOf ( '(' , 8 ) ;
1994
+ if ( idx !== - 1 ) {
1995
+ const name = slicedCode . slice ( 8 , idx ) . trim ( ) ;
1996
+ // eslint-disable-next-line no-eval
1997
+ return ( 0 , eval ) ( '({' + JSON . stringify ( name ) + ':function(){}})' ) [ name ] ;
1998
+ }
1999
+ } else if ( slicedCode . startsWith ( 'class ') ) {
2000
+ const idx = slicedCode . indexOf ( '{' , 5 ) ;
2001
+ if ( idx !== - 1 ) {
2002
+ const name = slicedCode . slice ( 5 , idx ) . trim ( ) ;
2003
+ // eslint-disable-next-line no-eval
2004
+ return ( 0 , eval ) ( '({' + JSON . stringify ( name ) + ':class{}})' ) [ name ] ;
2005
+ }
2006
+ }
2007
+ return function ( ) { } ;
2008
+ }
2009
+
1972
2010
function parseModelString (
1973
2011
response : Response ,
1974
2012
parentObject : Object ,
@@ -2158,41 +2196,37 @@ function parseModelString(
2158
2196
// This should not compile to eval() because then it has local scope access.
2159
2197
const code = value . slice ( 2 ) ;
2160
2198
try {
2161
- // eslint-disable-next-line no-eval
2162
- return ( 0 , eval ) ( code ) ;
2199
+ // If this might be a class constructor with a static initializer or
2200
+ // static constructor then don't eval it. It might cause unexpected
2201
+ // side-effects. Instead, fallback to parsing out the function type
2202
+ // and name.
2203
+ if ( ! mightHaveStaticConstructor . test ( code ) ) {
2204
+ // eslint-disable-next-line no-eval
2205
+ return ( 0 , eval ) ( code ) ;
2206
+ }
2163
2207
} catch ( x ) {
2164
- // We currently use this to express functions so we fail parsing it,
2165
- // let's just return a blank function as a place holder.
2166
- if ( code . startsWith ( '(async function' ) ) {
2167
- const idx = code . indexOf ( '(' , 15 ) ;
2168
- if ( idx !== - 1 ) {
2169
- const name = code . slice ( 15 , idx ) . trim ( ) ;
2170
- // eslint-disable-next-line no-eval
2171
- return ( 0 , eval ) (
2172
- '({' + JSON . stringify ( name ) + ':async function(){}})' ,
2173
- ) [ name ] ;
2174
- }
2175
- } else if ( code . startsWith ( '(function' ) ) {
2176
- const idx = code . indexOf ( '(' , 9 ) ;
2177
- if ( idx !== - 1 ) {
2178
- const name = code . slice ( 9 , idx ) . trim ( ) ;
2179
- // eslint-disable-next-line no-eval
2180
- return ( 0 , eval ) (
2181
- '({' + JSON . stringify ( name ) + ':function(){}})' ,
2182
- ) [ name ] ;
2183
- }
2184
- } else if ( code . startsWith ( '(class' ) ) {
2185
- const idx = code . indexOf ( '{' , 6 ) ;
2208
+ // Fallthrough to fallback case.
2209
+ }
2210
+ // We currently use this to express functions so we fail parsing it,
2211
+ // let's just return a blank function as a place holder.
2212
+ let fn ;
2213
+ try {
2214
+ fn = getInferredFunctionApproximate ( code ) ;
2215
+ if ( code . startsWith ( 'Object.defineProperty(' ) ) {
2216
+ const DESCRIPTOR = ', "name ", { value :"';
2217
+ const idx = code . lastIndexOf ( DESCRIPTOR ) ;
2186
2218
if ( idx !== - 1 ) {
2187
- const name = code . slice ( 6 , idx ) . trim ( ) ;
2188
- // eslint-disable-next-line no-eval
2189
- return ( 0 , eval ) ( '({' + JSON . stringify ( name ) + ':class{}})' ) [
2190
- name
2191
- ] ;
2219
+ const name = JSON . parse (
2220
+ code . slice ( idx + DESCRIPTOR . length - 1 , code . length - 2 ) ,
2221
+ ) ;
2222
+ // $FlowFixMe[cannot-write]
2223
+ Object . defineProperty ( fn , 'name' , { value : name } ) ;
2192
2224
}
2193
2225
}
2194
- return function ( ) { } ;
2226
+ } catch ( _ ) {
2227
+ fn = function ( ) { } ;
2195
2228
}
2229
+ return fn ;
2196
2230
}
2197
2231
// Fallthrough
2198
2232
}
0 commit comments