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 Q4 2019 (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.
As of Chrome 76, PNaCl on the open web has been moved behind an
Origin Trial,
which is a mechanism for web developers to register and get access to a feature that isn’t on by default.
This is usually a new proposed feature but in this case it’s a feature being deprecated.
A developer can register on the Origin Trial Console
and receive a token, which can be embedded into a page and will enable the feature without the user needing to use a flag.
(For more details see the linked guide). The trial is scheduled to last through Chrome 78, approximately until December 2019.
This change is not intended to affect NaCl or PNaCl in Chrome Apps or extensions, and the “enable-nacl”
flag in chrome://flags can also be used to enable PNaCl locally for testing
(this flag also retains its current function of enabling non-PNaCl “native” NaCl on any page).
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
The AudioWorkletSpec is done, but AudioDeviceClient may be a better fit for this API. The AudioDeviceClient is still being specified by the community. The worklet may not be the rough equivalent for this API.
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. The next version of the Web Audio spec will implement support for 16-bit samples. An optimization for AudioBuffer could be implemented similar to Firefox by using 16-bit buffer for audio that comes from decodeAudioData
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
The next version of the Web Audio spec will implement support for 16-bit samples.
GetSampleRate
SDL
AudioContext.sampleRate
GetSampleFrameCount
SDL
AudioBuffer.length
RecommendSampleRate
SDL
AudioContext.sampleRate (from default construct)
An AudioContext will have the preferred sampling rate that matches the actual sample rate of the hardware audio device by default.
RecommendSampleFrameCount
GAP
GAP - Would be handled with the planned AudioDeviceClient
There is an open issue to allow a user-specified size, but that is still being defined. This is probably best handled with AudioDeviceClient which can tell you what the appropriate size would be for the given hardware.
PPB_Console
PPAPI Method
Assumes Threads
Emscripten
Web API
Limitations
Log
utime
console.log/warn/error/...
LogWithSource
GAP
GAP
The Console API is regarded as a sufficiently complete replacement, unless there are specific use cases raised by developers for the functionality provided by LogWithSource. DevTools Source Maps can be used to debug transpiled JavaScript in their original source language.
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)
window.chooseFileSystemEntries()
Create and open are used differently, but the pieces are of equal power.
GAP (partial) - Blob.type can also be used to check the MIME type. The file system type, creation time, and last access time can not be determined with the Native File System API.
GAP (partial) - Files are flushed when FileSystemWrite.close() is called
This is intended by design because the Native File System API files are exposed to the OS, therefore a Safe Browsing check needs to be performed before data is shown to the OS.
Close
FS (partial)
FileSystemWriter.close()
Does not cancel pending operations, but flushes any data written so far to disk.
GAP (partial) - With the Native File System API, the relative path of a file can be determined from reference to a directory that contains the file using FileSystemHandle.resolve(FileSystemHandle)
The absolute path of a file cannot be determined, and the user has to grant permission to access the directory containing the file.
GetParent
FS (partial)
GAP (partial) - With the Native File System API, the relative path of a file can be determined from reference to a directory that contains the file using FileSystemHandle.resolve(FileSystemHandle)
The user has to grant permission to access the directory containing the file.
Unlike the PPAPI, directories do not have to be empty.
Rename
FS (partial)
GAP (partial) - With the Native File System API, the file can be written with the new name using a combination of FileSystemFileHandle.getFile() for the new name and FileSystemFileHandle.createWriter().write() with the contents of the old file. Then FileSystemDirectoryHandle.removeEntry() to delete the old file.
There is not a direct API that will do this in one step in the Native File System API.
GAP (partial) - Blob.type can also be used to check the MIME type. The file system type, creation time, and last access time can not be determined with the Native File System API.
ReadDirectoryEntries
FS (partial)
FileSystemDirectoryHandle.getEntries()
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
JS API does both in one step
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.*
The Gamepad object exposes a timestamp relative to navigationStart. It is updated when data is received from the hardware https://www.w3.org/TR/gamepad/#gamepad-interface
GAP (partial) - Can be implemented by drawing the canvas onto itself, with an offset, using drawImage, and then filling in the rest.
ReplaceContents
SDL
CanvasRenderingContext2D.drawImage
Flush
GAP
No direct equivalent
GAP (partial) -
There is always an implicit flush at the end of draw code; this is unlikely
to change. However, the combination of
OffscreenCanvas
and
ImageBitmapRenderingContext
provide similar functionality.
GAP (partial) - WebGL 2.0 and Emscripten's exposure of OpenGL ES 3.0 support user-defined multisampled framebuffers, in which all of the parameters configurable via PPAPI can be set.
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
No direct equivalent
GAP (partial) -
There is always an implicit flush at the end of draw code; this is unlikely
to change. However, the combination of
OffscreenCanvas
and
ImageBitmapRenderingContext
provide similar functionality.
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 kind of contains this info, but incompletely.
There is discussion on implementing a WheelEvent.deltaMode API: https://github.com/w3c/uievents/issues/181#issuecomment-537811017
GetScrollByPage
GAP
GAP - deltaMode kind of contains this info, but incompletely.
There is discussion on implementing a WheelEvent.deltaMode API: https://github.com/w3c/uievents/issues/181#issuecomment-537811017
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
This data can potentially be retrieved from CompositionEvent.data.
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.
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.
PPB_MediaStreamAudioTrack
PPAPI Method
Assumes Threads
Emscripten
Web API
Limitations
Configure
GAP
getUserMedia()
The constraints from getUserMedia() can provide the configuration values to use in MediaStreamTrack.
GetAttrib
GAP
MediaStreamTrack.getSettings()
GetId
GAP
MediaStreamTrack.id
HasEnded
GAP
MediaStreamTrack.readyState
GetBuffer
GAP
GAP - No equivalent
RecycleBuffer
GAP
GAP - No equivalent
Close
GAP
MediaStreamTrack.stop()
PPB_MediaStreamVideoTrack
PPAPI Method
Assumes Threads
Emscripten
Web API
Limitations
Create
GAP
Canvas Capture
Canvas Capture provides the ability to introduce video frames programmatically.
Configure
GAP
applyConstraints(), getUserMedia()
GAP (partial) - The extent of configurations available in the Web API may differ from the PPAPI.
GetAttrib
GAP
MediaStreamSettings.width
GAP
MediaStreamSettings.height
GAP
GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_BUFFERED_FRAMES
MediaStream cannot be preloaded, so it will never buffer: https://www.w3.org/TR/mediacapture-streams/#mediastreams-in-media-elements
GAP
GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT
GetId
GAP
MediaStreamTrack.id
HasEnded
GAP
MediaStreamTrack.readyState
GetFrame
GAP
GAP - No equivalent
RecycleFrame
GAP
GAP - No equivalent
Close
GAP
MediaStreamTrack.stop()
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
OffscreenCanvas
PPB_TextInputController
PPAPI Method
Assumes Threads
Emscripten
Web API
Limitations
SetTextInputType
GAP
GAP - Potentially filled by Input Method Editor API
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 - Potentially filled by Input Method Editor API
https://www.w3.org/TR/ime-api/
CancelCompositionText
GAP
GAP - Potentially filled by Input Method Editor API
https://www.w3.org/TR/ime-api/
UpdateSurroundingText
GAP
GAP - Potentially filled by Input Method Editor API
https://www.w3.org/TR/ime-api/
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
FetchObserver
Not specced or implemented yet; https://github.com/whatwg/fetch/issues/607
GetDownloadProgress
embind
XMLHttpRequest 'progress' Event
GAP
FetchObserver
Not specced or implemented yet; https://github.com/whatwg/fetch/issues/607
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
Fetch API: AbortSignal and AbortController
PPB_URLRequestInfo
PPAPI Method
Assumes Threads
Emscripten
Web API
Limitations
Create
embind
XMLHttpRequest
embind
Fetch Request
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.
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 - Would be handled with the proposed WebCodecs API using VideoDecoder()
GAP - Would be handled with the proposed WebCodecs API. The current design will automatically recycle the pictures and keep the decoding process going.
GAP - Would be handled with the proposed WebCodecs API. The API will be called Flush(), however there is still discussion on how it will be sequenced in relation to decode calls.
GAP - Would be handled with the proposed WebCodecs API by destroying the VideoDecoder instance and creating a new one. This won't be as efficient as a dedicated reset method, but the semantics for a Reset() API is still being discussed.
GAP - Would be handled with the proposed WebCodecs API using VideoEncoder()
GetSupportedProfiles
GAP
GAP (partial) - navigator.mediaCapabilities.encodingInfo()
The supported profiles have to be checked one by one.
Initialize
GAP
GAP - Would be handled with the proposed WebCodecs API using VideoEncoder() initialization parameters
GetFramesRequired
GAP
GAP - No equivalent
It is unlikely that the frame pool used internally by the Web Codecs API is exposed.
GetFrameCodedSize
GAP
GAP - No equivalent
It is unlikely that the frame pool used internally by the Web Codecs API is exposed.
GetVideoFrame
GAP
GAP - Would be handled with the proposed WebCodecs API by using ReadableStream.pipeThrough(VideoEncoder). This would directly encode the data in the Readable stream instead of grabbing a single frame to fill with data before encoding.
Encode
GAP
GAP - Would be handled with the proposed WebCodecs API using ReadableStream.pipeThrough(VideoEncoder)
GetBitstreamBuffer
GAP
GAP - Would be handled with the proposed WebCodecs API. The current design will automatically go through the encoded bitstream buffer that is piped through.
The WebCodecs API currently assumes that bitstream buffer can be copied rather than pooled, so it will not need to be recycled.
RecycleBitstreamBuffer
GAP
GAP - Would be handled with the proposed WebCodecs API. The current design will automatically recycle the buffer to keep the encoding process going.
This is unlikely to change in the future as performance implications are smaller.
RequestEncodingParametersChange
GAP
GAP - Would be handled by the proposed Web Codecs API. Certain parameters will have the capability of being changed on the fly, while others will require the encoder to be torn down.
Close
GAP
GAP - Would be handled with the proposed WebCodecs API by using VideoEncoder.Close()
PPB_VideoFrame
PPAPI Method
Assumes Threads
Emscripten
Web API
Limitations
GetTimestamp
GAP
GAP - Would be handled with the proposed WebCodecs API.
SetTimestamp
GAP
GAP - Would be handled with the proposed WebCodecs API.
GetFormat
GAP
GAP - Would be handled with the proposed WebCodecs API.
GetSize
GAP
GAP - Would be handled with the proposed WebCodecs API.
GetDataBuffer
GAP
GAP - Would be handled with the proposed WebCodecs API.
GetDataBufferSize
GAP
GAP - Would be handled with the proposed WebCodecs API.
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.
Element 'pointerlockchange', 'pointerlockerror' Events
IRT
PPB_Audio
PPAPI Method
Assumes Threads
Emscripten
Web API
Limitations
Create
x
SDL (partial)
GAP (partial) - AudioWorkletNode ROUGHLY equivalent
The AudioWorkletSpec is done, but AudioDeviceClient may be a better fit for this API. The AudioDeviceClient is still being specified by the community. The worklet may not be the rough equivalent for this API.
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. The next version of the Web Audio spec will implement support for 16-bit samples. An optimization for AudioBuffer could be implemented similar to Firefox by using 16-bit buffer for audio that comes from decodeAudioData
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
The next version of the Web Audio spec will implement support for 16-bit samples.
GetSampleRate
SDL
AudioContext.sampleRate
GetSampleFrameCount
SDL
AudioBuffer.length
RecommendSampleRate
SDL
AudioContext.sampleRate (from default construct)
An AudioContext will have the preferred sampling rate that matches the actual sample rate of the hardware audio device by default.
RecommendSampleFrameCount
GAP
GAP - Would be handled with the planned AudioDeviceClient
There is an open issue to allow a user-specified size, but that is still being defined. This is probably best handled with AudioDeviceClient which can tell you what the appropriate size would be for the given hardware.
PPB_Console
PPAPI Method
Assumes Threads
Emscripten
Web API
Limitations
Log
utime
console.log/warn/error/...
LogWithSource
GAP
GAP
The Console API is regarded as a sufficiently complete replacement, unless there are specific use cases raised by developers for the functionality provided by LogWithSource. DevTools Source Maps can be used to debug transpiled JavaScript in their original source language.
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)
window.chooseFileSystemEntries()
Create and open are used differently, but the pieces are of equal power.
GAP (partial) - Blob.type can also be used to check the MIME type. The file system type, creation time, and last access time can not be determined with the Native File System API.
GAP (partial) - Files are flushed when FileSystemWrite.close() is called
This is intended by design because the Native File System API files are exposed to the OS, therefore a Safe Browsing check needs to be performed before data is shown to the OS.
Close
FS (partial)
FileSystemWriter.close()
Does not cancel pending operations, but flushes any data written so far to disk.
GAP (partial) - With the Native File System API, the relative path of a file can be determined from reference to a directory that contains the file using FileSystemHandle.resolve(FileSystemHandle)
The absolute path of a file cannot be determined, and the user has to grant permission to access the directory containing the file.
GetParent
FS (partial)
GAP (partial) - With the Native File System API, the relative path of a file can be determined from reference to a directory that contains the file using FileSystemHandle.resolve(FileSystemHandle)
The user has to grant permission to access the directory containing the file.
Unlike the PPAPI, directories do not have to be empty.
Rename
FS (partial)
GAP (partial) - With the Native File System API, the file can be written with the new name using a combination of FileSystemFileHandle.getFile() for the new name and FileSystemFileHandle.createWriter().write() with the contents of the old file. Then FileSystemDirectoryHandle.removeEntry() to delete the old file.
There is not a direct API that will do this in one step in the Native File System API.
GAP (partial) - Blob.type can also be used to check the MIME type. The file system type, creation time, and last access time can not be determined with the Native File System API.
ReadDirectoryEntries
FS (partial)
FileSystemDirectoryHandle.getEntries()
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
JS API does both in one step
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.*
The Gamepad object exposes a timestamp relative to navigationStart. It is updated when data is received from the hardware https://www.w3.org/TR/gamepad/#gamepad-interface
GAP (partial) - Can be implemented by drawing the canvas onto itself, with an offset, using drawImage, and then filling in the rest.
ReplaceContents
SDL
CanvasRenderingContext2D.drawImage
Flush
GAP
No direct equivalent
GAP (partial) -
There is always an implicit flush at the end of draw code; this is unlikely
to change. However, the combination of
OffscreenCanvas
and
ImageBitmapRenderingContext
provide similar functionality.
GAP (partial) - WebGL 2.0 and Emscripten's exposure of OpenGL ES 3.0 support user-defined multisampled framebuffers, in which all of the parameters configurable via PPAPI can be set.
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
No direct equivalent
GAP (partial) -
There is always an implicit flush at the end of draw code; this is unlikely
to change. However, the combination of
OffscreenCanvas
and
ImageBitmapRenderingContext
provide similar functionality.
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 kind of contains this info, but incompletely.
There is discussion on implementing a WheelEvent.deltaMode API: https://github.com/w3c/uievents/issues/181#issuecomment-537811017
GetScrollByPage
GAP
GAP - deltaMode kind of contains this info, but incompletely.
There is discussion on implementing a WheelEvent.deltaMode API: https://github.com/w3c/uievents/issues/181#issuecomment-537811017
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
This data can potentially be retrieved from CompositionEvent.data.
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.
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.
PPB_MediaStreamAudioTrack
PPAPI Method
Assumes Threads
Emscripten
Web API
Limitations
Configure
GAP
getUserMedia()
The constraints from getUserMedia() can provide the configuration values to use in MediaStreamTrack.
GetAttrib
GAP
MediaStreamTrack.getSettings()
GetId
GAP
MediaStreamTrack.id
HasEnded
GAP
MediaStreamTrack.readyState
GetBuffer
GAP
GAP - No equivalent
RecycleBuffer
GAP
GAP - No equivalent
Close
GAP
MediaStreamTrack.stop()
PPB_MediaStreamVideoTrack
PPAPI Method
Assumes Threads
Emscripten
Web API
Limitations
Create
GAP
Canvas Capture
Canvas Capture provides the ability to introduce video frames programmatically.
Configure
GAP
applyConstraints(), getUserMedia()
GAP (partial) - The extent of configurations available in the Web API may differ from the PPAPI.
GetAttrib
GAP
MediaStreamSettings.width
GAP
MediaStreamSettings.height
GAP
GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_BUFFERED_FRAMES
MediaStream cannot be preloaded, so it will never buffer: https://www.w3.org/TR/mediacapture-streams/#mediastreams-in-media-elements
GAP
GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT
GetId
GAP
MediaStreamTrack.id
HasEnded
GAP
MediaStreamTrack.readyState
GetFrame
GAP
GAP - No equivalent
RecycleFrame
GAP
GAP - No equivalent
Close
GAP
MediaStreamTrack.stop()
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
OffscreenCanvas
PPB_TextInputController
PPAPI Method
Assumes Threads
Emscripten
Web API
Limitations
SetTextInputType
GAP
GAP - Potentially filled by Input Method Editor API
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 - Potentially filled by Input Method Editor API
https://www.w3.org/TR/ime-api/
CancelCompositionText
GAP
GAP - Potentially filled by Input Method Editor API
https://www.w3.org/TR/ime-api/
UpdateSurroundingText
GAP
GAP - Potentially filled by Input Method Editor API
https://www.w3.org/TR/ime-api/
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
FetchObserver
Not specced or implemented yet; https://github.com/whatwg/fetch/issues/607
GetDownloadProgress
embind
XMLHttpRequest 'progress' Event
GAP
FetchObserver
Not specced or implemented yet; https://github.com/whatwg/fetch/issues/607
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
Fetch API: AbortSignal and AbortController
PPB_URLRequestInfo
PPAPI Method
Assumes Threads
Emscripten
Web API
Limitations
Create
embind
XMLHttpRequest
embind
Fetch Request
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.
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 - Would be handled with the proposed WebCodecs API using VideoDecoder()
GAP - Would be handled with the proposed WebCodecs API. The current design will automatically recycle the pictures and keep the decoding process going.
GAP - Would be handled with the proposed WebCodecs API. The API will be called Flush(), however there is still discussion on how it will be sequenced in relation to decode calls.
GAP - Would be handled with the proposed WebCodecs API by destroying the VideoDecoder instance and creating a new one. This won't be as efficient as a dedicated reset method, but the semantics for a Reset() API is still being discussed.
GAP - Would be handled with the proposed WebCodecs API using VideoEncoder()
GetSupportedProfiles
GAP
GAP (partial) - navigator.mediaCapabilities.encodingInfo()
The supported profiles have to be checked one by one.
Initialize
GAP
GAP - Would be handled with the proposed WebCodecs API using VideoEncoder() initialization parameters
GetFramesRequired
GAP
GAP - No equivalent
It is unlikely that the frame pool used internally by the Web Codecs API is exposed.
GetFrameCodedSize
GAP
GAP - No equivalent
It is unlikely that the frame pool used internally by the Web Codecs API is exposed.
GetVideoFrame
GAP
GAP - Would be handled with the proposed WebCodecs API by using ReadableStream.pipeThrough(VideoEncoder). This would directly encode the data in the Readable stream instead of grabbing a single frame to fill with data before encoding.
Encode
GAP
GAP - Would be handled with the proposed WebCodecs API using ReadableStream.pipeThrough(VideoEncoder)
GetBitstreamBuffer
GAP
GAP - Would be handled with the proposed WebCodecs API. The current design will automatically go through the encoded bitstream buffer that is piped through.
The WebCodecs API currently assumes that bitstream buffer can be copied rather than pooled, so it will not need to be recycled.
RecycleBitstreamBuffer
GAP
GAP - Would be handled with the proposed WebCodecs API. The current design will automatically recycle the buffer to keep the encoding process going.
This is unlikely to change in the future as performance implications are smaller.
RequestEncodingParametersChange
GAP
GAP - Would be handled by the proposed Web Codecs API. Certain parameters will have the capability of being changed on the fly, while others will require the encoder to be torn down.
Close
GAP
GAP - Would be handled with the proposed WebCodecs API by using VideoEncoder.Close()
PPB_VideoFrame
PPAPI Method
Assumes Threads
Emscripten
Web API
Limitations
GetTimestamp
GAP
GAP - Would be handled with the proposed WebCodecs API.
SetTimestamp
GAP
GAP - Would be handled with the proposed WebCodecs API.
GetFormat
GAP
GAP - Would be handled with the proposed WebCodecs API.
GetSize
GAP
GAP - Would be handled with the proposed WebCodecs API.
GetDataBuffer
GAP
GAP - Would be handled with the proposed WebCodecs API.
GetDataBufferSize
GAP
GAP - Would be handled with the proposed WebCodecs API.
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.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2022-05-27 UTC."],[],[]]