WebAssembly Migration Guide

(P)NaCl Deprecation Announcements

Given the momentum of cross-browser WebAssembly support, we plan to focus our native code efforts on WebAssembly going forward and plan to remove support for PNaCl in Q1 2018 (except for Chrome Apps). We believe that the vibrant ecosystem around WebAssembly makes it a better fit for new and existing high-performance web apps and that usage of PNaCl is sufficiently low to warrant deprecation.

We also recently announced the deprecation Q1 2018 of Chrome Apps outside of ChromeOS.

Toolchain Migration

For the majority of (P)NaCl uses cases we recommend transitioning from the NaCl SDK to Emscripten. Migration is likely to be reasonably straightforward if your application is portable to Linux, uses SDL, or POSIX APIs. While direct support for NaCl / Pepper APIs in not available, we’ve attempted to list Web API equivalents. For more challenging porting cases, please reach out on native-client-discuss@googlegroups.com

API Migration

We’ve outlined here the status of Web Platform substitutes for each of the APIs exposed to (P)NaCl. Additionally, the table lists the library or option in Emscripten that offers the closest substitute.

We expect to add shared memory threads support to WebAssembly in 2017, as threads are crucial to matching (P)NaCl’s most interesting use cases. Migration items which assume forthcoming threads support are marked below. If your application’s flow control relies heavily on blocking APIs, you may also find threads support is required for convenient porting.

While we’ve tried to be accurate in this table, there are no doubt errors or omissions. If you encounter one, please reach out to us on native-client-discuss@googlegroups.com

PPAPI

PPB_Audio

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create x SDL (partial) GAP (partial) - AudioWorkletNode ROUGHLY equivalent Still being standardized.
GetCurrentConfig SDL AudioContext.* (gets back settings passed in)
StartPlayback SDL AudioBufferSourceNode.start
StopPlayback SDL AudioBufferSourceNode.stop

PPB_AudioBuffer

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetTimestamp SDL AudioBufferSourceNode.start (parameter) Passed in each time instead of attached to the buffer.
SetTimestamp SDL AudioBufferSourceNode.start (parameter)
GetSampleRate SDL AudioBuffer.sampleRate
GetSampleSize GAP GAP - WebAudio only uses 32-bit float, PPAPI does 16-bit int. PPAPI theoretically supports multiple sampling sizes. In practice, it only supports 16-bit samples. Unfortunately, developers have requested 16-bit sample sizes to save on memory use.
GetNumberOfChannels SDL AudioBuffer.numberOfChannels
GetDataBuffer SDL AudioBuffer.getChannelData
GetBufferSize SDL AudioBuffer.length

PPB_AudioConfig

PPAPI Method Assumes Threads Emscripten Web API Limitations
CreateStereo16Bit GAP GAP - Only 32-bit float samples supported
GetSampleRate SDL AudioContext.sampleRate
GetSampleFrameCount SDL AudioBuffer.length
RecommendSampleRate SDL AudioContext.sampleRate (from default construct) An AudioContext will have the preferred sampling rate by default.
RecommendSampleFrameCount GAP GAP - No mechanism to get a recomended buffer size.

PPB_Console

PPAPI Method Assumes Threads Emscripten Web API Limitations
Log utime console.log/warn/error/...
LogWithSource GAP GAP PPAPI provides a way to override the source filename and line number in a console message. (Though JS API provides way to style text).

PPB_Core

PPAPI Method Assumes Threads Emscripten Web API Limitations
getTime utime new Date().getTime()
getTimeTicks utime new Date().getTime()
IsMainThread GAP window.document !== undefined
CallOnMainThread GAP Worker.postMessage + Atomics.wait Equivalent synchronization can be built.

PPB_FileIO

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create FS (partial) FileReader / FileWrite (Entry.createReader / Entry.createWriter) Create and open are used differently, but the pieces are of equal power.
Open FS (partial) FileReader / FileWrite (Entry.createReader / Entry.createWriter)
Query FS (partial) Entry.getMetadata
Touch FS (partial) GAP (partial) - No direct equivalent, but no access time either. Modify time can be bumped by writing.
Read FS (partial) Entry.getFile + Blob.slice + FileReader.getBinaryData Note, this API requires an extra copy to get a read into linear memory, and may be worse than that if Blob slices are not optimizes to use mmap.
Write FS (partial) FileWriter.seek + FileWriter.write 'write*' Events
SetLength FS (partial) FileWriter.truncate + 'write*' Events
Flush GAP GAP - No equivalent, no way to flush.
Close FS (partial) No equivalent, open files and directories are implicitly closed.
ReadToArray GAP GAP - No equivalent. Allows multiple subrange reads in parallel.

PPB_FileRef

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create FS (partial) Entry.getFile(..., {create:true})
GetFileSystemType FS (partial) FileSystem.type
GetName FS (partial) Entry.name
GetPath FS (partial) Entry.fullPath
GetParent FS (partial) Entry.getParent
MakeDirectory FS (partial) Entry.getDirectory(..., {create:true})
Touch FS (partial) GAP (partial) - No direct equivalent, but no access time either. Modify time can be bumped by writing.
Delete FS (partial) Entry.remove
Rename FS (partial) Entry.moveTo
Query GAP Entry.getMetadata GAP - JS API has file size and last modified date, but doesn't have creation date and last accessed date.
ReadDirectoryEntries FS (partial) Directory.readEntries

PPB_FileSystem

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create FS (partial) window.requestFileSystem JS API does both in one step
Open GAP window.requestFileSystem GAP - Filesystems API is chrome only. IndexedDB has additional performance limitations around subrange writes.
GetType GAP FileSystem.type

PPB_Fullscreen

PPAPI Method Assumes Threads Emscripten Web API Limitations
IsFullScreen html5.h Document.fullscreenEnabled
SetFullscreen html5.h Document.requestFullscreen
GetScreenSize html5.h Document.exitFullscreen

PPB_Gamepad

PPAPI Method Assumes Threads Emscripten Web API Limitations
Sample SDL Gamepad.* GAP - PPAPI exposes a timestamp value, but the JS API doesn't provide this (though it is spec'd).

PPB_Graphics2D

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL Canvas.getContext('2d')
Describe SDL Canvas.clientWidth + Canvas.clientHeight
PaintImageData SDL CanvasRenderingContext2d.putImageData
Scroll GAP CanvasRenderingContext2d.scrollIntoView GAP (partial) - Not an exact match (might have to resort to getImageData + putImageData which will be slow). Not a cross-browser standard.
ReplaceContents SDL CanvasRenderingContext2d.drawImage
Flush GAP GAP - Only returning to the event loop triggers the flush.
SetScale SDL CanvasRenderingContext2d.scale
GetScale SDL CanvasRenderingContext2d.currentTransform
SetLayerTransform SDL CanvasRenderingContext2d.setTransform CanvasRenderingContext2d.scale CanvasRenderingContext2d.translate

PPB_Graphics3D

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetAttribMaxValue GAP GAP - Canvas.getContext lets you set booleans requesting depth / stencil buffers of certain sizes, but does not have a way to query what's possible (or get anything other than on or off for each)
Create SDL Canvas.getContext
GetAttribs SDL WebGLRenderingContext.getContextAttributes
SetAttribs SDL Canvas.getContext(.., OPTIONS)
GetError SDL WebGLRenderingContext.getError
ResizeBuffers SDL Canvas.width = w; Canvas.height = h;
SwapBuffers GAP GAP - No way to explicitly flip a frame, must return to the event loop.

PPB_ImageData

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetNativeImageDataFormat SDL ImageData mandates RGBA order
IsImageDataFormatSupported SDL ImageData mandates RGBA order
Create SDL CanvasRenderingContext2d.createImageData
Describe SDL ImageData never has a stride
Map SDL ImageData.data
Unmap SDL ImageData.data

PPB_InputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
RequestInputEvents SDL No direct equivalent The lack of this feature is probably less relevant as JS / Wasm runs on the main thread and can more cheaply filter events without incurring a cross process round-trip.
RequestFilteringInputEvents SDL mouse* key* wheel* touch* composition* Events
SDL Element.addEventListener
ClearInputEventRequest SDL Element.removeEventListener
GetType SDL Event class descendants
GetTimeStamp SDL Event.timeStamp
GetModifiers SDL *Event.altKey/shiftKey/metaKey/ctrlKey

PPB_MouseInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL MouseEvent
GetButton SDL MouseEvent.button
GetPosition SDL MouseEvent.client*/page*/offset*
GetClickCount SDL dblclick' vs 'mousedown' Events
GetMovement SDL MouseEvent.movement*

PPB_WheelInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL WheelEvent
GetDelta SDL WheelEvent.delta*
GetTicks GAP GAP - deltaMode kinda of contains this info, but incompletely.
GetScrollByPage GAP GAP - deltaMode kinda of contains this info, but incompletely.

PPB_KeyboardInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL KeyboardEvent
GetKeyCode SDL KeyboardEvent.keyCode
GetCharacterText SDL KeyboardEvent.key
GetCode SDL KeyboardEvent.code

PPB_TouchInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL TouchEvent
AddTouchPoint SDL TouchEvent.touches.push
GetTouchCount SDL TouchEvent.touches.length
GetTouchByIndex SDL TouchEvent.touches[i]
GetTouchById SDL Touch.indentifer (to figure this out yourself)

PPB_IMEInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP CompositionEvent
GetText GAP CompositionEvent.data
GetSegmentNumber GAP GAP - No direct equivalent
GetSegmentOffset GAP GAP - No direct equivalent
GetTargetSegment GAP GAP - No direct equivalent
GetSelection GAP GAP - No direct equivalent

PPB_Instance

PPAPI Method Assumes Threads Emscripten Web API Limitations
BindGraphics SDL Canvas.getContext (moot as binding is automatic).
IsFullFrame GAP GAP - No equivalent to mime type handlers. NaCl apps can be registered to handle a particular mime type and own the whole document.

PPB_MediaStreamAudioTrack

PPAPI Method Assumes Threads Emscripten Web API Limitations
Configure GAP GAP - No equivalent
GetAttrib GAP MediaStreamSettings.channelCount
GAP MediaStreamSettings.sampleSize
GAP MediaStreamSettings.sampleRate
GAP GAP - no equivalent to PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS
GAP GAP - no equivalent to PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION
GetId GAP MediaStream.id
HasEnded GAP MediaStream.ended
GetBuffer GAP GAP - No equivalent
RecycleBuffer GAP GAP - No equivalent
Close GAP GAP - No equivalent

PPB_MediaStreamVideoTrack

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP GAP - No equivalent Ability to create synthetic stream.
Configure GAP GAP - No equivalent
GetAttrib GAP MediaStreamSettings.width
GAP MediaStreamSettings.height
GAP GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_BUFFERED_FRAMES
GAP GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT
GetId GAP MediaStream.id
HasEnded GAP MediaStream.ended
GetFrame GAP GAP - No equivalent
RecycleFrame GAP GAP - No equivalent
Close GAP GAP - No equivalent
GetEmptyFrame GAP GAP - No equivalent
PutFrame GAP GAP - No equivalent

PPB_MessageLoop

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create N/A Mostly moot, workers get an implicit event loop.
GetForMainThread N/A Mostly moot, workers get an implicit event loop.
GetCurrent N/A Mostly moot, workers get an implicit event loop.
AttachToCurrentThread N/A Mostly moot, workers get an implicit event loop.
Run N/A Mostly moot, workers get an implicit event loop.
PostWork N/A Mostly moot, workers get an implicit event loop.
PostQuit N/A Mostly moot, workers get an implicit event loop.

PPB_Messaging

PPAPI Method Assumes Threads Emscripten Web API Limitations
PostMessage N/A Window.postMessage
RegisterMessageHandler N/A Window.addEventListener
UnregisterMessageHandler N/A Window.removeEventListener

PPB_MouseCursor

PPAPI Method Assumes Threads Emscripten Web API Limitations
SetCursor SDL Element.style.cursor Same set of stock cursors are supported. Custom cursors can be done with url(..). Dynamic custom cursors can be done with data URIs. CSS3 supports specifying the hotspot.

PPB_MouseLock

PPAPI Method Assumes Threads Emscripten Web API Limitations
LockMouse SDL Element.requestPointerLock
UnlockMouse SDL Element.exitPointerLock

PPB_OpenGLES2

PPAPI Method Assumes Threads Emscripten Web API Limitations
Several Methods OpenGLES Close to WebGL 1.0 in functionality.
x GAP - Without offscreen canvas, rendering must be done on the main thread.

PPB_TextInputController

PPAPI Method Assumes Threads Emscripten Web API Limitations
SetTextInputType GAP GAP - No equivalent hints to browser about canvas containing input. Some developers would like to either be able to hint in this fashion, or preferrably the ability to intercept and display IME events / output inline inside a canvas.
UpdateCaretPosition GAP GAP - No equivalent hints to browser about canvas containing input.
CancelCompositionText GAP GAP - No equivalent hints to browser about canvas containing input.
UpdateSurroundingText GAP GAP - No equivalent hints to browser about canvas containing input.

PPB_URLLoader

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind new XMLHttpRequest();
Open embind XMLHttpRequest.open
FollowRedirect embind Request.redirect
GAP GAP - No XMLHTTPRequest equivalent
GetUploadProgress embind XMLHttpRequest 'progress' Event
GAP GAP - No Fetch API equivalent
GetDownloadProgress embind XMLHttpRequest 'progress' Event
GAP GAP - No Fetch API equivalent
GetResponseInfo embind XMLHttpRequest.getAllResponseHeaders
embind Fetch Response.*
ReadResponseBody embind XMLHttpRequest.response
embind Body.* (Response is a Body)
FinishStreamingToFile embind GAP - No direct equivalent XMLHttpRequest and Fetch both assume streaming to memory, rather than directly to a storage.
Close embind XMLHttpRequest.abort
GAP GAP - No Fetch API equivalent

PPB_URLRequestInfo

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind XMLHttpRequest
embind Fetch Request No way to stream to a file.
SetProperty GAP GAP - No direct equivalent for XMLHttpRequest XMLHttpRequest doesn't provide direct ways to per-request limit following redirects, stream to a file, set referrer or credentials policy.
embind Request.*
AppendDataToBody embind XMLHttpRequest.send GAP - Both must have the whole body, rather than a chunk.
embind fetch(.., options:body)
AppendFileToBody GAP GAP - No direct equivalent
N/A <form> You can also read with FileReader and upload, but that's more like AppendDataToBody

PPB_URLResponseInfo

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetProperty embind XMLHttpRequest.getAllResponseHeaders + others
embind Fetch Response.*
GetBodyAsFileRef embind Fetch Response (Body) .blob() Assumes storage layer optimizes transfer.

PPB_Var

PPAPI Method Assumes Threads Emscripten Web API Limitations
VarFromUtf8 embind TextDecoder.decode
VarToUtf8 embind TextEncoder.encode
VarFromResource N/A N/A
VarToResource N/A N/A

PPB_VarArray

PPAPI Method Assumes Threads Emscripten Web API Limitations
Get embind Array[i]
Set embind Array[i] = x
GetLength embind Array.length
SetLength embind Array.length = n

PPB_VarArrayBuffer

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind new ArrayBuffer(n)
ByteLength embind ArrayBuffer.byteLength
Map GAP GAP - No direct equivalent Asm.js / Wasm modules are unable to map regions of an ArrayBuffer other than their single linear memory heap. Future multiple memories or memory mapping might improve this.
Unmap GAP GAP - No direct equivalent

PPB_VarDictionary

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind {}
Get embind <Object>[i]
Set embind <Object>[i] = x
Delete embind delete <Object>[i]
HasKey embind x in <Object>
GetKeys embind for (k in <Object>) {} No literal equivalent, but it can be built.

PPB_VideoDecoder

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP GAP - No equivalent
Initialize GAP GAP - No equivalent
Decode GAP GAP - No equivalent
GetPicture GAP GAP - No equivalent
RecyclePicture GAP GAP - No equivalent
Flush GAP GAP - No equivalent
Reset GAP GAP - No equivalent

PPB_VideoEncoder

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP GAP - No equivalent Overlap with MediaRecorder API, but not exact.
GetSupportedProfiles GAP GAP - No equivalent
Initialize GAP GAP - No equivalent
GetFramesRequired GAP GAP - No equivalent
GetFrameCodedSize GAP GAP - No equivalent
GetVideoFrame GAP GAP - No equivalent
Encode GAP GAP - No equivalent
GetBitstreamBuffer GAP GAP - No equivalent
RecycleBitstreamBuffer GAP GAP - No equivalent
RequestEncodingParametersChange GAP GAP - No equivalent
Close GAP GAP - No equivalent

PPB_VideoFrame

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetTimestamp GAP GAP - No equivalent
SetTimestamp GAP GAP - No equivalent
GetFormat GAP GAP - No equivalent
GetSize GAP GAP - No equivalent
GetDataBuffer GAP GAP - No equivalent
GetDataBufferSize GAP GAP - No equivalent

PPB_View

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetRect embind Element.getBoundingClientRect
IsFullscreen embind Document.fullScreenEnabled Pertains to document instead of just single element.
IsVisible embind IntersectionObserver
IsPageVisible embind document.visibilityState
GetClipRect embind IntersectionObserver
GetDeviceScale embind window.devicePixelRatio
GetCSSScale embind <Element>.getBoundingClientRect().width / <Element>.offsetWidth
GetScrollOffset embind <Element>.scrollTop / <Element>.scrollLeft

PPB_WebSocket

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP WebSocket.WebSocket
Connect GAP WebSocket.WebSocket(url, ...) WebSocket 'open' Event
Close GAP WebSocket.close
ReceiveMessage GAP WebSocket 'message' Event WebSocket 'error' Event WebSocket 'close' Event
SendMessage GAP WebSocket.send
GetBufferedAmount GAP WebSocket.bufferedAmount
GetCloseCode GAP CloseEvent.code
GetCloseReason GAP CloseEvent.reason
GetCloseWasClean GAP CloseEvent.wasClean
GetExtensions GAP WebSocket.extensions
GetProtocol GAP WebSocket.protocol
GetReadyState GAP WebSocket.readyState
GetURL GAP WebSocket.url

PPP_Graphics3D

PPAPI Method Assumes Threads Emscripten Web API Limitations
Graphics3DContextLost SDL Canvas 'webglcontextlost' Event

PPP_InputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
HandleInputEvent SDL Element.addEventListener

PPP_Instance

PPAPI Method Assumes Threads Emscripten Web API Limitations
DidCreate N/A <Element>[key] General DOM access lets you fish out tag attributes
DidDestroy N/A N/A Not triggered for NaCl
DidChangeView N/A Element 'resize' Event
DidChangeFocus N/A Element 'focus', 'focusin', 'focusout' Events
HandleDocumentLoad N/A GAP - No way to register as a mime type handler NaCl modules via apps + a manifest entry can be set up to handle particular mime types.

PPP_MessageHandler

PPAPI Method Assumes Threads Emscripten Web API Limitations
HandleMessage embind MessagePort 'message' Event Window 'message' Event
HandleBlockingMessage N/A GAP - No direct equivalent Similar synchronization can be done off main thread with Atomics.wait. This was added to support emulation of synchronous plugin APIs.

PPP_Messaging

PPAPI Method Assumes Threads Emscripten Web API Limitations
HandleMessage embind MessagePort 'message' Event Window 'message' Event

PPP_MouseLock

PPAPI Method Assumes Threads Emscripten Web API Limitations
MouseLockLost SDL Element 'pointerlockchange', 'pointerlockerror' Events

IRT

PPB_Audio

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create x SDL (partial) GAP (partial) - AudioWorkletNode ROUGHLY equivalent Still being standardized.
GetCurrentConfig SDL AudioContext.* (gets back settings passed in)
StartPlayback SDL AudioBufferSourceNode.start
StopPlayback SDL AudioBufferSourceNode.stop

PPB_AudioBuffer

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetTimestamp SDL AudioBufferSourceNode.start (parameter) Passed in each time instead of attached to the buffer.
SetTimestamp SDL AudioBufferSourceNode.start (parameter)
GetSampleRate SDL AudioBuffer.sampleRate
GetSampleSize GAP GAP - WebAudio only uses 32-bit float, PPAPI does 16-bit int. PPAPI theoretically supports multiple sampling sizes. In practice, it only supports 16-bit samples. Unfortunately, developers have requested 16-bit sample sizes to save on memory use.
GetNumberOfChannels SDL AudioBuffer.numberOfChannels
GetDataBuffer SDL AudioBuffer.getChannelData
GetBufferSize SDL AudioBuffer.length

PPB_AudioConfig

PPAPI Method Assumes Threads Emscripten Web API Limitations
CreateStereo16Bit GAP GAP - Only 32-bit float samples supported
GetSampleRate SDL AudioContext.sampleRate
GetSampleFrameCount SDL AudioBuffer.length
RecommendSampleRate SDL AudioContext.sampleRate (from default construct) An AudioContext will have the preferred sampling rate by default.
RecommendSampleFrameCount GAP GAP - No mechanism to get a recomended buffer size.

PPB_Console

PPAPI Method Assumes Threads Emscripten Web API Limitations
Log utime console.log/warn/error/...
LogWithSource GAP GAP PPAPI provides a way to override the source filename and line number in a console message. (Though JS API provides way to style text).

PPB_Core

PPAPI Method Assumes Threads Emscripten Web API Limitations
getTime utime new Date().getTime()
getTimeTicks utime new Date().getTime()
IsMainThread GAP window.document !== undefined
CallOnMainThread GAP Worker.postMessage + Atomics.wait Equivalent synchronization can be built.

PPB_FileIO

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create FS (partial) FileReader / FileWrite (Entry.createReader / Entry.createWriter) Create and open are used differently, but the pieces are of equal power.
Open FS (partial) FileReader / FileWrite (Entry.createReader / Entry.createWriter)
Query FS (partial) Entry.getMetadata
Touch FS (partial) GAP (partial) - No direct equivalent, but no access time either. Modify time can be bumped by writing.
Read FS (partial) Entry.getFile + Blob.slice + FileReader.getBinaryData Note, this API requires an extra copy to get a read into linear memory, and may be worse than that if Blob slices are not optimizes to use mmap.
Write FS (partial) FileWriter.seek + FileWriter.write 'write*' Events
SetLength FS (partial) FileWriter.truncate + 'write*' Events
Flush GAP GAP - No equivalent, no way to flush.
Close FS (partial) No equivalent, open files and directories are implicitly closed.
ReadToArray GAP GAP - No equivalent. Allows multiple subrange reads in parallel.

PPB_FileRef

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create FS (partial) Entry.getFile(..., {create:true})
GetFileSystemType FS (partial) FileSystem.type
GetName FS (partial) Entry.name
GetPath FS (partial) Entry.fullPath
GetParent FS (partial) Entry.getParent
MakeDirectory FS (partial) Entry.getDirectory(..., {create:true})
Touch FS (partial) GAP (partial) - No direct equivalent, but no access time either. Modify time can be bumped by writing.
Delete FS (partial) Entry.remove
Rename FS (partial) Entry.moveTo
Query GAP Entry.getMetadata GAP - JS API has file size and last modified date, but doesn't have creation date and last accessed date.
ReadDirectoryEntries FS (partial) Directory.readEntries

PPB_FileSystem

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create FS (partial) window.requestFileSystem JS API does both in one step
Open GAP window.requestFileSystem GAP - Filesystems API is chrome only. IndexedDB has additional performance limitations around subrange writes.
GetType GAP FileSystem.type

PPB_Fullscreen

PPAPI Method Assumes Threads Emscripten Web API Limitations
IsFullScreen html5.h Document.fullscreenEnabled
SetFullscreen html5.h Document.requestFullscreen
GetScreenSize html5.h Document.exitFullscreen

PPB_Gamepad

PPAPI Method Assumes Threads Emscripten Web API Limitations
Sample SDL Gamepad.* GAP - PPAPI exposes a timestamp value, but the JS API doesn't provide this (though it is spec'd).

PPB_Graphics2D

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL Canvas.getContext('2d')
Describe SDL Canvas.clientWidth + Canvas.clientHeight
PaintImageData SDL CanvasRenderingContext2d.putImageData
Scroll GAP CanvasRenderingContext2d.scrollIntoView GAP (partial) - Not an exact match (might have to resort to getImageData + putImageData which will be slow). Not a cross-browser standard.
ReplaceContents SDL CanvasRenderingContext2d.drawImage
Flush GAP GAP - Only returning to the event loop triggers the flush.
SetScale SDL CanvasRenderingContext2d.scale
GetScale SDL CanvasRenderingContext2d.currentTransform
SetLayerTransform SDL CanvasRenderingContext2d.setTransform CanvasRenderingContext2d.scale CanvasRenderingContext2d.translate

PPB_Graphics3D

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetAttribMaxValue GAP GAP - Canvas.getContext lets you set booleans requesting depth / stencil buffers of certain sizes, but does not have a way to query what's possible (or get anything other than on or off for each)
Create SDL Canvas.getContext
GetAttribs SDL WebGLRenderingContext.getContextAttributes
SetAttribs SDL Canvas.getContext(.., OPTIONS)
GetError SDL WebGLRenderingContext.getError
ResizeBuffers SDL Canvas.width = w; Canvas.height = h;
SwapBuffers GAP GAP - No way to explicitly flip a frame, must return to the event loop.

PPB_ImageData

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetNativeImageDataFormat SDL ImageData mandates RGBA order
IsImageDataFormatSupported SDL ImageData mandates RGBA order
Create SDL CanvasRenderingContext2d.createImageData
Describe SDL ImageData never has a stride
Map SDL ImageData.data
Unmap SDL ImageData.data

PPB_InputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
RequestInputEvents SDL No direct equivalent The lack of this feature is probably less relevant as JS / Wasm runs on the main thread and can more cheaply filter events without incurring a cross process round-trip.
RequestFilteringInputEvents SDL mouse* key* wheel* touch* composition* Events
SDL Element.addEventListener
ClearInputEventRequest SDL Element.removeEventListener
GetType SDL Event class descendants
GetTimeStamp SDL Event.timeStamp
GetModifiers SDL *Event.altKey/shiftKey/metaKey/ctrlKey

PPB_MouseInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL MouseEvent
GetButton SDL MouseEvent.button
GetPosition SDL MouseEvent.client*/page*/offset*
GetClickCount SDL dblclick' vs 'mousedown' Events
GetMovement SDL MouseEvent.movement*

PPB_WheelInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL WheelEvent
GetDelta SDL WheelEvent.delta*
GetTicks GAP GAP - deltaMode kinda of contains this info, but incompletely.
GetScrollByPage GAP GAP - deltaMode kinda of contains this info, but incompletely.

PPB_KeyboardInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL KeyboardEvent
GetKeyCode SDL KeyboardEvent.keyCode
GetCharacterText SDL KeyboardEvent.key
GetCode SDL KeyboardEvent.code

PPB_TouchInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL TouchEvent
AddTouchPoint SDL TouchEvent.touches.push
GetTouchCount SDL TouchEvent.touches.length
GetTouchByIndex SDL TouchEvent.touches[i]
GetTouchById SDL Touch.indentifer (to figure this out yourself)

PPB_IMEInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP CompositionEvent
GetText GAP CompositionEvent.data
GetSegmentNumber GAP GAP - No direct equivalent
GetSegmentOffset GAP GAP - No direct equivalent
GetTargetSegment GAP GAP - No direct equivalent
GetSelection GAP GAP - No direct equivalent

PPB_Instance

PPAPI Method Assumes Threads Emscripten Web API Limitations
BindGraphics SDL Canvas.getContext (moot as binding is automatic).
IsFullFrame GAP GAP - No equivalent to mime type handlers. NaCl apps can be registered to handle a particular mime type and own the whole document.

PPB_MediaStreamAudioTrack

PPAPI Method Assumes Threads Emscripten Web API Limitations
Configure GAP GAP - No equivalent
GetAttrib GAP MediaStreamSettings.channelCount
GAP MediaStreamSettings.sampleSize
GAP MediaStreamSettings.sampleRate
GAP GAP - no equivalent to PP_MEDIASTREAMAUDIOTRACK_ATTRIB_BUFFERS
GAP GAP - no equivalent to PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION
GetId GAP MediaStream.id
HasEnded GAP MediaStream.ended
GetBuffer GAP GAP - No equivalent
RecycleBuffer GAP GAP - No equivalent
Close GAP GAP - No equivalent

PPB_MediaStreamVideoTrack

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP GAP - No equivalent Ability to create synthetic stream.
Configure GAP GAP - No equivalent
GetAttrib GAP MediaStreamSettings.width
GAP MediaStreamSettings.height
GAP GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_BUFFERED_FRAMES
GAP GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT
GetId GAP MediaStream.id
HasEnded GAP MediaStream.ended
GetFrame GAP GAP - No equivalent
RecycleFrame GAP GAP - No equivalent
Close GAP GAP - No equivalent
GetEmptyFrame GAP GAP - No equivalent
PutFrame GAP GAP - No equivalent

PPB_MessageLoop

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create N/A Mostly moot, workers get an implicit event loop.
GetForMainThread N/A Mostly moot, workers get an implicit event loop.
GetCurrent N/A Mostly moot, workers get an implicit event loop.
AttachToCurrentThread N/A Mostly moot, workers get an implicit event loop.
Run N/A Mostly moot, workers get an implicit event loop.
PostWork N/A Mostly moot, workers get an implicit event loop.
PostQuit N/A Mostly moot, workers get an implicit event loop.

PPB_Messaging

PPAPI Method Assumes Threads Emscripten Web API Limitations
PostMessage N/A Window.postMessage
RegisterMessageHandler N/A Window.addEventListener
UnregisterMessageHandler N/A Window.removeEventListener

PPB_MouseCursor

PPAPI Method Assumes Threads Emscripten Web API Limitations
SetCursor SDL Element.style.cursor Same set of stock cursors are supported. Custom cursors can be done with url(..). Dynamic custom cursors can be done with data URIs. CSS3 supports specifying the hotspot.

PPB_MouseLock

PPAPI Method Assumes Threads Emscripten Web API Limitations
LockMouse SDL Element.requestPointerLock
UnlockMouse SDL Element.exitPointerLock

PPB_OpenGLES2

PPAPI Method Assumes Threads Emscripten Web API Limitations
Several Methods OpenGLES Close to WebGL 1.0 in functionality.
x GAP - Without offscreen canvas, rendering must be done on the main thread.

PPB_TextInputController

PPAPI Method Assumes Threads Emscripten Web API Limitations
SetTextInputType GAP GAP - No equivalent hints to browser about canvas containing input. Some developers would like to either be able to hint in this fashion, or preferrably the ability to intercept and display IME events / output inline inside a canvas.
UpdateCaretPosition GAP GAP - No equivalent hints to browser about canvas containing input.
CancelCompositionText GAP GAP - No equivalent hints to browser about canvas containing input.
UpdateSurroundingText GAP GAP - No equivalent hints to browser about canvas containing input.

PPB_URLLoader

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind new XMLHttpRequest();
Open embind XMLHttpRequest.open
FollowRedirect embind Request.redirect
GAP GAP - No XMLHTTPRequest equivalent
GetUploadProgress embind XMLHttpRequest 'progress' Event
GAP GAP - No Fetch API equivalent
GetDownloadProgress embind XMLHttpRequest 'progress' Event
GAP GAP - No Fetch API equivalent
GetResponseInfo embind XMLHttpRequest.getAllResponseHeaders
embind Fetch Response.*
ReadResponseBody embind XMLHttpRequest.response
embind Body.* (Response is a Body)
FinishStreamingToFile embind GAP - No direct equivalent XMLHttpRequest and Fetch both assume streaming to memory, rather than directly to a storage.
Close embind XMLHttpRequest.abort
GAP GAP - No Fetch API equivalent

PPB_URLRequestInfo

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind XMLHttpRequest
embind Fetch Request No way to stream to a file.
SetProperty GAP GAP - No direct equivalent for XMLHttpRequest XMLHttpRequest doesn't provide direct ways to per-request limit following redirects, stream to a file, set referrer or credentials policy.
embind Request.*
AppendDataToBody embind XMLHttpRequest.send GAP - Both must have the whole body, rather than a chunk.
embind fetch(.., options:body)
AppendFileToBody GAP GAP - No direct equivalent
N/A <form> You can also read with FileReader and upload, but that's more like AppendDataToBody

PPB_URLResponseInfo

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetProperty embind XMLHttpRequest.getAllResponseHeaders + others
embind Fetch Response.*
GetBodyAsFileRef embind Fetch Response (Body) .blob() Assumes storage layer optimizes transfer.

PPB_Var

PPAPI Method Assumes Threads Emscripten Web API Limitations
VarFromUtf8 embind TextDecoder.decode
VarToUtf8 embind TextEncoder.encode
VarFromResource N/A N/A
VarToResource N/A N/A

PPB_VarArray

PPAPI Method Assumes Threads Emscripten Web API Limitations
Get embind Array[i]
Set embind Array[i] = x
GetLength embind Array.length
SetLength embind Array.length = n

PPB_VarArrayBuffer

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind new ArrayBuffer(n)
ByteLength embind ArrayBuffer.byteLength
Map GAP GAP - No direct equivalent Asm.js / Wasm modules are unable to map regions of an ArrayBuffer other than their single linear memory heap. Future multiple memories or memory mapping might improve this.
Unmap GAP GAP - No direct equivalent

PPB_VarDictionary

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind {}
Get embind <Object>[i]
Set embind <Object>[i] = x
Delete embind delete <Object>[i]
HasKey embind x in <Object>
GetKeys embind for (k in <Object>) {} No literal equivalent, but it can be built.

PPB_VideoDecoder

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP GAP - No equivalent
Initialize GAP GAP - No equivalent
Decode GAP GAP - No equivalent
GetPicture GAP GAP - No equivalent
RecyclePicture GAP GAP - No equivalent
Flush GAP GAP - No equivalent
Reset GAP GAP - No equivalent

PPB_VideoEncoder

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP GAP - No equivalent Overlap with MediaRecorder API, but not exact.
GetSupportedProfiles GAP GAP - No equivalent
Initialize GAP GAP - No equivalent
GetFramesRequired GAP GAP - No equivalent
GetFrameCodedSize GAP GAP - No equivalent
GetVideoFrame GAP GAP - No equivalent
Encode GAP GAP - No equivalent
GetBitstreamBuffer GAP GAP - No equivalent
RecycleBitstreamBuffer GAP GAP - No equivalent
RequestEncodingParametersChange GAP GAP - No equivalent
Close GAP GAP - No equivalent

PPB_VideoFrame

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetTimestamp GAP GAP - No equivalent
SetTimestamp GAP GAP - No equivalent
GetFormat GAP GAP - No equivalent
GetSize GAP GAP - No equivalent
GetDataBuffer GAP GAP - No equivalent
GetDataBufferSize GAP GAP - No equivalent

PPB_View

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetRect embind Element.getBoundingClientRect
IsFullscreen embind Document.fullScreenEnabled Pertains to document instead of just single element.
IsVisible embind IntersectionObserver
IsPageVisible embind document.visibilityState
GetClipRect embind IntersectionObserver
GetDeviceScale embind window.devicePixelRatio
GetCSSScale embind <Element>.getBoundingClientRect().width / <Element>.offsetWidth
GetScrollOffset embind <Element>.scrollTop / <Element>.scrollLeft

PPB_WebSocket

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP WebSocket.WebSocket
Connect GAP WebSocket.WebSocket(url, ...) WebSocket 'open' Event
Close GAP WebSocket.close
ReceiveMessage GAP WebSocket 'message' Event WebSocket 'error' Event WebSocket 'close' Event
SendMessage GAP WebSocket.send
GetBufferedAmount GAP WebSocket.bufferedAmount
GetCloseCode GAP CloseEvent.code
GetCloseReason GAP CloseEvent.reason
GetCloseWasClean GAP CloseEvent.wasClean
GetExtensions GAP WebSocket.extensions
GetProtocol GAP WebSocket.protocol
GetReadyState GAP WebSocket.readyState
GetURL GAP WebSocket.url

PPP_Graphics3D

PPAPI Method Assumes Threads Emscripten Web API Limitations
Graphics3DContextLost SDL Canvas 'webglcontextlost' Event

PPP_InputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
HandleInputEvent SDL Element.addEventListener

PPP_Instance

PPAPI Method Assumes Threads Emscripten Web API Limitations
DidCreate N/A <Element>[key] General DOM access lets you fish out tag attributes
DidDestroy N/A N/A Not triggered for NaCl
DidChangeView N/A Element 'resize' Event
DidChangeFocus N/A Element 'focus', 'focusin', 'focusout' Events
HandleDocumentLoad N/A GAP - No way to register as a mime type handler NaCl modules via apps + a manifest entry can be set up to handle particular mime types.

PPP_MessageHandler

PPAPI Method Assumes Threads Emscripten Web API Limitations
HandleMessage embind MessagePort 'message' Event Window 'message' Event
HandleBlockingMessage N/A GAP - No direct equivalent Similar synchronization can be done off main thread with Atomics.wait. This was added to support emulation of synchronous plugin APIs.

PPP_Messaging

PPAPI Method Assumes Threads Emscripten Web API Limitations
HandleMessage embind MessagePort 'message' Event Window 'message' Event

PPP_MouseLock

PPAPI Method Assumes Threads Emscripten Web API Limitations
MouseLockLost SDL Element 'pointerlockchange', 'pointerlockerror' Events

PPAPI (Apps)

PPB_HostResolver

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create x GAP GAP (partial) - No direct equivalent
Resolve x GAP GAP (partial) - No direct equivalent
GetCanonicalName x GAP GAP (partial) - No direct equivalent
GetNetAddressCount x GAP GAP (partial) - No direct equivalent
GetNetAddress x GAP GAP (partial) - No direct equivalent

PPB_NetAddress

PPAPI Method Assumes Threads Emscripten Web API Limitations
CreateFromIPv4Address x GAP GAP (partial) - No direct equivalent
CreateFromIPv6Address x GAP GAP (partial) - No direct equivalent
GetFamily x GAP GAP (partial) - No direct equivalent
DescribeAsString x GAP GAP (partial) - No direct equivalent
DescribeAsIPv4Address x GAP GAP (partial) - No direct equivalent
DescribeAsIPv6Address x GAP GAP (partial) - No direct equivalent

PPB_NetworkList

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetCount x GAP GAP - No direct equivalent
GetName x GAP GAP - No direct equivalent
GetType x GAP GAP - No direct equivalent
GetState x GAP GAP - No direct equivalent
GetIpAddress x GAP GAP - No direct equivalent
GetDisplayName x GAP GAP - No direct equivalent
GetMTU x GAP GAP - No direct equivalent

PPB_NetworkMonitor

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create x GAP GAP - No direct equivalent
UpdateNetworkList x GAP GAP - No direct equivalent

PPB_NetworkProxy

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetProxyForURL x GAP GAP - No direct equivalent

PPB_TCPSocket

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create x GAP chrome.sockets.tcp.create WebSockets / WebRTC closest practical equivalent on open Web.
x GAP chrome.sockets.tcpServer.create
Bind x GAP chrome.sockets.tcpServer.create
Connect x GAP chrome.sockets.tcp.connect
GetLocalAddress x GAP chrome.sockets.udp.SocketInfo
GetRemoteAddress x GAP chrome.sockets.udp.SocketInfo
Read x GAP onReceive* Events
Write x GAP chrome.sockets.tcp.send
Listen x GAP chrome.sockets.tcpServer.listen
Accept x GAP onAccept* Events
Close x GAP chrome.sockets.tcp.close
x GAP chrome.sockets.tcpServer.close
SetOption x GAP chrome.sockets.tcp.update
x GAP chrome.sockets.tcpServer.update

PPB_UDPSocket

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create x GAP chrome.sockets.udp.create GAP (partial) - WebRTC closest practical open Web equivalent
Bind x GAP chrome.sockets.udp.bind
GetBoundAddress x GAP chrome.sockets.udp.SocketInfo
RecvFrom x GAP onReceive* Events
SendTo x GAP chrome.sockets.udp.send
Close x GAP chrome.sockets.udp.close
SetOption x GAP chrome.sockets.udp.update
JoinGroup x GAP chrome.sockets.udp.joinGroup
LeaveGroup x GAP chrome.sockets.udp.leaveGroup