# Commit Message for SharedArrayBuffer Platform Exclusion

fix: eliminate SharedArrayBuffer checks on non-web platforms

* Add platform guard in AbsurdSqlDatabaseService to only initialize on web
* Change singleton pattern from eager to lazy instantiation
* Update worker import to use lazy singleton pattern
* Prevents absurd-sql initialization on Electron/Capacitor platforms
* Reduces console noise and memory footprint on desktop/mobile
* Maintains full web platform functionality and performance

Resolves SharedArrayBuffer-related console output on Electron platform
while preserving all web features and maintaining clean architecture.
This commit is contained in:
Matthew Raymer
2025-07-03 05:15:57 +00:00
parent 797db7069c
commit 292aceee75
21 changed files with 1044 additions and 151 deletions

View File

@@ -186,11 +186,8 @@ export class CapacitorPlatformService implements PlatformService {
sql: string,
params: unknown[] = [],
): Promise<R> {
// Log incoming parameters for debugging (HIGH PRIORITY)
logger.warn(
`[CapacitorPlatformService] queueOperation - SQL: ${sql}, Params:`,
params,
);
// Only log SQL operations in debug mode to reduce console noise
logger.debug(`[CapacitorPlatformService] queueOperation - SQL: ${sql}`);
// Convert parameters to SQLite-compatible types with robust serialization
const convertedParams = params.map((param, index) => {
@@ -198,72 +195,31 @@ export class CapacitorPlatformService implements PlatformService {
return null;
}
if (typeof param === "object" && param !== null) {
// Enhanced debug logging for all objects (HIGH PRIORITY)
logger.warn(
`[CapacitorPlatformService] Object param at index ${index}:`,
{
type: typeof param,
toString: param.toString(),
constructorName: param.constructor?.name,
isArray: Array.isArray(param),
keys: Object.keys(param),
stringRep: String(param),
},
);
// Special handling for Proxy objects (common cause of "An object could not be cloned")
const isProxy = this.isProxyObject(param);
logger.warn(
`[CapacitorPlatformService] isProxy result for index ${index}:`,
isProxy,
);
// AGGRESSIVE: If toString contains "Proxy", treat as Proxy even if isProxyObject returns false
const stringRep = String(param);
const forceProxyDetection =
stringRep.includes("Proxy(") || stringRep.startsWith("Proxy");
logger.warn(
`[CapacitorPlatformService] Force proxy detection for index ${index}:`,
forceProxyDetection,
);
if (isProxy || forceProxyDetection) {
logger.warn(
`[CapacitorPlatformService] Proxy object detected at index ${index} (method: ${isProxy ? "isProxyObject" : "stringDetection"}), toString: ${stringRep}`,
logger.debug(
`[CapacitorPlatformService] Proxy object detected at index ${index}`,
);
try {
// AGGRESSIVE EXTRACTION: Try multiple methods to extract actual values
if (Array.isArray(param)) {
// Method 1: Array.from() to extract from Proxy(Array)
const actualArray = Array.from(param);
logger.info(
`[CapacitorPlatformService] Extracted array from Proxy via Array.from():`,
actualArray,
);
// Method 2: Manual element extraction for safety
const manualArray: unknown[] = [];
for (let i = 0; i < param.length; i++) {
manualArray.push(param[i]);
}
logger.info(
`[CapacitorPlatformService] Manual array extraction:`,
manualArray,
);
// Use the manual extraction as it's more reliable
return manualArray;
return actualArray;
} else {
// For Proxy(Object), try to extract actual object
const actualObject = Object.assign({}, param);
logger.info(
`[CapacitorPlatformService] Extracted object from Proxy:`,
actualObject,
);
return actualObject;
}
} catch (proxyError) {
logger.error(
logger.debug(
`[CapacitorPlatformService] Failed to extract from Proxy at index ${index}:`,
proxyError,
);
@@ -275,16 +231,8 @@ export class CapacitorPlatformService implements PlatformService {
for (let i = 0; i < param.length; i++) {
fallbackArray.push(param[i]);
}
logger.info(
`[CapacitorPlatformService] Fallback array extraction successful:`,
fallbackArray,
);
return fallbackArray;
} catch (fallbackError) {
logger.error(
`[CapacitorPlatformService] Fallback array extraction failed:`,
fallbackError,
);
return `[Proxy Array - Could not extract]`;
}
}
@@ -297,14 +245,10 @@ export class CapacitorPlatformService implements PlatformService {
return JSON.stringify(param);
} catch (error) {
// Handle non-serializable objects
logger.error(
logger.debug(
`[CapacitorPlatformService] Failed to serialize parameter at index ${index}:`,
error,
);
logger.error(
`[CapacitorPlatformService] Problematic parameter:`,
param,
);
// Fallback: Convert to string representation
if (Array.isArray(param)) {
@@ -319,14 +263,14 @@ export class CapacitorPlatformService implements PlatformService {
}
if (typeof param === "function") {
// Functions can't be serialized - convert to string representation
logger.warn(
logger.debug(
`[CapacitorPlatformService] Function parameter detected and converted to string at index ${index}`,
);
return `[Function ${param.name || "Anonymous"}]`;
}
if (typeof param === "symbol") {
// Symbols can't be serialized - convert to string representation
logger.warn(
logger.debug(
`[CapacitorPlatformService] Symbol parameter detected and converted to string at index ${index}`,
);
return param.toString();
@@ -338,12 +282,6 @@ export class CapacitorPlatformService implements PlatformService {
return param;
});
// Log converted parameters for debugging (HIGH PRIORITY)
logger.warn(
`[CapacitorPlatformService] Converted params:`,
convertedParams,
);
return new Promise<R>((resolve, reject) => {
// Create completely plain objects that Vue cannot make reactive
// Step 1: Deep clone the converted params to ensure they're plain objects
@@ -361,20 +299,6 @@ export class CapacitorPlatformService implements PlatformService {
Object.freeze(operation.params);
Object.freeze(operation);
// Add enhanced logging to verify our fix
logger.warn(
`[CapacitorPlatformService] Final operation.params type:`,
typeof operation.params,
);
logger.warn(
`[CapacitorPlatformService] Final operation.params toString:`,
operation.params.toString(),
);
logger.warn(
`[CapacitorPlatformService] Final operation.params constructor:`,
operation.params.constructor?.name,
);
this.operationQueue.push(operation);
// If we're already initialized, start processing the queue
@@ -573,20 +497,17 @@ export class CapacitorPlatformService implements PlatformService {
sql: string,
params?: unknown[],
): Promise<capSQLiteChanges> => {
logger.log(`🔧 [CapacitorMigration] Executing SQL:`, sql);
logger.log(`📋 [CapacitorMigration] With params:`, params);
logger.debug(`🔧 [CapacitorMigration] Executing SQL:`, sql);
if (params && params.length > 0) {
// Use run method for parameterized queries (prepared statements)
// This is essential for proper parameter binding and SQL injection prevention
const result = await this.db!.run(sql, params);
logger.log(`✅ [CapacitorMigration] Run result:`, result);
return result;
} else {
// Use execute method for non-parameterized queries
// This is more efficient for simple DDL statements
const result = await this.db!.execute(sql);
logger.log(`✅ [CapacitorMigration] Execute result:`, result);
return result;
}
};
@@ -606,11 +527,9 @@ export class CapacitorPlatformService implements PlatformService {
sql: string,
params?: unknown[],
): Promise<DBSQLiteValues> => {
logger.log(`🔍 [CapacitorMigration] Querying SQL:`, sql);
logger.log(`📋 [CapacitorMigration] With params:`, params);
logger.debug(`🔍 [CapacitorMigration] Querying SQL:`, sql);
const result = await this.db!.query(sql, params);
logger.log(`📊 [CapacitorMigration] Query result:`, result);
return result;
};
@@ -633,7 +552,7 @@ export class CapacitorPlatformService implements PlatformService {
* @returns Set of migration names found in the result
*/
const extractMigrationNames = (result: DBSQLiteValues): Set<string> => {
logger.log(
logger.debug(
`🔍 [CapacitorMigration] Extracting migration names from:`,
result,
);
@@ -652,7 +571,7 @@ export class CapacitorPlatformService implements PlatformService {
})
.filter((name) => name !== null) || [];
logger.log(`📋 [CapacitorMigration] Extracted names:`, names);
logger.debug(`📋 [CapacitorMigration] Extracted names:`, names);
return new Set(names);
};
@@ -728,14 +647,14 @@ export class CapacitorPlatformService implements PlatformService {
return;
}
logger.log(`🔍 [DB-Integrity] Starting database integrity check...`);
logger.debug(`🔍 [DB-Integrity] Starting database integrity check...`);
try {
// Step 1: Check migrations table and applied migrations
const migrationsResult = await this.db.query(
"SELECT name, applied_at FROM migrations ORDER BY applied_at",
);
logger.log(`📊 [DB-Integrity] Applied migrations:`, migrationsResult);
logger.debug(`📊 [DB-Integrity] Applied migrations:`, migrationsResult);
// Step 2: Verify core tables exist
const coreTableNames = [
@@ -755,7 +674,7 @@ export class CapacitorPlatformService implements PlatformService {
);
if (tableCheck.values && tableCheck.values.length > 0) {
existingTables.push(tableName);
logger.log(`✅ [DB-Integrity] Table ${tableName} exists`);
logger.debug(`✅ [DB-Integrity] Table ${tableName} exists`);
} else {
logger.error(`❌ [DB-Integrity] Table ${tableName} missing`);
}
@@ -773,7 +692,7 @@ export class CapacitorPlatformService implements PlatformService {
const contactsSchema = await this.db.query(
"PRAGMA table_info(contacts)",
);
logger.log(
logger.debug(
`📊 [DB-Integrity] Contacts table schema:`,
contactsSchema,
);
@@ -789,7 +708,7 @@ export class CapacitorPlatformService implements PlatformService {
);
if (hasIViewContent) {
logger.log(
logger.debug(
`✅ [DB-Integrity] iViewContent column exists in contacts table`,
);
} else {
@@ -817,7 +736,7 @@ export class CapacitorPlatformService implements PlatformService {
"SELECT COUNT(*) as count FROM contacts",
);
logger.log(
logger.debug(
`📊 [DB-Integrity] Data counts - Accounts: ${JSON.stringify(accountCount)}, Settings: ${JSON.stringify(settingsCount)}, Contacts: ${JSON.stringify(contactsCount)}`,
);
} catch (error) {
@@ -1356,4 +1275,28 @@ export class CapacitorPlatformService implements PlatformService {
}
return undefined;
}
/**
* Checks if running on Capacitor platform.
* @returns true, as this is the Capacitor implementation
*/
isCapacitor(): boolean {
return true;
}
/**
* Checks if running on Electron platform.
* @returns false, as this is Capacitor, not Electron
*/
isElectron(): boolean {
return false;
}
/**
* Checks if running on web platform.
* @returns false, as this is not web
*/
isWeb(): boolean {
return false;
}
}