From 6bd0203d146b8c3520f68f43234fdfbaa6d776c3 Mon Sep 17 00:00:00 2001 From: Cody Bennett Date: Sat, 21 Oct 2023 02:31:03 -0500 Subject: [PATCH 1/8] fix(native): restore safety checks in loader polyfills --- .prettierrc | 3 ++- packages/fiber/src/native/polyfills.ts | 32 ++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/.prettierrc b/.prettierrc index 5553e1cf25..754aefb5df 100644 --- a/.prettierrc +++ b/.prettierrc @@ -4,5 +4,6 @@ "singleQuote": true, "tabWidth": 2, "printWidth": 120, - "jsxBracketSameLine": true + "jsxBracketSameLine": true, + "endOfLine": "auto" } diff --git a/packages/fiber/src/native/polyfills.ts b/packages/fiber/src/native/polyfills.ts index 3e07eef93a..fe7d0fda27 100644 --- a/packages/fiber/src/native/polyfills.ts +++ b/packages/fiber/src/native/polyfills.ts @@ -1,8 +1,16 @@ import { Image } from 'react-native' import { Asset } from 'expo-asset' -import { cacheDirectory, copyAsync } from 'expo-file-system' +import { cacheDirectory, copyAsync, writeAsStringAsync, readAsStringAsync, EncodingType } from 'expo-file-system' import * as THREE from 'three' +function uuidv4() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { + const r = (Math.random() * 16) | 0, + v = c == 'x' ? r : (r & 0x3) | 0x8 + return v.toString(16) + }) +} + async function getAsset(input: string | number): Promise { const asset = typeof input === 'string' ? Asset.fromURI(input) : Asset.fromModule(input) @@ -11,8 +19,9 @@ async function getAsset(input: string | number): Promise { // Unpack assets in Android Release Mode if (!localUri.includes('://')) { - localUri = `${cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}` - await copyAsync({ from: localUri, to: localUri }) + const targetUri = `${cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}` + await copyAsync({ from: localUri, to: targetUri }) + localUri = targetUri } return localUri @@ -31,6 +40,15 @@ export function _polyfills() { getAsset(url) .then(async (localUri) => { + // Create safe URI for JSI + if (localUri.startsWith('data:')) { + const [header, data] = localUri.split(',') + const [, type] = header.split('/') + + localUri = cacheDirectory + uuidv4() + `.${type}` + await writeAsStringAsync(localUri, data, { encoding: EncodingType.Base64 }) + } + const { width, height } = await new Promise<{ width: number; height: number }>((res, rej) => Image.getSize(localUri, (width, height) => res({ width, height }), rej), ) @@ -62,7 +80,13 @@ export function _polyfills() { const request = new XMLHttpRequest() getAsset(url) - .then((localUri) => { + .then(async (localUri) => { + // Make FS paths web-safe + if (localUri.startsWith('file://')) { + const data = await readAsStringAsync(localUri, { encoding: EncodingType.Base64 }) + localUri = `data:application/octet-stream;base64,${data}` + } + request.open('GET', localUri, true) request.addEventListener( From 87c6cd5bc36f1dadc8279609ec05fcae5025c692 Mon Sep 17 00:00:00 2001 From: Cody Bennett Date: Sat, 21 Oct 2023 02:51:55 -0500 Subject: [PATCH 2/8] experiment: revert to network stack, eagerly polyfill for race conditions --- packages/fiber/src/native.tsx | 4 +- packages/fiber/src/native/Canvas.tsx | 4 + packages/fiber/src/native/polyfills.ts | 144 +++++++++++++++++++------ 3 files changed, 115 insertions(+), 37 deletions(-) diff --git a/packages/fiber/src/native.tsx b/packages/fiber/src/native.tsx index b7b796eef0..c37809041f 100644 --- a/packages/fiber/src/native.tsx +++ b/packages/fiber/src/native.tsx @@ -21,6 +21,6 @@ export type { GlobalRenderCallback, GlobalEffectType } from './core/loop' export * from './core' import { Platform } from 'react-native' -import { _polyfills } from './native/polyfills' +import { polyfills } from './native/polyfills' -if (Platform.OS !== 'web') _polyfills() +if (Platform.OS !== 'web') polyfills() diff --git a/packages/fiber/src/native/Canvas.tsx b/packages/fiber/src/native/Canvas.tsx index 81a6d35c7f..a7fdc17397 100644 --- a/packages/fiber/src/native/Canvas.tsx +++ b/packages/fiber/src/native/Canvas.tsx @@ -7,6 +7,7 @@ import { SetBlock, Block, ErrorBoundary, useMutableCallback } from '../core/util import { extend, createRoot, unmountComponentAtNode, RenderProps, ReconcilerRoot } from '../core' import { createTouchEvents } from './events' import { RootState, Size } from '../core/store' +import { polyfills } from './polyfills' export interface CanvasProps extends Omit, 'size' | 'dpr'>, ViewProps { children: React.ReactNode @@ -42,6 +43,9 @@ const CanvasImpl = /*#__PURE__*/ React.forwardRef( }, forwardedRef, ) => { + // Eagerly polyfill + React.useMemo(() => polyfills(), []) + // Create a known catalogue of Threejs-native elements // This will include the entire THREE namespace by default, users can extend // their own elements by using the createRoot API instead diff --git a/packages/fiber/src/native/polyfills.ts b/packages/fiber/src/native/polyfills.ts index fe7d0fda27..88f87ae9d9 100644 --- a/packages/fiber/src/native/polyfills.ts +++ b/packages/fiber/src/native/polyfills.ts @@ -1,33 +1,107 @@ -import { Image } from 'react-native' -import { Asset } from 'expo-asset' -import { cacheDirectory, copyAsync, writeAsStringAsync, readAsStringAsync, EncodingType } from 'expo-file-system' import * as THREE from 'three' +import { Image, NativeModules } from 'react-native' +import { Asset } from 'expo-asset' +import * as fs from 'expo-file-system' +import { fromByteArray } from 'base64-js' + +export function polyfills() { + function uuidv4() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { + const r = (Math.random() * 16) | 0, + v = c == 'x' ? r : (r & 0x3) | 0x8 + return v.toString(16) + }) + } -function uuidv4() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { - const r = (Math.random() * 16) | 0, - v = c == 'x' ? r : (r & 0x3) | 0x8 - return v.toString(16) - }) -} - -async function getAsset(input: string | number): Promise { - const asset = typeof input === 'string' ? Asset.fromURI(input) : Asset.fromModule(input) + // Patch Blob for ArrayBuffer if unsupported + try { + new Blob([new ArrayBuffer(4) as any]) + } catch (_) { + const BlobManager = require('react-native/Libraries/Blob/BlobManager.js') + + BlobManager.createFromParts = function createFromParts(parts: Array, options: any) { + const blobId = uuidv4() + + const items = parts.map((part) => { + if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) { + const data = fromByteArray(new Uint8Array(part as ArrayBuffer)) + return { + data, + type: 'string', + } + } else if (part instanceof Blob) { + return { + data: (part as any).data, + type: 'blob', + } + } else { + return { + data: String(part), + type: 'string', + } + } + }) + const size = items.reduce((acc, curr) => { + if (curr.type === 'string') { + return acc + global.unescape(encodeURI(curr.data)).length + } else { + return acc + curr.data.size + } + }, 0) - await asset.downloadAsync() - let localUri = asset.localUri || asset.uri + NativeModules.BlobModule.createFromParts(items, blobId) - // Unpack assets in Android Release Mode - if (!localUri.includes('://')) { - const targetUri = `${cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}` - await copyAsync({ from: localUri, to: targetUri }) - localUri = targetUri + return BlobManager.createFromOptions({ + blobId, + offset: 0, + size, + type: options ? options.type : '', + lastModified: options ? options.lastModified : Date.now(), + }) + } } - return localUri -} + async function getAsset(input: string | number): Promise { + if (typeof input === 'string') { + // Don't process storage or data uris + if (input.startsWith('file:') || input.startsWith('data:')) return input + + // Unpack Blobs from react-native BlobManager + if (input.startsWith('blob:')) { + const blob = await new Promise((res, rej) => { + const xhr = new XMLHttpRequest() + xhr.open('GET', input as string) + xhr.responseType = 'blob' + xhr.onload = () => res(xhr.response) + xhr.onerror = rej + xhr.send() + }) + + const data = await new Promise((res, rej) => { + const reader = new FileReader() + reader.onload = () => res(reader.result as string) + reader.onerror = rej + reader.readAsText(blob) + }) + + return `data:${blob.type};base64,${data}` + } + } + + // Download bundler module or external URL + const asset = await Asset.fromModule(input).downloadAsync() + let uri = asset.localUri || asset.uri + + // Unpack assets in Android Release Mode + if (!uri.includes(':')) { + const file = `${fs.cacheDirectory}ExponentAsset-${asset.hash}.${asset.type}` + await fs.copyAsync({ from: uri, to: file }) + uri = file + } + + return uri + } -export function _polyfills() { // Don't pre-process urls, let expo-asset generate an absolute URL const extractUrlBase = THREE.LoaderUtils.extractUrlBase.bind(THREE.LoaderUtils) THREE.LoaderUtils.extractUrlBase = (url: string) => (typeof url === 'string' ? extractUrlBase(url) : './') @@ -39,22 +113,22 @@ export function _polyfills() { const texture = new THREE.Texture() getAsset(url) - .then(async (localUri) => { + .then(async (uri) => { // Create safe URI for JSI - if (localUri.startsWith('data:')) { - const [header, data] = localUri.split(',') + if (uri.startsWith('data:')) { + const [header, data] = uri.split(',') const [, type] = header.split('/') - localUri = cacheDirectory + uuidv4() + `.${type}` - await writeAsStringAsync(localUri, data, { encoding: EncodingType.Base64 }) + uri = fs.cacheDirectory + uuidv4() + `.${type}` + await fs.writeAsStringAsync(uri, data, { encoding: fs.EncodingType.Base64 }) } const { width, height } = await new Promise<{ width: number; height: number }>((res, rej) => - Image.getSize(localUri, (width, height) => res({ width, height }), rej), + Image.getSize(uri, (width, height) => res({ width, height }), rej), ) texture.image = { - data: { localUri }, + data: { localUri: uri }, width, height, } @@ -80,14 +154,14 @@ export function _polyfills() { const request = new XMLHttpRequest() getAsset(url) - .then(async (localUri) => { + .then(async (uri) => { // Make FS paths web-safe - if (localUri.startsWith('file://')) { - const data = await readAsStringAsync(localUri, { encoding: EncodingType.Base64 }) - localUri = `data:application/octet-stream;base64,${data}` + if (uri.startsWith('file://')) { + const data = await fs.readAsStringAsync(uri, { encoding: fs.EncodingType.Base64 }) + uri = `data:application/octet-stream;base64,${data}` } - request.open('GET', localUri, true) + request.open('GET', uri, true) request.addEventListener( 'load', From a6d0e9c0f10e5f84c68f9036a963a273c5311eea Mon Sep 17 00:00:00 2001 From: Cody Bennett Date: Sat, 21 Oct 2023 02:56:32 -0500 Subject: [PATCH 3/8] experiment: don't call polyfills --- packages/fiber/src/native.tsx | 5 +---- packages/fiber/src/native/Canvas.tsx | 4 ---- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/fiber/src/native.tsx b/packages/fiber/src/native.tsx index c37809041f..b061c66184 100644 --- a/packages/fiber/src/native.tsx +++ b/packages/fiber/src/native.tsx @@ -20,7 +20,4 @@ export { createTouchEvents as events } from './native/events' export type { GlobalRenderCallback, GlobalEffectType } from './core/loop' export * from './core' -import { Platform } from 'react-native' -import { polyfills } from './native/polyfills' - -if (Platform.OS !== 'web') polyfills() +export { polyfills } from './native/polyfills' diff --git a/packages/fiber/src/native/Canvas.tsx b/packages/fiber/src/native/Canvas.tsx index a7fdc17397..81a6d35c7f 100644 --- a/packages/fiber/src/native/Canvas.tsx +++ b/packages/fiber/src/native/Canvas.tsx @@ -7,7 +7,6 @@ import { SetBlock, Block, ErrorBoundary, useMutableCallback } from '../core/util import { extend, createRoot, unmountComponentAtNode, RenderProps, ReconcilerRoot } from '../core' import { createTouchEvents } from './events' import { RootState, Size } from '../core/store' -import { polyfills } from './polyfills' export interface CanvasProps extends Omit, 'size' | 'dpr'>, ViewProps { children: React.ReactNode @@ -43,9 +42,6 @@ const CanvasImpl = /*#__PURE__*/ React.forwardRef( }, forwardedRef, ) => { - // Eagerly polyfill - React.useMemo(() => polyfills(), []) - // Create a known catalogue of Threejs-native elements // This will include the entire THREE namespace by default, users can extend // their own elements by using the createRoot API instead From 5098d00aef3c6085eb426764f2a0eb33f6a88b11 Mon Sep 17 00:00:00 2001 From: Cody Bennett Date: Sat, 21 Oct 2023 03:36:26 -0500 Subject: [PATCH 4/8] fix: restore polyfill IIFE, pipe data from FS --- packages/fiber/package.json | 1 - packages/fiber/src/native.tsx | 5 +- packages/fiber/src/native/polyfills.ts | 96 +++++++------------------- 3 files changed, 28 insertions(+), 74 deletions(-) diff --git a/packages/fiber/package.json b/packages/fiber/package.json index 6379f80057..2866ad8683 100644 --- a/packages/fiber/package.json +++ b/packages/fiber/package.json @@ -44,7 +44,6 @@ "dependencies": { "@babel/runtime": "^7.17.8", "@types/react-reconciler": "^0.26.7", - "base64-js": "^1.5.1", "its-fine": "^1.0.6", "react-reconciler": "^0.27.0", "react-use-measure": "^2.1.1", diff --git a/packages/fiber/src/native.tsx b/packages/fiber/src/native.tsx index b061c66184..c37809041f 100644 --- a/packages/fiber/src/native.tsx +++ b/packages/fiber/src/native.tsx @@ -20,4 +20,7 @@ export { createTouchEvents as events } from './native/events' export type { GlobalRenderCallback, GlobalEffectType } from './core/loop' export * from './core' -export { polyfills } from './native/polyfills' +import { Platform } from 'react-native' +import { polyfills } from './native/polyfills' + +if (Platform.OS !== 'web') polyfills() diff --git a/packages/fiber/src/native/polyfills.ts b/packages/fiber/src/native/polyfills.ts index 88f87ae9d9..072663638d 100644 --- a/packages/fiber/src/native/polyfills.ts +++ b/packages/fiber/src/native/polyfills.ts @@ -63,8 +63,8 @@ export function polyfills() { async function getAsset(input: string | number): Promise { if (typeof input === 'string') { - // Don't process storage or data uris - if (input.startsWith('file:') || input.startsWith('data:')) return input + // Don't process storage + if (input.startsWith('file:')) return input // Unpack Blobs from react-native BlobManager if (input.startsWith('blob:')) { @@ -84,7 +84,16 @@ export function polyfills() { reader.readAsText(blob) }) - return `data:${blob.type};base64,${data}` + input = `data:${blob.type};base64,${data}` + } + + // Create safe URI for JSI + if (input.startsWith('data:')) { + const [header, data] = input.split(',') + const [, type] = header.split('/') + + const uri = fs.cacheDirectory + uuidv4() + `.${type}` + await fs.writeAsStringAsync(uri, data, { encoding: fs.EncodingType.Base64 }) } } @@ -108,7 +117,7 @@ export function polyfills() { // There's no Image in native, so create a data texture instead THREE.TextureLoader.prototype.load = function load(url, onLoad, onProgress, onError) { - if (this.path) url = this.path + url + if (this.path && typeof url === 'string') url = this.path + url const texture = new THREE.Texture() @@ -149,80 +158,23 @@ export function polyfills() { // Fetches assets via XMLHttpRequest THREE.FileLoader.prototype.load = function load(url, onLoad, onProgress, onError) { - if (this.path) url = this.path + url - - const request = new XMLHttpRequest() + if (this.path && typeof url === 'string') url = this.path + url getAsset(url) .then(async (uri) => { - // Make FS paths web-safe - if (uri.startsWith('file://')) { - const data = await fs.readAsStringAsync(uri, { encoding: fs.EncodingType.Base64 }) - uri = `data:application/octet-stream;base64,${data}` - } - - request.open('GET', uri, true) - - request.addEventListener( - 'load', - (event) => { - if (request.status === 200) { - onLoad?.(request.response) - - this.manager.itemEnd(url) - } else { - onError?.(event as unknown as ErrorEvent) - - this.manager.itemError(url) - this.manager.itemEnd(url) - } - }, - false, - ) - - request.addEventListener( - 'progress', - (event) => { - onProgress?.(event) - }, - false, - ) - - request.addEventListener( - 'error', - (event) => { - onError?.(event as unknown as ErrorEvent) - - this.manager.itemError(url) - this.manager.itemEnd(url) - }, - false, - ) - - request.addEventListener( - 'abort', - (event) => { - onError?.(event as unknown as ErrorEvent) - - this.manager.itemError(url) - this.manager.itemEnd(url) - }, - false, - ) - - if (this.responseType) request.responseType = this.responseType - if (this.withCredentials) request.withCredentials = this.withCredentials - - for (const header in this.requestHeader) { - request.setRequestHeader(header, this.requestHeader[header]) - } + this.manager.itemStart(url) - request.send(null) + const base64 = await fs.readAsStringAsync(uri, { encoding: fs.EncodingType.Base64 }) + const data = Buffer.from(base64, 'base64') + onLoad?.(data.buffer) - this.manager.itemStart(url) + this.manager.itemEnd(url) }) - .catch(onError) + .catch((error) => { + onError?.(error) - return request + this.manager.itemError(url) + this.manager.itemEnd(url) + }) } } From 75011cc64e10c55fd381d3d83a8f5e5206f3009e Mon Sep 17 00:00:00 2001 From: Cody Bennett Date: Sat, 21 Oct 2023 03:37:41 -0500 Subject: [PATCH 5/8] chore: unmangle --- packages/fiber/src/native/polyfills.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fiber/src/native/polyfills.ts b/packages/fiber/src/native/polyfills.ts index 072663638d..e4391ae0e1 100644 --- a/packages/fiber/src/native/polyfills.ts +++ b/packages/fiber/src/native/polyfills.ts @@ -2,7 +2,7 @@ import * as THREE from 'three' import { Image, NativeModules } from 'react-native' import { Asset } from 'expo-asset' import * as fs from 'expo-file-system' -import { fromByteArray } from 'base64-js' +import { Buffer } from 'buffer' export function polyfills() { function uuidv4() { From b9173443366d5a71974c225b83ec7d9fd8b66b42 Mon Sep 17 00:00:00 2001 From: Cody Bennett Date: Sat, 21 Oct 2023 03:39:24 -0500 Subject: [PATCH 6/8] fix: add missing deps --- packages/fiber/package.json | 2 ++ packages/fiber/src/native/polyfills.ts | 1 + yarn.lock | 15 ++++++++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/fiber/package.json b/packages/fiber/package.json index 2866ad8683..41212ab83e 100644 --- a/packages/fiber/package.json +++ b/packages/fiber/package.json @@ -44,6 +44,8 @@ "dependencies": { "@babel/runtime": "^7.17.8", "@types/react-reconciler": "^0.26.7", + "base64-js": "^1.5.1", + "buffer": "^6.0.3", "its-fine": "^1.0.6", "react-reconciler": "^0.27.0", "react-use-measure": "^2.1.1", diff --git a/packages/fiber/src/native/polyfills.ts b/packages/fiber/src/native/polyfills.ts index e4391ae0e1..69c1b6add9 100644 --- a/packages/fiber/src/native/polyfills.ts +++ b/packages/fiber/src/native/polyfills.ts @@ -2,6 +2,7 @@ import * as THREE from 'three' import { Image, NativeModules } from 'react-native' import { Asset } from 'expo-asset' import * as fs from 'expo-file-system' +import { fromByteArray } from 'base64-js' import { Buffer } from 'buffer' export function polyfills() { diff --git a/yarn.lock b/yarn.lock index 16f4f7ea20..d90433eb09 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3413,7 +3413,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.1.2, base64-js@^1.5.1: +base64-js@^1.1.2, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -3559,6 +3559,14 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + builtin-modules@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" @@ -5417,6 +5425,11 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore-walk@^3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335" From b93242e9fc2cb8cff042dfbfc86b8da08b1b3d1e Mon Sep 17 00:00:00 2001 From: Cody Bennett Date: Sat, 21 Oct 2023 03:43:57 -0500 Subject: [PATCH 7/8] fix: don't fallthrough blob data case --- packages/fiber/src/native/polyfills.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/fiber/src/native/polyfills.ts b/packages/fiber/src/native/polyfills.ts index 69c1b6add9..4b99bc5652 100644 --- a/packages/fiber/src/native/polyfills.ts +++ b/packages/fiber/src/native/polyfills.ts @@ -95,6 +95,8 @@ export function polyfills() { const uri = fs.cacheDirectory + uuidv4() + `.${type}` await fs.writeAsStringAsync(uri, data, { encoding: fs.EncodingType.Base64 }) + + return uri } } @@ -124,15 +126,6 @@ export function polyfills() { getAsset(url) .then(async (uri) => { - // Create safe URI for JSI - if (uri.startsWith('data:')) { - const [header, data] = uri.split(',') - const [, type] = header.split('/') - - uri = fs.cacheDirectory + uuidv4() + `.${type}` - await fs.writeAsStringAsync(uri, data, { encoding: fs.EncodingType.Base64 }) - } - const { width, height } = await new Promise<{ width: number; height: number }>((res, rej) => Image.getSize(uri, (width, height) => res({ width, height }), rej), ) From 248b895d7100b78156c6c57d80c18022e6320135 Mon Sep 17 00:00:00 2001 From: Cody Bennett Date: Sat, 21 Oct 2023 03:48:10 -0500 Subject: [PATCH 8/8] chore: cleanup manager lifecycle --- packages/fiber/src/native/polyfills.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/fiber/src/native/polyfills.ts b/packages/fiber/src/native/polyfills.ts index 4b99bc5652..3adfa5b198 100644 --- a/packages/fiber/src/native/polyfills.ts +++ b/packages/fiber/src/native/polyfills.ts @@ -122,6 +122,8 @@ export function polyfills() { THREE.TextureLoader.prototype.load = function load(url, onLoad, onProgress, onError) { if (this.path && typeof url === 'string') url = this.path + url + this.manager.itemStart(url) + const texture = new THREE.Texture() getAsset(url) @@ -145,7 +147,13 @@ export function polyfills() { onLoad?.(texture) }) - .catch(onError) + .catch((error) => { + onError?.(error) + this.manager.itemError(url) + }) + .finally(() => { + this.manager.itemEnd(url) + }) return texture } @@ -154,20 +162,19 @@ export function polyfills() { THREE.FileLoader.prototype.load = function load(url, onLoad, onProgress, onError) { if (this.path && typeof url === 'string') url = this.path + url + this.manager.itemStart(url) + getAsset(url) .then(async (uri) => { - this.manager.itemStart(url) - const base64 = await fs.readAsStringAsync(uri, { encoding: fs.EncodingType.Base64 }) const data = Buffer.from(base64, 'base64') onLoad?.(data.buffer) - - this.manager.itemEnd(url) }) .catch((error) => { onError?.(error) - this.manager.itemError(url) + }) + .finally(() => { this.manager.itemEnd(url) }) }