1'use strict'; 2 3const path = require('path'); 4const ParserStream = require('../lib'); 5const generateParsingTests = require('../../../test/utils/generate-parsing-tests'); 6const { makeChunks, generateTestsForEachTreeAdapter } = require('../../../test/utils/common'); 7 8function pause() { 9 return new Promise(resolve => setTimeout(resolve, 5)); 10} 11 12generateParsingTests( 13 module.exports, 14 'ParserStream - Scripting', 15 { 16 skipFragments: true, 17 withoutErrors: true, 18 testSuite: [path.join(__dirname, '../../../test/data/tree-construction-scripting')] 19 }, 20 async (test, opts) => { 21 const chunks = makeChunks(test.input); 22 const parser = new ParserStream(opts); 23 const document = parser.document; 24 25 const completionPromise = new Promise((resolve, reject) => { 26 parser.once('finish', () => resolve({ node: document })); 27 28 parser.on('script', async (scriptElement, documentWrite, resume) => { 29 const scriptTextNode = opts.treeAdapter.getChildNodes(scriptElement)[0]; 30 const script = scriptTextNode && opts.treeAdapter.getTextNodeContent(scriptTextNode); 31 32 document.write = documentWrite; 33 34 //NOTE: emulate postponed script execution 35 await pause(); 36 37 try { 38 /* eslint-disable no-eval */ 39 eval(script); 40 /* eslint-enable no-eval */ 41 resume(); 42 } catch (err) { 43 reject(err); 44 } 45 }); 46 }); 47 48 //NOTE: emulate async input stream behavior 49 for (const chunk of chunks) { 50 parser.write(chunk); 51 await pause(); 52 } 53 54 parser.end(); 55 56 return completionPromise; 57 } 58); 59 60generateTestsForEachTreeAdapter(module.exports, (_test, treeAdapter) => { 61 _test['Regression - Synchronously calling resume() leads to crash (GH-98)'] = function(done) { 62 const parser = new ParserStream({ treeAdapter: treeAdapter }); 63 64 parser.on('script', (el, docWrite, resume) => { 65 resume(); 66 }); 67 68 parser.end('<!doctype html><script>abc</script>'); 69 70 process.nextTick(done); 71 }; 72 73 _test['Regression - Parsing loop lock causes accidental hang ups (GH-101)'] = function(done) { 74 const parser = new ParserStream({ treeAdapter: treeAdapter }); 75 76 parser.once('finish', () => { 77 done(); 78 }); 79 80 parser.on('script', (scriptElement, documentWrite, resume) => { 81 process.nextTick(() => { 82 resume(); 83 }); 84 }); 85 86 parser.write('<script>yo</script>'); 87 parser.end('dawg'); 88 }; 89}); 90