(node)
| 126 | } |
| 127 | |
| 128 | function emitDownleveledClass(node) { |
| 129 | // Preserve leading trivia (including possible preceding import statements separated earlier by bundler) only remove the decorator itself. |
| 130 | const stripped = node.getText().replace(/@NativeClass(?:\((?:.|\n)*?\))?\s*/gm, ''); |
| 131 | const downleveled = ts |
| 132 | .transpileModule(stripped, { |
| 133 | compilerOptions: { |
| 134 | module: ts.ModuleKind.ESNext, |
| 135 | target: ts.ScriptTarget.ES5, |
| 136 | noEmitHelpers: true, |
| 137 | experimentalDecorators: true, |
| 138 | emitDecoratorMetadata: false, |
| 139 | useDefineForClassFields: false, |
| 140 | }, |
| 141 | }) |
| 142 | .outputText.replace(/(Object\.defineProperty\(.*?{.*?)(enumerable:\s*false)(.*?}\))/gs, '$1enumerable: true$3'); |
| 143 | |
| 144 | const helperSource = ts.createSourceFile( |
| 145 | (node.getSourceFile()?.fileName ?? 'NativeClass.ts') + '.helper.js', |
| 146 | downleveled, |
| 147 | ts.ScriptTarget.ES5, |
| 148 | true, |
| 149 | ts.ScriptKind.JS, |
| 150 | ); |
| 151 | |
| 152 | const statements = []; |
| 153 | for (const statement of helperSource.statements) { |
| 154 | if (statement.kind === ts.SyntaxKind.EndOfFileToken) { |
| 155 | continue; |
| 156 | } |
| 157 | // Explicitly skip import declarations accidentally re-emitted (shouldn't occur but defensive) |
| 158 | if (ts.isImportDeclaration(statement)) { |
| 159 | continue; |
| 160 | } |
| 161 | const prepared = prepareSynthesizedNode(statement, node); |
| 162 | statements.push(prepared); |
| 163 | } |
| 164 | |
| 165 | return statements; |
| 166 | } |
| 167 | |
| 168 | function prepareSynthesizedNode(node, original) { |
| 169 | const clone = ts.factory.cloneNode(node); |
no test coverage detected