isSharedArrayBuffer
Determines whether a value is a SharedArrayBuffer with enhanced type safety. Provides reliable SharedArrayBuffer detection with environment compatibility, identifying shared memory buffer objects used for multi-threaded JavaScript applications in both browsers (Web Workers) and Node.js (worker_threads). Returns false in environments where SharedArrayBuffer is not available.
Signature
const isSharedArrayBuffer: (value: unknown) => value is SharedArrayBuffer
Parameters
| Name | Type | Description |
|---|---|---|
value | - | Value to test for SharedArrayBuffer type |
Returns
Type-safe boolean indicating whether the value is a SharedArrayBuffer
Examples
Basic SharedArrayBuffer detection
import { isSharedArrayBuffer } from '@winglet/common-utils';
// True cases - SharedArrayBuffer instances (if supported)
if (typeof SharedArrayBuffer !== 'undefined') {
console.log(isSharedArrayBuffer(new SharedArrayBuffer(16))); // true
console.log(isSharedArrayBuffer(new SharedArrayBuffer(1024))); // true
}
// False cases - not SharedArrayBuffer
console.log(isSharedArrayBuffer(new ArrayBuffer(16))); // false (regular ArrayBuffer)
console.log(isSharedArrayBuffer(new Uint8Array(16))); // false (TypedArray)
console.log(isSharedArrayBuffer(new DataView(new ArrayBuffer(16)))); // false (DataView)
console.log(isSharedArrayBuffer({})); // false (object)
console.log(isSharedArrayBuffer(null)); // false
console.log(isSharedArrayBuffer('buffer')); // false (string)
// Environment without SharedArrayBuffer support
// (older browsers, restricted contexts)
console.log(isSharedArrayBuffer(anything)); // always false
Multi-threaded application setup
interface WorkerMessage {
type: 'INIT' | 'PROCESS' | 'RESULT';
buffer?: unknown;
data?: any;
}
function setupSharedMemoryWorker() {
if (typeof SharedArrayBuffer === 'undefined') {
throw new Error('SharedArrayBuffer not supported in this environment');
}
const sharedBuffer = new SharedArrayBuffer(1024);
const worker = new Worker('worker.js');
worker.postMessage({
type: 'INIT',
buffer: sharedBuffer
});
return { worker, sharedBuffer };
}
function handleWorkerMessage(message: WorkerMessage) {
if (message.type === 'INIT' && isSharedArrayBuffer(message.buffer)) {
// TypeScript knows buffer is SharedArrayBuffer
console.log(`Shared buffer initialized: ${message.buffer.byteLength} bytes`);
// Safe to create views
const int32View = new Int32Array(message.buffer);
const uint8View = new Uint8Array(message.buffer);
return { int32View, uint8View };
}
return null;
}
Cross-origin isolation check
function checkSharedArrayBufferSupport() {
const support = {
available: typeof SharedArrayBuffer !== 'undefined',
crossOriginIsolated: globalThis.crossOriginIsolated || false,
secureContext: globalThis.isSecureContext || false
};
if (!support.available) {
console.warn('SharedArrayBuffer not available');
return support;
}
if (!support.crossOriginIsolated) {
console.warn('SharedArrayBuffer requires cross-origin isolation');
}
return support;
}
function createSharedBuffer(size: number): SharedArrayBuffer | null {
const support = checkSharedArrayBufferSupport();
if (!support.available || !support.crossOriginIsolated) {
return null;
}
const buffer = new SharedArrayBuffer(size);
if (isSharedArrayBuffer(buffer)) {
console.log(`Created shared buffer: ${buffer.byteLength} bytes`);
return buffer;
}
return null;
}
Atomic operations with shared memory
interface SharedCounter {
buffer: SharedArrayBuffer;
view: Int32Array;
}
function createSharedCounter(): SharedCounter | null {
if (typeof SharedArrayBuffer === 'undefined') {
console.error('SharedArrayBuffer not supported');
return null;
}
const buffer = new SharedArrayBuffer(4); // 4 bytes for one Int32
if (!isSharedArrayBuffer(buffer)) {
console.error('Failed to create SharedArrayBuffer');
return null;
}
const view = new Int32Array(buffer);
Atomics.store(view, 0, 0); // Initialize counter to 0
return { buffer, view };
}
function incrementSharedCounter(counter: SharedCounter): number {
if (!isSharedArrayBuffer(counter.buffer)) {
throw new Error('Invalid shared buffer');
}
// Atomic increment operation
return Atomics.add(counter.view, 0, 1) + 1;
}
function getSharedCounterValue(counter: SharedCounter): number {
if (!isSharedArrayBuffer(counter.buffer)) {
throw new Error('Invalid shared buffer');
}
return Atomics.load(counter.view, 0);
}
Worker communication with shared memory
// Main thread
class SharedMemoryManager {
private sharedBuffers = new Map<string, SharedArrayBuffer>();
createBuffer(id: string, size: number): boolean {
if (typeof SharedArrayBuffer === 'undefined') {
console.error('SharedArrayBuffer not supported');
return false;
}
const buffer = new SharedArrayBuffer(size);
if (isSharedArrayBuffer(buffer)) {
this.sharedBuffers.set(id, buffer);
return true;
}
return false;
}
getBuffer(id: string): SharedArrayBuffer | null {
const buffer = this.sharedBuffers.get(id);
return isSharedArrayBuffer(buffer) ? buffer : null;
}
shareWithWorker(worker: Worker, bufferId: string): boolean {
const buffer = this.getBuffer(bufferId);
if (!buffer) {
return false;
}
worker.postMessage({
type: 'SHARED_BUFFER',
id: bufferId,
buffer
});
return true;
}
}
// Worker thread (worker.js)
self.onmessage = function(event) {
const { type, id, buffer } = event.data;
if (type === 'SHARED_BUFFER' && isSharedArrayBuffer(buffer)) {
console.log(`Worker received shared buffer ${id}: ${buffer.byteLength} bytes`);
// Process data in shared memory
const view = new Uint8Array(buffer);
for (let i = 0; i < view.length; i++) {
view[i] = i % 256; // Fill with test data
}
self.postMessage({ type: 'BUFFER_PROCESSED', id });
}
};
Environment capability detection
interface EnvironmentCapabilities {
sharedArrayBuffer: boolean;
atomics: boolean;
crossOriginIsolated: boolean;
workers: boolean;
}
function detectEnvironmentCapabilities(): EnvironmentCapabilities {
return {
sharedArrayBuffer: typeof SharedArrayBuffer !== 'undefined',
atomics: typeof Atomics !== 'undefined',
crossOriginIsolated: globalThis.crossOriginIsolated || false,
workers: typeof Worker !== 'undefined'
};
}
function validateSharedMemoryEnvironment(): string[] {
const errors: string[] = [];
const caps = detectEnvironmentCapabilities();
if (!caps.sharedArrayBuffer) {
errors.push('SharedArrayBuffer not supported');
}
if (!caps.atomics) {
errors.push('Atomics not supported');
}
if (!caps.crossOriginIsolated) {
errors.push('Cross-origin isolation required for SharedArrayBuffer');
}
if (!caps.workers) {
errors.push('Web Workers not supported');
}
return errors;
}
// Usage
const validationErrors = validateSharedMemoryEnvironment();
if (validationErrors.length > 0) {
console.warn('Shared memory features unavailable:', validationErrors);
} else {
console.log('Environment supports shared memory operations');
}
Node.js worker_threads usage
// main-thread.js (Node.js)
import { Worker, isMainThread, parentPort } from 'worker_threads';
import { isSharedArrayBuffer } from '@winglet/common-utils';
if (isMainThread) {
// Main thread
const sharedBuffer = new SharedArrayBuffer(1024);
if (isSharedArrayBuffer(sharedBuffer)) {
const worker = new Worker(__filename, {
workerData: { sharedBuffer }
});
worker.postMessage({ type: 'process', buffer: sharedBuffer });
}
} else {
// Worker thread
parentPort?.on('message', ({ type, buffer }) => {
if (type === 'process' && isSharedArrayBuffer(buffer)) {
// Safe to use shared buffer in worker thread
const view = new Int32Array(buffer);
Atomics.store(view, 0, 42);
parentPort?.postMessage({ done: true });
}
});
}
Playground
import { isSharedArrayBuffer } from '@winglet/common-utils'; // True cases - SharedArrayBuffer instances (if supported) if (typeof SharedArrayBuffer !== 'undefined') { console.log(isSharedArrayBuffer(new SharedArrayBuffer(16))); // true console.log(isSharedArrayBuffer(new SharedArrayBuffer(1024))); // true } // False cases - not SharedArrayBuffer console.log(isSharedArrayBuffer(new ArrayBuffer(16))); // false (regular ArrayBuffer) console.log(isSharedArrayBuffer(new Uint8Array(16))); // false (TypedArray) console.log(isSharedArrayBuffer(new DataView(new ArrayBuffer(16)))); // false (DataView) console.log(isSharedArrayBuffer({})); // false (object) console.log(isSharedArrayBuffer(null)); // false console.log(isSharedArrayBuffer('buffer')); // false (string) // Environment without SharedArrayBuffer support // (older browsers, restricted contexts) console.log(isSharedArrayBuffer(anything)); // always false
Notes
Environment Requirements:
- Browsers: Requires cross-origin isolation (COOP/COEP headers) and HTTPS
- Node.js: Supported since v10.5.0 with worker_threads module
- Not available in all browsers or restricted environments
- May be disabled due to Spectre vulnerability mitigations
Security Considerations:
- SharedArrayBuffer was temporarily disabled due to Spectre vulnerabilities
- Requires proper security headers: Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy
- Only available in secure contexts (HTTPS)
Use Cases:
- Multi-threaded JavaScript applications (Web Workers, worker_threads)
- High-performance computing in browsers
- Real-time data processing with workers
- Shared state between worker threads
- Atomic operations for thread synchronization
- Node.js multi-core processing pipelines
Performance: Direct instanceof check with environment validation provides optimal performance.
Related Functions:
- Use
isArrayBuffer()for regular ArrayBuffer detection - Use
isTypedArray()for TypedArray views - Use
isDataView()for DataView objects - Check
typeof SharedArrayBuffer !== 'undefined'for environment support