From 46a8215092c3e0cd56703b6ceb3c5a939d53c35c Mon Sep 17 00:00:00 2001 From: Jack Hanford Date: Thu, 11 Nov 2021 11:21:47 -0800 Subject: consolidate empty files / references to one empty.tsx --- packages/bun-framework-next/server-polyfills.tsx | 2 ++ 1 file changed, 2 insertions(+) (limited to 'packages/bun-framework-next/server-polyfills.tsx') diff --git a/packages/bun-framework-next/server-polyfills.tsx b/packages/bun-framework-next/server-polyfills.tsx index 474ee6ec9..d34c08fc5 100644 --- a/packages/bun-framework-next/server-polyfills.tsx +++ b/packages/bun-framework-next/server-polyfills.tsx @@ -13,6 +13,7 @@ class URL { } } var onlyChildPolyfill = React.Children.only; + React.Children.only = function (children) { if (children && typeof children === "object" && children.length == 1) { return onlyChildPolyfill(children[0]); @@ -20,6 +21,7 @@ React.Children.only = function (children) { return onlyChildPolyfill(children); }; + globalThis.URL = URL; import { TextEncoder, TextDecoder } from "./text-encoder-polyfill"; -- cgit v1.2.3 From 6ee673095cbddc97a56bae7a512a5271d4a977a2 Mon Sep 17 00:00:00 2001 From: Jack Hanford Date: Mon, 15 Nov 2021 15:45:37 -0800 Subject: continue fixing typescript errors --- packages/bun-framework-next/client.development.tsx | 59 +++++++++++++--------- .../bun-framework-next/fallback.development.tsx | 3 +- packages/bun-framework-next/package.json | 3 ++ packages/bun-framework-next/page-loader.ts | 16 ++++-- packages/bun-framework-next/server-polyfills.tsx | 12 ++++- packages/bun-framework-next/server.development.tsx | 1 + pnpm-lock.yaml | 31 ++++++++++++ 7 files changed, 93 insertions(+), 32 deletions(-) (limited to 'packages/bun-framework-next/server-polyfills.tsx') diff --git a/packages/bun-framework-next/client.development.tsx b/packages/bun-framework-next/client.development.tsx index f3d8d39e5..bf03af289 100644 --- a/packages/bun-framework-next/client.development.tsx +++ b/packages/bun-framework-next/client.development.tsx @@ -1,10 +1,20 @@ +/// + globalThis.global = globalThis; globalThis.Bun_disableCSSImports = true; import * as React from "react"; + var onlyChildPolyfill = React.Children.only; -React.Children.only = function (children) { - if (children && typeof children === "object" && children.length == 1) { + +React.Children.only = function only( + children: React.ReactNode | React.ReactNode[] +) { + if ( + children && + typeof children === "object" && + (children as any).length == 1 + ) { return onlyChildPolyfill(children[0]); } @@ -23,9 +33,7 @@ import Router, { PrivateRouteInfo, } from "next/dist/shared/lib/router/router"; -const App = NextApp; - -import * as NextRouteLoader from "next/dist/client/route-loader"; +import NextRouteLoader from "next/dist/client/route-loader"; import { isDynamicRoute } from "next/dist/shared/lib/router/utils/is-dynamic"; import { urlQueryToSearchParams, @@ -41,8 +49,11 @@ import { createRouter, makePublicRouterInstance, } from "next/dist/client/router"; + export const emitter: MittEmitter = mitt(); +const App = NextApp; + declare global { interface Window { /* test fns */ @@ -102,7 +113,8 @@ type RenderRouteInfo = PrivateRouteInfo & { const nextDataTag = document.getElementById("__NEXT_DATA__"); -const data: typeof window["__NEXT_DATA__"] = nextDataTag +// pages is added at runtime and doesn't exist in Next types +const data: NEXT_DATA & { pages: Record } = nextDataTag ? JSON.parse(document.getElementById("__NEXT_DATA__")!.textContent!) : nextDataFromBunData(); @@ -116,12 +128,14 @@ const { buildId, assetPrefix, runtimeConfig, + // Todo, revist this constant when supporting dynamic() dynamicIds, isFallback, locale, locales, domainLocales, isPreview, + pages, } = data; const prefix: string = assetPrefix || ""; @@ -138,24 +152,19 @@ if (hasBasePath(asPath)) { asPath = delBasePath(asPath); } -export const pageLoader: PageLoader = new PageLoader( - buildId, - prefix, - data.pages -); +export const pageLoader: PageLoader = new PageLoader(buildId, prefix, pages); const headManager: { mountedInstances: Set; updateHead: (head: JSX.Element[]) => void; } = initHeadManager(); -const appElement: HTMLElement | null = document.getElementById("__next"); export let router: Router; -let CachedApp: AppComponent = App, - onPerfEntry: (metric: any) => void; -export default function boot(EntryPointNamespace, loader) { - _boot(EntryPointNamespace).then(() => {}, false); +let CachedApp: AppComponent = null; + +export default function boot(EntryPointNamespace) { + _boot(EntryPointNamespace, false); } class Container extends React.Component<{ @@ -274,7 +283,7 @@ let reactRoot: any = null; const USE_REACT_18 = "hydrateRoot" in ReactDOM; export async function _boot(EntryPointNamespace, isError) { - NextRouteLoader.default.getClientBuildManifest = () => Promise.resolve({}); + NextRouteLoader.getClientBuildManifest = () => Promise.resolve({}); const PageComponent = EntryPointNamespace.default; @@ -293,6 +302,7 @@ export async function _boot(EntryPointNamespace, isError) { if (appSrc) { const AppModule = await import(appSrc); + console.assert( AppModule.default, appSrc + " must have a default export'd React component" @@ -332,7 +342,9 @@ export async function _boot(EntryPointNamespace, isError) { }); globalThis.next.router = router; + const domEl = document.querySelector("#__next"); + const reactEl = ( + ); @@ -381,18 +393,15 @@ export function render(props) { } export function renderError(e) { - const reactEl = ( - - UH OH!!!!} pageProps={data.props}> - - ); + // TODO verify this works + const reactEl = {null}; if (USE_REACT_18) { if (!reactRoot) { const domEl = document.querySelector("#__next"); // Unlike with createRoot, you don't need a separate root.render() call here - reactRoot = ReactDOM.createRoot(domEl, reactEl); + reactRoot = ReactDOM.hydrateRoot(domEl, reactEl); } else { reactRoot.render(reactEl); } diff --git a/packages/bun-framework-next/fallback.development.tsx b/packages/bun-framework-next/fallback.development.tsx index 54d31d5f5..460b5e165 100644 --- a/packages/bun-framework-next/fallback.development.tsx +++ b/packages/bun-framework-next/fallback.development.tsx @@ -1,5 +1,5 @@ import { insertStyleSheet } from "./page-loader"; -import type { FallbackMessageContainer } from "../../../src/api/schema"; +import type { FallbackMessageContainer } from "../../src/api/schema"; var once = false; function insertNextHeadCount() { @@ -65,6 +65,7 @@ function renderFallback({ router }: FallbackMessageContainer) { } export default function render(props: FallbackMessageContainer) { + // @ts-expect-error bun:error.js is real return import("/bun:error.js").then(({ renderFallbackError }) => { return renderFallback(props).then( () => { diff --git a/packages/bun-framework-next/package.json b/packages/bun-framework-next/package.json index b07199615..ea459412a 100644 --- a/packages/bun-framework-next/package.json +++ b/packages/bun-framework-next/package.json @@ -11,12 +11,15 @@ "author": "", "license": "MIT", "dependencies": { + "bun-framework-next": "^12.0.4", "react-is": "^17.0.2" }, "peerDependencies": { "next": "^12.0.0" }, "devDependencies": { + "@types/react": "^17.0.34", + "@types/react-dom": "^17.0.11", "next": "^12.0.0", "react-refresh": "^0.10.0", "typescript": "^4.4.4" diff --git a/packages/bun-framework-next/page-loader.ts b/packages/bun-framework-next/page-loader.ts index 2a8b402ad..3b31387d8 100644 --- a/packages/bun-framework-next/page-loader.ts +++ b/packages/bun-framework-next/page-loader.ts @@ -1,4 +1,6 @@ -import NextPageLoader from "next/dist/client/page-loader"; +import NextPageLoader, { + GoodPageCache as NextGoodPageCache, +} from "next/dist/client/page-loader"; import getAssetPathFromRoute from "next/dist/shared/lib/router/utils/get-asset-path-from-route"; export function insertStyleSheet(url: string) { @@ -10,8 +12,9 @@ export function insertStyleSheet(url: string) { const link = document.createElement("link"); link.rel = "stylesheet"; - link.onload = () => resolve(); - link.onerror = () => reject(); + // marking this resolve as void seems to break other things + link.onload = resolve; + link.onerror = reject; link.href = url; @@ -19,6 +22,11 @@ export function insertStyleSheet(url: string) { }); } +interface GoodPageCache extends NextGoodPageCache { + __N_SSG: boolean; + __N_SSP: boolean; +} + export default class PageLoader extends NextPageLoader { constructor(_, __, pages) { super(_, __); @@ -70,7 +78,7 @@ export default class PageLoader extends NextPageLoader { }; prefetch() { - return Promise.resolve({}); + return Promise.resolve(); } async loadPage(route: string): Promise { diff --git a/packages/bun-framework-next/server-polyfills.tsx b/packages/bun-framework-next/server-polyfills.tsx index d34c08fc5..8942154b7 100644 --- a/packages/bun-framework-next/server-polyfills.tsx +++ b/packages/bun-framework-next/server-polyfills.tsx @@ -7,15 +7,23 @@ globalThis.Buffer = Buffer; import * as React from "react"; class URL { - constructor(base, source) { + pathname: string; + href: string; + + constructor(base: string, source: string) { this.pathname = source; this.href = base + source; } } + var onlyChildPolyfill = React.Children.only; React.Children.only = function (children) { - if (children && typeof children === "object" && children.length == 1) { + if ( + children && + typeof children === "object" && + (children as any).length == 1 + ) { return onlyChildPolyfill(children[0]); } diff --git a/packages/bun-framework-next/server.development.tsx b/packages/bun-framework-next/server.development.tsx index 96ba55812..fd2a7b620 100644 --- a/packages/bun-framework-next/server.development.tsx +++ b/packages/bun-framework-next/server.development.tsx @@ -1,6 +1,7 @@ import nextPackage from "next/package.json"; import "./server-polyfills"; import { render } from "./renderDocument"; +import { ResolveError } from "../../src/runtime/errors"; const { version } = nextPackage; if ( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b96e023bc..4fa5982b1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,6 +43,9 @@ importers: packages/bun-framework-next: specifiers: + '@types/react': ^17.0.34 + '@types/react-dom': ^17.0.11 + bun-framework-next: ^12.0.4 next: ^12.0.0 react-is: ^17.0.2 react-refresh: ^0.10.0 @@ -50,6 +53,8 @@ importers: dependencies: react-is: 17.0.2 devDependencies: + '@types/react': 17.0.34 + '@types/react-dom': 17.0.11 next: 12.0.3_react-dom@17.0.2+react@17.0.2 react-refresh: 0.10.0 typescript: 4.4.4 @@ -279,12 +284,34 @@ packages: /@types/node/16.11.4: resolution: {integrity: sha512-TMgXmy0v2xWyuCSCJM6NCna2snndD8yvQF67J29ipdzMcsPa9u+o0tjF5+EQNdhcuZplYuouYqpc4zcd5I6amQ==} + /@types/prop-types/15.7.4: + resolution: {integrity: sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==} + dev: true + /@types/puppeteer/5.4.4: resolution: {integrity: sha512-3Nau+qi69CN55VwZb0ATtdUAlYlqOOQ3OfQfq0Hqgc4JMFXiQT/XInlwQ9g6LbicDslE6loIFsXFklGh5XmI6Q==} dependencies: '@types/node': 16.11.4 dev: true + /@types/react-dom/17.0.11: + resolution: {integrity: sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==} + dependencies: + '@types/react': 17.0.34 + dev: true + + /@types/react/17.0.34: + resolution: {integrity: sha512-46FEGrMjc2+8XhHXILr+3+/sTe3OfzSPU9YGKILLrUYbQ1CLQC9Daqo1KzENGXAWwrFwiY0l4ZbF20gRvgpWTg==} + dependencies: + '@types/prop-types': 15.7.4 + '@types/scheduler': 0.16.2 + csstype: 3.0.10 + dev: true + + /@types/scheduler/0.16.2: + resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} + dev: true + /@types/yauzl/2.9.2: resolution: {integrity: sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==} requiresBuild: true @@ -749,6 +776,10 @@ packages: postcss: 8.2.15 dev: true + /csstype/3.0.10: + resolution: {integrity: sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==} + dev: true + /data-uri-to-buffer/3.0.1: resolution: {integrity: sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==} engines: {node: '>= 6'} -- cgit v1.2.3 From 7f62169b5e50a6c01d261915a827bfcea98d522d Mon Sep 17 00:00:00 2001 From: Jack Hanford Date: Tue, 16 Nov 2021 10:22:22 -0800 Subject: add prettier to root --- package.json | 4 +- packages/bun-framework-next/package.json | 4 +- packages/bun-framework-next/server-polyfills.tsx | 14 +- .../bun-framework-next/text-encoder-polyfill.js | 302 --------------------- pnpm-lock.yaml | 6 +- 5 files changed, 10 insertions(+), 320 deletions(-) delete mode 100644 packages/bun-framework-next/text-encoder-polyfill.js (limited to 'packages/bun-framework-next/server-polyfills.tsx') diff --git a/package.json b/package.json index 563000fa7..8955f7ef2 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,6 @@ "highlight.js": "^11.3.1", "moment": "^2.29.1", "peechy": "0.4.20", - "prettier": "latest", "puppeteer": "^10.2.0", "react": "^17.0.2", "react-dom": "^17.0.2" @@ -15,7 +14,8 @@ }, "devDependencies": { "@types/node": "^16.9.2", - "@types/puppeteer": "^5.4.4" + "@types/puppeteer": "^5.4.4", + "prettier": "^2.4.1" }, "version": "0.0.0" } diff --git a/packages/bun-framework-next/package.json b/packages/bun-framework-next/package.json index 953ca29c3..d715a8ba4 100644 --- a/packages/bun-framework-next/package.json +++ b/packages/bun-framework-next/package.json @@ -11,7 +11,9 @@ "author": "", "license": "MIT", "dependencies": { - "react-is": "^17.0.2" + "fast-text-encoding": "^1.0.3", + "react-is": "^17.0.2", + "url-polyfill": "^1.1.12" }, "peerDependencies": { "next": "^12.0.0" diff --git a/packages/bun-framework-next/server-polyfills.tsx b/packages/bun-framework-next/server-polyfills.tsx index 8942154b7..887621978 100644 --- a/packages/bun-framework-next/server-polyfills.tsx +++ b/packages/bun-framework-next/server-polyfills.tsx @@ -1,21 +1,13 @@ globalThis.global = globalThis; import { Buffer } from "buffer"; +import { URL } from "url-polyfill"; +import { TextEncoder, TextDecoder } from "fast-text-encoding"; globalThis.Buffer = Buffer; import * as React from "react"; -class URL { - pathname: string; - href: string; - - constructor(base: string, source: string) { - this.pathname = source; - this.href = base + source; - } -} - var onlyChildPolyfill = React.Children.only; React.Children.only = function (children) { @@ -32,7 +24,5 @@ React.Children.only = function (children) { globalThis.URL = URL; -import { TextEncoder, TextDecoder } from "./text-encoder-polyfill"; - globalThis.TextEncoder ||= TextEncoder; globalThis.TextDecoder ||= TextDecoder; diff --git a/packages/bun-framework-next/text-encoder-polyfill.js b/packages/bun-framework-next/text-encoder-polyfill.js deleted file mode 100644 index 3dd95009f..000000000 --- a/packages/bun-framework-next/text-encoder-polyfill.js +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright 2017 Sam Thorogood. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -/** - * @fileoverview Polyfill for TextEncoder and TextDecoder. - * - * You probably want `text.min.js`, and not this file directly. - */ - -// used for FastTextDecoder -const validUtfLabels = ["utf-8", "utf8", "unicode-1-1-utf-8"]; - -/** - * @constructor - */ -function FastTextEncoder() { - // This does not accept an encoding, and always uses UTF-8: - // https://www.w3.org/TR/encoding/#dom-textencoder -} - -Object.defineProperty(FastTextEncoder.prototype, "encoding", { - value: "utf-8", -}); - -/** - * @param {string} string - * @param {{stream: boolean}=} options - * @return {!Uint8Array} - */ -FastTextEncoder.prototype["encode"] = function ( - string, - options = { stream: false } -) { - if (options.stream) { - throw new Error(`Failed to encode: the 'stream' option is unsupported.`); - } - - let pos = 0; - const len = string.length; - - let at = 0; // output position - let tlen = Math.max(32, len + (len >>> 1) + 7); // 1.5x size - let target = new Uint8Array((tlen >>> 3) << 3); // ... but at 8 byte offset - - while (pos < len) { - let value = string.charCodeAt(pos++); - if (value >= 0xd800 && value <= 0xdbff) { - // high surrogate - if (pos < len) { - const extra = string.charCodeAt(pos); - if ((extra & 0xfc00) === 0xdc00) { - ++pos; - value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; - } - } - if (value >= 0xd800 && value <= 0xdbff) { - continue; // drop lone surrogate - } - } - - // expand the buffer if we couldn't write 4 bytes - if (at + 4 > target.length) { - tlen += 8; // minimum extra - tlen *= 1.0 + (pos / string.length) * 2; // take 2x the remaining - tlen = (tlen >>> 3) << 3; // 8 byte offset - - const update = new Uint8Array(tlen); - update.set(target); - target = update; - } - - if ((value & 0xffffff80) === 0) { - // 1-byte - target[at++] = value; // ASCII - continue; - } else if ((value & 0xfffff800) === 0) { - // 2-byte - target[at++] = ((value >>> 6) & 0x1f) | 0xc0; - } else if ((value & 0xffff0000) === 0) { - // 3-byte - target[at++] = ((value >>> 12) & 0x0f) | 0xe0; - target[at++] = ((value >>> 6) & 0x3f) | 0x80; - } else if ((value & 0xffe00000) === 0) { - // 4-byte - target[at++] = ((value >>> 18) & 0x07) | 0xf0; - target[at++] = ((value >>> 12) & 0x3f) | 0x80; - target[at++] = ((value >>> 6) & 0x3f) | 0x80; - } else { - continue; // out of range - } - - target[at++] = (value & 0x3f) | 0x80; - } - - // Use subarray if slice isn't supported (IE11). This will use more memory - // because the original array still exists. - return target.slice ? target.slice(0, at) : target.subarray(0, at); -}; - -/** - * @constructor - * @param {string=} utfLabel - * @param {{fatal: boolean}=} options - */ -function FastTextDecoder(utfLabel = "utf-8", options = { fatal: false }) { - if (validUtfLabels.indexOf(utfLabel.toLowerCase()) === -1) { - throw new RangeError( - `Failed to construct 'TextDecoder': The encoding label provided ('${utfLabel}') is invalid.` - ); - } - if (options.fatal) { - throw new Error( - `Failed to construct 'TextDecoder': the 'fatal' option is unsupported.` - ); - } -} - -Object.defineProperty(FastTextDecoder.prototype, "encoding", { - value: "utf-8", -}); - -Object.defineProperty(FastTextDecoder.prototype, "fatal", { value: false }); - -Object.defineProperty(FastTextDecoder.prototype, "ignoreBOM", { - value: false, -}); - -/** - * @param {!Uint8Array} bytes - * @return {string} - */ -function decodeBuffer(bytes) { - return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString( - "utf-8" - ); -} - -/** - * @param {!Uint8Array} bytes - * @return {string} - */ -function decodeSyncXHR(bytes) { - const b = new Blob([bytes], { type: "text/plain;charset=UTF-8" }); - const u = URL.createObjectURL(b); - - // This hack will fail in non-Edgium Edge because sync XHRs are disabled (and - // possibly in other places), so ensure there's a fallback call. - try { - const x = new XMLHttpRequest(); - x.open("GET", u, false); - x.send(); - return x.responseText; - } catch (e) { - return decodeFallback(bytes); - } finally { - URL.revokeObjectURL(u); - } -} - -/** - * @param {!Uint8Array} bytes - * @return {string} - */ -function decodeFallback(bytes) { - let inputIndex = 0; - - // Create a working buffer for UTF-16 code points, but don't generate one - // which is too large for small input sizes. UTF-8 to UCS-16 conversion is - // going to be at most 1:1, if all code points are ASCII. The other extreme - // is 4-byte UTF-8, which results in two UCS-16 points, but this is still 50% - // fewer entries in the output. - const pendingSize = Math.min(256 * 256, bytes.length + 1); - const pending = new Uint16Array(pendingSize); - const chunks = []; - let pendingIndex = 0; - - for (;;) { - const more = inputIndex < bytes.length; - - // If there's no more data or there'd be no room for two UTF-16 values, - // create a chunk. This isn't done at the end by simply slicing the data - // into equal sized chunks as we might hit a surrogate pair. - if (!more || pendingIndex >= pendingSize - 1) { - // nb. .apply and friends are *really slow*. Low-hanging fruit is to - // expand this to literally pass pending[0], pending[1], ... etc, but - // the output code expands pretty fast in this case. - chunks.push( - String.fromCharCode.apply(null, pending.subarray(0, pendingIndex)) - ); - - if (!more) { - return chunks.join(""); - } - - // Move the buffer forward and create another chunk. - bytes = bytes.subarray(inputIndex); - inputIndex = 0; - pendingIndex = 0; - } - - // The native TextDecoder will generate "REPLACEMENT CHARACTER" where the - // input data is invalid. Here, we blindly parse the data even if it's - // wrong: e.g., if a 3-byte sequence doesn't have two valid continuations. - - const byte1 = bytes[inputIndex++]; - if ((byte1 & 0x80) === 0) { - // 1-byte or null - pending[pendingIndex++] = byte1; - } else if ((byte1 & 0xe0) === 0xc0) { - // 2-byte - const byte2 = bytes[inputIndex++] & 0x3f; - pending[pendingIndex++] = ((byte1 & 0x1f) << 6) | byte2; - } else if ((byte1 & 0xf0) === 0xe0) { - // 3-byte - const byte2 = bytes[inputIndex++] & 0x3f; - const byte3 = bytes[inputIndex++] & 0x3f; - pending[pendingIndex++] = ((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3; - } else if ((byte1 & 0xf8) === 0xf0) { - // 4-byte - const byte2 = bytes[inputIndex++] & 0x3f; - const byte3 = bytes[inputIndex++] & 0x3f; - const byte4 = bytes[inputIndex++] & 0x3f; - - // this can be > 0xffff, so possibly generate surrogates - let codepoint = - ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4; - if (codepoint > 0xffff) { - // codepoint &= ~0x10000; - codepoint -= 0x10000; - pending[pendingIndex++] = ((codepoint >>> 10) & 0x3ff) | 0xd800; - codepoint = 0xdc00 | (codepoint & 0x3ff); - } - pending[pendingIndex++] = codepoint; - } else { - // invalid initial byte - } - } -} - -// Decoding a string is pretty slow, but use alternative options where possible. -let decodeImpl = decodeFallback; -if (typeof Buffer === "function" && Buffer.from) { - // Buffer.from was added in Node v5.10.0 (2015-11-17). - decodeImpl = decodeBuffer; -} else if ( - typeof Blob === "function" && - typeof URL === "function" && - typeof URL.createObjectURL === "function" -) { - // Blob and URL.createObjectURL are available from IE10, Safari 6, Chrome 19 - // (all released in 2012), Firefox 19 (2013), ... - decodeImpl = decodeSyncXHR; -} - -/** - * @param {(!ArrayBuffer|!ArrayBufferView)} buffer - * @param {{stream: boolean}=} options - * @return {string} - */ -FastTextDecoder.prototype["decode"] = function ( - buffer, - options = { stream: false } -) { - if (options["stream"]) { - throw new Error(`Failed to decode: the 'stream' option is unsupported.`); - } - - let bytes; - - if (buffer instanceof Uint8Array) { - // Accept Uint8Array instances as-is. - bytes = buffer; - } else if (buffer.buffer instanceof ArrayBuffer) { - // Look for ArrayBufferView, which isn't a real type, but basically - // represents all the valid TypedArray types plus DataView. They all have - // ".buffer" as an instance of ArrayBuffer. - bytes = new Uint8Array(buffer.buffer); - } else { - // The only other valid argument here is that "buffer" is an ArrayBuffer. - // We also try to convert anything else passed to a Uint8Array, as this - // catches anything that's array-like. Native code would throw here. - bytes = new Uint8Array(buffer); - } - - return decodeImpl(/** @type {!Uint8Array} */ (bytes)); -}; - -export { FastTextEncoder as TextEncoder }; -export { FastTextDecoder as TextDecoder }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5a5574998..9fe0236df 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: highlight.js: ^11.3.1 moment: ^2.29.1 peechy: 0.4.20 - prettier: latest + prettier: ^2.4.1 puppeteer: ^10.2.0 react: ^17.0.2 react-dom: ^17.0.2 @@ -19,13 +19,13 @@ importers: highlight.js: 11.3.1 moment: 2.29.1 peechy: 0.4.20 - prettier: 2.4.1 puppeteer: 10.4.0 react: 17.0.2 react-dom: 17.0.2_react@17.0.2 devDependencies: '@types/node': 16.11.4 '@types/puppeteer': 5.4.4 + prettier: 2.4.1 packages/bun-error: specifiers: @@ -1835,7 +1835,7 @@ packages: resolution: {integrity: sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==} engines: {node: '>=10.13.0'} hasBin: true - dev: false + dev: true /pretty-format/3.8.0: resolution: {integrity: sha1-v77VbV6ad2ZF9LH/eqGjrE+jw4U=} -- cgit v1.2.3 From c06e34c687187a528d0da39eddec71323b56e77a Mon Sep 17 00:00:00 2001 From: Jack Hanford Date: Mon, 22 Nov 2021 10:23:14 -0800 Subject: misc --- packages/bun-framework-next/renderDocument.tsx | 24 +++++++++--------------- packages/bun-framework-next/server-polyfills.tsx | 7 ++----- 2 files changed, 11 insertions(+), 20 deletions(-) (limited to 'packages/bun-framework-next/server-polyfills.tsx') diff --git a/packages/bun-framework-next/renderDocument.tsx b/packages/bun-framework-next/renderDocument.tsx index 5b4cab0ce..661bebdc0 100644 --- a/packages/bun-framework-next/renderDocument.tsx +++ b/packages/bun-framework-next/renderDocument.tsx @@ -1,4 +1,4 @@ -import * as App from "next/app"; +import App from "next/app"; import { AmpStateContext } from "next/dist/shared/lib/amp-context"; import { HeadManagerContext } from "next/dist/shared/lib/head-manager-context"; import Loadable from "next/dist/shared/lib/loadable"; @@ -23,7 +23,9 @@ import * as NextDocument from "next/document"; import * as ReactDOMServer from "react-dom/server.browser"; import * as React from "react"; import * as ReactIs from "react-is"; -import { BODY_RENDER_TARGET } from "next/constants"; + +// This constant was removed from Next, Is it doing anything? +const BODY_RENDER_TARGET = "__NEXT_BODY_RENDER_TARGET__"; const dev = process.env.NODE_ENV === "development"; @@ -362,11 +364,8 @@ export async function render({ pages["/_app"] = []; } - const AppComponent = AppComponent_ || App.default; - const Document = - (DocumentNamespace && DocumentNamespace.default) || NextDocument.default; - // Document.Html.prototype.getScripts = getScripts; - // } + const AppComponent = AppComponent_ || App; + const Document = (DocumentNamespace as any)?.default || NextDocument.default; const callMiddleware = async (method: string, args: any[], props = false) => { let results: any = props ? {} : []; @@ -422,7 +421,7 @@ export async function render({ delete query.__nextLocale; delete query.__nextDefaultLocale; - const isSSG = !!getStaticProps; + // const isSSG = !!getStaticProps; const defaultAppGetInitialProps = App.getInitialProps === (App as any).origGetInitialProps; @@ -518,7 +517,7 @@ export async function render({ ); }, defaultGetInitialProps: async ( - docCtx: DocumentContext + docCtx: NextDocument.DocumentContext ): Promise => { const enhanceApp = (AppComp: any) => { return (props: any) => ; @@ -696,13 +695,7 @@ export async function render({ const renderOpts = { params: route.params, }; - // renderOpts.params = _params || params; - // parsedUrl.pathname = denormalizePagePath(parsedUrl.pathname!); - // renderOpts.resolvedUrl = formatUrl({ - // ...parsedUrl, - // query: origQuery, - // }); const docComponentsRendered: DocumentProps["docComponentsRendered"] = {}; let html = renderDocument(Document, { @@ -752,6 +745,7 @@ export async function render({ nextExport: nextExport, useMaybeDeferContent, }); + // __NEXT_BODY_RENDER_TARGET__ const bodyRenderIdx = html.indexOf(BODY_RENDER_TARGET); html = html.substring(0, bodyRenderIdx) + diff --git a/packages/bun-framework-next/server-polyfills.tsx b/packages/bun-framework-next/server-polyfills.tsx index 887621978..57960e4fa 100644 --- a/packages/bun-framework-next/server-polyfills.tsx +++ b/packages/bun-framework-next/server-polyfills.tsx @@ -3,12 +3,9 @@ globalThis.global = globalThis; import { Buffer } from "buffer"; import { URL } from "url-polyfill"; import { TextEncoder, TextDecoder } from "fast-text-encoding"; - -globalThis.Buffer = Buffer; - import * as React from "react"; -var onlyChildPolyfill = React.Children.only; +const onlyChildPolyfill = React.Children.only; React.Children.only = function (children) { if ( @@ -22,7 +19,7 @@ React.Children.only = function (children) { return onlyChildPolyfill(children); }; +globalThis.Buffer = Buffer; globalThis.URL = URL; - globalThis.TextEncoder ||= TextEncoder; globalThis.TextDecoder ||= TextDecoder; -- cgit v1.2.3 From 9ab9b01a640cd157634494b6b703d095897ac412 Mon Sep 17 00:00:00 2001 From: Jack Hanford Date: Tue, 23 Nov 2021 10:51:08 -0500 Subject: stop installing textencoder --- packages/bun-framework-next/package.json | 1 - packages/bun-framework-next/server-polyfills.tsx | 3 +- .../bun-framework-next/text-encoder-polyfill.js | 306 +++++++++++++++++++++ 3 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 packages/bun-framework-next/text-encoder-polyfill.js (limited to 'packages/bun-framework-next/server-polyfills.tsx') diff --git a/packages/bun-framework-next/package.json b/packages/bun-framework-next/package.json index d715a8ba4..646b8e4af 100644 --- a/packages/bun-framework-next/package.json +++ b/packages/bun-framework-next/package.json @@ -11,7 +11,6 @@ "author": "", "license": "MIT", "dependencies": { - "fast-text-encoding": "^1.0.3", "react-is": "^17.0.2", "url-polyfill": "^1.1.12" }, diff --git a/packages/bun-framework-next/server-polyfills.tsx b/packages/bun-framework-next/server-polyfills.tsx index 57960e4fa..f0a2b5c3a 100644 --- a/packages/bun-framework-next/server-polyfills.tsx +++ b/packages/bun-framework-next/server-polyfills.tsx @@ -2,7 +2,7 @@ globalThis.global = globalThis; import { Buffer } from "buffer"; import { URL } from "url-polyfill"; -import { TextEncoder, TextDecoder } from "fast-text-encoding"; +import { TextEncoder, TextDecoder } from "./text-encoder-polyfill"; import * as React from "react"; const onlyChildPolyfill = React.Children.only; @@ -21,5 +21,6 @@ React.Children.only = function (children) { globalThis.Buffer = Buffer; globalThis.URL = URL; +// @ts-expect-error encodeInto is missing in our polyfill globalThis.TextEncoder ||= TextEncoder; globalThis.TextDecoder ||= TextDecoder; diff --git a/packages/bun-framework-next/text-encoder-polyfill.js b/packages/bun-framework-next/text-encoder-polyfill.js new file mode 100644 index 000000000..01c7cbbe8 --- /dev/null +++ b/packages/bun-framework-next/text-encoder-polyfill.js @@ -0,0 +1,306 @@ +/* + * Copyright 2017 Sam Thorogood. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +/** + * @fileoverview Polyfill for TextEncoder and TextDecoder. + * + * You probably want `text.min.js`, and not this file directly. + */ + +// used for FastTextDecoder +const validUtfLabels = ["utf-8", "utf8", "unicode-1-1-utf-8"]; + +/** + * @constructor + */ +function FastTextEncoder() { + // This does not accept an encoding, and always uses UTF-8: + // https://www.w3.org/TR/encoding/#dom-textencoder +} + +Object.defineProperty(FastTextEncoder.prototype, "encoding", { + value: "utf-8", +}); + +Object.defineProperty(FastTextEncoder.prototype, "encodeInto", { + value: "", +}); + +/** + * @param {string} string + * @param {{stream: boolean}=} options + * @return {!Uint8Array} + */ +FastTextEncoder.prototype["encode"] = function ( + string, + options = { stream: false } +) { + if (options.stream) { + throw new Error(`Failed to encode: the 'stream' option is unsupported.`); + } + + let pos = 0; + const len = string.length; + + let at = 0; // output position + let tlen = Math.max(32, len + (len >>> 1) + 7); // 1.5x size + let target = new Uint8Array((tlen >>> 3) << 3); // ... but at 8 byte offset + + while (pos < len) { + let value = string.charCodeAt(pos++); + if (value >= 0xd800 && value <= 0xdbff) { + // high surrogate + if (pos < len) { + const extra = string.charCodeAt(pos); + if ((extra & 0xfc00) === 0xdc00) { + ++pos; + value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000; + } + } + if (value >= 0xd800 && value <= 0xdbff) { + continue; // drop lone surrogate + } + } + + // expand the buffer if we couldn't write 4 bytes + if (at + 4 > target.length) { + tlen += 8; // minimum extra + tlen *= 1.0 + (pos / string.length) * 2; // take 2x the remaining + tlen = (tlen >>> 3) << 3; // 8 byte offset + + const update = new Uint8Array(tlen); + update.set(target); + target = update; + } + + if ((value & 0xffffff80) === 0) { + // 1-byte + target[at++] = value; // ASCII + continue; + } else if ((value & 0xfffff800) === 0) { + // 2-byte + target[at++] = ((value >>> 6) & 0x1f) | 0xc0; + } else if ((value & 0xffff0000) === 0) { + // 3-byte + target[at++] = ((value >>> 12) & 0x0f) | 0xe0; + target[at++] = ((value >>> 6) & 0x3f) | 0x80; + } else if ((value & 0xffe00000) === 0) { + // 4-byte + target[at++] = ((value >>> 18) & 0x07) | 0xf0; + target[at++] = ((value >>> 12) & 0x3f) | 0x80; + target[at++] = ((value >>> 6) & 0x3f) | 0x80; + } else { + continue; // out of range + } + + target[at++] = (value & 0x3f) | 0x80; + } + + // Use subarray if slice isn't supported (IE11). This will use more memory + // because the original array still exists. + return target.slice ? target.slice(0, at) : target.subarray(0, at); +}; + +/** + * @constructor + * @param {string=} utfLabel + * @param {{fatal: boolean}=} options + */ +function FastTextDecoder(utfLabel = "utf-8", options = { fatal: false }) { + if (validUtfLabels.indexOf(utfLabel.toLowerCase()) === -1) { + throw new RangeError( + `Failed to construct 'TextDecoder': The encoding label provided ('${utfLabel}') is invalid.` + ); + } + if (options.fatal) { + throw new Error( + `Failed to construct 'TextDecoder': the 'fatal' option is unsupported.` + ); + } +} + +Object.defineProperty(FastTextDecoder.prototype, "encoding", { + value: "utf-8", +}); + +Object.defineProperty(FastTextDecoder.prototype, "fatal", { value: false }); + +Object.defineProperty(FastTextDecoder.prototype, "ignoreBOM", { + value: false, +}); + +/** + * @param {!Uint8Array} bytes + * @return {string} + */ +function decodeBuffer(bytes) { + return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString( + "utf-8" + ); +} + +/** + * @param {!Uint8Array} bytes + * @return {string} + */ +function decodeSyncXHR(bytes) { + const b = new Blob([bytes], { type: "text/plain;charset=UTF-8" }); + const u = URL.createObjectURL(b); + + // This hack will fail in non-Edgium Edge because sync XHRs are disabled (and + // possibly in other places), so ensure there's a fallback call. + try { + const x = new XMLHttpRequest(); + x.open("GET", u, false); + x.send(); + return x.responseText; + } catch (e) { + return decodeFallback(bytes); + } finally { + URL.revokeObjectURL(u); + } +} + +/** + * @param {!Uint8Array} bytes + * @return {string} + */ +function decodeFallback(bytes) { + let inputIndex = 0; + + // Create a working buffer for UTF-16 code points, but don't generate one + // which is too large for small input sizes. UTF-8 to UCS-16 conversion is + // going to be at most 1:1, if all code points are ASCII. The other extreme + // is 4-byte UTF-8, which results in two UCS-16 points, but this is still 50% + // fewer entries in the output. + const pendingSize = Math.min(256 * 256, bytes.length + 1); + const pending = new Uint16Array(pendingSize); + const chunks = []; + let pendingIndex = 0; + + for (;;) { + const more = inputIndex < bytes.length; + + // If there's no more data or there'd be no room for two UTF-16 values, + // create a chunk. This isn't done at the end by simply slicing the data + // into equal sized chunks as we might hit a surrogate pair. + if (!more || pendingIndex >= pendingSize - 1) { + // nb. .apply and friends are *really slow*. Low-hanging fruit is to + // expand this to literally pass pending[0], pending[1], ... etc, but + // the output code expands pretty fast in this case. + chunks.push( + String.fromCharCode.apply(null, pending.subarray(0, pendingIndex)) + ); + + if (!more) { + return chunks.join(""); + } + + // Move the buffer forward and create another chunk. + bytes = bytes.subarray(inputIndex); + inputIndex = 0; + pendingIndex = 0; + } + + // The native TextDecoder will generate "REPLACEMENT CHARACTER" where the + // input data is invalid. Here, we blindly parse the data even if it's + // wrong: e.g., if a 3-byte sequence doesn't have two valid continuations. + + const byte1 = bytes[inputIndex++]; + if ((byte1 & 0x80) === 0) { + // 1-byte or null + pending[pendingIndex++] = byte1; + } else if ((byte1 & 0xe0) === 0xc0) { + // 2-byte + const byte2 = bytes[inputIndex++] & 0x3f; + pending[pendingIndex++] = ((byte1 & 0x1f) << 6) | byte2; + } else if ((byte1 & 0xf0) === 0xe0) { + // 3-byte + const byte2 = bytes[inputIndex++] & 0x3f; + const byte3 = bytes[inputIndex++] & 0x3f; + pending[pendingIndex++] = ((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3; + } else if ((byte1 & 0xf8) === 0xf0) { + // 4-byte + const byte2 = bytes[inputIndex++] & 0x3f; + const byte3 = bytes[inputIndex++] & 0x3f; + const byte4 = bytes[inputIndex++] & 0x3f; + + // this can be > 0xffff, so possibly generate surrogates + let codepoint = + ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4; + if (codepoint > 0xffff) { + // codepoint &= ~0x10000; + codepoint -= 0x10000; + pending[pendingIndex++] = ((codepoint >>> 10) & 0x3ff) | 0xd800; + codepoint = 0xdc00 | (codepoint & 0x3ff); + } + pending[pendingIndex++] = codepoint; + } else { + // invalid initial byte + } + } +} + +// Decoding a string is pretty slow, but use alternative options where possible. +let decodeImpl = decodeFallback; +if (typeof Buffer === "function" && Buffer.from) { + // Buffer.from was added in Node v5.10.0 (2015-11-17). + decodeImpl = decodeBuffer; +} else if ( + typeof Blob === "function" && + typeof URL === "function" && + typeof URL.createObjectURL === "function" +) { + // Blob and URL.createObjectURL are available from IE10, Safari 6, Chrome 19 + // (all released in 2012), Firefox 19 (2013), ... + decodeImpl = decodeSyncXHR; +} + +/** + * @param {(!ArrayBuffer|!ArrayBufferView)} buffer + * @param {{stream: boolean}=} options + * @return {string} + */ +FastTextDecoder.prototype["decode"] = function ( + buffer, + options = { stream: false } +) { + if (options["stream"]) { + throw new Error(`Failed to decode: the 'stream' option is unsupported.`); + } + + let bytes; + + if (buffer instanceof Uint8Array) { + // Accept Uint8Array instances as-is. + bytes = buffer; + } else if (buffer.buffer instanceof ArrayBuffer) { + // Look for ArrayBufferView, which isn't a real type, but basically + // represents all the valid TypedArray types plus DataView. They all have + // ".buffer" as an instance of ArrayBuffer. + bytes = new Uint8Array(buffer.buffer); + } else { + // The only other valid argument here is that "buffer" is an ArrayBuffer. + // We also try to convert anything else passed to a Uint8Array, as this + // catches anything that's array-like. Native code would throw here. + bytes = new Uint8Array(buffer); + } + + return decodeImpl(/** @type {!Uint8Array} */ (bytes)); +}; + +export { FastTextEncoder as TextEncoder }; +export { FastTextDecoder as TextDecoder }; -- cgit v1.2.3