(generator, columnMap, moduleName)
| 121 | } |
| 122 | |
| 123 | function wrapGenerator(generator, columnMap, moduleName) { |
| 124 | return function* virtualTable(...args) { |
| 125 | /* |
| 126 | We must defensively clone any buffers in the arguments, because |
| 127 | otherwise the generator could mutate one of them, which would cause |
| 128 | us to return incorrect values for hidden columns, potentially |
| 129 | corrupting the database. |
| 130 | */ |
| 131 | const output = args.map(x => Buffer.isBuffer(x) ? Buffer.from(x) : x); |
| 132 | for (let i = 0; i < columnMap.size; ++i) { |
| 133 | output.push(null); // Fill with nulls to prevent gaps in array (v8 optimization) |
| 134 | } |
| 135 | for (const row of generator(...args)) { |
| 136 | if (Array.isArray(row)) { |
| 137 | extractRowArray(row, output, columnMap.size, moduleName); |
| 138 | yield output; |
| 139 | } else if (typeof row === 'object' && row !== null) { |
| 140 | extractRowObject(row, output, columnMap, moduleName); |
| 141 | yield output; |
| 142 | } else { |
| 143 | throw new TypeError(`Virtual table module "${moduleName}" yielded something that isn't a valid row object`); |
| 144 | } |
| 145 | } |
| 146 | }; |
| 147 | } |
| 148 | |
| 149 | function extractRowArray(row, output, columnCount, moduleName) { |
| 150 | if (row.length !== columnCount) { |
no test coverage detected