@@ -42,17 +42,20 @@ const {
4242
4343const { getConstructorOf, removeColors } = require ( 'internal/util' ) ;
4444const {
45- ERR_ARG_NOT_ITERABLE ,
46- ERR_INVALID_ARG_TYPE ,
47- ERR_INVALID_ARG_VALUE ,
48- ERR_INVALID_FILE_URL_HOST ,
49- ERR_INVALID_FILE_URL_PATH ,
50- ERR_INVALID_THIS ,
51- ERR_INVALID_TUPLE ,
52- ERR_INVALID_URL ,
53- ERR_INVALID_URL_SCHEME ,
54- ERR_MISSING_ARGS
55- } = require ( 'internal/errors' ) . codes ;
45+ codes : {
46+ ERR_ARG_NOT_ITERABLE ,
47+ ERR_INVALID_ARG_TYPE ,
48+ ERR_INVALID_ARG_VALUE ,
49+ ERR_INVALID_FILE_URL_HOST ,
50+ ERR_INVALID_FILE_URL_PATH ,
51+ ERR_INVALID_THIS ,
52+ ERR_INVALID_TUPLE ,
53+ ERR_INVALID_URL ,
54+ ERR_INVALID_URL_SCHEME ,
55+ ERR_MISSING_ARGS ,
56+ ERR_NO_CRYPTO ,
57+ } ,
58+ } = require ( 'internal/errors' ) ;
5659const {
5760 CHAR_AMPERSAND ,
5861 CHAR_BACKWARD_SLASH ,
@@ -100,6 +103,11 @@ const {
100103 kSchemeStart
101104} = internalBinding ( 'url' ) ;
102105
106+ const {
107+ storeDataObject,
108+ revokeDataObject,
109+ } = internalBinding ( 'blob' ) ;
110+
103111const context = Symbol ( 'context' ) ;
104112const cannotBeBase = Symbol ( 'cannot-be-base' ) ;
105113const cannotHaveUsernamePasswordPort =
@@ -108,6 +116,24 @@ const special = Symbol('special');
108116const searchParams = Symbol ( 'query' ) ;
109117const kFormat = Symbol ( 'format' ) ;
110118
119+ let blob ;
120+ let cryptoRandom ;
121+
122+ function lazyBlob ( ) {
123+ blob ??= require ( 'internal/blob' ) ;
124+ return blob ;
125+ }
126+
127+ function lazyCryptoRandom ( ) {
128+ try {
129+ cryptoRandom ??= require ( 'internal/crypto/random' ) ;
130+ } catch {
131+ // If Node.js built without crypto support, we'll fall
132+ // through here and handle it later.
133+ }
134+ return cryptoRandom ;
135+ }
136+
111137// https://tc39.github.io/ecma262/#sec-%iteratorprototype%-object
112138const IteratorPrototype = ObjectGetPrototypeOf (
113139 ObjectGetPrototypeOf ( [ ] [ SymbolIterator ] ( ) )
@@ -930,6 +956,37 @@ class URL {
930956 toJSON ( ) {
931957 return this [ kFormat ] ( { } ) ;
932958 }
959+
960+ static createObjectURL ( obj ) {
961+ const cryptoRandom = lazyCryptoRandom ( ) ;
962+ if ( cryptoRandom === undefined )
963+ throw new ERR_NO_CRYPTO ( ) ;
964+
965+ // Yes, lazy loading is annoying but because of circular
966+ // references between the url, internal/blob, and buffer
967+ // modules, lazy loading here makes sure that things work.
968+ const blob = lazyBlob ( ) ;
969+ if ( ! blob . isBlob ( obj ) )
970+ throw new ERR_INVALID_ARG_TYPE ( 'obj' , 'Blob' , obj ) ;
971+
972+ const id = cryptoRandom . randomUUID ( ) ;
973+
974+ storeDataObject ( id , obj [ blob . kHandle ] , obj . size , obj . type ) ;
975+
976+ return `blob:nodedata:${ id } ` ;
977+ }
978+
979+ static revokeObjectURL ( url ) {
980+ url = `${ url } ` ;
981+ try {
982+ const parsed = new URL ( url ) ;
983+ const { 1 : id } = StringPrototypeSplit ( parsed . pathname , ':' ) ;
984+ if ( id !== undefined )
985+ revokeDataObject ( id ) ;
986+ } catch {
987+ // If there's an error, it's ignored.
988+ }
989+ }
933990}
934991
935992ObjectDefineProperties ( URL . prototype , {
0 commit comments