Skip to content

Commit

Permalink
refactor: replaced Promise.withResolvers polyfill with internal `De…
Browse files Browse the repository at this point in the history
…tachedPromise`
  • Loading branch information
wyattjoh committed Oct 17, 2023
1 parent 5e474a3 commit adb06d8
Show file tree
Hide file tree
Showing 12 changed files with 35 additions and 63 deletions.
1 change: 0 additions & 1 deletion packages/next/src/build/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import '../server/require-hook'
import '../server/node-polyfill-fetch'
import '../server/node-polyfill-crypto'
import '../server/node-environment'
import '../lib/polyfill-promise-with-resolvers'

import { green, yellow, red, cyan, bold, underline } from '../lib/picocolors'
import getGzipSize from 'next/dist/compiled/gzip-size'
Expand Down
1 change: 0 additions & 1 deletion packages/next/src/export/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import type {
import '../server/node-polyfill-fetch'
import '../server/node-polyfill-web-streams'
import '../server/node-environment'
import '../lib/polyfill-promise-with-resolvers'

process.env.NEXT_IS_EXPORT_WORKER = 'true'

Expand Down
7 changes: 2 additions & 5 deletions packages/next/src/lib/batcher.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
// This takes advantage of `Promise.withResolvers` which is polyfilled in
// this imported module.
import './polyfill-promise-with-resolvers'

import type { SchedulerFn } from '../server/lib/schedule-on-next-tick'
import { DetachedPromise } from './detached-promise'

type CacheKeyFn<K, C extends string | number | null> = (
key: K
Expand Down Expand Up @@ -72,7 +69,7 @@ export class Batcher<K, V, C extends string | number | null> {
const pending = this.pending.get(cacheKey)
if (pending) return pending

const { promise, resolve, reject } = Promise.withResolvers<V>()
const { promise, resolve, reject } = new DetachedPromise<V>()
this.pending.set(cacheKey, promise)

this.schedulerFn(async () => {
Expand Down
27 changes: 27 additions & 0 deletions packages/next/src/lib/detached-promise.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* A `Promise.withResolvers` implementation that exposes the `resolve` and
* `reject` functions on a `Promise`.
*
* @see https://tc39.es/proposal-promise-with-resolvers/
*/
export class DetachedPromise<T = any> {
public readonly resolve: (value: T | PromiseLike<T>) => void
public readonly reject: (reason: any) => void
public readonly promise: Promise<T>

constructor() {
let resolve: (value: T | PromiseLike<T>) => void
let reject: (reason: any) => void

// Create the promise and assign the resolvers to the object.
this.promise = new Promise<T>((res, rej) => {
resolve = res
reject = rej
})

// We know that resolvers is defined because the Promise constructor runs
// synchronously.
this.resolve = resolve!
this.reject = reject!
}
}
31 changes: 0 additions & 31 deletions packages/next/src/lib/polyfill-promise-with-resolvers.ts

This file was deleted.

3 changes: 2 additions & 1 deletion packages/next/src/server/dev/next-dev-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import { DefaultFileReader } from '../future/route-matcher-providers/dev/helpers
import { NextBuildContext } from '../../build/build-context'
import LRUCache from 'next/dist/compiled/lru-cache'
import { getMiddlewareRouteMatcher } from '../../shared/lib/router/utils/middleware-route-matcher'
import { DetachedPromise } from '../../lib/detached-promise'

// Load ReactDevOverlay only when needed
let ReactDevOverlayImpl: FunctionComponent
Expand Down Expand Up @@ -89,7 +90,7 @@ export default class DevServer extends Server {
* The promise that resolves when the server is ready. When this is unset
* the server is ready.
*/
private ready? = Promise.withResolvers<void>()
private ready? = new DetachedPromise<void>()
protected sortedRoutes?: string[]
private pagesDir?: string
private appDir?: string
Expand Down
1 change: 0 additions & 1 deletion packages/next/src/server/dev/static-paths-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type { NextConfigComplete } from '../config-shared'
import '../require-hook'
import '../node-polyfill-fetch'
import '../node-environment'
import '../../lib/polyfill-promise-with-resolvers'

import {
buildAppStaticPaths,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
// This takes advantage of `Promise.withResolvers` which is polyfilled in
// this imported module.
import '../../../lib/polyfill-promise-with-resolvers'

import { isDynamicRoute } from '../../../shared/lib/router/utils'
import type { RouteKind } from '../route-kind'
import type { RouteMatch } from '../route-matches/route-match'
Expand All @@ -12,6 +8,7 @@ import type { MatchOptions, RouteMatcherManager } from './route-matcher-manager'
import { getSortedRoutes } from '../../../shared/lib/router/utils'
import { LocaleRouteMatcher } from '../route-matchers/locale-route-matcher'
import { ensureLeadingSlash } from '../../../shared/lib/page-path/ensure-leading-slash'
import { DetachedPromise } from '../../../lib/detached-promise'

interface RouteMatchers {
static: ReadonlyArray<RouteMatcher>
Expand Down Expand Up @@ -46,7 +43,7 @@ export class DefaultRouteMatcherManager implements RouteMatcherManager {

private previousMatchers: ReadonlyArray<RouteMatcher> = []
public async reload() {
const { promise, resolve, reject } = Promise.withResolvers<void>()
const { promise, resolve, reject } = new DetachedPromise<void>()
this.waitTillReadyPromise = promise

// Grab the compilation ID for this run, we'll verify it at the end to
Expand Down
1 change: 0 additions & 1 deletion packages/next/src/server/lib/router-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import type { NextUrlWithParsedQuery } from '../request-meta'
import '../node-polyfill-fetch'
import '../node-environment'
import '../require-hook'
import '../../lib/polyfill-promise-with-resolvers'

import url from 'url'
import path from 'path'
Expand Down
1 change: 0 additions & 1 deletion packages/next/src/server/next-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import './node-polyfill-fetch'
import './node-polyfill-form'
import './node-polyfill-web-streams'
import './node-polyfill-crypto'
import '../lib/polyfill-promise-with-resolvers'

import type { TLSSocket } from 'tls'
import type { CacheFs } from '../shared/lib/utils'
Expand Down
3 changes: 2 additions & 1 deletion packages/next/src/server/response-cache/web.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { DetachedPromise } from '../../lib/detached-promise'
import type { ResponseCacheEntry, ResponseGenerator } from './types'

/**
Expand Down Expand Up @@ -45,7 +46,7 @@ export default class WebResponseCache {
promise,
resolve: resolver,
reject: rejecter,
} = Promise.withResolvers<ResponseCacheEntry | null>()
} = new DetachedPromise<ResponseCacheEntry | null>()
if (pendingResponseKey) {
this.pendingResponses.set(pendingResponseKey, promise)
}
Expand Down
15 changes: 0 additions & 15 deletions packages/next/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,21 +318,6 @@ declare global {
randomUUID(): string
}

// TODO: remove this polyfill when it is adopted into the spec.
interface PromiseConstructor {
/**
* Creates a new promise with exposed resolvers to resolve/reject. This will
* be adopted into the spec as `Promise.withResolvers`.
*
* @see https://tc39.es/proposal-promise-with-resolvers/
*/
withResolvers<T>(): {
promise: Promise<T>
resolve: (value: T | PromiseLike<T>) => void
reject: (reason?: unknown) => void
}
}

var __NEXT_HTTP_AGENT_OPTIONS: { keepAlive?: boolean } | undefined
var __NEXT_UNDICI_AGENT_SET: boolean
var __NEXT_HTTP_AGENT: HttpAgent
Expand Down

0 comments on commit adb06d8

Please sign in to comment.