(funcString: string)
| 100 | // are represented. If these change, this will likely break us. |
| 101 | /** @internal */ |
| 102 | export function parseFunction(funcString: string): [string, ParsedFunction] { |
| 103 | const [error, functionCode] = parseFunctionCode(funcString); |
| 104 | if (error) { |
| 105 | return [error, undefined as any]; |
| 106 | } |
| 107 | |
| 108 | // In practice it's not guaranteed that a function's toString is parsable by TypeScript. |
| 109 | // V8 intrinsics are prefixed with a '%' and TypeScript does not consider that to be a valid |
| 110 | // identifier. |
| 111 | const [parseError, file] = createSourceFile(functionCode); |
| 112 | if (parseError) { |
| 113 | return [parseError, undefined as any]; |
| 114 | } |
| 115 | |
| 116 | const capturedVariables = computeCapturedVariableNames(file!); |
| 117 | |
| 118 | // if we're looking at an arrow function, the it is always using lexical 'this's |
| 119 | // so we don't have to bother even examining it. |
| 120 | const usesNonLexicalThis = !functionCode.isArrowFunction && computeUsesNonLexicalThis(file!); |
| 121 | |
| 122 | const result = functionCode as ParsedFunction; |
| 123 | result.capturedVariables = capturedVariables; |
| 124 | result.usesNonLexicalThis = usesNonLexicalThis; |
| 125 | |
| 126 | if (result.capturedVariables.required.has('this')) { |
| 127 | return [ |
| 128 | "arrow function captured 'this'. Assign 'this' to another name outside function and capture that.", |
| 129 | result, |
| 130 | ]; |
| 131 | } |
| 132 | |
| 133 | return ['', result]; |
| 134 | } |
| 135 | |
| 136 | function parseFunctionCode(funcString: string): [string, ParsedFunctionCode] { |
| 137 | if (funcString.startsWith('[Function:')) { |
no test coverage detected