@@ -1969,6 +1969,44 @@ function createModel(response: Response, model: any): any {
19691969 return model ;
19701970}
19711971
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+
19722010function parseModelString (
19732011 response : Response ,
19742012 parentObject : Object ,
@@ -2158,41 +2196,37 @@ function parseModelString(
21582196 // This should not compile to eval() because then it has local scope access.
21592197 const code = value . slice ( 2 ) ;
21602198 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+ }
21632207 } 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 ) ;
21862218 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 } ) ;
21922224 }
21932225 }
2194- return function ( ) { } ;
2226+ } catch ( _ ) {
2227+ fn = function ( ) { } ;
21952228 }
2229+ return fn ;
21962230 }
21972231 // Fallthrough
21982232 }
0 commit comments