(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 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.
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. |
Open |
|
FS (partial) |
window.chooseFileSystemEntries() |
|
Query |
|
FS (partial) |
Blob.size, FileSystemHandle.getFile(), FileSystemHandle.getDirectory(), File.lastModified |
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. |
Touch |
|
FS (partial) |
FileSystemDirectoryHandle.getFile("name", {create: true}) |
|
Read |
|
FS (partial) |
Blob.slice().arrayBuffer() |
|
Write |
|
FS (partial) |
FileSystemWriter.write() |
|
SetLength |
|
FS (partial) |
FileSystemWriter.truncate() |
|
Flush |
|
GAP (partial) |
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. |
ReadToArray |
|
GAP |
Blob.slice().arrayBuffer() or Blob.arrayBuffer() |
Allows multiple subrange reads in parallel. |
PPB_FileRef
PPAPI Method |
Assumes Threads |
Emscripten |
Web API |
Limitations |
Create |
|
FS (partial) |
FileSystemDirectoryHandle.getFile("name", {create: true}) |
|
GetFileSystemType |
|
FS (partial) |
FileSystem.type |
|
GetName |
|
FS (partial) |
File.name |
|
GetPath |
|
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 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. |
MakeDirectory |
|
FS (partial) |
FileSystemHandle.getDirectory(..., {createIfNotExists: true}) |
|
Touch |
|
FS (partial) |
FileSystemDirectoryHandle.getFile("name", {create: true}) |
Modify time can be bumped by writing. |
Delete |
|
FS (partial) |
FileSystemDirectoryHandle.removeEntry() |
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. |
Query |
|
GAP (partial) |
Blob.size, FileSystemHandle.getFile(), FileSystemHandle.getDirectory(), File.lastModified |
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 |
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, CanvasRenderingContext2D.drawImage |
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. |
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 |
|
OpenGL ES 3.0 |
WebGL 2.0 |
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 |
|
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 |
|
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* |
|
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 |
PPAPI Method |
Assumes Threads |
Emscripten |
Web API |
Limitations |
Create |
|
SDL |
KeyboardEvent |
|
GetKeyCode |
|
SDL |
KeyboardEvent.keyCode |
|
GetCharacterText |
|
SDL |
KeyboardEvent.key |
|
GetCode |
|
SDL |
KeyboardEvent.code |
|
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) |
|
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. |
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() |
|
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. |
|
|
embind |
fetch(.., options:body) |
|
AppendFileToBody |
|
GAP |
fetch() upload streaming |
https://www.chromestatus.com/features/5274139738767360 |
|
|
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 - Would be handled with the proposed WebCodecs API using VideoDecoder() |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
Initialize |
|
GAP |
GAP - Would be handled with the proposed WebCodecs API using VideoDecoder() initialization parameters (VideoDecoderInitParameters) |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
Decode |
|
GAP |
GAP - Would be handled with the proposed WebCodecs API using ReadableStream.pipeThrough(VideoDecoder) |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
GetPicture |
|
GAP |
GAP - Would be handled with the proposed WebCodecs API using ReadableStream.pipeThrough(VideoDecoder).pipeTo(VideoTrackWriter().writable) |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
RecyclePicture |
|
GAP |
GAP - Would be handled with the proposed WebCodecs API. The current design will automatically recycle the pictures and keep the decoding process going. |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
Flush |
|
GAP |
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. |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
Reset |
|
GAP |
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. |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
PPB_VideoEncoder
PPAPI Method |
Assumes Threads |
Emscripten |
Web API |
Limitations |
Create |
|
GAP |
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. |
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 |
|
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 |
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. |
Open |
|
FS (partial) |
window.chooseFileSystemEntries() |
|
Query |
|
FS (partial) |
Blob.size, FileSystemHandle.getFile(), FileSystemHandle.getDirectory(), File.lastModified |
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. |
Touch |
|
FS (partial) |
FileSystemDirectoryHandle.getFile("name", {create: true}) |
|
Read |
|
FS (partial) |
Blob.slice().arrayBuffer() |
|
Write |
|
FS (partial) |
FileSystemWriter.write() |
|
SetLength |
|
FS (partial) |
FileSystemWriter.truncate() |
|
Flush |
|
GAP (partial) |
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. |
ReadToArray |
|
GAP |
Blob.slice().arrayBuffer() or Blob.arrayBuffer() |
Allows multiple subrange reads in parallel. |
PPB_FileRef
PPAPI Method |
Assumes Threads |
Emscripten |
Web API |
Limitations |
Create |
|
FS (partial) |
FileSystemDirectoryHandle.getFile("name", {create: true}) |
|
GetFileSystemType |
|
FS (partial) |
FileSystem.type |
|
GetName |
|
FS (partial) |
File.name |
|
GetPath |
|
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 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. |
MakeDirectory |
|
FS (partial) |
FileSystemHandle.getDirectory(..., {createIfNotExists: true}) |
|
Touch |
|
FS (partial) |
FileSystemDirectoryHandle.getFile("name", {create: true}) |
Modify time can be bumped by writing. |
Delete |
|
FS (partial) |
FileSystemDirectoryHandle.removeEntry() |
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. |
Query |
|
GAP (partial) |
Blob.size, FileSystemHandle.getFile(), FileSystemHandle.getDirectory(), File.lastModified |
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 |
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, CanvasRenderingContext2D.drawImage |
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. |
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 |
|
OpenGL ES 3.0 |
WebGL 2.0 |
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 |
|
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 |
|
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* |
|
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 |
PPAPI Method |
Assumes Threads |
Emscripten |
Web API |
Limitations |
Create |
|
SDL |
KeyboardEvent |
|
GetKeyCode |
|
SDL |
KeyboardEvent.keyCode |
|
GetCharacterText |
|
SDL |
KeyboardEvent.key |
|
GetCode |
|
SDL |
KeyboardEvent.code |
|
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) |
|
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. |
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() |
|
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. |
|
|
embind |
fetch(.., options:body) |
|
AppendFileToBody |
|
GAP |
fetch() upload streaming |
https://www.chromestatus.com/features/5274139738767360 |
|
|
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 - Would be handled with the proposed WebCodecs API using VideoDecoder() |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
Initialize |
|
GAP |
GAP - Would be handled with the proposed WebCodecs API using VideoDecoder() initialization parameters (VideoDecoderInitParameters) |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
Decode |
|
GAP |
GAP - Would be handled with the proposed WebCodecs API using ReadableStream.pipeThrough(VideoDecoder) |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
GetPicture |
|
GAP |
GAP - Would be handled with the proposed WebCodecs API using ReadableStream.pipeThrough(VideoDecoder).pipeTo(VideoTrackWriter().writable) |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
RecyclePicture |
|
GAP |
GAP - Would be handled with the proposed WebCodecs API. The current design will automatically recycle the pictures and keep the decoding process going. |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
Flush |
|
GAP |
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. |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
Reset |
|
GAP |
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. |
https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming |
PPB_VideoEncoder
PPAPI Method |
Assumes Threads |
Emscripten |
Web API |
Limitations |
Create |
|
GAP |
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. |
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 |
|
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 and PPB_UDPSocket
There is not a direct 1:1 mapping for migration. Instead, we have outlined some
user scenarios below and what the recommended migration path is.
Use Case |
Recommendations |
Screen sharing |
getDisplayMedia and
WebRTC (
demo)
|
Loading from a
local server to minimize bandwidth usage |
XHR, Fetch, Streams, Service Worker, Cache APIs |
Loading from a
local instance of a web app / Connecting to a local instance of a web app |
WebRTC |
Chat |
WebSocket*
|
Realtime
audio/video communication |
WebRTC |
Collaboration |
WebSocket*
|
Realtime
multiplayer games |
WebTransport**
unless P2P in which case WebRTC (or
WebTransport over RTCIceTransport)
|
Realtime
interactive streaming |
WebTransport**
|
Communicating
with legacy server |
Proxy server or middleware to do protocol conversion. Feedback to
bit.ly/network-api-gaps
|
*: Or WebTransport in the future
**: See chromestatus for availability