@@ -15,8 +15,10 @@ const {
1515const { internalBinding } = require ( 'internal/bootstrap/loaders' ) ;
1616const { MessagePort, MessageChannel } = internalBinding ( 'messaging' ) ;
1717const { handle_onclose } = internalBinding ( 'symbols' ) ;
18+ const locks = internalBinding ( 'locks' ) ;
1819const { clearAsyncIdStack } = require ( 'internal/async_hooks' ) ;
1920const { serializeError, deserializeError } = require ( 'internal/error-serdes' ) ;
21+ const DOMException = require ( 'internal/domexception' ) ;
2022
2123util . inherits ( MessagePort , EventEmitter ) ;
2224
@@ -44,6 +46,7 @@ const kStdioWantsMoreDataCallback = Symbol('kStdioWantsMoreDataCallback');
4446const kStartedReading = Symbol ( 'kStartedReading' ) ;
4547const kWaitingStreams = Symbol ( 'kWaitingStreams' ) ;
4648const kIncrementsPortRef = Symbol ( 'kIncrementsPortRef' ) ;
49+ const kMode = Symbol ( 'mode' ) ;
4750
4851const debug = util . debuglog ( 'worker' ) ;
4952
@@ -505,12 +508,159 @@ function pipeWithoutWarning(source, dest) {
505508 dest . _maxListeners = destMaxListeners ;
506509}
507510
511+ // https://wicg.github.io/web-locks/#api-lock
512+ class Lock {
513+ constructor ( ) {
514+ // eslint-disable-next-line no-restricted-syntax
515+ throw new TypeError ( 'Illegal constructor' ) ;
516+ }
517+
518+ get name ( ) {
519+ return this [ kName ] ;
520+ }
521+
522+ get mode ( ) {
523+ return this [ kMode ] ;
524+ }
525+ }
526+
527+ Object . defineProperties ( Lock . prototype , {
528+ name : { enumerable : true } ,
529+ mode : { enumerable : true } ,
530+ [ Symbol . toStringTag ] : {
531+ value : 'Lock' ,
532+ writable : false ,
533+ enumerable : false ,
534+ configurable : true ,
535+ } ,
536+ } ) ;
537+
538+ // https://wicg.github.io/web-locks/#api-lock-manager
539+ class LockManager {
540+ constructor ( ) {
541+ // eslint-disable-next-line no-restricted-syntax
542+ throw new TypeError ( 'Illegal constructor' ) ;
543+ }
544+
545+ // https://wicg.github.io/web-locks/#api-lock-manager-request
546+ request ( name , options , callback ) {
547+ if ( callback === undefined ) {
548+ callback = options ;
549+ options = undefined ;
550+ }
551+
552+ // Let promise be a new promise.
553+ let reject ;
554+ let resolve ;
555+ const promise = new Promise ( ( res , rej ) => {
556+ resolve = res ;
557+ reject = rej ;
558+ } ) ;
559+
560+ // If options was not passed, then let options be a new LockOptions
561+ // dictionary with default members.
562+ if ( options === undefined ) {
563+ options = {
564+ mode : 'exclusive' ,
565+ ifAvailable : false ,
566+ steal : false ,
567+ } ;
568+ }
569+
570+ if ( name . startsWith ( '-' ) ) {
571+ // if name starts with U+002D HYPHEN-MINUS (-), then reject promise with a
572+ // "NotSupportedError" DOMException.
573+ reject ( new DOMException ( 'NotSupportedError' ) ) ;
574+ } else if ( options . ifAvailable === true && options . steal === true ) {
575+ // Otherwise, if both options' steal dictionary member and option's
576+ // ifAvailable dictionary member are true, then reject promise with a
577+ // "NotSupportedError" DOMException.
578+ reject ( new DOMException ( 'NotSupportedError' ) ) ;
579+ } else if ( options . steal === true && options . mode !== 'exclusive' ) {
580+ // Otherwise, if options' steal dictionary member is true and option's
581+ // mode dictionary member is not "exclusive", then reject promise with a
582+ // "NotSupportedError" DOMException.
583+ reject ( new DOMException ( 'NotSupportedError' ) ) ;
584+ } else {
585+ // Otherwise, run these steps:
586+
587+ // Let request be the result of running the steps to request a lock with
588+ // promise, the current agent, environment's id, origin, callback, name,
589+ // options' mode dictionary member, options' ifAvailable dictionary
590+ // member, and option's steal dictionary member.
591+ process . nextTick ( ( ) => {
592+ locks . request (
593+ promise ,
594+ ( name , mode , waitingPromise , release ) => {
595+ const lock = Object . create ( Lock . prototype , {
596+ [ kName ] : {
597+ value : name ,
598+ writable : false ,
599+ enumerable : false ,
600+ configurable : false ,
601+ } ,
602+ [ kMode ] : {
603+ value : mode === 0 ? 'shared' : 'exclusive' ,
604+ writable : false ,
605+ enumerable : false ,
606+ configurable : false ,
607+ } ,
608+ } ) ;
609+
610+ // When lock lock's waiting promise settles (fulfills or rejects),
611+ // enqueue the following steps on the lock task queue:
612+ waitingPromise
613+ . finally ( ( ) => undefined )
614+ . then ( ( ) => {
615+ // Release the lock lock.
616+ release ( ) ;
617+
618+ // Resolve lock's released promise with lock's waiting promise.
619+ resolve ( waitingPromise ) ;
620+ } ) ;
621+
622+ return callback ( lock ) ;
623+ } ,
624+ name ,
625+ options . mode === 'shared' ? 0 : 1 ,
626+ options . ifAvailable ,
627+ options . steal ) ;
628+ } ) ;
629+ }
630+
631+ // Return promise.
632+ return promise ;
633+ }
634+
635+ // https://wicg.github.io/web-locks/#api-lock-manager-query
636+ query ( ) {
637+ return new Promise ( ( resolve ) => {
638+ process . nextTick ( ( ) => {
639+ const snapshot = locks . snapshot ( ) ;
640+ resolve ( snapshot ) ;
641+ } ) ;
642+ } ) ;
643+ }
644+ }
645+
646+ Object . defineProperties ( LockManager . prototype , {
647+ request : { enumerable : true } ,
648+ query : { enumerable : true } ,
649+ [ Symbol . toStringTag ] : {
650+ value : 'LockManager' ,
651+ writable : false ,
652+ enumerable : false ,
653+ configurable : true ,
654+ } ,
655+ } ) ;
656+
508657module . exports = {
509658 MessagePort,
510659 MessageChannel,
511660 threadId,
512661 Worker,
513662 setupChild,
514663 isMainThread,
515- workerStdio
664+ workerStdio,
665+ LockManager,
516666} ;
0 commit comments