Alteração interruptiva: métodos de sincronização para AccessHandles

O origin private file system oferece acesso a um tipo especial de arquivo altamente otimizado para desempenho, por exemplo, oferecendo acesso de gravação exclusivo e no local ao conteúdo de um arquivo. Os desenvolvedores podem acessar esses arquivos chamando createSyncAccessHandle(), que é um método exposto em objetos FileSystemFileHandle. Essa chamada resulta em um FileSystemSyncAccessHandle.

FileSystemSyncAccessHandle é uma primitiva de arquivo que oferece acesso eficiente a arquivos locais. Um dos principais casos de uso é a portabilidade de código C/C++ para Wasm. No entanto, as chamadas assíncronas ainda não têm suporte total no Wasm, e o uso da biblioteca Asyncify como alternativa reduziu significativamente a performance. Fazer com que todos os métodos do FileSystemSyncAccessHandle sejam síncronos correspondem à expectativa do aplicativo baseado em Wasm da API de arquivos síncrona e semelhante ao POSIX, tornando a API mais ergonômica e trazendo ganhos de desempenho substanciais.

O que há de novo?

FileSystemSyncAccessHandle expõe os seguintes métodos que costumavam ser assíncronos, mas que são síncronos a partir do Chromium 108.

  • truncate(newSize): redimensiona o arquivo associado ao identificador de acesso para ter newSize bytes de comprimento. Se newSize for maior que o tamanho do arquivo atual, ele será preenchido com bytes nulos. Caso contrário, o arquivo será truncado.
  • getSize(): retorna o tamanho do arquivo associado ao identificador de acesso em bytes.
  • flush(): garante que o conteúdo do arquivo associado ao identificador de acesso contenha todas as modificações feitas por write().
  • close(): limpa o identificador de acesso e o fecha. O fechamento de um identificador de acesso desativa outras operações nele e libera a trava na entrada associada ao identificador de acesso.
// 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();

O que eu preciso fazer?

A mudança de métodos assíncronos para síncronos é uma mudança exposta à Web com possíveis falhas. Embora o uso de await em métodos síncronos seja uma operação nula, qualquer uso de Promise.then() será interrompido. Se você encadenar uma chamada then() no resultado de qualquer um dos métodos anteriormente assíncronos e agora síncronos, será necessário mudar o 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 */