@@ -9,9 +9,17 @@ import { default as internalTypes } from 'node-internal:internal_types';
99import { default as utilImpl } from 'node-internal:util' ;
1010
1111import {
12- validateFunction
12+ validateFunction ,
13+ validateAbortSignal ,
14+ validateObject ,
1315} from 'node-internal:validators' ;
1416
17+ import {
18+ debuglog ,
19+ } from 'node-internal:debuglog' ;
20+ export const debug = debuglog ;
21+ export { debuglog } ;
22+
1523import {
1624 ERR_FALSY_VALUE_REJECTION ,
1725 ERR_INVALID_ARG_TYPE ,
@@ -171,6 +179,74 @@ export function _extend(target: Object, source: Object) {
171179 return target ;
172180}
173181
182+ export const TextDecoder = globalThis . TextDecoder ;
183+ export const TextEncoder = globalThis . TextEncoder ;
184+
185+ export function toUSVString ( input : any ) {
186+ // TODO(cleanup): Apparently the typescript types for this aren't available yet?
187+ return ( `${ input } ` as any ) . toWellFormed ( ) ;
188+ }
189+
190+ function pad ( n : any ) : string {
191+ return `${ n } ` . padStart ( 2 , '0' ) ;
192+ }
193+
194+ const months = [ 'Jan' , 'Feb' , 'Mar' , 'Apr' , 'May' , 'Jun' , 'Jul' , 'Aug' , 'Sep' ,
195+ 'Oct' , 'Nov' , 'Dec' ] ;
196+
197+ function timestamp ( ) : string {
198+ const d = new Date ( ) ;
199+ const t = [
200+ pad ( d . getHours ( ) ) ,
201+ pad ( d . getMinutes ( ) ) ,
202+ pad ( d . getSeconds ( ) ) ,
203+ ] . join ( ':' ) ;
204+ return `${ d . getDate ( ) } ${ months [ d . getMonth ( ) ] } ${ t } ` ;
205+ }
206+
207+ export function log ( ...args : any [ ] ) {
208+ console . log ( '%s - %s' , timestamp ( ) , format ( ...args ) ) ;
209+ }
210+
211+ export function parseArgs ( ..._ : any [ ] ) : any {
212+ // We currently have no plans to implement the util.parseArgs API.
213+ throw new Error ( 'node:util parseArgs is not implemented' ) ;
214+ }
215+
216+ export function transferableAbortController ( ..._ : any [ ] ) : any {
217+ throw new Error ( 'node:util transferableAbortController is not implemented' ) ;
218+ }
219+
220+ export function transferableAbortSignal ( ..._ : any [ ] ) : any {
221+ throw new Error ( 'node:util transferableAbortSignal is not implemented' ) ;
222+ }
223+
224+ export async function aborted ( signal : AbortSignal , resource : object ) {
225+ if ( signal === undefined ) {
226+ throw new ERR_INVALID_ARG_TYPE ( 'signal' , 'AbortSignal' , signal ) ;
227+ }
228+ // Node.js defines that the resource is held weakly such that if it is gc'd, we
229+ // will drop the event handler on the signal and the promise will remain pending
230+ // forever. We don't want gc to be observable in the same way so we won't support
231+ // this additional option. Unfortunately Node.js does not make this argument optional.
232+ // We'll just ignore it.
233+ validateAbortSignal ( signal , 'signal' ) ;
234+ validateObject ( resource , 'resource' , { allowArray : true , allowFunction : true } ) ;
235+ if ( signal . aborted ) return Promise . resolve ( ) ;
236+ // TODO(cleanup): Apparently withResolvers isn't part of type defs we use yet
237+ const { promise, resolve } = ( Promise as any ) . withResolvers ( ) ;
238+ const opts = { __proto__ : null , once : true } ;
239+ signal . addEventListener ( 'abort' , resolve , opts ) ;
240+ return promise ;
241+ }
242+
243+ export function deprecate ( fn : Function , _1 ?: string , _2 ?: string , _3 ? : boolean ) {
244+ // TODO(soon): Node.js's implementation wraps the given function in a new function that
245+ // logs a warning to the console if the function is called. Do we want to support that?
246+ // For now, we're just going to silently return the input method unmodified.
247+ return fn ;
248+ }
249+
174250export default {
175251 types,
176252 callbackify,
@@ -183,18 +259,42 @@ export default {
183259 _extend,
184260 MIMEParams,
185261 MIMEType,
262+ toUSVString,
263+ log,
264+ aborted,
265+ debuglog,
266+ debug,
267+ deprecate,
268+ // Node.js originally exposed TextEncoder and TextDecoder off the util
269+ // module originally, so let's just go ahead and do the same.
270+ TextEncoder,
271+ TextDecoder,
272+ // We currently have no plans to implement the following APIs but we want
273+ // to provide throwing placeholders for them. We may eventually come back
274+ // around and implement these later.
275+ parseArgs,
276+ transferableAbortController,
277+ transferableAbortSignal,
186278} ;
187279
188280// Node.js util APIs we're currently not supporting
189- // TODO(soon): Revisit these
190- //
191- // debug/debuglog -- The semantics of these depend on configuration through environment
192- // variables to enable specific debug categories. We have no notion
193- // of that in the runtime currently and it's not yet clear if we should.
194- // deprecate -- Not clear how broadly this is used in the ecosystem outside of node.js
195- // getSystemErrorMap/getSystemErrorName -- libuv specific. No use in workerd?
196- // is{Type} variants -- these are deprecated in Node. Use util.types
197- // toUSVString -- Not clear how broadly this is used in the ecosystem outside of node.js.
198- // also this is soon to be obsoleted by toWellFormed in the language.
199- // transferableAbortSignal/transferableAbortController -- postMessage and worker threads
200- // are not implemented in workerd. No use case for these.
281+ // * util._errnoException
282+ // * util._exceptionWithHostPort
283+ // * util.getSystemErrorMap
284+ // * util.getSystemErrorName
285+ // * util.isArray
286+ // * util.isBoolean
287+ // * util.isBuffer
288+ // * util.isDate
289+ // * util.isDeepStrictEqual
290+ // * util.isError
291+ // * util.isFunction
292+ // * util.isNull
293+ // * util.isNullOrUndefined
294+ // * util.isNumber
295+ // * util.isObject
296+ // * util.isPrimitive
297+ // * util.isRegExp
298+ // * util.isString
299+ // * util.isSymbol
300+ // * util.isUndefined
0 commit comments