From affd06d05cc756df33854bc1d56e2284ff22b22d Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Fri, 7 Jul 2023 15:10:33 -0700 Subject: [PATCH] Update types, partially fix `typecheck` (#3551) * Update types * Remove caret --- packages/bun-types/assert.d.ts | 6 +- packages/bun-types/ffi.d.ts | 1 + packages/bun-types/fs.d.ts | 213 +++++++++++------- packages/bun-types/globals.d.ts | 31 ++- packages/bun-types/http.d.ts | 18 ++ packages/bun-types/tests/fs.test-d.ts | 9 + .../builtins/ReadableStreamDefaultReader.ts | 4 +- src/js/builtins/ReadableStreamInternals.ts | 1 + src/js/builtins/StreamInternals.ts | 2 +- src/js/builtins/TransformStream.ts | 1 + src/js/builtins/TransformStreamInternals.ts | 1 + .../builtins/WritableStreamDefaultWriter.ts | 1 + src/js/builtins/WritableStreamInternals.ts | 9 +- src/js/builtins/builtins.d.ts | 6 +- src/js/bun/ffi.ts | 8 +- src/js/node/trace_events.ts | 2 + src/js/private.d.ts | 3 +- test/bun.lockb | Bin 141113 -> 148733 bytes .../{fs.watch.test.js => fs.watch.test.ts} | 86 +++---- test/js/third_party/socket.io/support/util.ts | 1 + test/js/web/html/FormData.test.ts | 19 +- test/js/web/html/URLSearchParams.test.ts | 5 + test/package.json | 9 +- test/tsconfig.json | 34 +-- tsconfig.json | 9 +- 25 files changed, 275 insertions(+), 204 deletions(-) rename test/js/node/watch/{fs.watch.test.js => fs.watch.test.ts} (89%) diff --git a/packages/bun-types/assert.d.ts b/packages/bun-types/assert.d.ts index ae3b54ff2a..658e7df5b6 100644 --- a/packages/bun-types/assert.d.ts +++ b/packages/bun-types/assert.d.ts @@ -931,7 +931,11 @@ declare module "assert" { * instance of an `Error` then it will be thrown instead of the `AssertionError`. */ // FIXME: assert.doesNotMatch is typed, but not in the browserify polyfill? - // function doesNotMatch(value: string, regExp: RegExp, message?: string | Error): void; + function doesNotMatch( + value: string, + regExp: RegExp, + message?: string | Error, + ): void; const strict: Omit< typeof assert, diff --git a/packages/bun-types/ffi.d.ts b/packages/bun-types/ffi.d.ts index 3e7e91534e..9705e810bc 100644 --- a/packages/bun-types/ffi.d.ts +++ b/packages/bun-types/ffi.d.ts @@ -344,6 +344,7 @@ declare module "bun:ffi" { * */ u64_fast = 16, + function = 17, } type UNTYPED = never; diff --git a/packages/bun-types/fs.d.ts b/packages/bun-types/fs.d.ts index 5dfb2c7f25..379e0ef253 100644 --- a/packages/bun-types/fs.d.ts +++ b/packages/bun-types/fs.d.ts @@ -3932,100 +3932,141 @@ declare module "fs" { } export interface FSWatcher extends EventEmitter { - /** - * Stop watching for changes on the given `fs.FSWatcher`. Once stopped, the `fs.FSWatcher` object is no longer usable. - * @since v0.6.8 - */ - close(): void; - - /** - * When called, requests that the Node.js event loop not exit so long as the is active. Calling watcher.ref() multiple times will have no effect. - */ - ref(): void; - - /** - * When called, the active object will not require the Node.js event loop to remain active. If there is no other activity keeping the event loop running, the process may exit before the object's callback is invoked. Calling watcher.unref() multiple times will have no effect. - */ - unref(): void; - - /** - * events.EventEmitter - * 1. change - * 2. error - */ - addListener(event: string, listener: (...args: any[]) => void): this; - addListener(event: 'change', listener: (eventType: string, filename: string | Buffer) => void): this; - addListener(event: 'error', listener: (error: Error) => void): this; - addListener(event: 'close', listener: () => void): this; - on(event: string, listener: (...args: any[]) => void): this; - on(event: 'change', listener: (eventType: string, filename: string | Buffer) => void): this; - on(event: 'error', listener: (error: Error) => void): this; - on(event: 'close', listener: () => void): this; - once(event: string, listener: (...args: any[]) => void): this; - once(event: 'change', listener: (eventType: string, filename: string | Buffer) => void): this; - once(event: 'error', listener: (error: Error) => void): this; - once(event: 'close', listener: () => void): this; - prependListener(event: string, listener: (...args: any[]) => void): this; - prependListener(event: 'change', listener: (eventType: string, filename: string | Buffer) => void): this; - prependListener(event: 'error', listener: (error: Error) => void): this; - prependListener(event: 'close', listener: () => void): this; - prependOnceListener(event: string, listener: (...args: any[]) => void): this; - prependOnceListener(event: 'change', listener: (eventType: string, filename: string | Buffer) => void): this; - prependOnceListener(event: 'error', listener: (error: Error) => void): this; - prependOnceListener(event: 'close', listener: () => void): this; - } - /** - * Watch for changes on `filename`, where `filename` is either a file or a - * directory. - * - * The second argument is optional. If `options` is provided as a string, it - * specifies the `encoding`. Otherwise `options` should be passed as an object. - * - * The listener callback gets two arguments `(eventType, filename)`. `eventType`is either `'rename'` or `'change'`, and `filename` is the name of the file - * which triggered the event. - * - * On most platforms, `'rename'` is emitted whenever a filename appears or - * disappears in the directory. - * - * The listener callback is attached to the `'change'` event fired by `fs.FSWatcher`, but it is not the same thing as the `'change'` value of`eventType`. - * - * If a `signal` is passed, aborting the corresponding AbortController will close - * the returned `fs.FSWatcher`. + /** + * Stop watching for changes on the given `fs.FSWatcher`. Once stopped, the `fs.FSWatcher` object is no longer usable. * @since v0.6.8 - * @param listener */ - export function watch( - filename: PathLike, - options: - | (WatchOptions & { - encoding: 'buffer'; - }) - | 'buffer', - listener?: WatchListener - ): FSWatcher; + close(): void; + /** - * Watch for changes on `filename`, where `filename` is either a file or a directory, returning an `FSWatcher`. - * @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol. - * @param options Either the encoding for the filename provided to the listener, or an object optionally specifying encoding, persistent, and recursive options. - * If `encoding` is not supplied, the default of `'utf8'` is used. - * If `persistent` is not supplied, the default of `true` is used. - * If `recursive` is not supplied, the default of `false` is used. + * When called, requests that the Node.js event loop not exit so long as the is active. Calling watcher.ref() multiple times will have no effect. */ - export function watch(filename: PathLike, options?: WatchOptions | BufferEncoding | null, listener?: WatchListener): FSWatcher; + ref(): void; + /** - * Watch for changes on `filename`, where `filename` is either a file or a directory, returning an `FSWatcher`. - * @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol. - * @param options Either the encoding for the filename provided to the listener, or an object optionally specifying encoding, persistent, and recursive options. - * If `encoding` is not supplied, the default of `'utf8'` is used. - * If `persistent` is not supplied, the default of `true` is used. - * If `recursive` is not supplied, the default of `false` is used. + * When called, the active object will not require the Node.js event loop to remain active. If there is no other activity keeping the event loop running, the process may exit before the object's callback is invoked. Calling watcher.unref() multiple times will have no effect. */ - export function watch(filename: PathLike, options: WatchOptions | string, listener?: WatchListener): FSWatcher; + unref(): void; + /** - * Watch for changes on `filename`, where `filename` is either a file or a directory, returning an `FSWatcher`. - * @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * events.EventEmitter + * 1. change + * 2. error */ - export function watch(filename: PathLike, listener?: WatchListener): FSWatcher; + addListener(event: string, listener: (...args: any[]) => void): this; + addListener( + event: "change", + listener: (eventType: string, filename: string | Buffer) => void, + ): this; + addListener(event: "error", listener: (error: Error) => void): this; + addListener(event: "close", listener: () => void): this; + on(event: string, listener: (...args: any[]) => void): this; + on( + event: "change", + listener: (eventType: string, filename: string | Buffer) => void, + ): this; + on(event: "error", listener: (error: Error) => void): this; + on(event: "close", listener: () => void): this; + once(event: string, listener: (...args: any[]) => void): this; + once( + event: "change", + listener: (eventType: string, filename: string | Buffer) => void, + ): this; + once(event: "error", listener: (error: Error) => void): this; + once(event: "close", listener: () => void): this; + prependListener(event: string, listener: (...args: any[]) => void): this; + prependListener( + event: "change", + listener: (eventType: string, filename: string | Buffer) => void, + ): this; + prependListener(event: "error", listener: (error: Error) => void): this; + prependListener(event: "close", listener: () => void): this; + prependOnceListener( + event: string, + listener: (...args: any[]) => void, + ): this; + prependOnceListener( + event: "change", + listener: (eventType: string, filename: string | Buffer) => void, + ): this; + prependOnceListener(event: "error", listener: (error: Error) => void): this; + prependOnceListener(event: "close", listener: () => void): this; + } + + type WatchOptions = { + encoding?: BufferEncoding; + persistent?: boolean; + recursive?: boolean; + signal?: AbortSignal; + }; + type WatchEventType = "rename" | "change" | "error" | "close"; + type WatchListener = ( + event: WatchEventType, + filename: T | Error | undefined, + ) => void; + /** + * Watch for changes on `filename`, where `filename` is either a file or a + * directory. + * + * The second argument is optional. If `options` is provided as a string, it + * specifies the `encoding`. Otherwise `options` should be passed as an object. + * + * The listener callback gets two arguments `(eventType, filename)`. `eventType`is either `'rename'` or `'change'`, and `filename` is the name of the file + * which triggered the event. + * + * On most platforms, `'rename'` is emitted whenever a filename appears or + * disappears in the directory. + * + * The listener callback is attached to the `'change'` event fired by `fs.FSWatcher`, but it is not the same thing as the `'change'` value of`eventType`. + * + * If a `signal` is passed, aborting the corresponding AbortController will close + * the returned `fs.FSWatcher`. + * @since v0.6.8 + * @param listener + */ + export function watch( + filename: PathLike, + options: + | (WatchOptions & { + encoding: "buffer"; + }) + | "buffer", + listener?: WatchListener, + ): FSWatcher; + /** + * Watch for changes on `filename`, where `filename` is either a file or a directory, returning an `FSWatcher`. + * @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * @param options Either the encoding for the filename provided to the listener, or an object optionally specifying encoding, persistent, and recursive options. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `persistent` is not supplied, the default of `true` is used. + * If `recursive` is not supplied, the default of `false` is used. + */ + export function watch( + filename: PathLike, + options?: WatchOptions | BufferEncoding | null, + listener?: WatchListener, + ): FSWatcher; + /** + * Watch for changes on `filename`, where `filename` is either a file or a directory, returning an `FSWatcher`. + * @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + * @param options Either the encoding for the filename provided to the listener, or an object optionally specifying encoding, persistent, and recursive options. + * If `encoding` is not supplied, the default of `'utf8'` is used. + * If `persistent` is not supplied, the default of `true` is used. + * If `recursive` is not supplied, the default of `false` is used. + */ + export function watch( + filename: PathLike, + options: WatchOptions | string, + listener?: WatchListener, + ): FSWatcher; + /** + * Watch for changes on `filename`, where `filename` is either a file or a directory, returning an `FSWatcher`. + * @param filename A path to a file or directory. If a URL is provided, it must use the `file:` protocol. + */ + export function watch( + filename: PathLike, + listener?: WatchListener, + ): FSWatcher; } declare module "node:fs" { diff --git a/packages/bun-types/globals.d.ts b/packages/bun-types/globals.d.ts index 5784f91c29..da412b2115 100644 --- a/packages/bun-types/globals.d.ts +++ b/packages/bun-types/globals.d.ts @@ -1401,21 +1401,6 @@ declare function clearTimeout(id?: number | Timer): void; declare function clearImmediate(id?: number | Timer): void; // declare function createImageBitmap(image: ImageBitmapSource, options?: ImageBitmapOptions): Promise; // declare function createImageBitmap(image: ImageBitmapSource, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise; -/** - * Send a HTTP(s) request - * - * @param url URL string - * @param init A structured value that contains settings for the fetch() request. - * - * @returns A promise that resolves to {@link Response} object. - * - * - */ - -declare function fetch( - url: string | URL | Request, - init?: FetchRequestInit, -): Promise; /** * Send a HTTP(s) request @@ -1429,6 +1414,20 @@ declare function fetch( */ // tslint:disable-next-line:unified-signatures declare function fetch(request: Request, init?: RequestInit): Promise; +/** + * Send a HTTP(s) request + * + * @param url URL string + * @param init A structured value that contains settings for the fetch() request. + * + * @returns A promise that resolves to {@link Response} object. + * + * + */ +declare function fetch( + url: string | URL | Request, + init?: FetchRequestInit, +): Promise; declare function queueMicrotask(callback: (...args: any[]) => void): void; /** @@ -1951,7 +1950,7 @@ interface URLSearchParams { ): void; /** Returns a string containing a query string suitable for use in a URL. Does not include the question mark. */ toString(): string; - [Symbol.iterator](): IterableIterator<[string, FormDataEntryValue]>; + [Symbol.iterator](): IterableIterator<[string, string]>; } declare var URLSearchParams: { diff --git a/packages/bun-types/http.d.ts b/packages/bun-types/http.d.ts index 710fea4f4f..118cf7ac1a 100644 --- a/packages/bun-types/http.d.ts +++ b/packages/bun-types/http.d.ts @@ -1785,6 +1785,24 @@ declare module "http" { callback?: (res: IncomingMessage) => void, ): ClientRequest; + /** + * Performs the low-level validations on the provided name that are done when `res.setHeader(name, value)` is called. + * Passing illegal value as name will result in a TypeError being thrown, identified by `code: 'ERR_INVALID_HTTP_TOKEN'`. + * @param name Header name + * @since v14.3.0 + */ + function validateHeaderName(name: string): void; + /** + * Performs the low-level validations on the provided value that are done when `res.setHeader(name, value)` is called. + * Passing illegal value as value will result in a TypeError being thrown. + * - Undefined value error is identified by `code: 'ERR_HTTP_INVALID_HEADER_VALUE'`. + * - Invalid value character error is identified by `code: 'ERR_INVALID_CHAR'`. + * @param name Header name + * @param value Header value + * @since v14.3.0 + */ + function validateHeaderValue(name: string, value: string): void; + let globalAgent: Agent; /** diff --git a/packages/bun-types/tests/fs.test-d.ts b/packages/bun-types/tests/fs.test-d.ts index 1ef14a2f82..3acfafa76b 100644 --- a/packages/bun-types/tests/fs.test-d.ts +++ b/packages/bun-types/tests/fs.test-d.ts @@ -1,6 +1,15 @@ +import { watch } from "node:fs"; import * as tsd from "tsd"; import * as fs from "fs"; import { exists } from "fs/promises"; tsd.expectType>(exists("/etc/passwd")); tsd.expectType>(fs.promises.exists("/etc/passwd")); + +// file path +watch(".", (eventType, filename) => { + console.log(`event type = ${eventType}`); + if (filename) { + console.log(`filename = ${filename}`); + } +}); diff --git a/src/js/builtins/ReadableStreamDefaultReader.ts b/src/js/builtins/ReadableStreamDefaultReader.ts index 70c6df8c32..a5654d834a 100644 --- a/src/js/builtins/ReadableStreamDefaultReader.ts +++ b/src/js/builtins/ReadableStreamDefaultReader.ts @@ -75,7 +75,7 @@ export function readMany(this: ReadableStreamDefaultReader): ReadableStreamDefau var length = values.length; if (length > 0) { - var outValues = $newArrayWithSize(length); + var outValues = $newArrayWithSize(length); if ($isReadableByteStreamController(controller)) { { const buf = values[0]; @@ -150,7 +150,7 @@ export function readMany(this: ReadableStreamDefaultReader): ReadableStreamDefau var pullResult = controller.$pull(controller); if (pullResult && $isPromise(pullResult)) { - return pullResult.$then(onPullMany); + return pullResult.$then(onPullMany) as any; } return onPullMany(pullResult); diff --git a/src/js/builtins/ReadableStreamInternals.ts b/src/js/builtins/ReadableStreamInternals.ts index 0c4e816f45..a9d67aa06e 100644 --- a/src/js/builtins/ReadableStreamInternals.ts +++ b/src/js/builtins/ReadableStreamInternals.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (C) 2015 Canon Inc. All rights reserved. * Copyright (C) 2015 Igalia. diff --git a/src/js/builtins/StreamInternals.ts b/src/js/builtins/StreamInternals.ts index b42dc2f576..7bb2629517 100644 --- a/src/js/builtins/StreamInternals.ts +++ b/src/js/builtins/StreamInternals.ts @@ -184,7 +184,7 @@ export function createFIFO() { this._capacityMask = (this._capacityMask << 1) | 1; } - shrinkArray() { + _shrinkArray() { this._list.length >>>= 1; this._capacityMask >>>= 1; } diff --git a/src/js/builtins/TransformStream.ts b/src/js/builtins/TransformStream.ts index 54467db392..2a124d4e16 100644 --- a/src/js/builtins/TransformStream.ts +++ b/src/js/builtins/TransformStream.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (C) 2020 Apple Inc. All rights reserved. * diff --git a/src/js/builtins/TransformStreamInternals.ts b/src/js/builtins/TransformStreamInternals.ts index 9994d1282b..9da403e715 100644 --- a/src/js/builtins/TransformStreamInternals.ts +++ b/src/js/builtins/TransformStreamInternals.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (C) 2020 Apple Inc. All rights reserved. * diff --git a/src/js/builtins/WritableStreamDefaultWriter.ts b/src/js/builtins/WritableStreamDefaultWriter.ts index 795b438924..50b2cd13fc 100644 --- a/src/js/builtins/WritableStreamDefaultWriter.ts +++ b/src/js/builtins/WritableStreamDefaultWriter.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (C) 2020 Apple Inc. All rights reserved. * diff --git a/src/js/builtins/WritableStreamInternals.ts b/src/js/builtins/WritableStreamInternals.ts index f436a285e5..2008dab1c5 100644 --- a/src/js/builtins/WritableStreamInternals.ts +++ b/src/js/builtins/WritableStreamInternals.ts @@ -610,16 +610,17 @@ export function setUpWritableStreamDefaultControllerFromUnderlyingSink( highWaterMark, sizeAlgorithm, ) { + // @ts-ignore const controller = new $WritableStreamDefaultController(); - let startAlgorithm = () => {}; - let writeAlgorithm = () => { + let startAlgorithm: (...args: any[]) => any = () => {}; + let writeAlgorithm: (...args: any[]) => any = () => { return Promise.$resolve(); }; - let closeAlgorithm = () => { + let closeAlgorithm: (...args: any[]) => any = () => { return Promise.$resolve(); }; - let abortAlgorithm = () => { + let abortAlgorithm: (...args: any[]) => any = () => { return Promise.$resolve(); }; diff --git a/src/js/builtins/builtins.d.ts b/src/js/builtins/builtins.d.ts index 2de8d82060..9b32ea45eb 100644 --- a/src/js/builtins/builtins.d.ts +++ b/src/js/builtins/builtins.d.ts @@ -57,6 +57,9 @@ declare function $getPromiseInternalField( promise: Promise, key: K, ): PromiseFieldToValue; +declare function $fulfillPromise(...args: any[]): TODO; +declare function $evaluateCommonJSModule(...args: any[]): TODO; +declare function $loadCJS2ESM(...args: any[]): TODO; declare function $getGeneratorInternalField(): TODO; declare function $getAsyncGeneratorInternalField(): TODO; declare function $getAbstractModuleRecordInternalField(): TODO; @@ -229,7 +232,7 @@ declare function $createFIFO(): TODO; declare function $createNativeReadableStream(): TODO; declare function $createReadableStream(): TODO; declare function $createUninitializedArrayBuffer(size: number): ArrayBuffer; -declare function $createWritableStreamFromInternal(): TODO; +declare function $createWritableStreamFromInternal(...args: any[]): TODO; declare function $cwd(): TODO; declare function $data(): TODO; declare function $dataView(): TODO; @@ -330,6 +333,7 @@ declare function $read(): TODO; declare function $readIntoRequests(): TODO; declare function $readRequests(): TODO; declare function $readable(): TODO; +declare function $readableByteStreamControllerGetDesiredSize(...args: any): TODO; declare function $readableStreamController(): TODO; declare function $readableStreamToArray(): TODO; declare function $reader(): TODO; diff --git a/src/js/bun/ffi.ts b/src/js/bun/ffi.ts index 7abfe50788..1272e7450a 100644 --- a/src/js/bun/ffi.ts +++ b/src/js/bun/ffi.ts @@ -239,7 +239,7 @@ ffiWrappers[FFIType.function] = function functionType(val) { }; function FFIBuilder(params, returnType, functionToCall, name) { - const hasReturnType = typeof FFIType[returnType] === "number" && FFIType[returnType] !== FFIType.void; + const hasReturnType = typeof FFIType[returnType] === "number" && FFIType[returnType as string] !== FFIType.void; var paramNames = new Array(params.length); var args = new Array(params.length); for (let i = 0; i < params.length; i++) { @@ -255,7 +255,7 @@ function FFIBuilder(params, returnType, functionToCall, name) { var code = `functionToCall(${args.join(", ")})`; if (hasReturnType) { - if (FFIType[returnType] === FFIType.cstring) { + if (FFIType[returnType as string] === FFIType.cstring) { code = `return (${cstringReturnType.toString()})(${code})`; } else { code = `return ${code}`; @@ -328,7 +328,7 @@ export function dlopen(path, options) { for (let key in result.symbols) { var symbol = result.symbols[key]; - if (options[key]?.args?.length || FFIType[options[key]?.returns] === FFIType.cstring) { + if (options[key]?.args?.length || FFIType[options[key]?.returns as string] === FFIType.cstring) { result.symbols[key] = FFIBuilder( options[key].args ?? [], options[key].returns ?? FFIType.void, @@ -354,7 +354,7 @@ export function linkSymbols(options) { for (let key in result.symbols) { var symbol = result.symbols[key]; - if (options[key]?.args?.length || FFIType[options[key]?.returns] === FFIType.cstring) { + if (options[key]?.args?.length || FFIType[options[key]?.returns as string] === FFIType.cstring) { result.symbols[key] = FFIBuilder(options[key].args ?? [], options[key].returns ?? FFIType.void, symbol, key); } else { // consistentcy diff --git a/src/js/node/trace_events.ts b/src/js/node/trace_events.ts index 789c412228..7edcc57d0c 100644 --- a/src/js/node/trace_events.ts +++ b/src/js/node/trace_events.ts @@ -13,10 +13,12 @@ function ERR_INVALID_ARG_TYPE(name, type, value) { function createTracing(opts) { if (typeof opts !== "object" || opts == null) { + // @ts-ignore throw new ERR_INVALID_ARG_TYPE("options", "Object", opts); } // TODO: validate categories + // @ts-ignore return new Tracing(opts); } diff --git a/src/js/private.d.ts b/src/js/private.d.ts index 500048dd71..d59c6aad8e 100644 --- a/src/js/private.d.ts +++ b/src/js/private.d.ts @@ -7,9 +7,8 @@ declare function $bundleError(error: string); type BunFSWatchOptions = { encoding?: BufferEncoding; persistent?: boolean; recursive?: boolean; signal?: AbortSignal }; - type BunWatchEventType = "rename" | "change" | "error" | "close"; -type BunWatchListener = (event: WatchEventType, filename: T | Error | undefined) => void; +type BunWatchListener = (event: WatchEventType, filename: T | undefined) => void; interface BunFSWatcher { /** diff --git a/test/bun.lockb b/test/bun.lockb index c35182d46e378de888f05757cd18177bc512d985..01afbfa4efd2d59bdd49e4b761c9d4ad92ce80c3 100755 GIT binary patch delta 32631 zcmeHQcU)9Q*S>dUl~qwxR1gqQ)POEs7DQRGD}p5|U_p`Q(wjZ9*lTPP9lOSkVv8DM zjm8*z)I^Ob_GkoqVu>c|_ncb*^O}5b-Wc;w?vLl5IcLtyoH=u5?(DL=v;A|+XA^bP zJ={Lqbl&sRLhthPqeq-bad+N(!|{^qRom&oUd_Joy6IAVcWNt*K-c&g5l-ftqeO`j zgq-;797-MpDhNW};Q0O-F|o-)L>WP-3_cuG2YL;qDgP_bN}z#|R|n0B&&rO^5`=bI zL8uD;1JLrIt3XLV3k^~EnAr5JG_>IZd5vxm?6eRBJJ8H>f?yBY6SOAigR(MJ<=K{U zLl>cML;9$VD&C<`Jq)P`zB_9#I+>rKZPL03S_||fD0QPHD4BN}wNUADR&qB6#ANFe zQeqN+K^0WXJ=`ciCnh7Ne@eXIs&u~=D5}UyHKoSu3Ag?3@33>BT z0V(E~(uQVd3>7AWC-+kiselW3>hUO09Vj&nv2c&+v`*$-9&&YQF=^?hI6;Wd?mrOY zE%b6Aa~c3>B>5pbI^GT zwG4d<0wG5j9wf}0xGSU(_sh>#T|>!+m0 z#bhHcY@lZiy$XtceD=T`Q%bg=QTXqhO7)oY5)=bs2gI1jy!FlGifEJu#iR&v@$nh@ z_{@}Liu^s$%Bc8ll%wt&jIu%5rbH>6XtXoZ(^HxtUx$1>D8+AfPMjVgC)g_TGN9$r z#k~7i8_2)cnRmIGQ4d4ppx6ylD7vx-#ivkMYynTz{oF#9XJ(VJg0QxwtZ&sy_M-qw z&8-C`|1AZja*x^j|=NKSlO9P};0qkePV)6TL#ZYdN6Oldg*LLn+7 zpMs|m7QRy&IHAxHsD#EW1C$JP=_XTKQ0ne)SCYF*epYwc5QJb#GM+qw`b<@qnxQ@9 ziVlHN0|`n)JtO47j~|kO{$~q|B4q=qdswN2+EFr}ofDHYFgrebI`V0t$AHqxlPz~# z7^3jqseC0^thpF z_xlgUN{zhp(31x44X=^ESt7Az_+Qt^xcE5idIaIOJw*UYJ#P+59@=Y?J*ZBN>PfQP zi}KmP3f0W|WLe?>O1^eQ4*A+1lwz<|s=S?ZSEvmrJq{kH$eWc5pmyL7D0CgDE%@1> zH9<##+JGi0a`;^uTgOZ(e{;EtQI_U9KKIw23#rpFc3#1a=IL>luC=_fr~CM-Ro8s@ zYo`st4WC{0oa|*|^nL!RzlY}GcxC~Df&uSdh`A>JbS)de`~YA_s%4g zSuyG1$1`iL4zU}Py?)cLTET0`-4tvDghL8-R;a_=dNahlid&JTTo?~r*qTY#cdW3c zQT&d%*&4+JX2QLI<>P*x72;lxx!D;-6EordjOF9rlNI8=i@DV@ia#?G?*1$v_hGCM z_X6f-Z`4#M$CB)W#VIV`-l)4+4tpp#z6`q`7GPlshUx8t#0kvgVAOsKz70#Q6{K;| zu_A|H-8&fTU}$StW`_V~ax`knlxJ%kgT)wD=x7w*XKuBPIx9>nKPXu+Z##o71YCer zWRs&oI}}`Jrnd{y9Y(6RB)@NOKu=6gMlqS?WI7r|BQv=e#i1-8_YYa2i&1wQ`FN^PN#uJnQyrsrMrD}B z);R|04j|PWxmxD!Y|z=l>v(d@y1H)Q@H|(zsY;%f>d_qm*9LhaaT@C?%-uCujAABN zqqu_Q7ks7Ot#Rrc*IB}DcLF~>7>lwvW%&oprcLzCG zi&5%+ErZyK<<~cAt6~$>oUN-Lr0t4SD@ut=n5ltLdlq~fiFad#;Nvmj`bnAxkcyO2 zj+k7*QfdfN-K5k5q>`jmG^St&DdmaD*;z`Nk!mNU4i={>*Aj%Tk}L+PXiDimMk+|Q z)xjV>Wo`|PVmLE3H0mZ{Q6R@_sTaDl;NCQG;s;wNE5*aZZ$X>(6TJk z)gWGAg^i3lS4Y)zq|qB(J7~aj7}Dh|UvCtzu|mC3_cmTzVEvZ;EpBHf52N^y<$D;l zP4FVagQdC#=>{T2t%=eoYy(GwtYP;X7_>IdXX~7UbZe24&C2wEA>hamEz5+9ov<1!E`}iy;K*bc372stPY%5k;FL}y zPlso63%Pxm6$-8?yX_F98;=yVRZbd+JIt-IQR`eEwvr{|z=09%9Di{<+p#d)j{_bbfJVAR^ZB?#@=?FK<&f0l2MCOxEO-4RsmwjoH{ z8>yD;wo{O93sQlow+i!aY|z~XN46ojFa!-7%HaeKL72!)fky30$Xbwn;tf^^Uf)O% z3{;*pYb zKR~K2(+4-TKtis!MPq7f9YjdTqLWC;`i}4zY=f0?NQFwN4M@p)KO-gUwKhny=1nb; zAa_Y4uRRD3)2~*L_90SDq=^^=|51cu+BYzW!o%TU&Z`n%Ww5KO%<~8Z5+^Crz+oQ5|RxPkF401CHE5>T zF2*sp_C{Kg+8cF`A*HhN5~N2bD3lObP6k~(IJs98Fw2l^BWYsE&=rCUm)k_tH#f@m z2oze{Vc@WwU_Nd{is}>CeSd@QhN6W94qP2LTn zN}i=O!>mIP8{l9u9@E{KTbL0$2NUl5SbmsMC!$gmAWxyDFmO~Bt5;)#IFXscjk-OM z$s>RoG@6#IC_GrqWp15}x@~w2Duo*vH1@67nohyGeyvnXGqGX#5L~bnH4l)IN8x_& z087{;GvurR;3(wqTnIC0=YaF4kkfsR6qzFhm99MeSsa+UCg3mwsAH%ht(c>AeknM4 zm=IFpIhNnmsIzPh$DIEu;_^C%&nVI zmk(J7SswxQ6FB@)aO(}?U{=`8sQtLTAas|)$_9#*TbA8-GH7$b$>Dv36?Ql3Du>Fs z2!2}n!I4*_nsjTyQ7Z@lwDM5Nlj;%MGPek$c1%ZjMDo-Yq%ck>Nmf2$g%L)bdziYm zdAG)9FVZM3W%-dt-33K%Lm{E55zgGBg0_RXkwYx4KFjE6ku2q?CbofIc{E zp2C83mlQed#`Ctu+p0|%ZfzuSH2*a7-e&GSgLP+>Y$;N-9^Iq|SzwSZ6Dh1Kd5+SA zEFgI?_bWK8V|i6+(rFuamllt}AkFCRtf*J8?f?WnQa`XdY94oINxg%0K|SOJ1MOgZ z$AKe9!3CJ$Ux1^?hugXtG?gOQn#f>XLWDfsr0Jkp8NrJB1ncr6)ny0eG(SYLr08Is zTa+vmq+M=e6f24j)-HyymE_i|NMT)|+FcDA*Pd)m-(X$$p6X=Ayw%MDN2?j0wRmWL z3691`8bw`&Ud3xYLfQb%i@dB&L<;`KIBY^nSr{-5_rV3Q+l_*>ZoMU4Xhb1J9>JQ0 zefZ?wEUAC6W@m4^L(yaldgj(GH!_B*Dg*jc$J87;u#HQaz8?OmkWNhw1tjU>s2BPGlB zBPHwU;?&$Qq~zRLNOhD-TrQTm#na}LY8i}_oVy<>rIrM>Y!{^D)@BvU&Lbt4a7$E6 zq$AZqs&6||a=YRHRWA%FNv4~H6!{gw>2J^+9>9{)f_0X73qx4}5Pi+TQS=FncFVco z$Uo8xE~``ET7k2`I)lOJE3Y&4lH~F>v|rWr0T&{bApb4`M^hD(6XAY2i6x~6>zXCY zONBH9n(Sm&lpd_vn#|lYf;CT)SrUj}3R{yAtc^~UUX5i0X+JDZRZ5dyZ$TD~6kbsw zwF{{pQmSgYni_xCFSbYBSqmMExK>@%@l;;#G#9o0rm2O zydmU!_Et_BRL=e?v$nO>e3QwFvYUiBK#5QZa0hGwI8C~UY5=%Rx=PcskaPen*sL5U zR*+*!h#_sPnNle%ZPHbmmVpGTk#v=&A|#OjQ7kgjMU?b0t0g(6DO%GHG>B!`tbu5A zAlj5+rg8`#>G~r|_8|_Wizt=DC`(sqN_r`ZoG5t|u9ob{R^+9qSrU~J6!X+T4nXc2 zCP`&VatxJp5heZ|nSCWCgK`0K$Vf$xs3kB_KunUtWPmK4255oz0J?~hd=4?Vh?4$1 zg)UI&B2c=BQbX?pWY|)GE}|m4J;=#SxvNNot28C;)d10afUeS%T3riJegQxiQR3GD zl)nL>izvxADs+=VKakcyFi1!jQ5~>TW?!OI!7h@sM251OE$s6F0zANRvOi6xEkrSnQ zeo}a%l>Y#raC-`r2P{Y^Q8`Q{0m-zuQ3aNYLTOq9^4g00wNYuB{v8#UGL+)Hj=~eA z4%Sn6GbJcpUlEk1RM1_?Z>Z!Gr5Wa{@I)!;r_jcVoG2yz75;Z<{g)I-*Ps+2N|rVO zEyvaktI3WHv!<99T0o*8%J#Q>q|Zk(Z|A+5V7IR;-d=no_xVMNX6&8~{op`gc2BB~%IG z5KT*)U&$vFy7lsaNwsAMcsGX4yuB8!!BucGAorAj_g^5{xX zlIP2Evy`Cp8d)Gw@<0K260K9{dWCKvAughn+^FzGoxq<^c%oF#DTRL(wV;1!o`HfD z6t5_XL@9Yy;a^3`bvKm!zd}Wdze1&=(v(C+xKR&oDfxdyDd>Ju^!|vF$^+agf>Px! zG$s~EP==OT`wgwZ9L-Lwk=gpcftjjpfLf^5hDxoC6siZspWsQi-%x7Z3v!AK`iK%; zucDOik9?X_%@w^;RG!VH1XRzf6n|Gvb+%9{Rw*evDEQ-ztv#u}yuXIp9`E00ep zf#fdYDFFW6*-Gx99WF)SzdKubJ$TiQmK;TL3Y&j-wzbI(xc&^K6}pa6jwr3H^%VZ! zoozeC6R)B)H#;Ez-<|EhJ6nW;w8Q;(XG@+ay%YX-XDjb?X(4$HJKJ#b@1NSq{#O5` zo$cnp$y0inf1dvAe3uFl=gQ4o)BSq6&>x;Za6GlHS|wxeu&$S^cbTIW1Sj@S&)OdS z$*i=TfqnM+RCqVL$&kej?nbsM=u_vwmABD^C_JzH9DS^yESS`)#r~Dq{&!aU^!K$c zTYdlcp$$8&TAh9S-ny?BwLdcXM!-Ft|H|FxKa4zV*K1gCFdNle}BlbTHm_NI{Df8yhIyzKUMqk;G+wz>i)8$ly#L$Ti4~#cdpl#FWMYebJ@|p$BQzu zo4hro`deRDznRc9dHx)$Ue6AnnjRsPv-4UrK4;E_Gu_UvjQs3Wf}3SPvhHN1e!10p zvfZ#Q-%FUisS!UK(8R?$c0)#`#}!>pTiq;|eSN~o3Ac8{RP#9UPV|DSIYIL@%V##3 zeW-WQL1%HA`>usk7eCF_4f3P6?N#4ZDQ(@uIT3H2xVb+!$I#Prd(5}?cAt%Z@NR?g z4L%(*<%?adF26nGs|wEdUijMeG{=1W=uX41D#o!J-n+H-nRUxa^Ro{0_&%Pc7TTH{ zt+YAoT(jOlXL0DWF1A;8Uac{{Ud`G^FRt3YVEe?~1M8J<*y)q0-<;mt*}L-bkLT2z zzh!6HDP3y~?r8bJ_#vNf*;}QQb=68+_ray>Q?_;<{c!`Yb?+rk9WqAT6QJGWSmx^@ z^PY|;Pxrm@;OVt`o{bvVEvwq0(&X)D=I%M}wXDD`$AA6A2OcrTZ;w13#M8x%TpZ-F7+m=Zi|QqKcc zN!x#!Wm)CzopuWgzBupg;P@>2qeqpV9~rkh^z6+6O$)1k{SiA3>mnQWO!ZiI{zTQ8 z)Ax1l@o=VZ!JX(GpY2=dKC^Pdp@4l(BQM_E-MPZbZ^n1s*f(|2ul;^%Hzcv@Sziyg zHogTmlcujKWnInE*7;uDKY!gXfm3_{r?YmQbZ@O*Y(Yx`;x6VbBZ?WCInC0Tq(fr z>d@Q=-ZN6JxLkb1H*CIqwAIx~J?iY57ubjCZ`pQC{?N4DzuOtV)WsD?HBLQr?JK{1 zu`SMb8xeYU%zih2he3S`Zhz8z-pmyjcV7z)eB64Nu;*}o^K$2=*u5~n6CB%mbSdlX z+4k!Z?8YrC=J-RX=*UbzM6fxxt=MsJPR#B`1Z#K4ijBAtD!Q=4;C=?DFANpyvY~|$ zZ1r6$b{-r)dRr91BJWwTcZ)*B2JCBamiMh#vzwu!8=H7Df_((;Hn@f?@KyvH@S_!5 zcq>%YvqEsTKUuM`+oAYW>fGBA>=3wT;JjJ;I}vQi11q-fPN?Y1o`8Gnp%v?MH&krQ z^6y5lbKtD*g^C6ibuWTVcx1(Pg9~K3`w=YQu@y_bA1Vg1?ci>JbNn$>Y{pDKqJKZ5 zf8dPF?kDu`3HtX_s2IWygZmkr{z0hNk_~+jfe)RY!o4+fdl(_MVIy&G%f80F9rJz^ zA+~1|aqqw`;~vTaA4iBC*$mvnSRwA=Eac}1u@jq%duMhZ_b#mclL)aZdms0=*%REm zu`W*|@HwJ<+|@6D<_ixB%T6YkM$AMSmb z-SY^sAIro&h8@PeKXZ8zA;z+yxW}(yzqwp;(z*;kJ}?ilv-Cp9LNsh`qd^mlDde78=-;(2Y!idB{o z`^JykY5n&16%&f;=dQT2w&`Q%556z|#isM2O*BdMt4FRsw)|P;4TD2`mK?b`Xi1}W zUg^f6KdoMMY2PoUf;h9Zb?-j-WuoE5m6p>VdVJ#8H>9p>&ld0Bxw(Dn)K9D}^!wcA z|FpaLuw%PgnfER#un4L7t4YS z=TSu7;hTtz;JR`kxjcr5nQteO$E#R^jN~RFqxe1|qq&_9WDL(FGL|1EGLE~H7dy*u zX5l|*gXK@Pa49!ZR4E>9)f*|CPL+}bIk7VliZ9j)&@D^g8@ET-h`U3ACRY(o1 zU)=o(uTaPsYWOwD%*DM^zxA7mH#_l92dR<2UxxpG{{4;oK^rvwZ??xT8)JTRu70^; zrCsws>wfyz%|GdW9om0oq|>xhzvmsBV)97B``aXQt}1_UMHl{W4J+-MU-NkWS!2xqtot$lD5}-(>3`!WKlNxx-i*vF|3HA+Fd1{- zN&W($)>;1cEgAE-$;@w}kw0j|{I~Y*4;oh5HA~;Md>yW)p*vkq-k@9nwN_TvKbB$s z|96UiU5^Y@f0E&=21=ltUnP8nj0&s2+py}bl5N;um6_=$U0!E}f3iM#|3|^_zxISY zqyE4|xL*Dmx#}$e*KEjWC#|;evJCq_^;aoWMJk+?o{};!1E0M0C|Lvk8yS^Vf6t?Hz+f|WX&6FSZUY%`>uH-#+d(E_g7H&f4>_bf3p|N z|4qXb!RpVGjKbS%_@I+ConC{?EWG9l|73mmNdsCKUPDj*WW!3kX6093R42Z?IvdU7CNtwDh$n&}cl))85!~c(qw2N zC}rcl8Q~BWz(rq3q$EBpAPhx<3{6sGm60AMeZCfnWC+Ovcq?3Zhf3f|Qxxfga#VVZ2Z$oDgz>9C^GUud&N$POk+Q1;=K#6}njs;p>ASt(kp$OZ zMX@H*=Ou|C3{hnCnZk>TjCzDW$)zhOfoqr|tA+Gfq^XzmJI$0$->Vu=30%}kYS&C( z$)cW8&vQX3AOD1sdPTh?14&jJ=!gXMGEb2?A>D~Gag9`D&PYE6sF$N4qmH=%8l*`^ zUzx<8PzQKO<4+266=7YZe*~!K^B^M&U4bHidcHuB;lCTjKP|9GDO(@1Rsda#6&e1? zK);wIT}za*_}>Bj_=j{Y6;V6nf*Y_wmI=$0!mGzo4t|Q_UA{h3tj|woiv4293JPKJ zFZr`MOr)>U8GryF5NHAf0ZoBsKrmng=&N{sKx2TS+a7QL9D&+^6X484vc#H>^c}*o zKsmq?&;jLv3P43Z0xIUJNYc-S+W^&p8bD3J7O(?q0rYLoO~7VgEASz(9oPZv1a<+t zfscW`z$d_d;8Wl;;2=PA=`e5vI0_sG@Oc@t^wm*vG&y!EFb$Xi%mf(l9xw}_FWFK^ zQwURdQaDoh(d49gM{}kPa1ic11RMsA07rpiz;WPn;3RMg_yYJ+;5)L#IxaM2Xo_3_ zXj-@f4S_}g{_P=n@Mqa#kX0~}MxZ$m!dvHv4a^im6fzVd6cY5kO8Vse_rMRp6`&9} z0ZaypfSbU1U@1URLX(c-nZlRCbv{5LN?#M60MLA*`9pz36AvG}lD_j2O705-6AsV> zdK+j9Gy#Hura&_w7%&3OfrdaMKo58TUVsnq6O5;iqx}jz16n}V5@-NC0)H2n1H1!_ z07e00(7rGhiE+RLU?4CU7y=9hQh-z-4M+zPfdN1Q5C!xEdI2=yXo9r`+5!844}i_U z7GNvzA+Qbj2-ptn0P@kkum)HLEC3b)-C=PLAOctetOZsAtAT|8JqZ$kXrM395AX&2 zfyRIqCO5i-5(z5}-F4iUN89y?}K<0gw+20Ac}pwD|#bfEZf$I-_7X&;={V>w%?2 zq1X+SmL>X`4SGh>mwsIUdgi?k3?X3Bu_9Vc zQ-t*VqLsZ1&{dJq3a&vKE3~vA7lE!)^5{7>P)Spzgcv?!uo&8*7LxXW1K4*nsZ(^- z1)T^=yc0m7M)Qfnjz*Y#;tJ3Mt-gr;2hBz|pbYRfcg({A-WRo4mdP0S$fSOOd8{eHL+M8)Q#RC0-7@!|OYeF>82j~s-0(t^bKqL?W(E38_ zOo<)8Z$>Kge#eYNDa>f*WC57~&5FUmAb@5^>GWvuqkxe>9$*G?ff2wvz;Iv~FczR| z$!s~%?G!J{6AQepQB3`XYmFG~el_En>f23diX>g6`>*4Fsm=7H#I@-^N0#<{(+}QDY z_u5vu8qv?gAQfBAH;oeQ#4Y?NOcHnV7o)_)#s{HJeJdP%#^Y4yuRfC1eITs`*HlN2 zop%+{+i6e@_`}Piv42($s-H*-lFO&^E@NQpJe~|aaT#As+-AOg zjM%XJUX-eYQq?s4&KS|wUOn0+I9jvo^j*t~N-eO%m%EHbxz;?0NFUyPtmxZ#FqUgf zki17@KkVn-EcL#m9!O@ZpMp%EbE0zYgpM3JejeU_9*u>0d^c*aFF;Xi6diDP%iXSi zIc`vB?BPv5*~RZu6GwT4aj^F*ZX74t`Co%N`8J@#kvl%~YYma=^YIA8XRwjuh@7BF zOTY7Rd9n{VK5!j8V^xMv9VgmqYL(&6E5zy+J_f;+??Y{(o_|Yq2lC3}MZ3o82}r+A zST*z9=b6=|8vG>Zmyth6vMT=ej8QPGbt8Xi+HFj4r6ujiHk(#ez0sr*m&q!50ZRtss_~hq)$LDH9Zx0#~ zJfFDtM6{X7Ly43W%;aVW?A2qKT)y>;ZV>JA1KPkqkr6HV=83SmJO6>mNp3$0>gu^n zV~nTmJDfb!7V0$hq5gz-nuMO-vsr0a;!wJoE86KlGstBwdT%~ zMcc-e5GFL?lbgLaA@j@c4nh-#lkZ-U(-^~pwyyEi$(R)C8A`r0V~6cqxMYMzyk13m zv7PsV@0<)P)I*oH*&g`rM>2(6WcxCvcmNpXeeXw+Yq-F zXYo!`L>JMQXHJ19XYy(9f^6cwh@9phldy=7mpZkB?J-YJ8B^4>n%k`-?t>%}fme}+u zuR`2){(@{$&wVm1|KY7w>!0VBRMm&~g`T~7K-4>v7roo{SErpN3QCV(*_K>8Rt%~` zwc}4ZMXCQ~>lL%r)2E&c8GZk1y+w8!(H$!;UG;g`bTlawd-Z^@Lxp|?12eNSsoP}Vy2n~DnbRfG>tN78b zxerhUJ+RP}JimFPSz;|s88_Z;7N)Y58=pN(^l?xR8M3M(j>)b$atlg%VHH9t7dKvh zuIM99<~3)-cX}Q=8@_A8<7bPl>$Y^0pB3sST^#Dy+At!yF+C-HFyFD-Ch+6Xw^vVX z`mo?!z?gTOKc&rsucR=FiyReB=Jp`=>JeB@0i(muq>Yg_8M59=-U$kgH>1VM82u`) zPSv_C`1OWOaZr7N99oUah8|p8@Xg)fB{|3VLJrf<@Ke;%MShc7x(Ri9Zv7fv{-dAj z#O9Z%KjKbvpcleN}mbF)p@#-lq__odC#Tn=;9*(r?<@5LF zpq;t=+a)M?2L&~%_excO^*my(I1)Yndal?|Y{|9r#QRu$AJ0Po{Qjc0i}#%mtEThJ z&7zGnHamgBa!=_EvAnLqCmT9AR#{~Mr+P~{JNP;%+p8ySEwcC8@nvCb&k}{J{4&+{ zi2nlOpq@hWiEyWF{X$Li5VE#!VpNgED`4!!?|Ho?;N%+qAgJHt?~?j5zKYbPzzMTg4-{*6Ys<3UMXQ=4z_91R z22EJcTfPrH10PJ}I$ulVA-@P>ub%VuAXU3@l5Uy-r2^zq!Cb!-jdbE|mqI;~4+m$j z9_cl0ZrcGr+ONT8U1|g)m%}$KMR=~|-pf$xF%JdN2(7roa`f7&70+9Scu*GC50+ta zEak_cVy_+`R&K$JV|7PgUy2&(d5k4QR#xh`;n1S3JcTyk?gG-9suXb<9dSBPGJZ*OZwQ#P%9y;P@#Ip*v;U*iyP!_$HPlnIAKOpJ`FWsV&|_C=ZkXt_&VfJm_Zv~ z>-A#w+P;2*dU#ouHu?IE=F@*Jd08c|*Wxk$3$|ru^~^B!q#}ByB<o? zznt@*udc8xOE0g~6Uo$rkYKj2oTHvurXH0fjgG&E8IgfP(m81A=}XAM3mtk6W+*47 zspmA23H0V)$(d^ENlq3N71AD2>@2@<8hvI*QH{Q?N36x*X7o_>E&yiDK=2DL^2VtCgpj+M4Cw<3-bciO;;nf)OT)J_ud@MHd(?%n+ zHd=c0O3w^C&E0PNSU#ql^mNfTrAh52s3*WVE!14{tGb2u{$3tF2!DU|2)J<1PnOyp z*>5A6Ck+y|@8N6ktXB_*>!0b`ta*jX0c4Eici~VEzF>`LYoi_$_r$8s*6Pid;Bnp| zf*)EVI{Papr{#_5WSQ1<^xU4(PLn2G@kwNjj-0u*?qs#rl;a~k7KqK&gO`{muj>gVVc_hho!yOi=+NSNapiK8(^MdJMXta z^ivI2Y|PWht@~(J^x_E{v9FTXSqJs#yWtPc2AbDqM3NEGs|q1Antu+(-?pb#OdbiB zd+tjv{$i7upjzPYs`qUCJbVz~vOnjknqmUC+lJ-rKSzFjjPxJcJZa-$CobocH)CB? z&+fE+`qaDY5&wAUks3fRlRoDkLqU`_7&b1FNId}5s%ERgMe7G0EK#oL#Vc*WyBp4! zBvmnaP1~EU_A8ruy+lLWc-V<;c&{yJRy}icZ5vacEMtQOC3@+68Wiv?aBMJaoTX;f zgG*ETEq!rz#`cgB<&FG2)ux_w`orv;AKy1V+F7C?Z9MG6Lf&vIwnyqosr#!+SjSCXT=s&~Z{tq2d-s$Q?k$hvRiRlWLR%psYd+=d|6C-Vi{5NE&TlTvu?k3?I4 z^&r3ez*!kx?S5QrfeDV+6?kl`NBwM35I-easPr|D~Fb7s0R)`^1w_SA6ox=NTxSYS>(c8r=EWf9=i%#N1ejlXP#Bljp z5*6q=y`f$Biq2oi+VQQp`wlU|y1Dci^vuRNzFBnkFQ2|cG}z$r7@MA!hI5lm>1q1x zoGepX;)i*Oe^`2@{@5?v-BG&bMRVh+?MP+(Cy!j?;jZ4RjL|H|C8`UEx zaajL>2?_C8`oUQ^6F7^G5s%N&;{f6~FgScPD?KMYHa&$Z#p%OwICeWL9!y$Hj%g5| zaaMG2d?`z5zgU%@tf{G2S$@b%d2~K153d2Cd`2pSa)O6^E7prZWwM8)en?5!P7fJa zTI_(BtgINEd@G;Ds;9F#V~V-Bn4I`x24|_pXW?jFzUhYOku_=!s*Fch zhhfrV8rc%n`|&E*#JY8hb*cW+Wr^3*uE4-ApA(&()jB1sN-IhNJ*NFbv93#Tby8PK zt4RXAkEB)w?x5pfDPKyPB^xO{c4<-wIK4E+ zq)>Xy6$80(uUO7jjtQu|6eEgp+hTN@o7KIFLm6ttX^a^j;65~Hr6WEjF+PoZSJXK0 zCC-|1-jX`Wa@4XCqnF+a3@BAtKCLw=hF7st%5tYeVr8CpS***WEj5Sn>r=`}TVsi}(Fx;SZWl>0v_np)-n delta 28135 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 u { // https://github.com/joyent/node/issues/2293 - non-persistent watcher should not block the event loop bunRun(path.join(import.meta.dir, "fixtures", "persistent.js")); done(); - } catch (e) { + } catch (e: any) { done(e); } }); @@ -39,7 +39,7 @@ describe("fs.watch", () => { try { bunRun(path.join(import.meta.dir, "fixtures", "close.js")); done(); - } catch (e) { + } catch (e: any) { done(e); } }); @@ -48,7 +48,7 @@ describe("fs.watch", () => { try { bunRun(path.join(import.meta.dir, "fixtures", "unref.js")); done(); - } catch (e) { + } catch (e: any) { done(e); } }); @@ -57,7 +57,7 @@ describe("fs.watch", () => { try { bunRunAsScript(testDir, path.join(import.meta.dir, "fixtures", "relative.js")); done(); - } catch (e) { + } catch (e: any) { done(e); } }); @@ -68,7 +68,7 @@ describe("fs.watch", () => { try { fs.mkdirSync(root); } catch {} - let err = undefined; + let err: Error | undefined = undefined; const watcher = fs.watch(root, { signal: AbortSignal.timeout(3000) }); watcher.on("change", (event, filename) => { count++; @@ -78,7 +78,7 @@ describe("fs.watch", () => { if (count >= 2) { watcher.close(); } - } catch (e) { + } catch (e: any) { err = e; watcher.close(); } @@ -106,9 +106,9 @@ describe("fs.watch", () => { const subfolder = path.join(root, "subfolder"); fs.mkdirSync(subfolder); const watcher = fs.watch(root, { recursive: true, signal: AbortSignal.timeout(3000) }); - let err = undefined; + let err: Error | undefined = undefined; watcher.on("change", (event, filename) => { - const basename = path.basename(filename); + const basename = path.basename(filename as string); if (basename === "subfolder") return; count++; @@ -118,7 +118,7 @@ describe("fs.watch", () => { if (count >= 2) { watcher.close(); } - } catch (e) { + } catch (e: any) { err = e; watcher.close(); } @@ -141,12 +141,12 @@ describe("fs.watch", () => { "deleted.txt": "hello", }); const filepath = path.join(testsubdir, "deleted.txt"); - let err = undefined; + let err: Error | undefined = undefined; const watcher = fs.watch(testsubdir, function (event, filename) { try { expect(event).toBe("rename"); expect(filename).toBe("deleted.txt"); - } catch (e) { + } catch (e: any) { err = e; } finally { clearInterval(interval); @@ -169,12 +169,12 @@ describe("fs.watch", () => { const filepath = path.join(testDir, "watch.txt"); const watcher = fs.watch(filepath); - let err = undefined; + let err: Error | undefined = undefined; watcher.on("change", function (event, filename) { try { expect(event).toBe("change"); expect(filename).toBe("watch.txt"); - } catch (e) { + } catch (e: any) { err = e; } finally { clearInterval(interval); @@ -195,7 +195,7 @@ describe("fs.watch", () => { try { fs.watch(path.join(testDir, "404.txt")); done(new Error("should not reach here")); - } catch (err) { + } catch (err: any) { expect(err).toBeInstanceOf(Error); expect(err.code).toBe("ENOENT"); expect(err.syscall).toBe("watch"); @@ -203,13 +203,13 @@ describe("fs.watch", () => { } }); - const encodings = ["utf8", "buffer", "hex", "ascii", "base64", "utf16le", "ucs2", "latin1", "binary"]; + const encodings = ["utf8", "buffer", "hex", "ascii", "base64", "utf16le", "ucs2", "latin1", "binary"] as const; test(`should work with encodings ${encodings.join(", ")}`, async () => { - const watchers = []; + const watchers: FSWatcher[] = []; const filepath = path.join(testDir, encodingFileName); - const promises = []; + const promises: Promise[] = []; encodings.forEach(name => { const encoded_filename = name !== "buffer" ? Buffer.from(encodingFileName, "utf8").toString(name) : Buffer.from(encodingFileName); @@ -225,11 +225,11 @@ describe("fs.watch", () => { expect(filename).toBe(encoded_filename); } else { expect(filename).toBeInstanceOf(Buffer); - expect(filename.toString("utf8")).toBe(encodingFileName); + expect((filename as any as Buffer)!.toString("utf8")).toBe(encodingFileName); } - resolve(); - } catch (e) { + resolve(undefined); + } catch (e: any) { reject(e); } }), @@ -254,12 +254,12 @@ describe("fs.watch", () => { const filepath = path.join(testDir, "url.txt"); try { const watcher = fs.watch(pathToFileURL(filepath)); - let err = undefined; + let err: Error | undefined = undefined; watcher.on("change", function (event, filename) { try { expect(event).toBe("change"); expect(filename).toBe("url.txt"); - } catch (e) { + } catch (e: any) { err = e; } finally { clearInterval(interval); @@ -274,7 +274,7 @@ describe("fs.watch", () => { const interval = repeat(() => { fs.writeFileSync(filepath, "world"); }); - } catch (e) { + } catch (e: any) { done(e); } }); @@ -288,12 +288,12 @@ describe("fs.watch", () => { try { watcher.close(); done(); - } catch (e) { + } catch (e: any) { done("Should not error when calling close from error event"); } }); ac.abort(); - } catch (e) { + } catch (e: any) { done(e); } }); @@ -308,13 +308,13 @@ describe("fs.watch", () => { try { watcher.close(); done(); - } catch (e) { + } catch (e: any) { done("Should not error when calling close from close event"); } }); ac.abort(); - } catch (e) { + } catch (e: any) { done(e); } }); @@ -325,7 +325,7 @@ describe("fs.watch", () => { const ac = new AbortController(); const promise = new Promise((resolve, reject) => { const watcher = fs.watch(filepath, { signal: ac.signal }); - watcher.once("error", err => (err.message === "The operation was aborted." ? resolve() : reject(err))); + watcher.once("error", err => (err.message === "The operation was aborted." ? resolve(undefined) : reject(err))); watcher.once("close", () => reject()); }); await Bun.sleep(10); @@ -339,7 +339,7 @@ describe("fs.watch", () => { const signal = AbortSignal.abort(); await new Promise((resolve, reject) => { const watcher = fs.watch(filepath, { signal }); - watcher.once("error", err => (err.message === "The operation was aborted." ? resolve() : reject(err))); + watcher.once("error", err => (err.message === "The operation was aborted." ? resolve(undefined) : reject(err))); watcher.once("close", () => reject()); }); }); @@ -353,13 +353,13 @@ describe("fs.watch", () => { }); const promise = new Promise((resolve, reject) => { - let timeout = null; + let timeout: any = null; const watcher = fs.watch(filepath, event => { clearTimeout(timeout); clearInterval(interval); try { resolve(event); - } catch (e) { + } catch (e: any) { reject(e); } finally { watcher.close(); @@ -383,7 +383,7 @@ describe("fs.promises.watch", () => { fs.mkdirSync(root); } catch {} let success = false; - let err = undefined; + let err: Error | undefined = undefined; try { const ac = new AbortController(); const watcher = fs.promises.watch(root, { signal: ac.signal }); @@ -405,13 +405,13 @@ describe("fs.promises.watch", () => { clearInterval(interval); ac.abort(); } - } catch (e) { + } catch (e: any) { err = e; clearInterval(interval); ac.abort(); } } - } catch (e) { + } catch (e: any) { if (!success) { throw err || e; } @@ -427,7 +427,7 @@ describe("fs.promises.watch", () => { const subfolder = path.join(root, "subfolder"); fs.mkdirSync(subfolder); let success = false; - let err = undefined; + let err: Error | undefined = undefined; try { const ac = new AbortController(); @@ -439,7 +439,7 @@ describe("fs.promises.watch", () => { fs.rmdirSync(path.join(subfolder, "new-folder.txt")); }); for await (const event of watcher) { - const basename = path.basename(event.filename); + const basename = path.basename(event.filename!); if (basename === "subfolder") continue; count++; @@ -452,13 +452,13 @@ describe("fs.promises.watch", () => { clearInterval(interval); ac.abort(); } - } catch (e) { + } catch (e: any) { err = e; clearInterval(interval); ac.abort(); } } - } catch (e) { + } catch (e: any) { if (!success) { throw err || e; } @@ -474,7 +474,7 @@ describe("fs.promises.watch", () => { const promise = (async () => { try { for await (const _ of watcher); - } catch (e) { + } catch (e: any) { expect(e.message).toBe("The operation was aborted."); } })(); @@ -491,7 +491,7 @@ describe("fs.promises.watch", () => { await (async () => { try { for await (const _ of watcher); - } catch (e) { + } catch (e: any) { expect(e.message).toBe("The operation was aborted."); } })(); @@ -511,7 +511,7 @@ describe("fs.promises.watch", () => { for await (const event of watcher) { return event.eventType; } - } catch (e) { + } catch (e: any) { expect("unreacheable").toBe(false); } finally { clearInterval(interval); diff --git a/test/js/third_party/socket.io/support/util.ts b/test/js/third_party/socket.io/support/util.ts index 597b40d652..b5f5155682 100644 --- a/test/js/third_party/socket.io/support/util.ts +++ b/test/js/third_party/socket.io/support/util.ts @@ -1,3 +1,4 @@ +// @ts-nocheck import type { Server } from "socket.io"; import request from "supertest"; diff --git a/test/js/web/html/FormData.test.ts b/test/js/web/html/FormData.test.ts index cbaf5aaa70..45b4f2f5a0 100644 --- a/test/js/web/html/FormData.test.ts +++ b/test/js/web/html/FormData.test.ts @@ -301,17 +301,18 @@ describe("FormData", () => { expect(await (body.get("foo") as Blob).text()).toBe("baz"); server.stop(true); }); - + type FetchReqArgs = [request: Request, init?: RequestInit]; + type FetchURLArgs = [url: string | URL | Request, init?: FetchRequestInit]; for (let useRequestConstructor of [true, false]) { describe(useRequestConstructor ? "Request constructor" : "fetch()", () => { - function send(args: Parameters) { + function send(args: FetchReqArgs | FetchURLArgs) { if (useRequestConstructor) { - return fetch(new Request(...args)); + return fetch(new Request(...(args as FetchReqArgs))); } else { - return fetch(...args); + return fetch(...(args as FetchURLArgs)); } } - for (let headers of [{}, undefined, { headers: { X: "Y" } }]) { + for (let headers of [{} as {}, undefined, { headers: { X: "Y" } }]) { describe("headers: " + Bun.inspect(headers).replaceAll(/([\n ])/gim, ""), () => { it("send on HTTP server with FormData & Blob (roundtrip)", async () => { let contentType = ""; @@ -330,11 +331,10 @@ describe("FormData", () => { form.append("bar", "baz"); // @ts-ignore - const reqBody = [ + const reqBody: FetchURLArgs = [ `http://${server.hostname}:${server.port}`, { body: form, - headers, method: "POST", }, @@ -364,7 +364,6 @@ describe("FormData", () => { form.append("foo", file); form.append("bar", "baz"); - // @ts-ignore const reqBody = [ `http://${server.hostname}:${server.port}`, { @@ -374,7 +373,7 @@ describe("FormData", () => { method: "POST", }, ]; - const res = await send(reqBody); + const res = await send(reqBody as FetchURLArgs); const body = await res.formData(); expect(await (body.get("foo") as Blob).text()).toBe(text); expect(contentType).toContain("multipart/form-data"); @@ -410,7 +409,7 @@ describe("FormData", () => { method: "POST", }, ]; - const res = await send(reqBody); + const res = await send(reqBody as FetchURLArgs); const body = await res.formData(); expect(contentType).toContain("multipart/form-data"); expect(body.get("foo")).toBe("boop"); diff --git a/test/js/web/html/URLSearchParams.test.ts b/test/js/web/html/URLSearchParams.test.ts index 120bb2321a..41c42c25d3 100644 --- a/test/js/web/html/URLSearchParams.test.ts +++ b/test/js/web/html/URLSearchParams.test.ts @@ -7,15 +7,20 @@ describe("URLSearchParams", () => { params.append("foo", "bar"); params.append("foo", "boop"); params.append("bar", "baz"); + // @ts-ignore expect(params.length).toBe(3); params.delete("foo"); + // @ts-ignore expect(params.length).toBe(1); params.append("foo", "bar"); + // @ts-ignore expect(params.length).toBe(2); params.delete("foo"); params.delete("foo"); + // @ts-ignore expect(params.length).toBe(1); params.delete("bar"); + // @ts-ignore expect(params.length).toBe(0); }); diff --git a/test/package.json b/test/package.json index 5529d3f20c..75f8d35e3a 100644 --- a/test/package.json +++ b/test/package.json @@ -8,6 +8,7 @@ "@swc/core": "1.3.38", "@types/react": "18.0.28", "@types/react-dom": "18.0.11", + "@types/supertest": "2.0.12", "bktree-fast": "0.0.7", "body-parser": "1.20.2", "dedent": "0.7.0", @@ -17,6 +18,9 @@ "jest-extended": "4.0.0", "lodash": "4.17.21", "nodemailer": "6.9.3", + "pg": "8.11.1", + "pg-connection-string": "2.6.1", + "postgres": "3.3.5", "prisma": "4.15.0", "socket.io": "4.7.1", "socket.io-client": "4.7.1", @@ -26,10 +30,7 @@ "undici": "5.20.0", "vitest": "0.32.2", "webpack": "5.88.0", - "webpack-cli": "4.7.2", - "pg": "8.11.1", - "postgres": "3.3.5", - "pg-connection-string": "2.6.1" + "webpack-cli": "4.7.2" }, "private": true, "scripts": { diff --git a/test/tsconfig.json b/test/tsconfig.json index 67f706cdf7..a5e77bf598 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -1,13 +1,8 @@ { - "include": [ - ".", - "../packages/bun-types/index.d.ts" - ], + "include": [".", "../packages/bun-types/index.d.ts"], "compilerOptions": { "noEmit": true, - "lib": [ - "ESNext" - ], + "lib": ["ESNext"], "module": "ESNext", "target": "ESNext", "moduleResolution": "bundler", @@ -23,25 +18,14 @@ "resolveJsonModule": true, "baseUrl": ".", "paths": { - "harness": [ - "harness.ts" - ], - "mkfifo": [ - "mkfifo.ts" - ], - "node-harness": [ - "js/node/harness.ts" - ], - "deno:harness": [ - "js/deno/harness.ts" - ], - "foo/bar": [ - "js/bun/resolve/baz.js" - ], - "@faasjs/*": [ - "js/bun/resolve/*.js" - ] + "harness": ["harness.ts"], + "mkfifo": ["mkfifo.ts"], + "node-harness": ["js/node/harness.ts"], + "deno:harness": ["js/deno/harness.ts"], + "foo/bar": ["js/bun/resolve/baz.js"], + "@faasjs/*": ["js/bun/resolve/*.js"] } }, + "exclude": ["bundler/fixtures", "snapshots", "js/deno"] } diff --git a/tsconfig.json b/tsconfig.json index 0ee640ea09..d8be0da039 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,12 +6,10 @@ // "skipLibCheck": true, "allowJs": true }, - "include": [ - ".", - "packages/bun-types/index.d.ts" - ], + "include": [".", "packages/bun-types/index.d.ts"], "exclude": [ "src/test", + // "src/js/builtins", "packages", "bench", "examples/*/*", @@ -21,5 +19,6 @@ "src/bun.js/WebKit", "src/api/demo", "node_modules" - ] + ], + "files": ["src/js/builtins/builtins.d.ts"] }