@@ -324,4 +324,198 @@ describe('Hooks', () => {
324324 const html = await marked . parse ( 'text' ) ;
325325 assert . strictEqual ( html . trim ( ) , 'test parser' ) ;
326326 } ) ;
327+
328+ it ( 'should not have race condition when parse and parseInline are called concurrently with async hooks' , async ( ) => {
329+ marked . use ( {
330+ async : true ,
331+ hooks : {
332+ async preprocess ( markdown ) {
333+ await timeout ( ) ;
334+ return markdown ;
335+ } ,
336+ } ,
337+ } ) ;
338+ const [ blockHtml , inlineHtml ] = await Promise . all ( [
339+ marked . parse ( '**text**' ) ,
340+ marked . parseInline ( '**text**' ) ,
341+ ] ) ;
342+ assert . strictEqual ( blockHtml . trim ( ) , '<p><strong>text</strong></p>' ) ;
343+ assert . strictEqual ( inlineHtml . trim ( ) , '<strong>text</strong>' ) ;
344+ } ) ;
345+
346+ it ( 'should not have race condition with multiple concurrent parse calls' , async ( ) => {
347+ marked . use ( {
348+ async : true ,
349+ hooks : {
350+ async preprocess ( markdown ) {
351+ await timeout ( ) ;
352+ return markdown ;
353+ } ,
354+ } ,
355+ } ) ;
356+ const [ html1 , html2 , html3 ] = await Promise . all ( [
357+ marked . parse ( '**bold**' ) ,
358+ marked . parseInline ( '**bold**' ) ,
359+ marked . parse ( '*italic*' ) ,
360+ ] ) ;
361+ assert . strictEqual ( html1 . trim ( ) , '<p><strong>bold</strong></p>' ) ;
362+ assert . strictEqual ( html2 . trim ( ) , '<strong>bold</strong>' ) ;
363+ assert . strictEqual ( html3 . trim ( ) , '<p><em>italic</em></p>' ) ;
364+ } ) ;
365+
366+ it ( 'should pass block=true to provideLexer when called from parse' , ( ) => {
367+ let receivedBlock ;
368+ marked . use ( {
369+ hooks : {
370+ provideLexer ( block ) {
371+ receivedBlock = block ;
372+ return ( ) => [ ] ;
373+ } ,
374+ } ,
375+ } ) ;
376+ marked . parse ( 'text' ) ;
377+ assert . strictEqual ( receivedBlock , true ) ;
378+ } ) ;
379+
380+ it ( 'should pass block=false to provideLexer when called from parseInline' , ( ) => {
381+ let receivedBlock ;
382+ marked . use ( {
383+ hooks : {
384+ provideLexer ( block ) {
385+ receivedBlock = block ;
386+ return ( ) => [ ] ;
387+ } ,
388+ } ,
389+ } ) ;
390+ marked . parseInline ( 'text' ) ;
391+ assert . strictEqual ( receivedBlock , false ) ;
392+ } ) ;
393+
394+ it ( 'should pass correct block to provideLexer for concurrent async parse and parseInline' , async ( ) => {
395+ const receivedBlocks = [ ] ;
396+ marked . use ( {
397+ async : true ,
398+ hooks : {
399+ async preprocess ( markdown ) {
400+ await timeout ( ) ;
401+ return markdown ;
402+ } ,
403+ provideLexer ( block ) {
404+ receivedBlocks . push ( block ) ;
405+ return ( ) => [ ] ;
406+ } ,
407+ } ,
408+ } ) ;
409+ await Promise . all ( [
410+ marked . parse ( 'text' ) ,
411+ marked . parseInline ( 'text' ) ,
412+ ] ) ;
413+ assert . deepStrictEqual ( receivedBlocks . slice ( ) . sort ( ) , [ false , true ] ) ;
414+ } ) ;
415+
416+ it ( 'should pass block=true to provideParser when called from parse' , ( ) => {
417+ let receivedBlock ;
418+ marked . use ( {
419+ hooks : {
420+ provideParser ( block ) {
421+ receivedBlock = block ;
422+ return ( ) => '' ;
423+ } ,
424+ } ,
425+ } ) ;
426+ marked . parse ( 'text' ) ;
427+ assert . strictEqual ( receivedBlock , true ) ;
428+ } ) ;
429+
430+ it ( 'should pass block=false to provideParser when called from parseInline' , ( ) => {
431+ let receivedBlock ;
432+ marked . use ( {
433+ hooks : {
434+ provideParser ( block ) {
435+ receivedBlock = block ;
436+ return ( ) => '' ;
437+ } ,
438+ } ,
439+ } ) ;
440+ marked . parseInline ( 'text' ) ;
441+ assert . strictEqual ( receivedBlock , false ) ;
442+ } ) ;
443+
444+ it ( 'should pass correct block to provideParser for concurrent async parse and parseInline' , async ( ) => {
445+ const receivedBlocks = [ ] ;
446+ marked . use ( {
447+ async : true ,
448+ hooks : {
449+ async preprocess ( markdown ) {
450+ await timeout ( ) ;
451+ return markdown ;
452+ } ,
453+ provideParser ( block ) {
454+ receivedBlocks . push ( block ) ;
455+ return ( ) => '' ;
456+ } ,
457+ } ,
458+ } ) ;
459+ await Promise . all ( [
460+ marked . parse ( 'text' ) ,
461+ marked . parseInline ( 'text' ) ,
462+ ] ) ;
463+ assert . deepStrictEqual ( receivedBlocks . slice ( ) . sort ( ) , [ false , true ] ) ;
464+ } ) ;
465+
466+ it ( 'should maintain this.block backwards compatibility in provideLexer for parse' , ( ) => {
467+ let blockFromThis ;
468+ marked . use ( {
469+ hooks : {
470+ provideLexer ( ) {
471+ blockFromThis = this . block ;
472+ return ( ) => [ ] ;
473+ } ,
474+ } ,
475+ } ) ;
476+ marked . parse ( 'text' ) ;
477+ assert . strictEqual ( blockFromThis , true ) ;
478+ } ) ;
479+
480+ it ( 'should maintain this.block backwards compatibility in provideLexer for parseInline' , ( ) => {
481+ let blockFromThis ;
482+ marked . use ( {
483+ hooks : {
484+ provideLexer ( ) {
485+ blockFromThis = this . block ;
486+ return ( ) => [ ] ;
487+ } ,
488+ } ,
489+ } ) ;
490+ marked . parseInline ( 'text' ) ;
491+ assert . strictEqual ( blockFromThis , false ) ;
492+ } ) ;
493+
494+ it ( 'should maintain this.block backwards compatibility in provideParser for parse' , ( ) => {
495+ let blockFromThis ;
496+ marked . use ( {
497+ hooks : {
498+ provideParser ( ) {
499+ blockFromThis = this . block ;
500+ return ( ) => '' ;
501+ } ,
502+ } ,
503+ } ) ;
504+ marked . parse ( 'text' ) ;
505+ assert . strictEqual ( blockFromThis , true ) ;
506+ } ) ;
507+
508+ it ( 'should maintain this.block backwards compatibility in provideParser for parseInline' , ( ) => {
509+ let blockFromThis ;
510+ marked . use ( {
511+ hooks : {
512+ provideParser ( ) {
513+ blockFromThis = this . block ;
514+ return ( ) => '' ;
515+ } ,
516+ } ,
517+ } ) ;
518+ marked . parseInline ( 'text' ) ;
519+ assert . strictEqual ( blockFromThis , false ) ;
520+ } ) ;
327521} ) ;
0 commit comments