2025-07-04 14:42:33 -07:00
/ * *
* Unified Text Encoding Utilities
*
* This module provides a consistent way to handle text encoding / decoding across all environments
* without relying on TextEncoder / TextDecoder polyfills or patches .
* /
/ * *
* A simple text encoder that works in all environments
* This avoids the need for TextEncoder polyfills and patches
* /
export class SimpleTextEncoder {
/ * *
* Encode a string to a Uint8Array
* @param input - The string to encode
* @returns A Uint8Array containing the encoded string
* /
encode ( input : string ) : Uint8Array {
// Simple UTF-8 encoding implementation that works everywhere
return new Uint8Array ( [ . . . input ] . map ( ( c ) = > c . charCodeAt ( 0 ) ) )
}
}
/ * *
* A simple text decoder that works in all environments
* This avoids the need for TextDecoder polyfills and patches
* /
export class SimpleTextDecoder {
/ * *
* Decode a Uint8Array to a string
* @param input - The Uint8Array to decode
* @returns The decoded string
* /
decode ( input : Uint8Array ) : string {
// Simple UTF-8 decoding implementation that works everywhere
return String . fromCharCode . apply ( null , [ . . . input ] )
}
}
// Create constructor functions that can be used as drop-in replacements
// for the native TextEncoder and TextDecoder
/ * *
* Interface for UniversalTextEncoder instance
* /
interface IUniversalTextEncoder {
encode : ( input : string ) = > Uint8Array ;
}
/ * *
* A constructor function for TextEncoder that works in all environments
* /
export function UniversalTextEncoder ( this : IUniversalTextEncoder ) {
if ( ! ( this instanceof UniversalTextEncoder ) ) {
return new ( UniversalTextEncoder as any ) ( )
}
try {
// Try to use the native TextEncoder if available
const nativeEncoder : TextEncoder = new TextEncoder ( )
this . encode = nativeEncoder . encode . bind ( nativeEncoder )
} catch ( e ) {
// Fall back to our simple implementation
const simpleEncoder : SimpleTextEncoder = new SimpleTextEncoder ( )
this . encode = simpleEncoder . encode . bind ( simpleEncoder )
}
}
/ * *
* Interface for UniversalTextDecoder instance
* /
interface IUniversalTextDecoder {
decode : ( input : Uint8Array ) = > string ;
}
/ * *
* A constructor function for TextDecoder that works in all environments
* /
export function UniversalTextDecoder ( this : IUniversalTextDecoder ) {
if ( ! ( this instanceof UniversalTextDecoder ) ) {
return new ( UniversalTextDecoder as any ) ( )
}
try {
// Try to use the native TextDecoder if available
const nativeDecoder : TextDecoder = new TextDecoder ( )
this . decode = nativeDecoder . decode . bind ( nativeDecoder )
} catch ( e ) {
// Fall back to our simple implementation
const simpleDecoder : SimpleTextDecoder = new SimpleTextDecoder ( )
this . decode = simpleDecoder . decode . bind ( simpleDecoder )
}
}
/ * *
* Get a text encoder that works in the current environment
* @returns A text encoder object with an encode method
* /
export function getTextEncoder ( ) : IUniversalTextEncoder {
return new ( UniversalTextEncoder as any ) ( )
}
/ * *
* Get a text decoder that works in the current environment
* @returns A text decoder object with a decode method
* /
export function getTextDecoder ( ) : IUniversalTextDecoder {
return new ( UniversalTextDecoder as any ) ( )
}
/ * *
* Apply the TensorFlow . js platform patch if needed
* This function patches the global object to provide a PlatformNode class
* that uses our text encoding utilities instead of relying on TextEncoder / TextDecoder
* /
export function applyTensorFlowPatch ( ) : void {
2025-07-07 10:19:04 -07:00
try {
// Get encoders/decoders
const encoder = getTextEncoder ( )
const decoder = getTextDecoder ( )
// Define a custom Platform class that works in both Node.js and browser environments
class Platform {
util : any
textEncoder : any
textDecoder : any
constructor ( ) {
// Create a util object with necessary methods and constructors
this . util = {
// Add TextEncoder and TextDecoder as constructors
TextEncoder : UniversalTextEncoder ,
TextDecoder : UniversalTextDecoder
2025-07-04 14:42:33 -07:00
}
2025-07-07 10:19:04 -07:00
// Initialize using the constructors from util
this . textEncoder = new this . util . TextEncoder ( )
this . textDecoder = new this . util . TextDecoder ( )
}
// Define isFloat32Array directly on the instance
isFloat32Array ( arr : any ) {
return ! ! (
arr instanceof Float32Array ||
( arr &&
Object . prototype . toString . call ( arr ) ===
'[object Float32Array]' )
)
2025-07-04 14:42:33 -07:00
}
2025-07-07 10:19:04 -07:00
// Define isTypedArray directly on the instance
isTypedArray ( arr : any ) {
return ! ! ( ArrayBuffer . isView ( arr ) && ! ( arr instanceof DataView ) )
}
}
2025-07-04 14:42:33 -07:00
2025-07-07 10:19:04 -07:00
// Get the global object in a way that works in both Node.js and browser
const globalObj = typeof global !== 'undefined' ? global :
typeof window !== 'undefined' ? window :
typeof self !== 'undefined' ? self :
{ } ;
// Only apply in Node.js environment
if (
typeof process !== 'undefined' &&
process . versions &&
process . versions . node
) {
// Assign the Platform class to the global object as PlatformNode for Node.js
( globalObj as any ) . PlatformNode = Platform ;
2025-07-04 14:42:33 -07:00
// Also create an instance and assign it to global.platformNode (lowercase p)
2025-07-07 10:19:04 -07:00
( globalObj as any ) . platformNode = new Platform ( ) ;
} else if ( typeof window !== 'undefined' || typeof self !== 'undefined' ) {
// In browser environments, we might need to provide similar functionality
// but we'll use a different name to avoid conflicts
( globalObj as any ) . PlatformBrowser = Platform ;
( globalObj as any ) . platformBrowser = new Platform ( ) ;
2025-07-04 14:42:33 -07:00
}
2025-07-07 10:19:04 -07:00
} catch ( error ) {
console . warn ( 'Failed to apply TensorFlow.js platform patch:' , error )
2025-07-04 14:42:33 -07:00
}
}