Cambio rotundo: métodos de sincronización para AccessHandles

El sistema de archivos privados de origen proporciona acceso a un tipo especial de archivo que está altamente optimizado para el rendimiento, por ejemplo, ofreciendo acceso de escritura exclusivo y en el lugar al contenido de un archivo. Los desarrolladores pueden obtener acceso a esos archivos llamando a createSyncAccessHandle(), que es un método expuesto en objetos FileSystemFileHandle. Esta llamada genera un FileSystemSyncAccessHandle.

FileSystemSyncAccessHandle es una primitiva de archivo que proporciona acceso de alto rendimiento a los archivos locales. Uno de sus principales casos de uso son las aplicaciones que portan código C/C++ a Wasm. Sin embargo, las llamadas asíncronas aún no son compatibles por completo con Wasm, y el uso de la biblioteca Asyncify como alternativa degradó significativamente el rendimiento. Hacer que todos los métodos de FileSystemSyncAccessHandle sean síncronos coincide con la aplicación basada en Wasm de la API de archivos síncronos similar a POSIX, lo que hace que la API sea más ergonómica y, al mismo tiempo, genera mejoras sustanciales en el rendimiento.

Novedades

FileSystemSyncAccessHandle expone los siguientes métodos que solían ser asíncronos, pero que son síncronos a partir de Chromium 108.

  • truncate(newSize): Cambia el tamaño del archivo asociado con el identificador de acceso para que sea de newSize bytes. Si newSize es mayor que el tamaño del archivo actual, lo completa con bytes nulos. De lo contrario, lo trunca.
  • getSize(): Muestra el tamaño del archivo asociado con el identificador de acceso en bytes.
  • flush(): Garantiza que el contenido del archivo asociado con el identificador de acceso contenga todas las modificaciones realizadas a través de write().
  • close(): Vacía el controlador de acceso y, luego, lo cierra. Cerrar un controlador de acceso inhabilita cualquier operación adicional en él y libera el bloqueo en la entrada asociada a él.
// In a `Worker`:
const root = await navigator.storage.getDirectory();
const fileHandle = await root.getFileHandle('test', { create: true });
// `createSyncAccessHandle()` is still async.
const accessHandle = await fileHandle.createSyncAccessHandle();
// Both `read()` and `write()` were sync before.
accessHandle.read(/* ... */);
accessHandle.write(/* ... */);

// New: synchronous as of Chromium 108.
console.log(accessHandle.getSize());
accessHandle.truncate(123);
accessHandle.flush();
accessHandle.close();

¿Qué debo hacer?

Ten en cuenta que cambiar los métodos de asíncronos a síncronos es un cambio expuesto a la Web con posibles fallas. Si bien usar await en métodos síncronos no realiza ninguna acción, cualquier uso de Promise.then() fallará. Si encadenas una llamada a then() en el resultado de cualquiera de los métodos previamente asíncronos y ahora síncronos, debes cambiar el código.

// (✅) This won't break, but you better remove the superfluous `await`:
await accessHandle.flush();
// ✅ Correct:
accessHandle.flush();
// ⛔️ This will break, and you need to restructure your code:
accessHandle.flush().then(/* Follow-up code */);
// ✅ Correct:
accessHandle.flush();
/* Follow-up code */