Merge mozilla-central to mozilla-inbound

This commit is contained in:
arthur.iakab 2018-12-18 07:36:08 +02:00
commit f1762a3667
187 changed files with 13218 additions and 10651 deletions

4
.gitignore vendored
View File

@ -153,9 +153,5 @@ lextab.py
!.vscode/extensions.json
!.vscode/tasks.json
# Ignore temp files created by patch command.
*.orig
*.rej
# Ignore file generated by lalrpop at build time.
third_party/rust/lalrpop/src/parser/lrgrammar.rs

View File

@ -182,10 +182,6 @@ tps_result\.json
# https://bz.mercurial-scm.org/show_bug.cgi?id=5322
^comm/
# Ignore temp files created by patch command.
\.orig$
\.rej$
# Ignore various raptor performance framework files
^testing/raptor/.raptor-venv
^testing/raptor/raptor-venv

View File

@ -1271,11 +1271,7 @@ pref("browser.library.activity-stream.enabled", true);
pref("browser.newtabpage.activity-stream.fxaccounts.endpoint", "https://accounts.firefox.com/");
// The pref that controls if the search shortcuts experiment is on
#ifdef EARLY_BETA_OR_EARLIER
pref("browser.newtabpage.activity-stream.improvesearch.topSiteSearchShortcuts", true);
#else
pref("browser.newtabpage.activity-stream.improvesearch.topSiteSearchShortcuts", false);
#endif
// ASRouter provider configuration
#if defined(NIGHTLY_BUILD)

View File

@ -1662,18 +1662,11 @@ var gBrowserInit = {
// We don't check if uriToLoad is a XULElement because this case has
// already been handled before first paint, and the argument cleared.
if (uriToLoad instanceof Ci.nsIArray) {
let count = uriToLoad.length;
let specs = [];
for (let i = 0; i < count; i++) {
let urisstring = uriToLoad.queryElementAt(i, Ci.nsISupportsString);
specs.push(urisstring.data);
}
if (Array.isArray(uriToLoad)) {
// This function throws for certain malformed URIs, so use exception handling
// so that we don't disrupt startup
try {
gBrowser.loadTabs(specs, {
gBrowser.loadTabs(uriToLoad, {
inBackground: false,
replace: true,
// See below for the semantics of window.arguments. Only the minimum is supported.
@ -1840,6 +1833,14 @@ var gBrowserInit = {
// If the given URI is different from the homepage, we want to load it.
if (uri != defaultArgs) {
if (uri instanceof Ci.nsIArray) {
// Transform the nsIArray of nsISupportsString's into a JS Array of
// JS strings.
return Array.from(uri.enumerate(Ci.nsISupportsString),
supportStr => supportStr.data);
} else if (uri instanceof Ci.nsISupportsString) {
return uri.data;
}
return uri;
}

View File

@ -298,6 +298,10 @@ window._gBrowser = {
remoteType = E10SUtils.NOT_REMOTE;
} else {
let uriToLoad = gBrowserInit.uriToLoadPromise;
if (uriToLoad && Array.isArray(uriToLoad)) {
uriToLoad = uriToLoad[0]; // we only care about the first item
}
if (uriToLoad && typeof uriToLoad == "string") {
remoteType = E10SUtils.getRemoteTypeForURI(
uriToLoad,

View File

@ -1715,6 +1715,19 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
}
]]></body>
</method>
<method name="removeHiddenFocus">
<body><![CDATA[
this.classList.remove("hidden-focus");
]]></body>
</method>
<method name="hiddenFocus">
<body><![CDATA[
this.classList.add("hidden-focus");
this.focus();
]]></body>
</method>
</implementation>
<handlers>

View File

@ -5,4 +5,6 @@ skip-if = !updater
reason = test depends on update channel
[browser_contentpermissionprompt.js]
[browser_default_bookmark_toolbar_visibility.js]
[browser_initial_tab_remoteType.js]
skip-if = verify && !debug && os == 'mac' # Bug 1514778
[browser_urlbar_matchBuckets_migration60.js]

View File

@ -0,0 +1,185 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* These tests test that the initial browser tab has the right
* process type assigned to it on creation, which avoids needless
* process flips.
*/
"use strict";
const PRIVILEGED_PROCESS_PREF =
"browser.tabs.remote.separatePrivilegedContentProcess";
const PRIVILEGED_PROCESS_ENABLED =
Services.prefs.getBoolPref(PRIVILEGED_PROCESS_PREF);
const REMOTE_BROWSER_SHOWN = "remote-browser-shown";
// When the privileged content process is enabled, we expect about:home
// to load in it. Otherwise, it's in a normal web content process.
const EXPECTED_ABOUTHOME_REMOTE_TYPE =
PRIVILEGED_PROCESS_ENABLED ? E10SUtils.PRIVILEGED_REMOTE_TYPE
: E10SUtils.DEFAULT_REMOTE_TYPE;
/**
* Test helper function that takes an nsICommandLine, and passes it
* into the default command line handler for the browser. It expects
* a new browser window to open, and then checks that the expected page
* loads in the initial tab in the expected remote type, without doing
* unnecessary process flips. The helper function then closes the window.
*
* @param aCmdLine (nsICommandLine)
* The command line to be processed by the default
* nsICommandLineHandler
* @param aExpectedURL (string)
* The URL that the initial browser tab is expected to load.
* @param aRemoteType (string)
* The expected remoteType on the initial browser tab.
* @returns Promise
* Resolves once the checks have completed, and the opened window
* have been closed.
*/
async function assertOneRemoteBrowserShown(aCmdLine, aExpectedURL,
aRemoteType) {
let shownRemoteBrowsers = 0;
let observer = () => {
shownRemoteBrowsers++;
};
Services.obs.addObserver(observer, REMOTE_BROWSER_SHOWN);
let newWinPromise = BrowserTestUtils.waitForNewWindow({
url: aExpectedURL,
});
let cmdLineHandler = Cc["@mozilla.org/browser/final-clh;1"]
.getService(Ci.nsICommandLineHandler);
cmdLineHandler.handle(aCmdLine);
let newWin = await newWinPromise;
Services.obs.removeObserver(observer, REMOTE_BROWSER_SHOWN);
Assert.equal(newWin.gBrowser.selectedBrowser.remoteType,
aRemoteType);
Assert.equal(shownRemoteBrowsers, 1,
"Should have only shown 1 remote browser");
await BrowserTestUtils.closeWindow(newWin);
}
/**
* Constructs an object that implements an nsICommandLine that should
* cause the default nsICommandLineHandler to open aURL as the initial
* tab in a new window. The returns nsICommandLine is stateful, and
* shouldn't be reused.
*
* @param aURL (string)
* The URL to load in the initial tab of the new window.
* @returns nsICommandLine
*/
function constructOnePageCmdLine(aURL) {
return {
_arg: aURL,
_argCount: 1,
get length() {
return this._argCount;
},
getArgument(aIndex) {
if (aIndex == 0 && this._argCount) {
return this._arg;
}
throw Cr.NS_ERROR_INVALID_ARG;
},
findFlag() {
return -1;
},
removeArguments() {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
handleFlag() {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
handleFlagWithParam() {
if (this._argCount) {
this._argCount = 0;
return this._arg;
}
return "";
},
get state() {
return 0;
},
STATE_INITIAL_LAUNCH: 0,
STATE_REMOTE_AUTO: 1,
STATE_REMOTE_EXPLICIT: 2,
preventDefault: false,
get workingDirectory() {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
get windowContext() {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
resolveFile() {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
resolveURI() {
return Services.io.newURI(this._arg);
},
QueryInterface: ChromeUtils.generateQI([Ci.nsICommandLine]),
};
}
add_task(async function setup() {
gBrowser.removePreloadedBrowser();
await SpecialPowers.pushPrefEnv({"set": [
["browser.startup.homepage", "about:home"],
["browser.startup.page", 1],
]});
});
/**
* This tests the default case, where no arguments are passed.
*/
add_task(async function test_default_args_and_homescreen() {
let cmdLine = Cu.createCommandLine();
await assertOneRemoteBrowserShown(cmdLine, "about:home",
EXPECTED_ABOUTHOME_REMOTE_TYPE);
});
/**
* This tests the case where about:home is passed as the lone
* argument.
*/
add_task(async function test_abouthome_arg() {
const URI = "about:home";
let cmdLine = constructOnePageCmdLine(URI);
await assertOneRemoteBrowserShown(cmdLine, URI,
EXPECTED_ABOUTHOME_REMOTE_TYPE);
});
/**
* This tests the case where example.com is passed as the lone
* argument.
*/
add_task(async function test_examplecom_arg() {
const URI = "http://example.com/";
let cmdLine = constructOnePageCmdLine(URI);
await assertOneRemoteBrowserShown(cmdLine, URI,
E10SUtils.DEFAULT_REMOTE_TYPE);
});

View File

@ -163,27 +163,6 @@ const UAOverrides = {
},
},
/*
* Bug 1483233 - Add a mobile UA override for ebay
* (Imported from ua-update.json.in)
*
* eBay's systems have an issue where Fennec gets sent into an endless
* redirect, rendering it completely unusable.
*/
{
matches: [
"*://*.ebay.at/*", "*://*.ebay.be/*", "*://*.ebay.ca/*", "*://*.ebay.ch/*",
"*://*.ebay.cn/*", "*://*.ebay.co.th/*", "*://*.ebay.co.uk/*", "*://*.ebay.com.au/*",
"*://*.ebay.com.hk/*", "*://*.ebay.com.my/*", "*://*.ebay.com.sg/*", "*://*.ebay.com.tw/*",
"*://*.ebay.com/*", "*://*.ebay.de/*", "*://*.ebay.es/*", "*://*.ebay.fr/*",
"*://*.ebay.ie/*", "*://*.ebay.in/*", "*://*.ebay.it/*", "*://*.ebay.nl/*",
"*://*.ebay.ph/*", "*://*.ebay.pl/*", "*://*.ebay.vn/*",
],
uaTransformer: (_) => {
return "Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36";
},
},
/*
* Bug 969844 - mobile.de sends desktop site to Firefox on Android
*

View File

@ -196,6 +196,7 @@ menuitem.bookmark-item {
%include ../shared/urlbar-searchbar.inc.css
#urlbar:not(:-moz-lwtheme):not([focused="true"]),
#urlbar:not(:-moz-lwtheme).hidden-focus,
.searchbar-textbox:not(:-moz-lwtheme):not([focused="true"]) {
border-color: ThreeDShadow;
}

View File

@ -258,7 +258,7 @@ html|input.urlbar-input {
line-height: 1.745em;
}
#urlbar[focused="true"],
#urlbar:not(.hidden-focus)[focused="true"],
.searchbar-textbox[focused="true"] {
box-shadow: 0 0 0 1px var(--toolbar-field-focus-border-color) inset,
0 0 0 1px var(--toolbar-field-focus-border-color);

View File

@ -51,11 +51,13 @@
}
#urlbar:not([focused="true"]):-moz-lwtheme,
#urlbar.hidden-focus:-moz-lwtheme,
#navigator-toolbox .searchbar-textbox:not([focused="true"]):-moz-lwtheme {
border-color: var(--lwt-toolbar-field-border-color, @fieldBorderColor@);
}
#urlbar:not([focused="true"]):-moz-lwtheme:hover,
#urlbar.hidden-focus:-moz-lwtheme:hover,
#navigator-toolbox .searchbar-textbox:not([focused="true"]):-moz-lwtheme:hover {
border-color: var(--lwt-toolbar-field-border-color, @fieldHoverBorderColor@);
}
@ -65,12 +67,12 @@
background-color: var(--lwt-toolbar-field-background-color, white);
}
#urlbar[focused="true"],
#urlbar:not(.hidden-focus)[focused="true"],
.searchbar-textbox[focused="true"] {
border-color: var(--toolbar-field-focus-border-color);
}
#urlbar:-moz-lwtheme[focused="true"],
#urlbar:not(.hidden-focus):-moz-lwtheme[focused="true"],
#navigator-toolbox .searchbar-textbox:-moz-lwtheme[focused="true"] {
background-color: var(--lwt-toolbar-field-focus, var(--lwt-toolbar-field-background-color, white));
color: var(--lwt-toolbar-field-focus-color, var(--lwt-toolbar-field-color, black));
@ -294,7 +296,8 @@
transition: none;
}
#nav-bar:not([customizing="true"]) > #nav-bar-customization-target > #urlbar-container:not(:hover) > #urlbar:not([focused]) > .urlbar-textbox-container > .urlbar-history-dropmarker {
#nav-bar:not([customizing="true"]) > #nav-bar-customization-target > #urlbar-container:not(:hover) > #urlbar:not([focused]) > .urlbar-textbox-container > .urlbar-history-dropmarker,
#nav-bar:not([customizing="true"]) > #nav-bar-customization-target > #urlbar-container:not(:hover) > #urlbar.hidden-focus > .urlbar-textbox-container > .urlbar-history-dropmarker {
opacity: 0;
}
@ -616,3 +619,7 @@
margin-inline-start: -26px;
margin-inline-end: 20px;
}
#urlbar.hidden-focus[focused="true"] {
caret-color: transparent;
}

View File

@ -554,6 +554,7 @@ menuitem.bookmark-item {
@media (-moz-windows-default-theme: 0) {
#urlbar:not(:-moz-lwtheme):not([focused="true"]),
#urlbar:not(:-moz-lwtheme).hidden-focus,
.searchbar-textbox:not(:-moz-lwtheme):not([focused="true"]) {
border-color: ThreeDShadow;
}

View File

@ -87,7 +87,7 @@ buildscript {
}
dependencies {
classpath 'org.mozilla.apilint:apilint:0.1.4'
classpath 'org.mozilla.apilint:apilint:0.1.5'
classpath 'com.android.tools.build:gradle:3.1.4'
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

View File

@ -19,6 +19,7 @@ const TEST_URL = `data:text/html;charset=utf-8,` + encodeURIComponent(`
<test-component>
<div slot="slot1" id="el1">slot1-1</div>
<div slot="slot1" id="el2">slot1-2</div>
<div slot="slot1" id="el3">slot1-2</div>
</test-component>
<script>
@ -27,7 +28,14 @@ const TEST_URL = `data:text/html;charset=utf-8,` + encodeURIComponent(`
constructor() {
super();
let shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = '<slot name="slot1"></slot>';
shadowRoot.innerHTML = \`
<style>
::slotted(#el3) {
color: green;
}
</style>
<slot name="slot1"></slot>
\`;
}
});
</script>
@ -57,11 +65,12 @@ add_task(async function() {
info("Expand the slot");
const shadowChildContainers = shadowRootContainer.getChildContainers();
const slotContainer = shadowChildContainers[0];
// shadowChildContainers[0] is the style node.
const slotContainer = shadowChildContainers[1];
await expandContainer(inspector, slotContainer);
const slotChildContainers = slotContainer.getChildContainers();
is(slotChildContainers.length, 2, "Expecting 2 slotted children");
is(slotChildContainers.length, 3, "Expecting 3 slotted children");
info("Select slotted node and check that the rule view displays correct content");
await selectNode(slotChildContainers[0].node, inspector);
@ -70,6 +79,10 @@ add_task(async function() {
info("Select another slotted node and check the rule view");
await selectNode(slotChildContainers[1].node, inspector);
checkRule(ruleview, "#el2", "color", "blue");
info("Select the last slotted node and check the rule view");
await selectNode(slotChildContainers[2].node, inspector);
checkRule(ruleview, "::slotted(#el3)", "color", "green");
});
function checkRule(ruleview, selector, name, expectedValue) {

View File

@ -136,6 +136,9 @@ RootActor.prototype = {
noBlackBoxing: false,
// Support for server pretty-printing has been removed.
noPrettyPrinting: true,
// Added in Firefox 66. Indicates that clients do not need to pause the
// debuggee before adding breakpoints.
breakpointWhileRunning: true,
// Trait added in Gecko 38, indicating that all features necessary for
// grabbing allocations from the MemoryActor are available for the performance tool
memoryActorAllocations: true,

View File

@ -194,6 +194,12 @@ SourceClient.prototype = {
});
};
// With async sourcemap processing removed from the server, it is not
// necessary for clients to pause the debuggee before adding breakpoints.
if (this._client.mainRoot.traits.breakpointWhileRunning) {
return doSetBreakpoint();
}
// If the debuggee is paused, just set the breakpoint.
if (this._activeThread.paused) {
return doSetBreakpoint();

View File

@ -68,7 +68,6 @@ function run_test() {
JSString: { count: Pattern.NATURAL },
"js::Shape": { count: Pattern.NATURAL },
JSObject: { count: Pattern.NATURAL },
JSScript: { count: Pattern.NATURAL },
})
.assert(saveHeapSnapshotAndTakeCensus(dbg, { breakdown: { by: "internalType" } }));
@ -85,7 +84,6 @@ function run_test() {
JSString: coarseTypePattern,
"js::Shape": coarseTypePattern,
JSObject: coarseTypePattern,
JSScript: coarseTypePattern,
})
.assert(saveHeapSnapshotAndTakeCensus(dbg, {
breakdown: { by: "internalType",

View File

@ -457,6 +457,7 @@ exports.getBindingElementAndPseudo = getBindingElementAndPseudo;
*/
function getCSSStyleRules(node) {
const { bindingElement, pseudo } = getBindingElementAndPseudo(node);
return InspectorUtils.getCSSStyleRules(bindingElement, pseudo);
const rules = InspectorUtils.getCSSStyleRules(bindingElement, pseudo);
return rules;
}
exports.getCSSStyleRules = getCSSStyleRules;

View File

@ -363,6 +363,13 @@ RefPtr<ClientOpPromise> ClientOpenWindowInCurrentProcess(
new ClientOpPromise::Private(__func__);
#ifdef MOZ_WIDGET_ANDROID
// This isn't currently available on GeckoView because we have no way of
// knowing which app to launch. Bug 1511033.
if (!jni::IsFennec()) {
promise->Reject(NS_ERROR_NOT_IMPLEMENTED, __func__);
return promise.forget();
}
// This fires an intent that will start launching Fennec and foreground it,
// if necessary. We create an observer so that we can determine when
// the launch has completed.

View File

@ -153,6 +153,7 @@
#include "nsIRemoteWindowContext.h"
#include "nsIScriptError.h"
#include "nsIScriptSecurityManager.h"
#include "nsIServiceWorkerManager.h"
#include "nsISiteSecurityService.h"
#include "nsISound.h"
#include "mozilla/mozSpellChecker.h"
@ -3847,6 +3848,33 @@ mozilla::ipc::IPCResult ContentParent::RecvOpenNotificationSettings(
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvNotificationEvent(
const nsString& aType, const NotificationEventData& aData) {
nsCOMPtr<nsIServiceWorkerManager> swm =
mozilla::services::GetServiceWorkerManager();
if (NS_WARN_IF(!swm)) {
// Probably shouldn't happen, but no need to crash the child process.
return IPC_OK();
}
if (aType.EqualsLiteral("click")) {
nsresult rv = swm->SendNotificationClickEvent(
aData.originSuffix(), aData.scope(), aData.ID(), aData.title(),
aData.dir(), aData.lang(), aData.body(), aData.tag(), aData.icon(),
aData.data(), aData.behavior());
Unused << NS_WARN_IF(NS_FAILED(rv));
} else {
MOZ_ASSERT(aType.EqualsLiteral("close"));
nsresult rv = swm->SendNotificationCloseEvent(
aData.originSuffix(), aData.scope(), aData.ID(), aData.title(),
aData.dir(), aData.lang(), aData.body(), aData.tag(), aData.icon(),
aData.data(), aData.behavior());
Unused << NS_WARN_IF(NS_FAILED(rv));
}
return IPC_OK();
}
mozilla::ipc::IPCResult ContentParent::RecvSyncMessage(
const nsString& aMsg, const ClonedMessageData& aData,
InfallibleTArray<CpowEntry>&& aCpows, const IPC::Principal& aPrincipal,
@ -5571,12 +5599,12 @@ mozilla::ipc::IPCResult
ContentParent::RecvFirstPartyStorageAccessGrantedForOrigin(
const Principal& aParentPrincipal, const Principal& aTrackingPrincipal,
const nsCString& aTrackingOrigin, const nsCString& aGrantedOrigin,
const bool& aAnySite,
const int& aAllowMode,
FirstPartyStorageAccessGrantedForOriginResolver&& aResolver) {
AntiTrackingCommon::
SaveFirstPartyStorageAccessGrantedForOriginOnParentProcess(
aParentPrincipal, aTrackingPrincipal, aTrackingOrigin, aGrantedOrigin,
aAnySite)
aAllowMode)
->Then(GetCurrentThreadSerialEventTarget(), __func__,
[aResolver = std::move(aResolver)](
AntiTrackingCommon::FirstPartyStorageAccessGrantPromise::

View File

@ -997,6 +997,9 @@ class ContentParent final : public PContentParent,
virtual mozilla::ipc::IPCResult RecvOpenNotificationSettings(
const IPC::Principal& aPrincipal) override;
virtual mozilla::ipc::IPCResult RecvNotificationEvent(
const nsString& aType, const NotificationEventData& aData) override;
virtual mozilla::ipc::IPCResult RecvLoadURIExternal(
const URIParams& uri, PBrowserParent* windowContext) override;
virtual mozilla::ipc::IPCResult RecvExtProtocolChannelConnectParent(
@ -1172,7 +1175,7 @@ class ContentParent final : public PContentParent,
virtual mozilla::ipc::IPCResult RecvFirstPartyStorageAccessGrantedForOrigin(
const Principal& aParentPrincipal, const Principal& aTrackingPrincipal,
const nsCString& aTrackingOrigin, const nsCString& aGrantedOrigin,
const bool& aAnySite,
const int& aAllowMode,
FirstPartyStorageAccessGrantedForOriginResolver&& aResolver) override;
virtual mozilla::ipc::IPCResult RecvStoreUserInteractionAsPermission(

View File

@ -304,6 +304,24 @@ struct IPCURLClassifierFeature
nsCString skipHostList;
};
// Transport structure for Notifications API notifications
// (https://developer.mozilla.org/en-US/docs/Web/API/notification) instances
// used exclusively by the NotificationEvent PContent method.
struct NotificationEventData
{
nsCString originSuffix;
nsCString scope;
nsString ID;
nsString title;
nsString dir;
nsString lang;
nsString body;
nsString tag;
nsString icon;
nsString data;
nsString behavior;
};
/**
* The PContent protocol is a top-level protocol between the UI process
* and a content process. There is exactly one PContentParent/PContentChild pair
@ -848,6 +866,22 @@ parent:
async OpenNotificationSettings(Principal principal);
// Request that the ServiceWorkerManager in the parent process create a
// notification "click" or "close" event and dispatch it on the relevant
// ServiceWorker. This needs to happen because when a notification is
// created it is tied to a specific content process and when the user clicks
// on the notification, it will be that content process that is notified.
// However, even if the ServiceWorker lives in that process (it may no
// longer be in that process, or may have never lived there), the right/only
// way to talk through the ServiceWorker is through the parent.
//
// This happens on PContent because the ServiceWorkerManager lives on the
// main thread and bouncing this off of PBackground would be silly and
// complex. In the long run, the notification implementation will be
// overhauled to directly process the notification click/close and directly
// translate that to a ServiceWorker event.
async NotificationEvent(nsString type, NotificationEventData data);
async PPSMContentDownloader(uint32_t aCertType);
async PExternalHelperApp(OptionalURIParams uri,
@ -1171,7 +1205,7 @@ parent:
Principal aTrackingPrincipal,
nsCString aTrackingOrigin,
nsCString aGrantedOrigin,
bool aAnySite)
int aAllowMode)
returns (bool unused);
async StoreUserInteractionAsPermission(Principal aPrincipal);

View File

@ -192,6 +192,9 @@ FFmpegDataDecoder<LIBAV_VER>::ProcessDrain() {
empty->mTimecode = mLastInputDts;
bool gotFrame = false;
DecodedData results;
// When draining the FFmpeg decoder will return either a single frame at a
// time until gotFrame is set to false; or return a block of frames with
// NS_ERROR_DOM_MEDIA_END_OF_STREAM
while (NS_SUCCEEDED(DoDecode(empty, &gotFrame, results)) && gotFrame) {
}
return DecodePromise::CreateAndResolve(std::move(results), __func__);

View File

@ -136,6 +136,8 @@ FFmpegLibWrapper::LinkResult FFmpegLibWrapper::Link() {
AV_FUNC(avcodec_alloc_frame, (AV_FUNC_53 | AV_FUNC_54))
AV_FUNC(avcodec_get_frame_defaults, (AV_FUNC_53 | AV_FUNC_54))
AV_FUNC(avcodec_free_frame, AV_FUNC_54)
AV_FUNC(avcodec_send_packet, AV_FUNC_58)
AV_FUNC(avcodec_receive_frame, AV_FUNC_58)
AV_FUNC_OPTION(av_rdft_init, AV_FUNC_AVCODEC_ALL)
AV_FUNC_OPTION(av_rdft_calc, AV_FUNC_AVCODEC_ALL)
AV_FUNC_OPTION(av_rdft_end, AV_FUNC_AVCODEC_ALL)

View File

@ -80,6 +80,10 @@ struct MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS FFmpegLibWrapper {
// libavcodec v54 only
void (*avcodec_free_frame)(AVFrame** frame);
// libavcodec v58 and later only
int (*avcodec_send_packet)(AVCodecContext* avctx, const AVPacket* avpkt);
int (*avcodec_receive_frame)(AVCodecContext* avctx, AVFrame* frame);
// libavcodec optional
AvRdftInitFn av_rdft_init;
AvRdftCalcFn av_rdft_calc;

View File

@ -7,8 +7,8 @@
#include "FFmpegVideoDecoder.h"
#include "FFmpegLog.h"
#include "ImageContainer.h"
#include "MediaInfo.h"
#include "MP4Decoder.h"
#include "MediaInfo.h"
#include "VPXDecoder.h"
#include "mozilla/layers/KnowsCompositor.h"
@ -193,6 +193,48 @@ MediaResult FFmpegVideoDecoder<LIBAV_VER>::DoDecode(
packet.flags = aSample->mKeyframe ? AV_PKT_FLAG_KEY : 0;
packet.pos = aSample->mOffset;
#if LIBAVCODEC_VERSION_MAJOR >= 58
packet.duration = aSample->mDuration.ToMicroseconds();
int res = mLib->avcodec_send_packet(mCodecContext, &packet);
if (res < 0) {
// In theory, avcodec_send_packet could sent -EAGAIN should its internal
// buffers be full. In practice this can't happen as we only feed one frame
// at a time, and we immediately call avcodec_receive_frame right after.
FFMPEG_LOG("avcodec_send_packet error: %d", res);
return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
RESULT_DETAIL("avcodec_send_packet error: %d", res));
}
if (aGotFrame) {
*aGotFrame = false;
}
do {
if (!PrepareFrame()) {
NS_WARNING("FFmpeg h264 decoder failed to allocate frame.");
return MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__);
}
res = mLib->avcodec_receive_frame(mCodecContext, mFrame);
if (res == int(AVERROR_EOF)) {
return NS_ERROR_DOM_MEDIA_END_OF_STREAM;
}
if (res == AVERROR(EAGAIN)) {
return NS_OK;
}
if (res < 0) {
FFMPEG_LOG("avcodec_receive_frame error: %d", res);
return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR,
RESULT_DETAIL("avcodec_receive_frame error: %d", res));
}
MediaResult rv = CreateImage(mFrame->pkt_pos, mFrame->pkt_pts,
mFrame->pkt_duration, aResults);
if (NS_FAILED(rv)) {
return rv;
}
if (aGotFrame) {
*aGotFrame = true;
}
} while (true);
#else
// LibAV provides no API to retrieve the decoded sample's duration.
// (FFmpeg >= 1.0 provides av_frame_get_pkt_duration)
// As such we instead use a map using the dts as key that we will retrieve
@ -248,9 +290,21 @@ MediaResult FFmpegVideoDecoder<LIBAV_VER>::DoDecode(
// against the map becoming extremely big.
mDurationMap.Clear();
}
MediaResult rv = CreateImage(aSample->mOffset, pts, duration, aResults);
if (NS_SUCCEEDED(rv) && aGotFrame) {
*aGotFrame = true;
}
return rv;
#endif
}
MediaResult FFmpegVideoDecoder<LIBAV_VER>::CreateImage(
int64_t aOffset, int64_t aPts, int64_t aDuration,
MediaDataDecoder::DecodedData& aResults) {
FFMPEG_LOG("Got one frame output with pts=%" PRId64 " dts=%" PRId64
" duration=%" PRId64 " opaque=%" PRId64,
pts, mFrame->pkt_dts, duration, mCodecContext->reordered_opaque);
aPts, mFrame->pkt_dts, aDuration, mCodecContext->reordered_opaque);
VideoData::YCbCrBuffer b;
b.mPlanes[0].mData = mFrame->data[0];
@ -332,8 +386,8 @@ MediaResult FFmpegVideoDecoder<LIBAV_VER>::DoDecode(
}
}
RefPtr<VideoData> v = VideoData::CreateAndCopyData(
mInfo, mImageContainer, aSample->mOffset, TimeUnit::FromMicroseconds(pts),
TimeUnit::FromMicroseconds(duration), b, !!mFrame->key_frame,
mInfo, mImageContainer, aOffset, TimeUnit::FromMicroseconds(aPts),
TimeUnit::FromMicroseconds(aDuration), b, !!mFrame->key_frame,
TimeUnit::FromMicroseconds(-1),
mInfo.ScaledImageRect(mFrame->width, mFrame->height), mImageAllocator);
@ -342,9 +396,6 @@ MediaResult FFmpegVideoDecoder<LIBAV_VER>::DoDecode(
RESULT_DETAIL("image allocation error"));
}
aResults.AppendElement(std::move(v));
if (aGotFrame) {
*aGotFrame = true;
}
return NS_OK;
}

View File

@ -57,12 +57,19 @@ class FFmpegVideoDecoder<LIBAV_VER>
void OutputDelayedFrames();
bool NeedParser() const override {
return
#if LIBAVCODEC_VERSION_MAJOR >= 58
false;
#else
#if LIBAVCODEC_VERSION_MAJOR >= 55
mCodecID == AV_CODEC_ID_VP9 ||
#endif
mCodecID == AV_CODEC_ID_VP8;
#endif
}
MediaResult CreateImage(int64_t aOffset, int64_t aPts, int64_t aDuration,
MediaDataDecoder::DecodedData& aResults);
/**
* This method allocates a buffer for FFmpeg's decoder, wrapped in an Image.
* Currently it only supports Planar YUV420, which appears to be the only

View File

@ -645,6 +645,8 @@ support-files =
very-short.mp3
video-overhang.ogg
video-overhang.ogg^headers^
vp9-superframes.webm
vp9-superframes.webm^headers^
vp9.webm
vp9.webm^headers^
vp9-short.webm
@ -1229,6 +1231,7 @@ skip-if = toolkit == 'android' # android(bug 1232305)
skip-if = android_version == '17' # android(bug 1232305)
[test_volume.html]
skip-if = toolkit == 'android' # android(bug 1232305)
[test_vp9_superframes.html]
[test_vttparser.html]
skip-if = android_version == '22' # android(bug 1368010)
tags = webvtt

View File

@ -0,0 +1,31 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test that all VP9 frames are decoded (contains superframes)</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
function test() {
var video = document.createElement("video");
video.src = "vp9-superframes.webm";
video.play();
video.addEventListener("ended", function () {
vpq = video.getVideoPlaybackQuality();
is(vpq.totalVideoFrames, 120, "totalVideoFrames must contains 120 frames");
SimpleTest.finish();
});
}
addLoadEvent(function() {
test();
});
</script>
</pre>
</body>
</html>

Binary file not shown.

View File

@ -0,0 +1 @@
Cache-Control: no-store

View File

@ -308,8 +308,6 @@ struct ParamTraits<mozilla::dom::RTCInboundRTPStreamStats> {
WriteParam(aMsg, aParam.mDiscardedPackets);
WriteParam(aMsg, aParam.mFramesDecoded);
WriteParam(aMsg, aParam.mJitter);
WriteParam(aMsg, aParam.mMozAvSyncDelay);
WriteParam(aMsg, aParam.mMozJitterBufferDelay);
WriteParam(aMsg, aParam.mRoundTripTime);
WriteParam(aMsg, aParam.mPacketsLost);
WriteParam(aMsg, aParam.mPacketsReceived);
@ -323,8 +321,6 @@ struct ParamTraits<mozilla::dom::RTCInboundRTPStreamStats> {
!ReadParam(aMsg, aIter, &(aResult->mDiscardedPackets)) ||
!ReadParam(aMsg, aIter, &(aResult->mFramesDecoded)) ||
!ReadParam(aMsg, aIter, &(aResult->mJitter)) ||
!ReadParam(aMsg, aIter, &(aResult->mMozAvSyncDelay)) ||
!ReadParam(aMsg, aIter, &(aResult->mMozJitterBufferDelay)) ||
!ReadParam(aMsg, aIter, &(aResult->mRoundTripTime)) ||
!ReadParam(aMsg, aIter, &(aResult->mPacketsLost)) ||
!ReadParam(aMsg, aIter, &(aResult->mPacketsReceived)) ||

View File

@ -1290,17 +1290,25 @@ ServiceWorkerNotificationObserver::Observe(nsISupports* aSubject,
return rv;
}
nsCOMPtr<nsIServiceWorkerManager> swm =
mozilla::services::GetServiceWorkerManager();
if (NS_WARN_IF(!swm)) {
return NS_ERROR_FAILURE;
}
if (!strcmp("alertclickcallback", aTopic)) {
rv = swm->SendNotificationClickEvent(
originSuffix, NS_ConvertUTF16toUTF8(mScope), mID, mTitle, mDir, mLang,
mBody, mTag, mIcon, mData, mBehavior);
Unused << NS_WARN_IF(NS_FAILED(rv));
if (XRE_IsParentProcess() || !ServiceWorkerParentInterceptEnabled()) {
nsCOMPtr<nsIServiceWorkerManager> swm =
mozilla::services::GetServiceWorkerManager();
if (NS_WARN_IF(!swm)) {
return NS_ERROR_FAILURE;
}
rv = swm->SendNotificationClickEvent(
originSuffix, NS_ConvertUTF16toUTF8(mScope), mID, mTitle, mDir, mLang,
mBody, mTag, mIcon, mData, mBehavior);
Unused << NS_WARN_IF(NS_FAILED(rv));
} else {
auto* cc = ContentChild::GetSingleton();
NotificationEventData data(originSuffix, NS_ConvertUTF16toUTF8(mScope),
mID, mTitle, mDir, mLang, mBody, mTag, mIcon,
mData, mBehavior);
Unused << cc->SendNotificationEvent(NS_LITERAL_STRING("click"), data);
}
return NS_OK;
}
@ -1318,10 +1326,24 @@ ServiceWorkerNotificationObserver::Observe(nsISupports* aSubject,
notificationStorage->Delete(origin, mID);
}
rv = swm->SendNotificationCloseEvent(
originSuffix, NS_ConvertUTF16toUTF8(mScope), mID, mTitle, mDir, mLang,
mBody, mTag, mIcon, mData, mBehavior);
Unused << NS_WARN_IF(NS_FAILED(rv));
if (XRE_IsParentProcess() || !ServiceWorkerParentInterceptEnabled()) {
nsCOMPtr<nsIServiceWorkerManager> swm =
mozilla::services::GetServiceWorkerManager();
if (NS_WARN_IF(!swm)) {
return NS_ERROR_FAILURE;
}
rv = swm->SendNotificationCloseEvent(
originSuffix, NS_ConvertUTF16toUTF8(mScope), mID, mTitle, mDir, mLang,
mBody, mTag, mIcon, mData, mBehavior);
Unused << NS_WARN_IF(NS_FAILED(rv));
} else {
auto* cc = ContentChild::GetSingleton();
NotificationEventData data(originSuffix, NS_ConvertUTF16toUTF8(mScope),
mID, mTitle, mDir, mLang, mBody, mTag, mIcon,
mData, mBehavior);
Unused << cc->SendNotificationEvent(NS_LITERAL_STRING("close"), data);
}
return NS_OK;
}

View File

@ -294,8 +294,15 @@ var NotificationDB = {
var notifications = [];
// Grab only the notifications for specified origin.
if (this.notifications[origin]) {
for (var i in this.notifications[origin]) {
notifications.push(this.notifications[origin][i]);
if (data.tag) {
let n;
if ((n = this.byTag[origin][data.tag])) {
notifications.push(n);
}
} else {
for (var i in this.notifications[origin]) {
notifications.push(this.notifications[origin][i]);
}
}
}
return Promise.resolve(notifications);

View File

@ -28,11 +28,6 @@ const kMessages = [
];
function NotificationStorage() {
// cache objects
this._notifications = {};
this._byTag = {};
this._cached = false;
this._requests = {};
this._requestCount = 0;
@ -83,37 +78,15 @@ NotificationStorage.prototype = {
serviceWorkerRegistrationScope: serviceWorkerRegistrationScope,
};
this._notifications[id] = notification;
if (tag) {
if (!this._byTag[origin]) {
this._byTag[origin] = {};
}
// We might have existing notification with this tag,
// if so we need to remove it from our cache.
if (this._byTag[origin][tag]) {
var oldNotification = this._byTag[origin][tag];
delete this._notifications[oldNotification.id];
}
this._byTag[origin][tag] = notification;
};
if (serviceWorkerRegistrationScope) {
Services.cpmm.sendAsyncMessage("Notification:Save", {
origin: origin,
notification: notification
});
}
Services.cpmm.sendAsyncMessage("Notification:Save", {
origin: origin,
notification: notification
});
},
get: function(origin, tag, callback) {
if (DEBUG) { debug("GET: " + origin + " " + tag); }
if (this._cached) {
this._fetchFromCache(origin, tag, callback);
} else {
this._fetchFromDB(origin, tag, callback);
}
this._fetchFromDB(origin, tag, callback);
},
getByID: function(origin, id, callback) {
@ -137,14 +110,6 @@ NotificationStorage.prototype = {
delete: function(origin, id) {
if (DEBUG) { debug("DELETE: " + id); }
var notification = this._notifications[id];
if (notification) {
if (notification.tag) {
delete this._byTag[origin][notification.tag];
}
delete this._notifications[id];
}
Services.cpmm.sendAsyncMessage("Notification:Delete", {
origin: origin,
id: id
@ -157,8 +122,8 @@ NotificationStorage.prototype = {
switch (message.name) {
case kMessageNotificationGetAllOk:
delete this._requests[message.data.requestID];
this._populateCache(message.data.notifications);
this._fetchFromCache(request.origin, request.tag, request.callback);
this._returnNotifications(message.data.notifications, request.origin,
request.tag, request.callback);
break;
case kMessageNotificationGetAllKo:
@ -184,33 +149,20 @@ NotificationStorage.prototype = {
_fetchFromDB: function(origin, tag, callback) {
var request = {
origin: origin,
tag: tag,
callback: callback
origin,
tag,
callback,
};
var requestID = this._requestCount++;
this._requests[requestID] = request;
Services.cpmm.sendAsyncMessage("Notification:GetAll", {
origin: origin,
requestID: requestID
origin,
tag,
requestID,
});
},
_fetchFromCache: function(origin, tag, callback) {
var notifications = [];
// If a tag was specified and we have a notification
// with this tag, return that. If no tag was specified
// simple return all stored notifications.
if (tag && this._byTag[origin] && this._byTag[origin][tag]) {
notifications.push(this._byTag[origin][tag]);
} else if (!tag) {
for (var id in this._notifications) {
if (this._notifications[id].origin === origin) {
notifications.push(this._notifications[id]);
}
}
}
_returnNotifications: function(notifications, origin, tag, callback) {
// Pass each notification back separately.
// The callback is called asynchronously to match the behaviour when
// fetching from the database.
@ -239,21 +191,6 @@ NotificationStorage.prototype = {
}
},
_populateCache: function(notifications) {
notifications.forEach(notification => {
this._notifications[notification.id] = notification;
if (notification.tag && notification.origin) {
let tag = notification.tag;
let origin = notification.origin;
if (!this._byTag[origin]) {
this._byTag[origin] = {};
}
this._byTag[origin][tag] = notification;
}
});
this._cached = true;
},
classID : Components.ID(NOTIFICATIONSTORAGE_CID),
contractID : NOTIFICATIONSTORAGE_CONTRACTID,
QueryInterface: ChromeUtils.generateQI([Ci.nsINotificationStorage]),

View File

@ -282,6 +282,7 @@ tags = mcb
[test_onmessageerror.html]
[test_opaque_intercept.html]
[test_openWindow.html]
skip-if = toolkit == 'android' && !isFennec
tags = openwindow
[test_origin_after_redirect.html]
[test_origin_after_redirect_cached.html]

View File

@ -54,8 +54,6 @@ dictionary RTCInboundRTPStreamStats : RTCRtpStreamStats {
unsigned long long bytesReceived;
double jitter;
unsigned long packetsLost;
long mozAvSyncDelay;
long mozJitterBufferDelay;
long roundTripTime;
// Video decoder measurement, not present in RTCP case

View File

@ -15,7 +15,8 @@
namespace mozilla {
namespace layers {
APZCTreeManagerChild::APZCTreeManagerChild() : mCompositorSession(nullptr) {}
APZCTreeManagerChild::APZCTreeManagerChild()
: mCompositorSession(nullptr), mIPCOpen(false) {}
APZCTreeManagerChild::~APZCTreeManagerChild() {}
@ -66,7 +67,9 @@ void APZCTreeManagerChild::SetTargetAPZC(
void APZCTreeManagerChild::UpdateZoomConstraints(
const ScrollableLayerGuid& aGuid,
const Maybe<ZoomConstraints>& aConstraints) {
SendUpdateZoomConstraints(aGuid, aConstraints);
if (mIPCOpen) {
SendUpdateZoomConstraints(aGuid, aConstraints);
}
}
void APZCTreeManagerChild::SetDPI(float aDpiValue) { SendSetDPI(aDpiValue); }
@ -101,6 +104,21 @@ APZInputBridge* APZCTreeManagerChild::InputBridge() {
return mInputBridge.get();
}
void APZCTreeManagerChild::AddIPDLReference() {
MOZ_ASSERT(mIPCOpen == false);
mIPCOpen = true;
AddRef();
}
void APZCTreeManagerChild::ReleaseIPDLReference() {
mIPCOpen = false;
Release();
}
void APZCTreeManagerChild::ActorDestroy(ActorDestroyReason aWhy) {
mIPCOpen = false;
}
mozilla::ipc::IPCResult APZCTreeManagerChild::RecvHandleTap(
const TapType& aType, const LayoutDevicePoint& aPoint,
const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid,

View File

@ -59,6 +59,10 @@ class APZCTreeManagerChild : public IAPZCTreeManager,
APZInputBridge* InputBridge() override;
void AddIPDLReference();
void ReleaseIPDLReference();
void ActorDestroy(ActorDestroyReason aWhy) override;
protected:
mozilla::ipc::IPCResult RecvHandleTap(const TapType& aType,
const LayoutDevicePoint& aPoint,
@ -79,6 +83,7 @@ class APZCTreeManagerChild : public IAPZCTreeManager,
private:
MOZ_NON_OWNING_REF RemoteCompositorSession* mCompositorSession;
RefPtr<APZInputBridgeChild> mInputBridge;
bool mIPCOpen;
};
} // namespace layers

View File

@ -953,7 +953,7 @@ bool CompositorBridgeChild::DeallocPCompositorWidgetChild(
PAPZCTreeManagerChild* CompositorBridgeChild::AllocPAPZCTreeManagerChild(
const LayersId& aLayersId) {
APZCTreeManagerChild* child = new APZCTreeManagerChild();
child->AddRef();
child->AddIPDLReference();
if (aLayersId.IsValid()) {
TabChild* tabChild = TabChild::GetFrom(aLayersId);
if (tabChild) {
@ -979,8 +979,8 @@ bool CompositorBridgeChild::DeallocPAPZChild(PAPZChild* aActor) {
bool CompositorBridgeChild::DeallocPAPZCTreeManagerChild(
PAPZCTreeManagerChild* aActor) {
APZCTreeManagerChild* parent = static_cast<APZCTreeManagerChild*>(aActor);
parent->Release();
APZCTreeManagerChild* child = static_cast<APZCTreeManagerChild*>(aActor);
child->ReleaseIPDLReference();
return true;
}

View File

@ -389,6 +389,11 @@ class gfxPrefs final {
DECL_GFX_PREF(Live, "dom.vr.oculus.present.timeout", VROculusPresentTimeout, int32_t, 500);
DECL_GFX_PREF(Live, "dom.vr.oculus.quit.timeout", VROculusQuitTimeout, int32_t, 10000);
DECL_GFX_PREF(Once, "dom.vr.openvr.enabled", VROpenVREnabled, bool, false);
#if defined(RELEASE_OR_BETA)
DECL_GFX_PREF(Once, "dom.vr.openvr.action_input", VROpenVRActionInputEnabled, bool, false);
#else
DECL_GFX_PREF(Once, "dom.vr.openvr.action_input", VROpenVRActionInputEnabled, bool, true);
#endif
DECL_GFX_PREF(Once, "dom.vr.osvr.enabled", VROSVREnabled, bool, false);
DECL_GFX_PREF(Live, "dom.vr.controller.enumerate.interval", VRControllerEnumerateInterval, int32_t, 1000);
DECL_GFX_PREF(Live, "dom.vr.display.enumerate.interval", VRDisplayEnumerateInterval, int32_t, 5000);

View File

@ -155,7 +155,10 @@ void VRDisplayClient::FireGamepadEvents() {
// Send events to notify that new controllers are added
RefPtr<dom::Gamepad> existing =
gamepadManager->GetGamepad(gamepadId, dom::GamepadServiceType::VR);
if (lastState.controllerName[0] == '\0' || !existing) {
// ControllerState in OpenVR action-based API gets delay to query btn and axis count.
// So, we need to check if they are more than zero.
if ((lastState.controllerName[0] == '\0' || !existing) &&
(state.numButtons > 0 || state.numAxes > 0)) {
dom::GamepadAdded info(NS_ConvertUTF8toUTF16(state.controllerName),
dom::GamepadMappingType::_empty, state.hand,
mDisplayInfo.mDisplayID, state.numButtons,

File diff suppressed because it is too large Load Diff

View File

@ -24,8 +24,18 @@ class VRThread;
static const int kNumOpenVRHaptics = 1;
class OpenVRSession : public VRSession {
public:
enum OpenVRHand : int8_t
{
Left = 0,
Right = 1,
Total = 2,
None = -1
};
class OpenVRSession : public VRSession
{
public:
OpenVRSession();
virtual ~OpenVRSession();
@ -40,7 +50,7 @@ class OpenVRSession : public VRSession {
void StopVibrateHaptic(uint32_t aControllerIdx) override;
void StopAllHaptics() override;
protected:
protected:
#if defined(XP_WIN)
bool SubmitFrame(const mozilla::gfx::VRLayer_Stereo_Immersive& aLayer,
ID3D11Texture2D* aTexture) override;
@ -49,12 +59,14 @@ class OpenVRSession : public VRSession {
const VRLayerTextureHandle& aTexture) override;
#endif
private:
private:
// OpenVR State
::vr::IVRSystem* mVRSystem = nullptr;
::vr::IVRChaperone* mVRChaperone = nullptr;
::vr::IVRCompositor* mVRCompositor = nullptr;
::vr::TrackedDeviceIndex_t mControllerDeviceIndex[kVRControllerMaxCount];
::vr::TrackedDeviceIndex_t mControllerDeviceIndexObsolete[kVRControllerMaxCount];
::vr::VRActionSetHandle_t mActionsetFirefox = vr::k_ulInvalidActionSetHandle;
OpenVRHand mControllerDeviceIndex[kVRControllerMaxCount];
float mHapticPulseRemaining[kVRControllerMaxCount][kNumOpenVRHaptics];
float mHapticPulseIntensity[kVRControllerMaxCount][kNumOpenVRHaptics];
bool mIsWindowsMR;
@ -65,9 +77,13 @@ class OpenVRSession : public VRSession {
void UpdateEyeParameters(mozilla::gfx::VRSystemState& aState);
void UpdateHeadsetPose(mozilla::gfx::VRSystemState& aState);
void EnumerateControllers(VRSystemState& aState);
void EnumerateControllersObsolete(VRSystemState& aState);
void UpdateControllerPoses(VRSystemState& aState);
void UpdateControllerPosesObsolete(VRSystemState& aState);
void UpdateControllerButtons(VRSystemState& aState);
void UpdateControllerButtonsObsolete(VRSystemState& aState);
void UpdateTelemetry(VRSystemState& aSystemState);
void SetupContollerActions();
bool SubmitFrame(const VRLayerTextureHandle& aTextureHandle,
::vr::ETextureType aTextureType,
@ -80,6 +96,7 @@ class OpenVRSession : public VRSession {
::vr::TrackedDeviceIndex_t aDeviceIndex,
nsCString& aId);
void UpdateHaptics();
void UpdateHapticsObsolete();
void StartHapticThread();
void StopHapticThread();
void StartHapticTimer();

View File

@ -0,0 +1,298 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_VR_BLINDING_OPENVRKNUCKLESBINDING_H
#define GFX_VR_BLINDING_OPENVRKNUCKLESBINDING_H
namespace mozilla {
namespace gfx {
struct OpenVRKnucklesBinding {
const char* binding =
"{\n"
" \"version\" : \"0.1\", \n"
" \"controller_type\" : \"knuckles\", \n"
" \"description\" : \"Bindings for Firefox OpenVR for the Knuckles controller\", \n"
" \"name\" : \"Firefox bindings for Knuckles Controller\", \n"
" \"bindings\" : { \n"
" \"/actions/firefox\" : { \n"
" \"poses\" : [ \n"
" { \n"
" \"output\" : \"/actions/firefox/in/LHand_pose\", \n"
" \"path\" : \"/user/hand/left/pose/raw\" \n"
" },\n"
" { \n"
" \"output\" : \"/actions/firefox/in/RHand_pose\", \n"
" \"path\" : \"/user/hand/right/pose/raw\" \n"
" }\n"
" ],\n"
" \"haptics\" : [ \n"
" {\n"
" \"output\" : \"/actions/firefox/out/LHand_haptic\", \n"
" \"path\" : \"/user/hand/left/output/haptic\" \n"
" },\n"
" { \n"
" \"output\" : \"/actions/firefox/out/RHand_haptic\", \n"
" \"path\" : \"/user/hand/right/output/haptic\" \n"
" }\n"
" ],\n"
" \"sources\" : [ \n"
" {\n"
" \"inputs\" : { \n"
" \"position\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_trackpad_analog\" \n"
" }, \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_trackpad_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_trackpad_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trackpad\", \n"
" \"path\" : \"/user/hand/left/input/trackpad\" \n"
" },\n"
" {\n"
" \"inputs\" : { \n"
" \"position\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_trackpad_analog\" \n"
" }, \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_trackpad_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_trackpad_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trackpad\", \n"
" \"path\" : \"/user/hand/right/input/trackpad\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_trigger_value\" \n"
" } \n"
" },\n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/left/input/trigger\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_trigger_value\" \n"
" } \n"
" },\n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/right/input/trigger\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_grip_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_grip_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/left/input/grip\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_grip_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_grip_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/right/input/grip\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_system_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_system_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/left/input/system\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_system_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_system_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/right/input/system\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_a_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_a_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/left/input/a\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_a_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_a_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/right/input/a\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_b_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_b_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/left/input/b\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_b_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_b_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/right/input/b\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"position\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_thumbstick_analog\" \n"
" }, \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_thumbstick_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_thumbstick_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"joystick\", \n"
" \"path\" : \"/user/hand/left/input/thumbstick\" \n"
" },\n"
" {\n"
" \"inputs\" : { \n"
" \"position\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_thumbstick_analog\" \n"
" }, \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_thumbstick_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_thumbstick_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"joystick\", \n"
" \"path\" : \"/user/hand/right/input/thumbstick\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_finger_index_value\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/left/input/finger/index\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_finger_index_value\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/right/input/finger/index\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_finger_middle_value\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/left/input/finger/middle\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_finger_middle_value\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/right/input/finger/middle\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_finger_ring_value\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/left/input/finger/ring\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_finger_ring_value\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/right/input/finger/ring\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_finger_pinky_value\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/left/input/finger/pinky\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_finger_pinky_value\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/right/input/finger/pinky\" \n"
" } \n"
" ]\n"
" }\n"
" }\n"
"}";
};
} // namespace mozilla
} // namespace gfx
#endif // GFX_VR_BLINDING_OPENVRKNUCKLESBINDING_H

View File

@ -0,0 +1,172 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_VR_BLINDING_OPENVRVIVEBINDING_H
#define GFX_VR_BLINDING_OPENVRVIVEBINDING_H
namespace mozilla {
namespace gfx {
struct OpenVRViveBinding {
const char* binding =
"{\n"
" \"version\" : \"0.1\", \n"
" \"controller_type\" : \"vive_controller\", \n"
" \"description\" : \"Bindings for Firefox OpenVR for the Vive controller\", \n"
" \"name\" : \"Firefox bindings for Vive Controller\", \n"
" \"bindings\" : { \n"
" \"/actions/firefox\" : { \n"
" \"poses\" : [ \n"
" { \n"
" \"output\" : \"/actions/firefox/in/LHand_pose\", \n"
" \"path\" : \"/user/hand/left/pose/raw\" \n"
" },\n"
" { \n"
" \"output\" : \"/actions/firefox/in/RHand_pose\", \n"
" \"path\" : \"/user/hand/right/pose/raw\" \n"
" }\n"
" ],\n"
" \"haptics\" : [ \n"
" {\n"
" \"output\" : \"/actions/firefox/out/LHand_haptic\", \n"
" \"path\" : \"/user/hand/left/output/haptic\" \n"
" },\n"
" { \n"
" \"output\" : \"/actions/firefox/out/RHand_haptic\", \n"
" \"path\" : \"/user/hand/right/output/haptic\" \n"
" }\n"
" ],\n"
" \"sources\" : [ \n"
" {\n"
" \"inputs\" : { \n"
" \"position\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_trackpad_analog\" \n"
" }, \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_trackpad_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_trackpad_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trackpad\", \n"
" \"path\" : \"/user/hand/left/input/trackpad\" \n"
" },\n"
" {\n"
" \"inputs\" : { \n"
" \"position\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_trackpad_analog\" \n"
" }, \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_trackpad_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_trackpad_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trackpad\", \n"
" \"path\" : \"/user/hand/right/input/trackpad\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_trigger_value\" \n"
" } \n"
" },\n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/left/input/trigger\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_trigger_value\" \n"
" } \n"
" },\n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/right/input/trigger\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_grip_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_grip_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/left/input/grip\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_grip_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_grip_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/right/input/grip\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_menu_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_menu_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/left/input/application_menu\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_menu_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_menu_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/right/input/application_menu\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_system_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_system_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/left/input/system\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_system_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_system_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/right/input/system\" \n"
" } \n"
" ]\n"
" }\n"
" }\n"
"}";
};
} // namespace mozilla
} // namespace gfx
#endif // GFX_VR_BLINDING_OPENVRVIVEBINDING_H

View File

@ -0,0 +1,192 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_VR_BLINDING_OPENVRWMRBINDING_H
#define GFX_VR_BLINDING_OPENVRWMRBINDING_H
namespace mozilla {
namespace gfx {
struct OpenVRWMRBinding
{
//OpenVRWMRBinding();
const char* binding =
"{\n"
" \"version\" : \"0.1\", \n"
" \"controller_type\" : \"holographic_controller\", \n"
" \"description\" : \"Bindings for Firefox OpenVR for the Windows Mixed Reality controller\", \n"
" \"name\" : \"Firefox bindings for Mixed Reality Controller\", \n"
" \"bindings\" : { \n"
" \"/actions/firefox\" : { \n"
" \"poses\" : [ \n"
" { \n"
" \"output\" : \"/actions/firefox/in/LHand_pose\", \n"
" \"path\" : \"/user/hand/left/pose/raw\" \n"
" },\n"
" { \n"
" \"output\" : \"/actions/firefox/in/RHand_pose\", \n"
" \"path\" : \"/user/hand/right/pose/raw\" \n"
" }\n"
" ],\n"
" \"haptics\" : [ \n"
" {\n"
" \"output\" : \"/actions/firefox/out/LHand_haptic\", \n"
" \"path\" : \"/user/hand/left/output/haptic\" \n"
" },\n"
" { \n"
" \"output\" : \"/actions/firefox/out/RHand_haptic\", \n"
" \"path\" : \"/user/hand/right/output/haptic\" \n"
" }\n"
" ],\n"
" \"sources\" : [ \n"
" {\n"
" \"inputs\" : { \n"
" \"position\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_trackpad_analog\" \n"
" }, \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_trackpad_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_trackpad_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trackpad\", \n"
" \"path\" : \"/user/hand/left/input/trackpad\" \n"
" },\n"
" {\n"
" \"inputs\" : { \n"
" \"position\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_trackpad_analog\" \n"
" }, \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_trackpad_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_trackpad_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"trackpad\", \n"
" \"path\" : \"/user/hand/right/input/trackpad\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_trigger_value\" \n"
" } \n"
" },\n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/left/input/trigger\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"pull\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_trigger_value\" \n"
" } \n"
" },\n"
" \"mode\" : \"trigger\", \n"
" \"path\" : \"/user/hand/right/input/trigger\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_grip_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_grip_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/left/input/grip\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_grip_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_grip_touched\" \n"
" } \n"
" }, \n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/right/input/grip\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_menu_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_menu_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/left/input/application_menu\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_menu_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_menu_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/right/input/application_menu\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_system_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_system_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/left/input/system\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"click\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_system_pressed\" \n"
" }, \n"
" \"touch\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_system_touched\" \n"
" } \n"
" },\n"
" \"mode\" : \"button\", \n"
" \"path\" : \"/user/hand/right/input/system\" \n"
" }, \n"
" {\n"
" \"inputs\" : { \n"
" \"position\" : { \n"
" \"output\" : \"/actions/firefox/in/LHand_thumbstick_analog\" \n"
" } \n"
" }, \n"
" \"mode\" : \"joystick\", \n"
" \"path\" : \"/user/hand/left/input/joystick\" \n"
" },\n"
" {\n"
" \"inputs\" : { \n"
" \"position\" : { \n"
" \"output\" : \"/actions/firefox/in/RHand_thumbstick_analog\" \n"
" } \n"
" }, \n"
" \"mode\" : \"joystick\", \n"
" \"path\" : \"/user/hand/right/input/joystick\" \n"
" } \n"
" ]\n"
" }\n"
" }\n"
"}";
};
} // namespace mozilla
} // namespace gfx
#endif // GFX_VR_BLINDING_OPENVRWMRBINDING_H

View File

@ -1,13 +1,13 @@
OpenVR SDK
---
OpenVR is an API and runtime that allows access to VR hardware from multiple
vendors without requiring that applications have specific knowledge of the
hardware they are targeting. This repository is an SDK that contains the API
and samples. The runtime is under SteamVR in Tools on Steam.
### Documentation
Documentation for the API is available on the [Github Wiki](https://github.com/ValveSoftware/openvr/wiki/API-Documentation)
More information on OpenVR and SteamVR can be found on http://steamvr.com
OpenVR SDK
---
OpenVR is an API and runtime that allows access to VR hardware from multiple
vendors without requiring that applications have specific knowledge of the
hardware they are targeting. This repository is an SDK that contains the API
and samples. The runtime is under SteamVR in Tools on Steam.
### Documentation
Documentation for the API is available on the [Github Wiki](https://github.com/ValveSoftware/openvr/wiki/API-Documentation)
More information on OpenVR and SteamVR can be found on http://steamvr.com

View File

@ -1,4 +1,4 @@
This directory contains files from the OpenVR SDK, version 1.0.18.
This directory contains files from the OpenVR SDK, version 1.0.17.
This SDK contains the OpenVR API interface headers and functions to load the
OpenVR runtime libraries which actually implement the functionality. The
@ -47,6 +47,8 @@ Steps to update the library:
- Replace the #define VR_INTERFACE in openvr.h to avoid extern'ing the functions.
Unlike the usual OpenVR API builds, we are not building a separate dll.
- Add explicit in CVRSettingHelper constructor.
- Update this README.mozilla file with the new OpenVR SDK version and any
additional steps needed for newer versions.

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +1,39 @@
This is the source code for the OpenVR API client binding library which connects
OpenVR applications to the SteamVR runtime, taking into account the version
of the OpenVR interface they were compiled against.
The client binding library - openvr_api.dll on Windows, openvr_api.so on
Linux, and openvr_api.dylib or OpenVR.framework on macOS - knows how to find
and read the SteamVR runtime installation information which allows it to
find and dynamically connect to the installed runtime. In combination with the
interface version identifiers from /include/openvr.h which are baked
into applications at the time they are built, the OpenVR API client
binding library captures and conveys to the SteamVR runtime the version
of the OpenVR API interface behavior that the application expects.
Applications carry with them a private/local copy of the client binding
library when they ship, and they should install it locally to their
application. Applications should not install the client binding library
globally or attempt to link to a globally installed client binding library.
Doing so negates at least part of the ability for the client binding library
to accurately reflect the version of the OpenVR API that the application
was built against, and so hinders compatibility support in the face of
API changes.
Most applications should simply link to and redistribute with their application
the pre-built client binding library found in the /bin directory of this
repository. Some small number of applications which have specific requirements
around redistributing only binaries they build themselves should build
the client library from this source and either statically link it into
their application or redistribute the binary they build.
This is a cmake project, to build it use the version of cmake appropriate
for your platform. For example, to build on a POSIX system simply perform
cd src; mkdir _build; cd _build; cmake ..; make
and you will end up with the static library /src/bin/<arch>/libopenvr_api.a
To build a shared library, pass -DBUILD_SHARED=1 to cmake.
To build as a framework on apple platforms, pass -DBUILD_FRAMEWORK=1 to cmake.
To see a complete list of configurable build options, use `cmake -LAH`
This is the source code for the OpenVR API client binding library which connects
OpenVR applications to the SteamVR runtime, taking into account the version
of the OpenVR interface they were compiled against.
The client binding library - openvr_api.dll on Windows, openvr_api.so on
Linux, and openvr_api.dylib or OpenVR.framework on macOS - knows how to find
and read the SteamVR runtime installation information which allows it to
find and dynamically connect to the installed runtime. In combination with the
interface version identifiers from /include/openvr.h which are baked
into applications at the time they are built, the OpenVR API client
binding library captures and conveys to the SteamVR runtime the version
of the OpenVR API interface behavior that the application expects.
Applications carry with them a private/local copy of the client binding
library when they ship, and they should install it locally to their
application. Applications should not install the client binding library
globally or attempt to link to a globally installed client binding library.
Doing so negates at least part of the ability for the client binding library
to accurately reflect the version of the OpenVR API that the application
was built against, and so hinders compatibility support in the face of
API changes.
Most applications should simply link to and redistribute with their application
the pre-built client binding library found in the /bin directory of this
repository. Some small number of applications which have specific requirements
around redistributing only binaries they build themselves should build
the client library from this source and either statically link it into
their application or redistribute the binary they build.
This is a cmake project, to build it use the version of cmake appropriate
for your platform. For example, to build on a POSIX system simply perform
cd src; mkdir _build; cd _build; cmake ..; make
and you will end up with the static library /src/bin/<arch>/libopenvr_api.a
To build a shared library, pass -DBUILD_SHARED=1 to cmake.
To build as a framework on apple platforms, pass -DBUILD_FRAMEWORK=1 to cmake.
To see a complete list of configurable build options, use `cmake -LAH`

View File

@ -1,101 +1,101 @@
//========= Copyright Valve Corporation ============//
#include "dirtools_public.h"
#include "strtools_public.h"
#include "pathtools_public.h"
#include <errno.h>
#include <string.h>
#ifdef _WIN32
#include "windows.h"
#else
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif
#if defined( OSX )
#include <sys/syslimits.h>
#endif
//-----------------------------------------------------------------------------
// Purpose: utility function to create dirs & subdirs
//-----------------------------------------------------------------------------
bool BCreateDirectoryRecursive( const char *pchPath )
{
// Does it already exist?
if ( Path_IsDirectory( pchPath ) )
return true;
// copy the path into something we can munge
int len = (int)strlen( pchPath );
char *path = (char *)malloc( len + 1 );
strcpy( path, pchPath );
// Walk backwards to first non-existing dir that we find
char *s = path + len - 1;
const char slash = Path_GetSlash();
while ( s > path )
{
if ( *s == slash )
{
*s = '\0';
bool bExists = Path_IsDirectory( path );
*s = slash;
if ( bExists )
{
++s;
break;
}
}
--s;
}
// and then move forwards from there
while ( *s )
{
if ( *s == slash )
{
*s = '\0';
BCreateDirectory( path );
*s = slash;
}
s++;
}
bool bRetVal = BCreateDirectory( path );
free( path );
return bRetVal;
}
//-----------------------------------------------------------------------------
// Purpose: Creates the directory, returning true if it is created, or if it already existed
//-----------------------------------------------------------------------------
bool BCreateDirectory( const char *pchPath )
{
#ifdef WIN32
std::wstring wPath = UTF8to16( pchPath );
if ( ::CreateDirectoryW( wPath.c_str(), NULL ) )
return true;
if ( ::GetLastError() == ERROR_ALREADY_EXISTS )
return true;
return false;
#else
int i = mkdir( pchPath, S_IRWXU | S_IRWXG | S_IRWXO );
if ( i == 0 )
return true;
if ( errno == EEXIST )
return true;
return false;
#endif
}
//========= Copyright Valve Corporation ============//
#include "dirtools_public.h"
#include "strtools_public.h"
#include "pathtools_public.h"
#include <errno.h>
#include <string.h>
#ifdef _WIN32
#include "windows.h"
#else
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif
#if defined( OSX )
#include <sys/syslimits.h>
#endif
//-----------------------------------------------------------------------------
// Purpose: utility function to create dirs & subdirs
//-----------------------------------------------------------------------------
bool BCreateDirectoryRecursive( const char *pchPath )
{
// Does it already exist?
if ( Path_IsDirectory( pchPath ) )
return true;
// copy the path into something we can munge
int len = (int)strlen( pchPath );
char *path = (char *)malloc( len + 1 );
strcpy( path, pchPath );
// Walk backwards to first non-existing dir that we find
char *s = path + len - 1;
const char slash = Path_GetSlash();
while ( s > path )
{
if ( *s == slash )
{
*s = '\0';
bool bExists = Path_IsDirectory( path );
*s = slash;
if ( bExists )
{
++s;
break;
}
}
--s;
}
// and then move forwards from there
while ( *s )
{
if ( *s == slash )
{
*s = '\0';
BCreateDirectory( path );
*s = slash;
}
s++;
}
bool bRetVal = BCreateDirectory( path );
free( path );
return bRetVal;
}
//-----------------------------------------------------------------------------
// Purpose: Creates the directory, returning true if it is created, or if it already existed
//-----------------------------------------------------------------------------
bool BCreateDirectory( const char *pchPath )
{
#ifdef WIN32
std::wstring wPath = UTF8to16( pchPath );
if ( ::CreateDirectoryW( wPath.c_str(), NULL ) )
return true;
if ( ::GetLastError() == ERROR_ALREADY_EXISTS )
return true;
return false;
#else
int i = mkdir( pchPath, S_IRWXU | S_IRWXG | S_IRWXO );
if ( i == 0 )
return true;
if ( errno == EEXIST )
return true;
return false;
#endif
}

View File

@ -1,17 +1,17 @@
//========= Copyright Valve Corporation ============//
#pragma once
#include <stdint.h>
#include <string>
#if !defined(_WIN32)
#include <sys/types.h>
#include <sys/stat.h>
#endif
extern bool BCreateDirectoryRecursive( const char *pchPath );
extern bool BCreateDirectory( const char *pchPath );
//========= Copyright Valve Corporation ============//
#pragma once
#include <stdint.h>
#include <string>
#if !defined(_WIN32)
#include <sys/types.h>
#include <sys/stat.h>
#endif
extern bool BCreateDirectoryRecursive( const char *pchPath );
extern bool BCreateDirectory( const char *pchPath );

View File

@ -1,46 +1,46 @@
//========= Copyright Valve Corporation ============//
#include "envvartools_public.h"
#include <stdlib.h>
#if defined(_WIN32)
#include <windows.h>
#undef GetEnvironmentVariable
#undef SetEnvironmentVariable
#endif
std::string GetEnvironmentVariable( const char *pchVarName )
{
#if defined(_WIN32)
char rchValue[32767]; // max size for an env var on Windows
DWORD cChars = GetEnvironmentVariableA( pchVarName, rchValue, sizeof( rchValue ) );
if( cChars == 0 )
return "";
else
return rchValue;
#elif defined(POSIX)
char *pchValue = getenv( pchVarName );
if( pchValue )
return pchValue;
else
return "";
#else
#error "Unsupported Platform"
#endif
}
bool SetEnvironmentVariable( const char *pchVarName, const char *pchVarValue )
{
#if defined(_WIN32)
return 0 != SetEnvironmentVariableA( pchVarName, pchVarValue );
#elif defined(POSIX)
if( pchVarValue == NULL )
return 0 == unsetenv( pchVarName );
else
return 0 == setenv( pchVarName, pchVarValue, 1 );
#else
#error "Unsupported Platform"
#endif
}
//========= Copyright Valve Corporation ============//
#include "envvartools_public.h"
#include <stdlib.h>
#if defined(_WIN32)
#include <windows.h>
#undef GetEnvironmentVariable
#undef SetEnvironmentVariable
#endif
std::string GetEnvironmentVariable( const char *pchVarName )
{
#if defined(_WIN32)
char rchValue[32767]; // max size for an env var on Windows
DWORD cChars = GetEnvironmentVariableA( pchVarName, rchValue, sizeof( rchValue ) );
if( cChars == 0 )
return "";
else
return rchValue;
#elif defined(POSIX)
char *pchValue = getenv( pchVarName );
if( pchValue )
return pchValue;
else
return "";
#else
#error "Unsupported Platform"
#endif
}
bool SetEnvironmentVariable( const char *pchVarName, const char *pchVarValue )
{
#if defined(_WIN32)
return 0 != SetEnvironmentVariableA( pchVarName, pchVarValue );
#elif defined(POSIX)
if( pchVarValue == NULL )
return 0 == unsetenv( pchVarName );
else
return 0 == setenv( pchVarName, pchVarValue, 1 );
#else
#error "Unsupported Platform"
#endif
}

View File

@ -1,7 +1,7 @@
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
std::string GetEnvironmentVariable( const char *pchVarName );
bool SetEnvironmentVariable( const char *pchVarName, const char *pchVarValue );
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
std::string GetEnvironmentVariable( const char *pchVarName );
bool SetEnvironmentVariable( const char *pchVarName, const char *pchVarValue );

View File

@ -1,228 +1,229 @@
//========= Copyright Valve Corporation ============//
#include "openvr.h"
#include "hmderrors_public.h"
#include <stdio.h>
#include <algorithm>
using namespace vr;
#define RETURN_ENUM_AS_STRING(enumValue) case enumValue: return #enumValue;
const char *GetEnglishStringForHmdError( vr::EVRInitError eError )
{
switch( eError )
{
case VRInitError_None: return "No Error (0)";
case VRInitError_Init_InstallationNotFound: return "Installation Not Found (100)";
case VRInitError_Init_InstallationCorrupt: return "Installation Corrupt (101)";
case VRInitError_Init_VRClientDLLNotFound: return "vrclient Shared Lib Not Found (102)";
case VRInitError_Init_FileNotFound: return "File Not Found (103)";
case VRInitError_Init_FactoryNotFound: return "Factory Function Not Found (104)";
case VRInitError_Init_InterfaceNotFound: return "Interface Not Found (105)";
case VRInitError_Init_InvalidInterface: return "Invalid Interface (106)";
case VRInitError_Init_UserConfigDirectoryInvalid: return "User Config Directory Invalid (107)";
case VRInitError_Init_HmdNotFound: return "Hmd Not Found (108)";
case VRInitError_Init_NotInitialized: return "Not Initialized (109)";
case VRInitError_Init_PathRegistryNotFound: return "Installation path could not be located (110)";
case VRInitError_Init_NoConfigPath: return "Config path could not be located (111)";
case VRInitError_Init_NoLogPath: return "Log path could not be located (112)";
case VRInitError_Init_PathRegistryNotWritable: return "Unable to write path registry (113)";
case VRInitError_Init_AppInfoInitFailed: return "App info manager init failed (114)";
case VRInitError_Init_Retry: return "Internal Retry (115)";
case VRInitError_Init_InitCanceledByUser: return "User Canceled Init (116)";
case VRInitError_Init_AnotherAppLaunching: return "Another app was already launching (117)";
case VRInitError_Init_SettingsInitFailed: return "Settings manager init failed (118)";
case VRInitError_Init_ShuttingDown: return "VR system shutting down (119)";
case VRInitError_Init_TooManyObjects: return "Too many tracked objects (120)";
case VRInitError_Init_NoServerForBackgroundApp: return "Not starting vrserver for background app (121)";
case VRInitError_Init_NotSupportedWithCompositor: return "The requested interface is incompatible with the compositor and the compositor is running (122)";
case VRInitError_Init_NotAvailableToUtilityApps: return "This interface is not available to utility applications (123)";
case VRInitError_Init_Internal: return "vrserver internal error (124)";
case VRInitError_Init_HmdDriverIdIsNone: return "Hmd DriverId is invalid (125)";
case VRInitError_Init_HmdNotFoundPresenceFailed: return "Hmd Not Found Presence Failed (126)";
case VRInitError_Init_VRMonitorNotFound: return "VR Monitor Not Found (127)";
case VRInitError_Init_VRMonitorStartupFailed: return "VR Monitor startup failed (128)";
case VRInitError_Init_LowPowerWatchdogNotSupported: return "Low Power Watchdog Not Supported (129)";
case VRInitError_Init_InvalidApplicationType: return "Invalid Application Type (130)";
case VRInitError_Init_NotAvailableToWatchdogApps: return "Not available to watchdog apps (131)";
case VRInitError_Init_WatchdogDisabledInSettings: return "Watchdog disabled in settings (132)";
case VRInitError_Init_VRDashboardNotFound: return "VR Dashboard Not Found (133)";
case VRInitError_Init_VRDashboardStartupFailed: return "VR Dashboard startup failed (134)";
case VRInitError_Init_VRHomeNotFound: return "VR Home Not Found (135)";
case VRInitError_Init_VRHomeStartupFailed: return "VR home startup failed (136)";
case VRInitError_Init_RebootingBusy: return "Rebooting In Progress (137)";
case VRInitError_Init_FirmwareUpdateBusy: return "Firmware Update In Progress (138)";
case VRInitError_Init_FirmwareRecoveryBusy: return "Firmware Recovery In Progress (139)";
case VRInitError_Init_USBServiceBusy: return "USB Service Busy (140)";
case VRInitError_Driver_Failed: return "Driver Failed (200)";
case VRInitError_Driver_Unknown: return "Driver Not Known (201)";
case VRInitError_Driver_HmdUnknown: return "HMD Not Known (202)";
case VRInitError_Driver_NotLoaded: return "Driver Not Loaded (203)";
case VRInitError_Driver_RuntimeOutOfDate: return "Driver runtime is out of date (204)";
case VRInitError_Driver_HmdInUse: return "HMD already in use by another application (205)";
case VRInitError_Driver_NotCalibrated: return "Device is not calibrated (206)";
case VRInitError_Driver_CalibrationInvalid: return "Device Calibration is invalid (207)";
case VRInitError_Driver_HmdDisplayNotFound: return "HMD detected over USB, but Monitor not found (208)";
case VRInitError_Driver_TrackedDeviceInterfaceUnknown: return "Driver Tracked Device Interface unknown (209)";
// case VRInitError_Driver_HmdDisplayNotFoundAfterFix: return "HMD detected over USB, but Monitor not found after attempt to fix (210)"; // taken out upon Ben's request: He thinks that there is no need to separate that error from 208
case VRInitError_Driver_HmdDriverIdOutOfBounds: return "Hmd DriverId is our of bounds (211)";
case VRInitError_Driver_HmdDisplayMirrored: return "HMD detected over USB, but Monitor may be mirrored instead of extended (212)";
case VRInitError_IPC_ServerInitFailed: return "VR Server Init Failed (300)";
case VRInitError_IPC_ConnectFailed: return "Connect to VR Server Failed (301)";
case VRInitError_IPC_SharedStateInitFailed: return "Shared IPC State Init Failed (302)";
case VRInitError_IPC_CompositorInitFailed: return "Shared IPC Compositor Init Failed (303)";
case VRInitError_IPC_MutexInitFailed: return "Shared IPC Mutex Init Failed (304)";
case VRInitError_IPC_Failed: return "Shared IPC Failed (305)";
case VRInitError_IPC_CompositorConnectFailed: return "Shared IPC Compositor Connect Failed (306)";
case VRInitError_IPC_CompositorInvalidConnectResponse: return "Shared IPC Compositor Invalid Connect Response (307)";
case VRInitError_IPC_ConnectFailedAfterMultipleAttempts: return "Shared IPC Connect Failed After Multiple Attempts (308)";
case VRInitError_Compositor_Failed: return "Compositor failed to initialize (400)";
case VRInitError_Compositor_D3D11HardwareRequired: return "Compositor failed to find DX11 hardware (401)";
case VRInitError_Compositor_FirmwareRequiresUpdate: return "Compositor requires mandatory firmware update (402)";
case VRInitError_Compositor_OverlayInitFailed: return "Compositor initialization succeeded, but overlay init failed (403)";
case VRInitError_Compositor_ScreenshotsInitFailed: return "Compositor initialization succeeded, but screenshot init failed (404)";
case VRInitError_Compositor_UnableToCreateDevice: return "Compositor unable to create graphics device (405)";
// Oculus
case VRInitError_VendorSpecific_UnableToConnectToOculusRuntime: return "Unable to connect to Oculus Runtime (1000)";
// Lighthouse
case VRInitError_VendorSpecific_HmdFound_CantOpenDevice: return "HMD found, but can not open device (1101)";
case VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart: return "HMD found, but unable to request config (1102)";
case VRInitError_VendorSpecific_HmdFound_NoStoredConfig: return "HMD found, but no stored config (1103)";
case VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck: return "HMD found, but failed configuration check (1113)";
case VRInitError_VendorSpecific_HmdFound_ConfigTooBig: return "HMD found, but config too big (1104)";
case VRInitError_VendorSpecific_HmdFound_ConfigTooSmall: return "HMD found, but config too small (1105)";
case VRInitError_VendorSpecific_HmdFound_UnableToInitZLib: return "HMD found, but unable to init ZLib (1106)";
case VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion: return "HMD found, but problems with the data (1107)";
case VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart: return "HMD found, but problems with the data (1108)";
case VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart: return "HMD found, but problems with the data (1109)";
case VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext: return "HMD found, but problems with the data (1110)";
case VRInitError_VendorSpecific_HmdFound_UserDataAddressRange: return "HMD found, but problems with the data (1111)";
case VRInitError_VendorSpecific_HmdFound_UserDataError: return "HMD found, but problems with the data (1112)";
case VRInitError_Steam_SteamInstallationNotFound: return "Unable to find Steam installation (2000)";
default:
return GetIDForVRInitError( eError );
}
}
const char *GetIDForVRInitError( vr::EVRInitError eError )
{
switch( eError )
{
RETURN_ENUM_AS_STRING( VRInitError_None );
RETURN_ENUM_AS_STRING( VRInitError_Unknown );
RETURN_ENUM_AS_STRING( VRInitError_Init_InstallationNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_InstallationCorrupt );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRClientDLLNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_FileNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_FactoryNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_InterfaceNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_InvalidInterface );
RETURN_ENUM_AS_STRING( VRInitError_Init_UserConfigDirectoryInvalid );
RETURN_ENUM_AS_STRING( VRInitError_Init_HmdNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_NotInitialized );
RETURN_ENUM_AS_STRING( VRInitError_Init_PathRegistryNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_NoConfigPath );
RETURN_ENUM_AS_STRING( VRInitError_Init_NoLogPath );
RETURN_ENUM_AS_STRING( VRInitError_Init_PathRegistryNotWritable );
RETURN_ENUM_AS_STRING( VRInitError_Init_AppInfoInitFailed );
RETURN_ENUM_AS_STRING( VRInitError_Init_Retry );
RETURN_ENUM_AS_STRING( VRInitError_Init_InitCanceledByUser );
RETURN_ENUM_AS_STRING( VRInitError_Init_AnotherAppLaunching );
RETURN_ENUM_AS_STRING( VRInitError_Init_SettingsInitFailed );
RETURN_ENUM_AS_STRING( VRInitError_Init_ShuttingDown );
RETURN_ENUM_AS_STRING( VRInitError_Init_TooManyObjects );
RETURN_ENUM_AS_STRING( VRInitError_Init_NoServerForBackgroundApp );
RETURN_ENUM_AS_STRING( VRInitError_Init_NotSupportedWithCompositor );
RETURN_ENUM_AS_STRING( VRInitError_Init_NotAvailableToUtilityApps );
RETURN_ENUM_AS_STRING( VRInitError_Init_Internal );
RETURN_ENUM_AS_STRING( VRInitError_Init_HmdDriverIdIsNone );
RETURN_ENUM_AS_STRING( VRInitError_Init_HmdNotFoundPresenceFailed );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRMonitorNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRMonitorStartupFailed );
RETURN_ENUM_AS_STRING( VRInitError_Init_LowPowerWatchdogNotSupported );
RETURN_ENUM_AS_STRING( VRInitError_Init_InvalidApplicationType );
RETURN_ENUM_AS_STRING( VRInitError_Init_NotAvailableToWatchdogApps );
RETURN_ENUM_AS_STRING( VRInitError_Init_WatchdogDisabledInSettings );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRDashboardNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRDashboardStartupFailed );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRHomeNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRHomeStartupFailed );
RETURN_ENUM_AS_STRING( VRInitError_Init_RebootingBusy );
RETURN_ENUM_AS_STRING( VRInitError_Init_FirmwareUpdateBusy );
RETURN_ENUM_AS_STRING( VRInitError_Init_FirmwareRecoveryBusy );
RETURN_ENUM_AS_STRING( VRInitError_Init_USBServiceBusy );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRWebHelperStartupFailed );
RETURN_ENUM_AS_STRING( VRInitError_Driver_Failed );
RETURN_ENUM_AS_STRING( VRInitError_Driver_Unknown );
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdUnknown);
RETURN_ENUM_AS_STRING( VRInitError_Driver_NotLoaded);
RETURN_ENUM_AS_STRING( VRInitError_Driver_RuntimeOutOfDate);
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdInUse);
RETURN_ENUM_AS_STRING( VRInitError_Driver_NotCalibrated);
RETURN_ENUM_AS_STRING( VRInitError_Driver_CalibrationInvalid);
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayNotFound);
RETURN_ENUM_AS_STRING( VRInitError_Driver_TrackedDeviceInterfaceUnknown );
// RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayNotFoundAfterFix );
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDriverIdOutOfBounds );
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayMirrored );
RETURN_ENUM_AS_STRING( VRInitError_IPC_ServerInitFailed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_ConnectFailed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_SharedStateInitFailed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_CompositorInitFailed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_MutexInitFailed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_Failed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_CompositorConnectFailed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_CompositorInvalidConnectResponse);
RETURN_ENUM_AS_STRING( VRInitError_IPC_ConnectFailedAfterMultipleAttempts);
RETURN_ENUM_AS_STRING( VRInitError_Compositor_Failed );
RETURN_ENUM_AS_STRING( VRInitError_Compositor_D3D11HardwareRequired );
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FirmwareRequiresUpdate );
RETURN_ENUM_AS_STRING( VRInitError_Compositor_OverlayInitFailed );
RETURN_ENUM_AS_STRING( VRInitError_Compositor_ScreenshotsInitFailed );
RETURN_ENUM_AS_STRING( VRInitError_Compositor_UnableToCreateDevice );
// Vendor-specific errors
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_UnableToConnectToOculusRuntime);
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_WindowsNotInDevMode );
// Lighthouse
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_CantOpenDevice);
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart);
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_NoStoredConfig);
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_ConfigTooBig );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_ConfigTooSmall );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToInitZLib );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UserDataAddressRange );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UserDataError );
RETURN_ENUM_AS_STRING( VRInitError_Steam_SteamInstallationNotFound );
default:
{
static char buf[128];
sprintf( buf, "Unknown error (%d)", eError );
return buf;
}
}
}
//========= Copyright Valve Corporation ============//
#include "openvr.h"
#include "hmderrors_public.h"
#include <stdio.h>
#include <algorithm>
using namespace vr;
#define RETURN_ENUM_AS_STRING(enumValue) case enumValue: return #enumValue;
const char *GetEnglishStringForHmdError( vr::EVRInitError eError )
{
switch( eError )
{
case VRInitError_None: return "No Error (0)";
case VRInitError_Init_InstallationNotFound: return "Installation Not Found (100)";
case VRInitError_Init_InstallationCorrupt: return "Installation Corrupt (101)";
case VRInitError_Init_VRClientDLLNotFound: return "vrclient Shared Lib Not Found (102)";
case VRInitError_Init_FileNotFound: return "File Not Found (103)";
case VRInitError_Init_FactoryNotFound: return "Factory Function Not Found (104)";
case VRInitError_Init_InterfaceNotFound: return "Interface Not Found (105)";
case VRInitError_Init_InvalidInterface: return "Invalid Interface (106)";
case VRInitError_Init_UserConfigDirectoryInvalid: return "User Config Directory Invalid (107)";
case VRInitError_Init_HmdNotFound: return "Hmd Not Found (108)";
case VRInitError_Init_NotInitialized: return "Not Initialized (109)";
case VRInitError_Init_PathRegistryNotFound: return "Installation path could not be located (110)";
case VRInitError_Init_NoConfigPath: return "Config path could not be located (111)";
case VRInitError_Init_NoLogPath: return "Log path could not be located (112)";
case VRInitError_Init_PathRegistryNotWritable: return "Unable to write path registry (113)";
case VRInitError_Init_AppInfoInitFailed: return "App info manager init failed (114)";
case VRInitError_Init_Retry: return "Internal Retry (115)";
case VRInitError_Init_InitCanceledByUser: return "User Canceled Init (116)";
case VRInitError_Init_AnotherAppLaunching: return "Another app was already launching (117)";
case VRInitError_Init_SettingsInitFailed: return "Settings manager init failed (118)";
case VRInitError_Init_ShuttingDown: return "VR system shutting down (119)";
case VRInitError_Init_TooManyObjects: return "Too many tracked objects (120)";
case VRInitError_Init_NoServerForBackgroundApp: return "Not starting vrserver for background app (121)";
case VRInitError_Init_NotSupportedWithCompositor: return "The requested interface is incompatible with the compositor and the compositor is running (122)";
case VRInitError_Init_NotAvailableToUtilityApps: return "This interface is not available to utility applications (123)";
case VRInitError_Init_Internal: return "vrserver internal error (124)";
case VRInitError_Init_HmdDriverIdIsNone: return "Hmd DriverId is invalid (125)";
case VRInitError_Init_HmdNotFoundPresenceFailed: return "Hmd Not Found Presence Failed (126)";
case VRInitError_Init_VRMonitorNotFound: return "VR Monitor Not Found (127)";
case VRInitError_Init_VRMonitorStartupFailed: return "VR Monitor startup failed (128)";
case VRInitError_Init_LowPowerWatchdogNotSupported: return "Low Power Watchdog Not Supported (129)";
case VRInitError_Init_InvalidApplicationType: return "Invalid Application Type (130)";
case VRInitError_Init_NotAvailableToWatchdogApps: return "Not available to watchdog apps (131)";
case VRInitError_Init_WatchdogDisabledInSettings: return "Watchdog disabled in settings (132)";
case VRInitError_Init_VRDashboardNotFound: return "VR Dashboard Not Found (133)";
case VRInitError_Init_VRDashboardStartupFailed: return "VR Dashboard startup failed (134)";
case VRInitError_Init_VRHomeNotFound: return "VR Home Not Found (135)";
case VRInitError_Init_VRHomeStartupFailed: return "VR home startup failed (136)";
case VRInitError_Init_RebootingBusy: return "Rebooting In Progress (137)";
case VRInitError_Init_FirmwareUpdateBusy: return "Firmware Update In Progress (138)";
case VRInitError_Init_FirmwareRecoveryBusy: return "Firmware Recovery In Progress (139)";
case VRInitError_Init_USBServiceBusy: return "USB Service Busy (140)";
case VRInitError_Driver_Failed: return "Driver Failed (200)";
case VRInitError_Driver_Unknown: return "Driver Not Known (201)";
case VRInitError_Driver_HmdUnknown: return "HMD Not Known (202)";
case VRInitError_Driver_NotLoaded: return "Driver Not Loaded (203)";
case VRInitError_Driver_RuntimeOutOfDate: return "Driver runtime is out of date (204)";
case VRInitError_Driver_HmdInUse: return "HMD already in use by another application (205)";
case VRInitError_Driver_NotCalibrated: return "Device is not calibrated (206)";
case VRInitError_Driver_CalibrationInvalid: return "Device Calibration is invalid (207)";
case VRInitError_Driver_HmdDisplayNotFound: return "HMD detected over USB, but Monitor not found (208)";
case VRInitError_Driver_TrackedDeviceInterfaceUnknown: return "Driver Tracked Device Interface unknown (209)";
// case VRInitError_Driver_HmdDisplayNotFoundAfterFix: return "HMD detected over USB, but Monitor not found after attempt to fix (210)"; // taken out upon Ben's request: He thinks that there is no need to separate that error from 208
case VRInitError_Driver_HmdDriverIdOutOfBounds: return "Hmd DriverId is our of bounds (211)";
case VRInitError_Driver_HmdDisplayMirrored: return "HMD detected over USB, but Monitor may be mirrored instead of extended (212)";
case VRInitError_IPC_ServerInitFailed: return "VR Server Init Failed (300)";
case VRInitError_IPC_ConnectFailed: return "Connect to VR Server Failed (301)";
case VRInitError_IPC_SharedStateInitFailed: return "Shared IPC State Init Failed (302)";
case VRInitError_IPC_CompositorInitFailed: return "Shared IPC Compositor Init Failed (303)";
case VRInitError_IPC_MutexInitFailed: return "Shared IPC Mutex Init Failed (304)";
case VRInitError_IPC_Failed: return "Shared IPC Failed (305)";
case VRInitError_IPC_CompositorConnectFailed: return "Shared IPC Compositor Connect Failed (306)";
case VRInitError_IPC_CompositorInvalidConnectResponse: return "Shared IPC Compositor Invalid Connect Response (307)";
case VRInitError_IPC_ConnectFailedAfterMultipleAttempts: return "Shared IPC Connect Failed After Multiple Attempts (308)";
case VRInitError_Compositor_Failed: return "Compositor failed to initialize (400)";
case VRInitError_Compositor_D3D11HardwareRequired: return "Compositor failed to find DX11 hardware (401)";
case VRInitError_Compositor_FirmwareRequiresUpdate: return "Compositor requires mandatory firmware update (402)";
case VRInitError_Compositor_OverlayInitFailed: return "Compositor initialization succeeded, but overlay init failed (403)";
case VRInitError_Compositor_ScreenshotsInitFailed: return "Compositor initialization succeeded, but screenshot init failed (404)";
case VRInitError_Compositor_UnableToCreateDevice: return "Compositor unable to create graphics device (405)";
// Oculus
case VRInitError_VendorSpecific_UnableToConnectToOculusRuntime: return "Unable to connect to Oculus Runtime (1000)";
// Lighthouse
case VRInitError_VendorSpecific_HmdFound_CantOpenDevice: return "HMD found, but can not open device (1101)";
case VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart: return "HMD found, but unable to request config (1102)";
case VRInitError_VendorSpecific_HmdFound_NoStoredConfig: return "HMD found, but no stored config (1103)";
case VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck: return "HMD found, but failed configuration check (1113)";
case VRInitError_VendorSpecific_HmdFound_ConfigTooBig: return "HMD found, but config too big (1104)";
case VRInitError_VendorSpecific_HmdFound_ConfigTooSmall: return "HMD found, but config too small (1105)";
case VRInitError_VendorSpecific_HmdFound_UnableToInitZLib: return "HMD found, but unable to init ZLib (1106)";
case VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion: return "HMD found, but problems with the data (1107)";
case VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart: return "HMD found, but problems with the data (1108)";
case VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart: return "HMD found, but problems with the data (1109)";
case VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext: return "HMD found, but problems with the data (1110)";
case VRInitError_VendorSpecific_HmdFound_UserDataAddressRange: return "HMD found, but problems with the data (1111)";
case VRInitError_VendorSpecific_HmdFound_UserDataError: return "HMD found, but problems with the data (1112)";
case VRInitError_Steam_SteamInstallationNotFound: return "Unable to find Steam installation (2000)";
default:
return GetIDForVRInitError( eError );
}
}
const char *GetIDForVRInitError( vr::EVRInitError eError )
{
switch( eError )
{
RETURN_ENUM_AS_STRING( VRInitError_None );
RETURN_ENUM_AS_STRING( VRInitError_Unknown );
RETURN_ENUM_AS_STRING( VRInitError_Init_InstallationNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_InstallationCorrupt );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRClientDLLNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_FileNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_FactoryNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_InterfaceNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_InvalidInterface );
RETURN_ENUM_AS_STRING( VRInitError_Init_UserConfigDirectoryInvalid );
RETURN_ENUM_AS_STRING( VRInitError_Init_HmdNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_NotInitialized );
RETURN_ENUM_AS_STRING( VRInitError_Init_PathRegistryNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_NoConfigPath );
RETURN_ENUM_AS_STRING( VRInitError_Init_NoLogPath );
RETURN_ENUM_AS_STRING( VRInitError_Init_PathRegistryNotWritable );
RETURN_ENUM_AS_STRING( VRInitError_Init_AppInfoInitFailed );
RETURN_ENUM_AS_STRING( VRInitError_Init_Retry );
RETURN_ENUM_AS_STRING( VRInitError_Init_InitCanceledByUser );
RETURN_ENUM_AS_STRING( VRInitError_Init_AnotherAppLaunching );
RETURN_ENUM_AS_STRING( VRInitError_Init_SettingsInitFailed );
RETURN_ENUM_AS_STRING( VRInitError_Init_ShuttingDown );
RETURN_ENUM_AS_STRING( VRInitError_Init_TooManyObjects );
RETURN_ENUM_AS_STRING( VRInitError_Init_NoServerForBackgroundApp );
RETURN_ENUM_AS_STRING( VRInitError_Init_NotSupportedWithCompositor );
RETURN_ENUM_AS_STRING( VRInitError_Init_NotAvailableToUtilityApps );
RETURN_ENUM_AS_STRING( VRInitError_Init_Internal );
RETURN_ENUM_AS_STRING( VRInitError_Init_HmdDriverIdIsNone );
RETURN_ENUM_AS_STRING( VRInitError_Init_HmdNotFoundPresenceFailed );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRMonitorNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRMonitorStartupFailed );
RETURN_ENUM_AS_STRING( VRInitError_Init_LowPowerWatchdogNotSupported );
RETURN_ENUM_AS_STRING( VRInitError_Init_InvalidApplicationType );
RETURN_ENUM_AS_STRING( VRInitError_Init_NotAvailableToWatchdogApps );
RETURN_ENUM_AS_STRING( VRInitError_Init_WatchdogDisabledInSettings );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRDashboardNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRDashboardStartupFailed );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRHomeNotFound );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRHomeStartupFailed );
RETURN_ENUM_AS_STRING( VRInitError_Init_RebootingBusy );
RETURN_ENUM_AS_STRING( VRInitError_Init_FirmwareUpdateBusy );
RETURN_ENUM_AS_STRING( VRInitError_Init_FirmwareRecoveryBusy );
RETURN_ENUM_AS_STRING( VRInitError_Init_USBServiceBusy );
RETURN_ENUM_AS_STRING( VRInitError_Init_VRWebHelperStartupFailed );
RETURN_ENUM_AS_STRING( VRInitError_Init_TrackerManagerInitFailed );
RETURN_ENUM_AS_STRING( VRInitError_Driver_Failed );
RETURN_ENUM_AS_STRING( VRInitError_Driver_Unknown );
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdUnknown);
RETURN_ENUM_AS_STRING( VRInitError_Driver_NotLoaded);
RETURN_ENUM_AS_STRING( VRInitError_Driver_RuntimeOutOfDate);
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdInUse);
RETURN_ENUM_AS_STRING( VRInitError_Driver_NotCalibrated);
RETURN_ENUM_AS_STRING( VRInitError_Driver_CalibrationInvalid);
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayNotFound);
RETURN_ENUM_AS_STRING( VRInitError_Driver_TrackedDeviceInterfaceUnknown );
// RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayNotFoundAfterFix );
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDriverIdOutOfBounds );
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayMirrored );
RETURN_ENUM_AS_STRING( VRInitError_IPC_ServerInitFailed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_ConnectFailed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_SharedStateInitFailed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_CompositorInitFailed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_MutexInitFailed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_Failed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_CompositorConnectFailed);
RETURN_ENUM_AS_STRING( VRInitError_IPC_CompositorInvalidConnectResponse);
RETURN_ENUM_AS_STRING( VRInitError_IPC_ConnectFailedAfterMultipleAttempts);
RETURN_ENUM_AS_STRING( VRInitError_Compositor_Failed );
RETURN_ENUM_AS_STRING( VRInitError_Compositor_D3D11HardwareRequired );
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FirmwareRequiresUpdate );
RETURN_ENUM_AS_STRING( VRInitError_Compositor_OverlayInitFailed );
RETURN_ENUM_AS_STRING( VRInitError_Compositor_ScreenshotsInitFailed );
RETURN_ENUM_AS_STRING( VRInitError_Compositor_UnableToCreateDevice );
// Vendor-specific errors
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_UnableToConnectToOculusRuntime);
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_WindowsNotInDevMode );
// Lighthouse
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_CantOpenDevice);
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart);
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_NoStoredConfig);
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_ConfigTooBig );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_ConfigTooSmall );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToInitZLib );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UserDataAddressRange );
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UserDataError );
RETURN_ENUM_AS_STRING( VRInitError_Steam_SteamInstallationNotFound );
default:
{
static char buf[128];
sprintf( buf, "Unknown error (%d)", eError );
return buf;
}
}
}

View File

@ -1,6 +1,6 @@
//========= Copyright Valve Corporation ============//
#pragma once
const char *GetEnglishStringForHmdError( vr::EVRInitError eError );
const char *GetIDForVRInitError( vr::EVRInitError eError );
//========= Copyright Valve Corporation ============//
#pragma once
const char *GetEnglishStringForHmdError( vr::EVRInitError eError );
const char *GetIDForVRInitError( vr::EVRInitError eError );

View File

@ -1,35 +1,35 @@
//========= Copyright Valve Corporation ============//
#pragma once
namespace vr
{
class IVRClientCore
{
public:
/** Initializes the system */
virtual EVRInitError Init( vr::EVRApplicationType eApplicationType ) = 0;
/** cleans up everything in vrclient.dll and prepares the DLL to be unloaded */
virtual void Cleanup() = 0;
/** checks to see if the specified interface/version is supported in this vrclient.dll */
virtual EVRInitError IsInterfaceVersionValid( const char *pchInterfaceVersion ) = 0;
/** Retrieves any interface from vrclient.dll */
virtual void *GetGenericInterface( const char *pchNameAndVersion, EVRInitError *peError ) = 0;
/** Returns true if any driver has an HMD attached. Can be called outside of Init/Cleanup */
virtual bool BIsHmdPresent() = 0;
/** Returns an English error string from inside vrclient.dll which might be newer than the API DLL */
virtual const char *GetEnglishStringForHmdError( vr::EVRInitError eError ) = 0;
/** Returns an error symbol from inside vrclient.dll which might be newer than the API DLL */
virtual const char *GetIDForVRInitError( vr::EVRInitError eError ) = 0;
};
static const char * const IVRClientCore_Version = "IVRClientCore_002";
}
//========= Copyright Valve Corporation ============//
#pragma once
namespace vr
{
class IVRClientCore
{
public:
/** Initializes the system */
virtual EVRInitError Init( vr::EVRApplicationType eApplicationType, const char *pStartupInfo ) = 0;
/** cleans up everything in vrclient.dll and prepares the DLL to be unloaded */
virtual void Cleanup() = 0;
/** checks to see if the specified interface/version is supported in this vrclient.dll */
virtual EVRInitError IsInterfaceVersionValid( const char *pchInterfaceVersion ) = 0;
/** Retrieves any interface from vrclient.dll */
virtual void *GetGenericInterface( const char *pchNameAndVersion, EVRInitError *peError ) = 0;
/** Returns true if any driver has an HMD attached. Can be called outside of Init/Cleanup */
virtual bool BIsHmdPresent() = 0;
/** Returns an English error string from inside vrclient.dll which might be newer than the API DLL */
virtual const char *GetEnglishStringForHmdError( vr::EVRInitError eError ) = 0;
/** Returns an error symbol from inside vrclient.dll which might be newer than the API DLL */
virtual const char *GetIDForVRInitError( vr::EVRInitError eError ) = 0;
};
static const char * const IVRClientCore_Version = "IVRClientCore_003";
}

View File

@ -1,298 +1,298 @@
//========= Copyright Valve Corporation ============//
#define VR_API_EXPORT 1
#include "openvr.h"
#include "ivrclientcore.h"
#include "pathtools_public.h"
#include "sharedlibtools_public.h"
#include "envvartools_public.h"
#include "hmderrors_public.h"
#include "vrpathregistry_public.h"
#include <mutex>
using vr::EVRInitError;
using vr::IVRSystem;
using vr::IVRClientCore;
using vr::VRInitError_None;
namespace vr
{
static void *g_pVRModule = NULL;
static IVRClientCore *g_pHmdSystem = NULL;
static std::recursive_mutex g_mutexSystem;
typedef void* (*VRClientCoreFactoryFn)(const char *pInterfaceName, int *pReturnCode);
static uint32_t g_nVRToken = 0;
uint32_t VR_GetInitToken()
{
return g_nVRToken;
}
EVRInitError VR_LoadHmdSystemInternal();
void CleanupInternalInterfaces();
uint32_t VR_InitInternal2( EVRInitError *peError, vr::EVRApplicationType eApplicationType, const char *pStartupInfo )
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
EVRInitError err = VR_LoadHmdSystemInternal();
if ( err == vr::VRInitError_None )
{
err = g_pHmdSystem->Init( eApplicationType );
}
if ( peError )
*peError = err;
if ( err != VRInitError_None )
{
SharedLib_Unload( g_pVRModule );
g_pHmdSystem = NULL;
g_pVRModule = NULL;
return 0;
}
return ++g_nVRToken;
}
VR_INTERFACE uint32_t VR_CALLTYPE VR_InitInternal( EVRInitError *peError, EVRApplicationType eApplicationType );
uint32_t VR_InitInternal( EVRInitError *peError, vr::EVRApplicationType eApplicationType )
{
return VR_InitInternal2( peError, eApplicationType, nullptr );
}
void VR_ShutdownInternal()
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if ( g_pHmdSystem )
{
g_pHmdSystem->Cleanup();
g_pHmdSystem = NULL;
}
if ( g_pVRModule )
{
SharedLib_Unload( g_pVRModule );
g_pVRModule = NULL;
}
#if !defined( VR_API_PUBLIC )
CleanupInternalInterfaces();
#endif
++g_nVRToken;
}
EVRInitError VR_LoadHmdSystemInternal()
{
std::string sRuntimePath, sConfigPath, sLogPath;
bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL );
if( !bReadPathRegistry )
{
return vr::VRInitError_Init_PathRegistryNotFound;
}
// figure out where we're going to look for vrclient.dll
// see if the specified path actually exists.
if( !Path_IsDirectory( sRuntimePath ) )
{
return vr::VRInitError_Init_InstallationNotFound;
}
// Because we don't have a way to select debug vs. release yet we'll just
// use debug if it's there
#if defined( LINUX64 )
std::string sTestPath = Path_Join( sRuntimePath, "bin", PLATSUBDIR );
#else
std::string sTestPath = Path_Join( sRuntimePath, "bin" );
#endif
if( !Path_IsDirectory( sTestPath ) )
{
return vr::VRInitError_Init_InstallationCorrupt;
}
#if defined( WIN64 )
std::string sDLLPath = Path_Join( sTestPath, "vrclient_x64" DYNAMIC_LIB_EXT );
#else
std::string sDLLPath = Path_Join( sTestPath, "vrclient" DYNAMIC_LIB_EXT );
#endif
// only look in the override
void *pMod = SharedLib_Load( sDLLPath.c_str() );
// nothing more to do if we can't load the DLL
if( !pMod )
{
return vr::VRInitError_Init_VRClientDLLNotFound;
}
VRClientCoreFactoryFn fnFactory = ( VRClientCoreFactoryFn )( SharedLib_GetFunction( pMod, "VRClientCoreFactory" ) );
if( !fnFactory )
{
SharedLib_Unload( pMod );
return vr::VRInitError_Init_FactoryNotFound;
}
int nReturnCode = 0;
g_pHmdSystem = static_cast< IVRClientCore * > ( fnFactory( vr::IVRClientCore_Version, &nReturnCode ) );
if( !g_pHmdSystem )
{
SharedLib_Unload( pMod );
return vr::VRInitError_Init_InterfaceNotFound;
}
g_pVRModule = pMod;
return VRInitError_None;
}
void *VR_GetGenericInterface(const char *pchInterfaceVersion, EVRInitError *peError)
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if (!g_pHmdSystem)
{
if (peError)
*peError = vr::VRInitError_Init_NotInitialized;
return NULL;
}
return g_pHmdSystem->GetGenericInterface(pchInterfaceVersion, peError);
}
bool VR_IsInterfaceVersionValid(const char *pchInterfaceVersion)
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if (!g_pHmdSystem)
{
return false;
}
return g_pHmdSystem->IsInterfaceVersionValid(pchInterfaceVersion) == VRInitError_None;
}
bool VR_IsHmdPresent()
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if( g_pHmdSystem )
{
// if we're already initialized, just call through
return g_pHmdSystem->BIsHmdPresent();
}
else
{
// otherwise we need to do a bit more work
EVRInitError err = VR_LoadHmdSystemInternal();
if( err != VRInitError_None )
return false;
bool bHasHmd = g_pHmdSystem->BIsHmdPresent();
g_pHmdSystem = NULL;
SharedLib_Unload( g_pVRModule );
g_pVRModule = NULL;
return bHasHmd;
}
}
/** Returns true if the OpenVR runtime is installed. */
bool VR_IsRuntimeInstalled()
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if( g_pHmdSystem )
{
// if we're already initialized, OpenVR is obviously installed
return true;
}
else
{
// otherwise we need to do a bit more work
std::string sRuntimePath, sConfigPath, sLogPath;
bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL );
if( !bReadPathRegistry )
{
return false;
}
// figure out where we're going to look for vrclient.dll
// see if the specified path actually exists.
if( !Path_IsDirectory( sRuntimePath ) )
{
return false;
}
// the installation may be corrupt in some way, but it certainly looks installed
return true;
}
}
/** Returns where OpenVR runtime is installed. */
const char *VR_RuntimePath()
{
// otherwise we need to do a bit more work
static std::string sRuntimePath;
std::string sConfigPath, sLogPath;
bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL );
if ( !bReadPathRegistry )
{
return nullptr;
}
// figure out where we're going to look for vrclient.dll
// see if the specified path actually exists.
if ( !Path_IsDirectory( sRuntimePath ) )
{
return nullptr;
}
return sRuntimePath.c_str();
}
/** Returns the symbol version of an HMD error. */
const char *VR_GetVRInitErrorAsSymbol( EVRInitError error )
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if( g_pHmdSystem )
return g_pHmdSystem->GetIDForVRInitError( error );
else
return GetIDForVRInitError( error );
}
/** Returns the english string version of an HMD error. */
const char *VR_GetVRInitErrorAsEnglishDescription( EVRInitError error )
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if ( g_pHmdSystem )
return g_pHmdSystem->GetEnglishStringForHmdError( error );
else
return GetEnglishStringForHmdError( error );
}
VR_INTERFACE const char *VR_CALLTYPE VR_GetStringForHmdError( vr::EVRInitError error );
/** Returns the english string version of an HMD error. */
const char *VR_GetStringForHmdError( EVRInitError error )
{
return VR_GetVRInitErrorAsEnglishDescription( error );
}
}
//========= Copyright Valve Corporation ============//
#define VR_API_EXPORT 1
#include "openvr.h"
#include "ivrclientcore.h"
#include "pathtools_public.h"
#include "sharedlibtools_public.h"
#include "envvartools_public.h"
#include "hmderrors_public.h"
#include "vrpathregistry_public.h"
#include <mutex>
using vr::EVRInitError;
using vr::IVRSystem;
using vr::IVRClientCore;
using vr::VRInitError_None;
namespace vr
{
static void *g_pVRModule = NULL;
static IVRClientCore *g_pHmdSystem = NULL;
static std::recursive_mutex g_mutexSystem;
typedef void* (*VRClientCoreFactoryFn)(const char *pInterfaceName, int *pReturnCode);
static uint32_t g_nVRToken = 0;
uint32_t VR_GetInitToken()
{
return g_nVRToken;
}
EVRInitError VR_LoadHmdSystemInternal();
void CleanupInternalInterfaces();
uint32_t VR_InitInternal2( EVRInitError *peError, vr::EVRApplicationType eApplicationType, const char *pStartupInfo )
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
EVRInitError err = VR_LoadHmdSystemInternal();
if ( err == vr::VRInitError_None )
{
err = g_pHmdSystem->Init( eApplicationType, pStartupInfo );
}
if ( peError )
*peError = err;
if ( err != VRInitError_None )
{
SharedLib_Unload( g_pVRModule );
g_pHmdSystem = NULL;
g_pVRModule = NULL;
return 0;
}
return ++g_nVRToken;
}
VR_INTERFACE uint32_t VR_CALLTYPE VR_InitInternal( EVRInitError *peError, EVRApplicationType eApplicationType );
uint32_t VR_InitInternal( EVRInitError *peError, vr::EVRApplicationType eApplicationType )
{
return VR_InitInternal2( peError, eApplicationType, nullptr );
}
void VR_ShutdownInternal()
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if ( g_pHmdSystem )
{
g_pHmdSystem->Cleanup();
g_pHmdSystem = NULL;
}
if ( g_pVRModule )
{
SharedLib_Unload( g_pVRModule );
g_pVRModule = NULL;
}
#if !defined( VR_API_PUBLIC )
CleanupInternalInterfaces();
#endif
++g_nVRToken;
}
EVRInitError VR_LoadHmdSystemInternal()
{
std::string sRuntimePath, sConfigPath, sLogPath;
bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL );
if( !bReadPathRegistry )
{
return vr::VRInitError_Init_PathRegistryNotFound;
}
// figure out where we're going to look for vrclient.dll
// see if the specified path actually exists.
if( !Path_IsDirectory( sRuntimePath ) )
{
return vr::VRInitError_Init_InstallationNotFound;
}
// Because we don't have a way to select debug vs. release yet we'll just
// use debug if it's there
#if defined( LINUX64 )
std::string sTestPath = Path_Join( sRuntimePath, "bin", PLATSUBDIR );
#else
std::string sTestPath = Path_Join( sRuntimePath, "bin" );
#endif
if( !Path_IsDirectory( sTestPath ) )
{
return vr::VRInitError_Init_InstallationCorrupt;
}
#if defined( WIN64 )
std::string sDLLPath = Path_Join( sTestPath, "vrclient_x64" DYNAMIC_LIB_EXT );
#else
std::string sDLLPath = Path_Join( sTestPath, "vrclient" DYNAMIC_LIB_EXT );
#endif
// only look in the override
void *pMod = SharedLib_Load( sDLLPath.c_str() );
// nothing more to do if we can't load the DLL
if( !pMod )
{
return vr::VRInitError_Init_VRClientDLLNotFound;
}
VRClientCoreFactoryFn fnFactory = ( VRClientCoreFactoryFn )( SharedLib_GetFunction( pMod, "VRClientCoreFactory" ) );
if( !fnFactory )
{
SharedLib_Unload( pMod );
return vr::VRInitError_Init_FactoryNotFound;
}
int nReturnCode = 0;
g_pHmdSystem = static_cast< IVRClientCore * > ( fnFactory( vr::IVRClientCore_Version, &nReturnCode ) );
if( !g_pHmdSystem )
{
SharedLib_Unload( pMod );
return vr::VRInitError_Init_InterfaceNotFound;
}
g_pVRModule = pMod;
return VRInitError_None;
}
void *VR_GetGenericInterface(const char *pchInterfaceVersion, EVRInitError *peError)
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if (!g_pHmdSystem)
{
if (peError)
*peError = vr::VRInitError_Init_NotInitialized;
return NULL;
}
return g_pHmdSystem->GetGenericInterface(pchInterfaceVersion, peError);
}
bool VR_IsInterfaceVersionValid(const char *pchInterfaceVersion)
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if (!g_pHmdSystem)
{
return false;
}
return g_pHmdSystem->IsInterfaceVersionValid(pchInterfaceVersion) == VRInitError_None;
}
bool VR_IsHmdPresent()
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if( g_pHmdSystem )
{
// if we're already initialized, just call through
return g_pHmdSystem->BIsHmdPresent();
}
else
{
// otherwise we need to do a bit more work
EVRInitError err = VR_LoadHmdSystemInternal();
if( err != VRInitError_None )
return false;
bool bHasHmd = g_pHmdSystem->BIsHmdPresent();
g_pHmdSystem = NULL;
SharedLib_Unload( g_pVRModule );
g_pVRModule = NULL;
return bHasHmd;
}
}
/** Returns true if the OpenVR runtime is installed. */
bool VR_IsRuntimeInstalled()
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if( g_pHmdSystem )
{
// if we're already initialized, OpenVR is obviously installed
return true;
}
else
{
// otherwise we need to do a bit more work
std::string sRuntimePath, sConfigPath, sLogPath;
bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL );
if( !bReadPathRegistry )
{
return false;
}
// figure out where we're going to look for vrclient.dll
// see if the specified path actually exists.
if( !Path_IsDirectory( sRuntimePath ) )
{
return false;
}
// the installation may be corrupt in some way, but it certainly looks installed
return true;
}
}
/** Returns where OpenVR runtime is installed. */
const char *VR_RuntimePath()
{
// otherwise we need to do a bit more work
static std::string sRuntimePath;
std::string sConfigPath, sLogPath;
bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL );
if ( !bReadPathRegistry )
{
return nullptr;
}
// figure out where we're going to look for vrclient.dll
// see if the specified path actually exists.
if ( !Path_IsDirectory( sRuntimePath ) )
{
return nullptr;
}
return sRuntimePath.c_str();
}
/** Returns the symbol version of an HMD error. */
const char *VR_GetVRInitErrorAsSymbol( EVRInitError error )
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if( g_pHmdSystem )
return g_pHmdSystem->GetIDForVRInitError( error );
else
return GetIDForVRInitError( error );
}
/** Returns the english string version of an HMD error. */
const char *VR_GetVRInitErrorAsEnglishDescription( EVRInitError error )
{
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
if ( g_pHmdSystem )
return g_pHmdSystem->GetEnglishStringForHmdError( error );
else
return GetEnglishStringForHmdError( error );
}
VR_INTERFACE const char *VR_CALLTYPE VR_GetStringForHmdError( vr::EVRInitError error );
/** Returns the english string version of an HMD error. */
const char *VR_GetStringForHmdError( EVRInitError error )
{
return VR_GetVRInitErrorAsEnglishDescription( error );
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,132 +1,132 @@
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
#include <stdint.h>
/** Returns the path (including filename) to the current executable */
std::string Path_GetExecutablePath();
/** Returns the path of the current working directory */
std::string Path_GetWorkingDirectory();
/** Sets the path of the current working directory. Returns true if this was successful. */
bool Path_SetWorkingDirectory( const std::string & sPath );
/** returns the path (including filename) of the current shared lib or DLL */
std::string Path_GetThisModulePath();
/** Returns the specified path without its filename.
* If slash is unspecified the native path separator of the current platform
* will be used. */
std::string Path_StripFilename( const std::string & sPath, char slash = 0 );
/** returns just the filename from the provided full or relative path. */
std::string Path_StripDirectory( const std::string & sPath, char slash = 0 );
/** returns just the filename with no extension of the provided filename.
* If there is a path the path is left intact. */
std::string Path_StripExtension( const std::string & sPath );
/** returns just extension of the provided filename (if any). */
std::string Path_GetExtension( const std::string & sPath );
/** Returns true if the path is absolute */
bool Path_IsAbsolute( const std::string & sPath );
/** Makes an absolute path from a relative path and a base path */
std::string Path_MakeAbsolute( const std::string & sRelativePath, const std::string & sBasePath );
/** Fixes the directory separators for the current platform.
* If slash is unspecified the native path separator of the current platform
* will be used. */
std::string Path_FixSlashes( const std::string & sPath, char slash = 0 );
/** Returns the path separator for the current platform */
char Path_GetSlash();
/** Jams two paths together with the right kind of slash */
std::string Path_Join( const std::string & first, const std::string & second, char slash = 0 );
std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, char slash = 0 );
std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, const std::string &fourth, char slash = 0 );
std::string Path_Join(
const std::string & first,
const std::string & second,
const std::string & third,
const std::string & fourth,
const std::string & fifth,
char slash = 0 );
/** Removes redundant <dir>/.. elements in the path. Returns an empty path if the
* specified path has a broken number of directories for its number of ..s.
* If slash is unspecified the native path separator of the current platform
* will be used. */
std::string Path_Compact( const std::string & sRawPath, char slash = 0 );
//** Removed trailing slashes */
std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash = 0 );
/** returns true if the specified path exists and is a directory */
bool Path_IsDirectory( const std::string & sPath );
/** returns true if the specified path represents an app bundle */
bool Path_IsAppBundle( const std::string & sPath );
/** returns true if the the path exists */
bool Path_Exists( const std::string & sPath );
/** Helper functions to find parent directories or subdirectories of parent directories */
std::string Path_FindParentDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName );
std::string Path_FindParentSubDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName );
/** Path operations to read or write text/binary files */
unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize );
uint32_t Path_ReadBinaryFile( const std::string &strFilename, unsigned char *pBuffer, uint32_t unSize );
bool Path_WriteBinaryFile( const std::string &strFilename, unsigned char *pData, unsigned nSize );
std::string Path_ReadTextFile( const std::string &strFilename );
bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pchData );
bool Path_WriteStringToTextFileAtomic( const std::string &strFilename, const char *pchData );
/** Returns a file:// url for paths, or an http or https url if that's what was provided */
std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath );
/** Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned */
std::string Path_UrlToFilePath( const std::string & sFileUrl );
/** Returns the root of the directory the system wants us to store user documents in */
std::string GetUserDocumentsPath();
#ifndef MAX_UNICODE_PATH
#define MAX_UNICODE_PATH 32767
#endif
#ifndef MAX_UNICODE_PATH_IN_UTF8
#define MAX_UNICODE_PATH_IN_UTF8 (MAX_UNICODE_PATH * 4)
#endif
//-----------------------------------------------------------------------------
#if defined(WIN32)
#define DYNAMIC_LIB_EXT ".dll"
#define PROGRAM_EXT ".exe"
#ifdef _WIN64
#define PLATSUBDIR "win64"
#else
#define PLATSUBDIR "win32"
#endif
#elif defined(OSX)
#define DYNAMIC_LIB_EXT ".dylib"
#define PLATSUBDIR "osx32"
#define PROGRAM_EXT ""
#elif defined(LINUX)
#define DYNAMIC_LIB_EXT ".so"
#define PROGRAM_EXT ""
#if defined( LINUX32 )
#define PLATSUBDIR "linux32"
#else
#define PLATSUBDIR "linux64"
#endif
#else
#warning "Unknown platform for PLATSUBDIR"
#define PLATSUBDIR "unknown_platform"
#endif
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
#include <stdint.h>
/** Returns the path (including filename) to the current executable */
std::string Path_GetExecutablePath();
/** Returns the path of the current working directory */
std::string Path_GetWorkingDirectory();
/** Sets the path of the current working directory. Returns true if this was successful. */
bool Path_SetWorkingDirectory( const std::string & sPath );
/** returns the path (including filename) of the current shared lib or DLL */
std::string Path_GetThisModulePath();
/** Returns the specified path without its filename.
* If slash is unspecified the native path separator of the current platform
* will be used. */
std::string Path_StripFilename( const std::string & sPath, char slash = 0 );
/** returns just the filename from the provided full or relative path. */
std::string Path_StripDirectory( const std::string & sPath, char slash = 0 );
/** returns just the filename with no extension of the provided filename.
* If there is a path the path is left intact. */
std::string Path_StripExtension( const std::string & sPath );
/** returns just extension of the provided filename (if any). */
std::string Path_GetExtension( const std::string & sPath );
/** Returns true if the path is absolute */
bool Path_IsAbsolute( const std::string & sPath );
/** Makes an absolute path from a relative path and a base path */
std::string Path_MakeAbsolute( const std::string & sRelativePath, const std::string & sBasePath );
/** Fixes the directory separators for the current platform.
* If slash is unspecified the native path separator of the current platform
* will be used. */
std::string Path_FixSlashes( const std::string & sPath, char slash = 0 );
/** Returns the path separator for the current platform */
char Path_GetSlash();
/** Jams two paths together with the right kind of slash */
std::string Path_Join( const std::string & first, const std::string & second, char slash = 0 );
std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, char slash = 0 );
std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, const std::string &fourth, char slash = 0 );
std::string Path_Join(
const std::string & first,
const std::string & second,
const std::string & third,
const std::string & fourth,
const std::string & fifth,
char slash = 0 );
/** Removes redundant <dir>/.. elements in the path. Returns an empty path if the
* specified path has a broken number of directories for its number of ..s.
* If slash is unspecified the native path separator of the current platform
* will be used. */
std::string Path_Compact( const std::string & sRawPath, char slash = 0 );
//** Removed trailing slashes */
std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash = 0 );
/** returns true if the specified path exists and is a directory */
bool Path_IsDirectory( const std::string & sPath );
/** returns true if the specified path represents an app bundle */
bool Path_IsAppBundle( const std::string & sPath );
/** returns true if the the path exists */
bool Path_Exists( const std::string & sPath );
/** Helper functions to find parent directories or subdirectories of parent directories */
std::string Path_FindParentDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName );
std::string Path_FindParentSubDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName );
/** Path operations to read or write text/binary files */
unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize );
uint32_t Path_ReadBinaryFile( const std::string &strFilename, unsigned char *pBuffer, uint32_t unSize );
bool Path_WriteBinaryFile( const std::string &strFilename, unsigned char *pData, unsigned nSize );
std::string Path_ReadTextFile( const std::string &strFilename );
bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pchData );
bool Path_WriteStringToTextFileAtomic( const std::string &strFilename, const char *pchData );
/** Returns a file:// url for paths, or an http or https url if that's what was provided */
std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath );
/** Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned */
std::string Path_UrlToFilePath( const std::string & sFileUrl );
/** Returns the root of the directory the system wants us to store user documents in */
std::string GetUserDocumentsPath();
#ifndef MAX_UNICODE_PATH
#define MAX_UNICODE_PATH 32767
#endif
#ifndef MAX_UNICODE_PATH_IN_UTF8
#define MAX_UNICODE_PATH_IN_UTF8 (MAX_UNICODE_PATH * 4)
#endif
//-----------------------------------------------------------------------------
#if defined(WIN32)
#define DYNAMIC_LIB_EXT ".dll"
#define PROGRAM_EXT ".exe"
#ifdef _WIN64
#define PLATSUBDIR "win64"
#else
#define PLATSUBDIR "win32"
#endif
#elif defined(OSX)
#define DYNAMIC_LIB_EXT ".dylib"
#define PLATSUBDIR "osx32"
#define PROGRAM_EXT ""
#elif defined(LINUX)
#define DYNAMIC_LIB_EXT ".so"
#define PROGRAM_EXT ""
#if defined( LINUX32 )
#define PLATSUBDIR "linux32"
#else
#define PLATSUBDIR "linux64"
#endif
#else
#warning "Unknown platform for PLATSUBDIR"
#define PLATSUBDIR "unknown_platform"
#endif

View File

@ -1,43 +1,43 @@
//========= Copyright Valve Corporation ============//
#include "sharedlibtools_public.h"
#include <string.h>
#if defined(_WIN32)
#include <windows.h>
#endif
#if defined(POSIX)
#include <dlfcn.h>
#endif
SharedLibHandle SharedLib_Load( const char *pchPath )
{
#if defined( _WIN32)
return (SharedLibHandle)LoadLibraryEx( pchPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
#elif defined(POSIX)
return (SharedLibHandle)dlopen(pchPath, RTLD_LOCAL|RTLD_NOW);
#endif
}
void *SharedLib_GetFunction( SharedLibHandle lib, const char *pchFunctionName)
{
#if defined( _WIN32)
return (void*)GetProcAddress( (HMODULE)lib, pchFunctionName );
#elif defined(POSIX)
return dlsym( lib, pchFunctionName );
#endif
}
void SharedLib_Unload( SharedLibHandle lib )
{
if ( !lib )
return;
#if defined( _WIN32)
FreeLibrary( (HMODULE)lib );
#elif defined(POSIX)
dlclose( lib );
#endif
}
//========= Copyright Valve Corporation ============//
#include "sharedlibtools_public.h"
#include <string.h>
#if defined(_WIN32)
#include <windows.h>
#endif
#if defined(POSIX)
#include <dlfcn.h>
#endif
SharedLibHandle SharedLib_Load( const char *pchPath )
{
#if defined( _WIN32)
return (SharedLibHandle)LoadLibraryEx( pchPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
#elif defined(POSIX)
return (SharedLibHandle)dlopen(pchPath, RTLD_LOCAL|RTLD_NOW);
#endif
}
void *SharedLib_GetFunction( SharedLibHandle lib, const char *pchFunctionName)
{
#if defined( _WIN32)
return (void*)GetProcAddress( (HMODULE)lib, pchFunctionName );
#elif defined(POSIX)
return dlsym( lib, pchFunctionName );
#endif
}
void SharedLib_Unload( SharedLibHandle lib )
{
if ( !lib )
return;
#if defined( _WIN32)
FreeLibrary( (HMODULE)lib );
#elif defined(POSIX)
dlclose( lib );
#endif
}

View File

@ -1,10 +1,10 @@
//========= Copyright Valve Corporation ============//
#pragma once
typedef void *SharedLibHandle;
SharedLibHandle SharedLib_Load( const char *pchPath );
void *SharedLib_GetFunction( SharedLibHandle lib, const char *pchFunctionName);
void SharedLib_Unload( SharedLibHandle lib );
//========= Copyright Valve Corporation ============//
#pragma once
typedef void *SharedLibHandle;
SharedLibHandle SharedLib_Load( const char *pchPath );
void *SharedLib_GetFunction( SharedLibHandle lib, const char *pchFunctionName);
void SharedLib_Unload( SharedLibHandle lib );

View File

@ -1,450 +1,449 @@
//========= Copyright Valve Corporation ============//
#include "strtools_public.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <iostream>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool StringHasPrefix( const std::string & sString, const std::string & sPrefix )
{
return 0 == strnicmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
}
bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix )
{
return 0 == strncmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
}
bool StringHasSuffix( const std::string &sString, const std::string &sSuffix )
{
size_t cStrLen = sString.length();
size_t cSuffixLen = sSuffix.length();
if ( cSuffixLen > cStrLen )
return false;
std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
return 0 == stricmp( sStringSuffix.c_str(), sSuffix.c_str() );
}
bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix )
{
size_t cStrLen = sString.length();
size_t cSuffixLen = sSuffix.length();
if ( cSuffixLen > cStrLen )
return false;
std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
return 0 == strncmp( sStringSuffix.c_str(), sSuffix.c_str(),cSuffixLen );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
std::string UTF16to8(const wchar_t * in)
{
std::string out;
unsigned int codepoint = 0;
for ( ; in && *in != 0; ++in )
{
if (*in >= 0xd800 && *in <= 0xdbff)
codepoint = ((*in - 0xd800) << 10) + 0x10000;
else
{
if (*in >= 0xdc00 && *in <= 0xdfff)
codepoint |= *in - 0xdc00;
else
codepoint = *in;
if (codepoint <= 0x7f)
out.append(1, static_cast<char>(codepoint));
else if (codepoint <= 0x7ff)
{
out.append(1, static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
else if (codepoint <= 0xffff)
{
out.append(1, static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
else
{
out.append(1, static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
codepoint = 0;
}
}
return out;
}
std::wstring UTF8to16(const char * in)
{
std::wstring out;
unsigned int codepoint = 0;
int following = 0;
for ( ; in && *in != 0; ++in )
{
unsigned char ch = *in;
if (ch <= 0x7f)
{
codepoint = ch;
following = 0;
}
else if (ch <= 0xbf)
{
if (following > 0)
{
codepoint = (codepoint << 6) | (ch & 0x3f);
--following;
}
}
else if (ch <= 0xdf)
{
codepoint = ch & 0x1f;
following = 1;
}
else if (ch <= 0xef)
{
codepoint = ch & 0x0f;
following = 2;
}
else
{
codepoint = ch & 0x07;
following = 3;
}
if (following == 0)
{
if (codepoint > 0xffff)
{
out.append(1, static_cast<wchar_t>(0xd800 + (codepoint >> 10)));
out.append(1, static_cast<wchar_t>(0xdc00 + (codepoint & 0x03ff)));
}
else
out.append(1, static_cast<wchar_t>(codepoint));
codepoint = 0;
}
}
return out;
}
void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource )
{
strncpy( pchBuffer, pchSource, unBufferSizeBytes - 1 );
pchBuffer[unBufferSizeBytes - 1] = '\0';
}
// --------------------------------------------------------------------
// Purpose: converts a string to upper case
// --------------------------------------------------------------------
std::string StringToUpper( const std::string & sString )
{
std::string sOut;
sOut.reserve( sString.size() + 1 );
for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
{
sOut.push_back( (char)toupper( *i ) );
}
return sOut;
}
// --------------------------------------------------------------------
// Purpose: converts a string to lower case
// --------------------------------------------------------------------
std::string StringToLower( const std::string & sString )
{
std::string sOut;
sOut.reserve( sString.size() + 1 );
for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
{
sOut.push_back( (char)tolower( *i ) );
}
return sOut;
}
uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen )
{
uint32_t unLen = (uint32_t)sValue.length() + 1;
if( !pchBuffer || !unBufferLen )
return unLen;
if( unBufferLen < unLen )
{
pchBuffer[0] = '\0';
}
else
{
memcpy( pchBuffer, sValue.c_str(), unLen );
}
return unLen;
}
// Commented out by Mozilla, please see README.mozilla
/** Returns a std::string from a uint64_t */
/*
std::string Uint64ToString( uint64_t ulValue )
{
char buf[ 22 ];
#if defined( _WIN32 )
sprintf_s( buf, "%llu", ulValue );
#else
snprintf( buf, sizeof( buf ), "%llu", (long long unsigned int ) ulValue );
#endif
return buf;
}
*/
/** returns a uint64_t from a string */
uint64_t StringToUint64( const std::string & sValue )
{
return strtoull( sValue.c_str(), NULL, 0 );
}
//-----------------------------------------------------------------------------
// Purpose: Helper for converting a numeric value to a hex digit, value should be 0-15.
//-----------------------------------------------------------------------------
char cIntToHexDigit( int nValue )
{
//Assert( nValue >= 0 && nValue <= 15 );
return "0123456789ABCDEF"[ nValue & 15 ];
}
//-----------------------------------------------------------------------------
// Purpose: Helper for converting a hex char value to numeric, return -1 if the char
// is not a valid hex digit.
//-----------------------------------------------------------------------------
int iHexCharToInt( char cValue )
{
int32_t iValue = cValue;
if ( (uint32_t)( iValue - '0' ) < 10 )
return iValue - '0';
iValue |= 0x20;
if ( (uint32_t)( iValue - 'a' ) < 6 )
return iValue - 'a' + 10;
return -1;
}
//-----------------------------------------------------------------------------
// Purpose: Internal implementation of encode, works in the strict RFC manner, or
// with spaces turned to + like HTML form encoding.
//-----------------------------------------------------------------------------
void V_URLEncodeInternal( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen, bool bUsePlusForSpace )
{
//AssertMsg( nDestLen > 3*nSourceLen, "Target buffer for V_URLEncode should be 3x source length, plus one for terminating null\n" );
int iDestPos = 0;
for ( int i=0; i < nSourceLen; ++i )
{
// worst case we need 3 additional chars
if( (iDestPos+3) > nDestLen )
{
pchDest[0] = '\0';
// AssertMsg( false, "Target buffer too short\n" );
return;
}
// We allow only a-z, A-Z, 0-9, period, underscore, and hyphen to pass through unescaped.
// These are the characters allowed by both the original RFC 1738 and the latest RFC 3986.
// Current specs also allow '~', but that is forbidden under original RFC 1738.
if ( !( pchSource[i] >= 'a' && pchSource[i] <= 'z' ) && !( pchSource[i] >= 'A' && pchSource[i] <= 'Z' ) && !(pchSource[i] >= '0' && pchSource[i] <= '9' )
&& pchSource[i] != '-' && pchSource[i] != '_' && pchSource[i] != '.'
)
{
if ( bUsePlusForSpace && pchSource[i] == ' ' )
{
pchDest[iDestPos++] = '+';
}
else
{
pchDest[iDestPos++] = '%';
uint8_t iValue = pchSource[i];
if ( iValue == 0 )
{
pchDest[iDestPos++] = '0';
pchDest[iDestPos++] = '0';
}
else
{
char cHexDigit1 = cIntToHexDigit( iValue % 16 );
iValue /= 16;
char cHexDigit2 = cIntToHexDigit( iValue );
pchDest[iDestPos++] = cHexDigit2;
pchDest[iDestPos++] = cHexDigit1;
}
}
}
else
{
pchDest[iDestPos++] = pchSource[i];
}
}
if( (iDestPos+1) > nDestLen )
{
pchDest[0] = '\0';
//AssertMsg( false, "Target buffer too short to terminate\n" );
return;
}
// Null terminate
pchDest[iDestPos++] = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Internal implementation of decode, works in the strict RFC manner, or
// with spaces turned to + like HTML form encoding.
//
// Returns the amount of space used in the output buffer.
//-----------------------------------------------------------------------------
size_t V_URLDecodeInternal( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen, bool bUsePlusForSpace )
{
if ( nDecodeDestLen < nEncodedSourceLen )
{
//AssertMsg( false, "V_URLDecode needs a dest buffer at least as large as the source" );
return 0;
}
int iDestPos = 0;
for( int i=0; i < nEncodedSourceLen; ++i )
{
if ( bUsePlusForSpace && pchEncodedSource[i] == '+' )
{
pchDecodeDest[ iDestPos++ ] = ' ';
}
else if ( pchEncodedSource[i] == '%' )
{
// Percent signifies an encoded value, look ahead for the hex code, convert to numeric, and use that
// First make sure we have 2 more chars
if ( i < nEncodedSourceLen - 2 )
{
char cHexDigit1 = pchEncodedSource[i+1];
char cHexDigit2 = pchEncodedSource[i+2];
// Turn the chars into a hex value, if they are not valid, then we'll
// just place the % and the following two chars direct into the string,
// even though this really shouldn't happen, who knows what bad clients
// may do with encoding.
bool bValid = false;
int iValue = iHexCharToInt( cHexDigit1 );
if ( iValue != -1 )
{
iValue *= 16;
int iValue2 = iHexCharToInt( cHexDigit2 );
if ( iValue2 != -1 )
{
iValue += iValue2;
pchDecodeDest[ iDestPos++ ] = (char)iValue;
bValid = true;
}
}
if ( !bValid )
{
pchDecodeDest[ iDestPos++ ] = '%';
pchDecodeDest[ iDestPos++ ] = cHexDigit1;
pchDecodeDest[ iDestPos++ ] = cHexDigit2;
}
}
// Skip ahead
i += 2;
}
else
{
pchDecodeDest[ iDestPos++ ] = pchEncodedSource[i];
}
}
// We may not have extra room to NULL terminate, since this can be used on raw data, but if we do
// go ahead and do it as this can avoid bugs.
if ( iDestPos < nDecodeDestLen )
{
pchDecodeDest[iDestPos] = 0;
}
return (size_t)iDestPos;
}
//-----------------------------------------------------------------------------
// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
// This version of the call isn't a strict RFC implementation, but uses + for space as is
// the standard in HTML form encoding, despite it not being part of the RFC.
//
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
//-----------------------------------------------------------------------------
void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen )
{
return V_URLEncodeInternal( pchDest, nDestLen, pchSource, nSourceLen, true );
}
//-----------------------------------------------------------------------------
// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
// This version of the call isn't a strict RFC implementation, but uses + for space as is
// the standard in HTML form encoding, despite it not being part of the RFC.
//
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed.
//-----------------------------------------------------------------------------
size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen )
{
return V_URLDecodeInternal( pchDecodeDest, nDecodeDestLen, pchEncodedSource, nEncodedSourceLen, true );
}
//-----------------------------------------------------------------------------
void V_StripExtension( std::string &in )
{
// Find the last dot. If it's followed by a dot or a slash, then it's part of a
// directory specifier like ../../somedir/./blah.
std::string::size_type test = in.rfind( '.' );
if ( test != std::string::npos )
{
// This handles things like ".\blah" or "c:\my@email.com\abc\def\geh"
// Which would otherwise wind up with "" and "c:\my@email", respectively.
if ( in.rfind( '\\' ) < test && in.rfind( '/' ) < test )
{
in.resize( test );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Tokenizes a string into a vector of strings
//-----------------------------------------------------------------------------
std::vector<std::string> TokenizeString( const std::string & sString, char cToken )
{
std::vector<std::string> vecStrings;
std::istringstream stream( sString );
std::string s;
while ( std::getline( stream, s, cToken ) )
{
vecStrings.push_back( s );
}
return vecStrings;
}
//========= Copyright Valve Corporation ============//
#include "strtools_public.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <iostream>
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool StringHasPrefix( const std::string & sString, const std::string & sPrefix )
{
return 0 == strnicmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
}
bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix )
{
return 0 == strncmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
}
bool StringHasSuffix( const std::string &sString, const std::string &sSuffix )
{
size_t cStrLen = sString.length();
size_t cSuffixLen = sSuffix.length();
if ( cSuffixLen > cStrLen )
return false;
std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
return 0 == stricmp( sStringSuffix.c_str(), sSuffix.c_str() );
}
bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix )
{
size_t cStrLen = sString.length();
size_t cSuffixLen = sSuffix.length();
if ( cSuffixLen > cStrLen )
return false;
std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
return 0 == strncmp( sStringSuffix.c_str(), sSuffix.c_str(),cSuffixLen );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
std::string UTF16to8(const wchar_t * in)
{
std::string out;
unsigned int codepoint = 0;
for ( ; in && *in != 0; ++in )
{
if (*in >= 0xd800 && *in <= 0xdbff)
codepoint = ((*in - 0xd800) << 10) + 0x10000;
else
{
if (*in >= 0xdc00 && *in <= 0xdfff)
codepoint |= *in - 0xdc00;
else
codepoint = *in;
if (codepoint <= 0x7f)
out.append(1, static_cast<char>(codepoint));
else if (codepoint <= 0x7ff)
{
out.append(1, static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
else if (codepoint <= 0xffff)
{
out.append(1, static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
else
{
out.append(1, static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f)));
out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
}
codepoint = 0;
}
}
return out;
}
std::wstring UTF8to16(const char * in)
{
std::wstring out;
unsigned int codepoint = 0;
int following = 0;
for ( ; in && *in != 0; ++in )
{
unsigned char ch = *in;
if (ch <= 0x7f)
{
codepoint = ch;
following = 0;
}
else if (ch <= 0xbf)
{
if (following > 0)
{
codepoint = (codepoint << 6) | (ch & 0x3f);
--following;
}
}
else if (ch <= 0xdf)
{
codepoint = ch & 0x1f;
following = 1;
}
else if (ch <= 0xef)
{
codepoint = ch & 0x0f;
following = 2;
}
else
{
codepoint = ch & 0x07;
following = 3;
}
if (following == 0)
{
if (codepoint > 0xffff)
{
out.append(1, static_cast<wchar_t>(0xd800 + (codepoint >> 10)));
out.append(1, static_cast<wchar_t>(0xdc00 + (codepoint & 0x03ff)));
}
else
out.append(1, static_cast<wchar_t>(codepoint));
codepoint = 0;
}
}
return out;
}
void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource )
{
strncpy( pchBuffer, pchSource, unBufferSizeBytes - 1 );
pchBuffer[unBufferSizeBytes - 1] = '\0';
}
// --------------------------------------------------------------------
// Purpose: converts a string to upper case
// --------------------------------------------------------------------
std::string StringToUpper( const std::string & sString )
{
std::string sOut;
sOut.reserve( sString.size() + 1 );
for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
{
sOut.push_back( (char)toupper( *i ) );
}
return sOut;
}
// --------------------------------------------------------------------
// Purpose: converts a string to lower case
// --------------------------------------------------------------------
std::string StringToLower( const std::string & sString )
{
std::string sOut;
sOut.reserve( sString.size() + 1 );
for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
{
sOut.push_back( (char)tolower( *i ) );
}
return sOut;
}
uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen )
{
uint32_t unLen = (uint32_t)sValue.length() + 1;
if( !pchBuffer || !unBufferLen )
return unLen;
if( unBufferLen < unLen )
{
pchBuffer[0] = '\0';
}
else
{
memcpy( pchBuffer, sValue.c_str(), unLen );
}
return unLen;
}
/** Returns a std::string from a uint64_t */
// std::string Uint64ToString( uint64_t ulValue )
// {
// char buf[ 22 ];
// #if defined( _WIN32 )
// sprintf_s( buf, "%llu", ulValue );
// #else
// snprintf( buf, sizeof( buf ), "%llu", (long long unsigned int ) ulValue );
// #endif
// return buf;
// }
/** returns a uint64_t from a string */
uint64_t StringToUint64( const std::string & sValue )
{
return strtoull( sValue.c_str(), NULL, 0 );
}
//-----------------------------------------------------------------------------
// Purpose: Helper for converting a numeric value to a hex digit, value should be 0-15.
//-----------------------------------------------------------------------------
char cIntToHexDigit( int nValue )
{
//Assert( nValue >= 0 && nValue <= 15 );
return "0123456789ABCDEF"[ nValue & 15 ];
}
//-----------------------------------------------------------------------------
// Purpose: Helper for converting a hex char value to numeric, return -1 if the char
// is not a valid hex digit.
//-----------------------------------------------------------------------------
int iHexCharToInt( char cValue )
{
int32_t iValue = cValue;
if ( (uint32_t)( iValue - '0' ) < 10 )
return iValue - '0';
iValue |= 0x20;
if ( (uint32_t)( iValue - 'a' ) < 6 )
return iValue - 'a' + 10;
return -1;
}
//-----------------------------------------------------------------------------
// Purpose: Internal implementation of encode, works in the strict RFC manner, or
// with spaces turned to + like HTML form encoding.
//-----------------------------------------------------------------------------
void V_URLEncodeInternal( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen, bool bUsePlusForSpace )
{
//AssertMsg( nDestLen > 3*nSourceLen, "Target buffer for V_URLEncode should be 3x source length, plus one for terminating null\n" );
int iDestPos = 0;
for ( int i=0; i < nSourceLen; ++i )
{
// worst case we need 3 additional chars
if( (iDestPos+3) > nDestLen )
{
pchDest[0] = '\0';
// AssertMsg( false, "Target buffer too short\n" );
return;
}
// We allow only a-z, A-Z, 0-9, period, underscore, and hyphen to pass through unescaped.
// These are the characters allowed by both the original RFC 1738 and the latest RFC 3986.
// Current specs also allow '~', but that is forbidden under original RFC 1738.
if ( !( pchSource[i] >= 'a' && pchSource[i] <= 'z' ) && !( pchSource[i] >= 'A' && pchSource[i] <= 'Z' ) && !(pchSource[i] >= '0' && pchSource[i] <= '9' )
&& pchSource[i] != '-' && pchSource[i] != '_' && pchSource[i] != '.'
)
{
if ( bUsePlusForSpace && pchSource[i] == ' ' )
{
pchDest[iDestPos++] = '+';
}
else
{
pchDest[iDestPos++] = '%';
uint8_t iValue = pchSource[i];
if ( iValue == 0 )
{
pchDest[iDestPos++] = '0';
pchDest[iDestPos++] = '0';
}
else
{
char cHexDigit1 = cIntToHexDigit( iValue % 16 );
iValue /= 16;
char cHexDigit2 = cIntToHexDigit( iValue );
pchDest[iDestPos++] = cHexDigit2;
pchDest[iDestPos++] = cHexDigit1;
}
}
}
else
{
pchDest[iDestPos++] = pchSource[i];
}
}
if( (iDestPos+1) > nDestLen )
{
pchDest[0] = '\0';
//AssertMsg( false, "Target buffer too short to terminate\n" );
return;
}
// Null terminate
pchDest[iDestPos++] = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Internal implementation of decode, works in the strict RFC manner, or
// with spaces turned to + like HTML form encoding.
//
// Returns the amount of space used in the output buffer.
//-----------------------------------------------------------------------------
size_t V_URLDecodeInternal( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen, bool bUsePlusForSpace )
{
if ( nDecodeDestLen < nEncodedSourceLen )
{
//AssertMsg( false, "V_URLDecode needs a dest buffer at least as large as the source" );
return 0;
}
int iDestPos = 0;
for( int i=0; i < nEncodedSourceLen; ++i )
{
if ( bUsePlusForSpace && pchEncodedSource[i] == '+' )
{
pchDecodeDest[ iDestPos++ ] = ' ';
}
else if ( pchEncodedSource[i] == '%' )
{
// Percent signifies an encoded value, look ahead for the hex code, convert to numeric, and use that
// First make sure we have 2 more chars
if ( i < nEncodedSourceLen - 2 )
{
char cHexDigit1 = pchEncodedSource[i+1];
char cHexDigit2 = pchEncodedSource[i+2];
// Turn the chars into a hex value, if they are not valid, then we'll
// just place the % and the following two chars direct into the string,
// even though this really shouldn't happen, who knows what bad clients
// may do with encoding.
bool bValid = false;
int iValue = iHexCharToInt( cHexDigit1 );
if ( iValue != -1 )
{
iValue *= 16;
int iValue2 = iHexCharToInt( cHexDigit2 );
if ( iValue2 != -1 )
{
iValue += iValue2;
pchDecodeDest[ iDestPos++ ] = (char)iValue;
bValid = true;
}
}
if ( !bValid )
{
pchDecodeDest[ iDestPos++ ] = '%';
pchDecodeDest[ iDestPos++ ] = cHexDigit1;
pchDecodeDest[ iDestPos++ ] = cHexDigit2;
}
}
// Skip ahead
i += 2;
}
else
{
pchDecodeDest[ iDestPos++ ] = pchEncodedSource[i];
}
}
// We may not have extra room to NULL terminate, since this can be used on raw data, but if we do
// go ahead and do it as this can avoid bugs.
if ( iDestPos < nDecodeDestLen )
{
pchDecodeDest[iDestPos] = 0;
}
return (size_t)iDestPos;
}
//-----------------------------------------------------------------------------
// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
// This version of the call isn't a strict RFC implementation, but uses + for space as is
// the standard in HTML form encoding, despite it not being part of the RFC.
//
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
//-----------------------------------------------------------------------------
void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen )
{
return V_URLEncodeInternal( pchDest, nDestLen, pchSource, nSourceLen, true );
}
//-----------------------------------------------------------------------------
// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
// This version of the call isn't a strict RFC implementation, but uses + for space as is
// the standard in HTML form encoding, despite it not being part of the RFC.
//
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed.
//-----------------------------------------------------------------------------
size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen )
{
return V_URLDecodeInternal( pchDecodeDest, nDecodeDestLen, pchEncodedSource, nEncodedSourceLen, true );
}
//-----------------------------------------------------------------------------
void V_StripExtension( std::string &in )
{
// Find the last dot. If it's followed by a dot or a slash, then it's part of a
// directory specifier like ../../somedir/./blah.
std::string::size_type test = in.rfind( '.' );
if ( test != std::string::npos )
{
// This handles things like ".\blah" or "c:\my@email.com\abc\def\geh"
// Which would otherwise wind up with "" and "c:\my@email", respectively.
if ( in.rfind( '\\' ) < test && in.rfind( '/' ) < test )
{
in.resize( test );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Tokenizes a string into a vector of strings
//-----------------------------------------------------------------------------
std::vector<std::string> TokenizeString( const std::string & sString, char cToken )
{
std::vector<std::string> vecStrings;
std::istringstream stream( sString );
std::string s;
while ( std::getline( stream, s, cToken ) )
{
vecStrings.push_back( s );
}
return vecStrings;
}

View File

@ -1,130 +1,132 @@
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
#include <stdint.h>
#include <sys/types.h>
#include <vector>
/** returns true if the string has the prefix */
bool StringHasPrefix( const std::string & sString, const std::string & sPrefix );
bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix );
/** returns if the string has the suffix */
bool StringHasSuffix( const std::string &sString, const std::string &sSuffix );
bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix );
/** converts a UTF-16 string to a UTF-8 string */
std::string UTF16to8(const wchar_t * in);
/** converts a UTF-8 string to a UTF-16 string */
std::wstring UTF8to16(const char * in);
#define Utf16FromUtf8 UTF8to16
/** safely copy a string into a buffer */
void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource );
template< size_t bufferSize >
void strcpy_safe( char (& buffer) [ bufferSize ], const char *pchSource )
{
strcpy_safe( buffer, bufferSize, pchSource );
}
/** converts a string to upper case */
std::string StringToUpper( const std::string & sString );
/** converts a string to lower case */
std::string StringToLower( const std::string & sString );
// we stricmp (from WIN) but it isn't POSIX - OSX/LINUX have strcasecmp so just inline bridge to it
#if defined( OSX ) || defined( LINUX )
#include <strings.h>
inline int stricmp(const char *pStr1, const char *pStr2) { return strcasecmp(pStr1,pStr2); }
#define _stricmp stricmp
inline int strnicmp( const char *pStr1, const char *pStr2, size_t unBufferLen ) { return strncasecmp( pStr1,pStr2, unBufferLen ); }
#define _strnicmp strnicmp
#define _vsnprintf_s vsnprintf
#define _TRUNCATE ((size_t)-1)
#endif
#if defined( OSX )
// behaviors ensure NULL-termination at least as well as _TRUNCATE does, but
// wcsncpy_s/strncpy_s can non-NULL-terminate, wcslcpy/strlcpy can not.
/*
// Commented out by Mozilla, please see README.mozilla
inline errno_t wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count)
{
return wcslcpy(strDest, strSource, numberOfElements);
}
inline errno_t strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
{
return strlcpy(strDest, strSource, numberOfElements);
}
*/
#endif
#if defined( LINUX )
// this implementation does not return whether or not the destination was
// truncated, but that is straightforward to fix if anybody actually needs the
// return code.
#include "string.h"
inline void wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count)
{
wcsncpy(strDest, strSource, numberOfElements);
strDest[numberOfElements-1] = '\0';
}
inline void strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
{
strncpy(strDest, strSource, numberOfElements);
strDest[numberOfElements-1] = '\0';
}
#endif
#if defined( _WIN32 ) && _MSC_VER < 1800
inline uint64_t strtoull(const char *str, char **endptr, int base) { return _strtoui64( str, endptr, base ); }
#endif
/* Handles copying a std::string into a buffer as would be provided in an API */
uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen );
/** Returns a std::string from a uint64_t */
// std::string Uint64ToString( uint64_t ulValue );
// Commented out by Mozilla, please see README.mozilla
/** returns a uint64_t from a string */
uint64_t StringToUint64( const std::string & sValue );
//-----------------------------------------------------------------------------
// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
// This version of the call isn't a strict RFC implementation, but uses + for space as is
// the standard in HTML form encoding, despite it not being part of the RFC.
//
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
//-----------------------------------------------------------------------------
void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen );
//-----------------------------------------------------------------------------
// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
// This version of the call isn't a strict RFC implementation, but uses + for space as is
// the standard in HTML form encoding, despite it not being part of the RFC.
//
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed.
//-----------------------------------------------------------------------------
size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen );
//-----------------------------------------------------------------------------
// Purpose: strip extension from a path
//-----------------------------------------------------------------------------
void V_StripExtension( std::string &in );
/** Tokenizes a string into a vector of strings */
std::vector<std::string> TokenizeString( const std::string & sString, char cToken );
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
#include <stdint.h>
#include <sys/types.h>
#include <vector>
/** returns true if the string has the prefix */
bool StringHasPrefix( const std::string & sString, const std::string & sPrefix );
bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix );
/** returns if the string has the suffix */
bool StringHasSuffix( const std::string &sString, const std::string &sSuffix );
bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix );
/** converts a UTF-16 string to a UTF-8 string */
std::string UTF16to8(const wchar_t * in);
/** converts a UTF-8 string to a UTF-16 string */
std::wstring UTF8to16(const char * in);
#define Utf16FromUtf8 UTF8to16
/** safely copy a string into a buffer */
void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource );
template< size_t bufferSize >
void strcpy_safe( char (& buffer) [ bufferSize ], const char *pchSource )
{
strcpy_safe( buffer, bufferSize, pchSource );
}
/** converts a string to upper case */
std::string StringToUpper( const std::string & sString );
/** converts a string to lower case */
std::string StringToLower( const std::string & sString );
// we stricmp (from WIN) but it isn't POSIX - OSX/LINUX have strcasecmp so just inline bridge to it
#if defined( OSX ) || defined( LINUX )
#include <strings.h>
inline int stricmp(const char *pStr1, const char *pStr2) { return strcasecmp(pStr1,pStr2); }
#ifndef _stricmp
#define _stricmp stricmp
#endif
inline int strnicmp( const char *pStr1, const char *pStr2, size_t unBufferLen ) { return strncasecmp( pStr1,pStr2, unBufferLen ); }
#ifndef _strnicmp
#define _strnicmp strnicmp
#endif
#ifndef _vsnprintf_s
#define _vsnprintf_s vsnprintf
#endif
#define _TRUNCATE ((size_t)-1)
#endif
#if defined( OSX )
// behaviors ensure NULL-termination at least as well as _TRUNCATE does, but
// wcsncpy_s/strncpy_s can non-NULL-terminate, wcslcpy/strlcpy can not.
// inline errno_t wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count)
// {
// return wcslcpy(strDest, strSource, numberOfElements);
// }
// inline errno_t strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
// {
// return strlcpy(strDest, strSource, numberOfElements);
// }
#endif
#if defined( LINUX )
// this implementation does not return whether or not the destination was
// truncated, but that is straightforward to fix if anybody actually needs the
// return code.
#include "string.h"
inline void wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count)
{
wcsncpy(strDest, strSource, numberOfElements);
strDest[numberOfElements-1] = '\0';
}
inline void strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
{
strncpy(strDest, strSource, numberOfElements);
strDest[numberOfElements-1] = '\0';
}
#endif
#if defined( _WIN32 ) && _MSC_VER < 1800
inline uint64_t strtoull(const char *str, char **endptr, int base) { return _strtoui64( str, endptr, base ); }
#endif
/* Handles copying a std::string into a buffer as would be provided in an API */
uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen );
/** Returns a std::string from a uint64_t */
//std::string Uint64ToString( uint64_t ulValue );
/** returns a uint64_t from a string */
uint64_t StringToUint64( const std::string & sValue );
//-----------------------------------------------------------------------------
// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
// This version of the call isn't a strict RFC implementation, but uses + for space as is
// the standard in HTML form encoding, despite it not being part of the RFC.
//
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
//-----------------------------------------------------------------------------
void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen );
//-----------------------------------------------------------------------------
// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
// This version of the call isn't a strict RFC implementation, but uses + for space as is
// the standard in HTML form encoding, despite it not being part of the RFC.
//
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed.
//-----------------------------------------------------------------------------
size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen );
//-----------------------------------------------------------------------------
// Purpose: strip extension from a path
//-----------------------------------------------------------------------------
void V_StripExtension( std::string &in );
/** Tokenizes a string into a vector of strings */
std::vector<std::string> TokenizeString( const std::string & sString, char cToken );

View File

@ -1,411 +1,411 @@
//========= Copyright Valve Corporation ============//
#include "vrpathregistry_public.h"
#include "json/json.h"
#include "pathtools_public.h"
#include "envvartools_public.h"
#include "strtools_public.h"
#include "dirtools_public.h"
#if defined( WIN32 )
#include <windows.h>
#include <shlobj.h>
#undef GetEnvironmentVariable
#elif defined OSX
#include <Foundation/Foundation.h>
#include <AppKit/AppKit.h>
#elif defined(LINUX)
#include <dlfcn.h>
#include <stdio.h>
#endif
#include <algorithm>
#ifndef VRLog
#if defined( __MINGW32__ )
#define VRLog(args...) fprintf(stderr, args)
#elif defined( WIN32 )
#define VRLog(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#else
#define VRLog(args...) fprintf(stderr, args)
#endif
#endif
/** Returns the root of the directory the system wants us to store user config data in */
static std::string GetAppSettingsPath()
{
#if defined( WIN32 )
WCHAR rwchPath[MAX_PATH];
if( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) )
{
return "";
}
// Convert the path to UTF-8 and store in the output
std::string sUserPath = UTF16to8( rwchPath );
return sUserPath;
#elif defined( OSX )
std::string sSettingsDir;
@autoreleasepool {
// Search for the path
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSApplicationSupportDirectory, NSUserDomainMask, YES );
if ( [paths count] == 0 )
{
return "";
}
NSString *resolvedPath = [paths objectAtIndex:0];
resolvedPath = [resolvedPath stringByAppendingPathComponent: @"OpenVR"];
if ( ![[NSFileManager defaultManager] createDirectoryAtPath: resolvedPath withIntermediateDirectories:YES attributes:nil error:nil] )
{
return "";
}
sSettingsDir.assign( [resolvedPath UTF8String] );
}
return sSettingsDir;
#elif defined( LINUX )
// As defined by XDG Base Directory Specification
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
const char *pchHome = getenv("XDG_CONFIG_HOME");
if ( ( pchHome != NULL) && ( pchHome[0] != '\0' ) )
{
return pchHome;
}
//
// XDG_CONFIG_HOME is not defined, use ~/.config instead
//
pchHome = getenv( "HOME" );
if ( pchHome == NULL )
{
return "";
}
std::string sUserPath( pchHome );
sUserPath = Path_Join( sUserPath, ".config" );
return sUserPath;
#else
#warning "Unsupported platform"
#endif
}
// ---------------------------------------------------------------------------
// Purpose: Constructor
// ---------------------------------------------------------------------------
CVRPathRegistry_Public::CVRPathRegistry_Public()
{
}
// ---------------------------------------------------------------------------
// Purpose: Computes the registry filename
// ---------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetOpenVRConfigPath()
{
std::string sConfigPath = GetAppSettingsPath();
if( sConfigPath.empty() )
return "";
#if defined( _WIN32 ) || defined( LINUX )
sConfigPath = Path_Join( sConfigPath, "openvr" );
#elif defined ( OSX )
sConfigPath = Path_Join( sConfigPath, ".openvr" );
#else
#warning "Unsupported platform"
#endif
sConfigPath = Path_FixSlashes( sConfigPath );
return sConfigPath;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetVRPathRegistryFilename()
{
std::string sPath = GetOpenVRConfigPath();
if ( sPath.empty() )
return "";
#if defined( _WIN32 )
sPath = Path_Join( sPath, "openvrpaths.vrpath" );
#elif defined ( POSIX )
sPath = Path_Join( sPath, "openvrpaths.vrpath" );
#else
#error "Unsupported platform"
#endif
sPath = Path_FixSlashes( sPath );
return sPath;
}
// ---------------------------------------------------------------------------
// Purpose: Converts JSON to a history array
// ---------------------------------------------------------------------------
static void ParseStringListFromJson( std::vector< std::string > *pvecHistory, const Json::Value & root, const char *pchArrayName )
{
if( !root.isMember( pchArrayName ) )
return;
const Json::Value & arrayNode = root[ pchArrayName ];
if( !arrayNode )
{
VRLog( "VR Path Registry node %s is not an array\n", pchArrayName );
return;
}
pvecHistory->clear();
pvecHistory->reserve( arrayNode.size() );
for( uint32_t unIndex = 0; unIndex < arrayNode.size(); unIndex++ )
{
std::string sPath( arrayNode[ unIndex ].asString() );
pvecHistory->push_back( sPath );
}
}
// ---------------------------------------------------------------------------
// Purpose: Converts a history array to JSON
// ---------------------------------------------------------------------------
static void StringListToJson( const std::vector< std::string > & vecHistory, Json::Value & root, const char *pchArrayName )
{
Json::Value & arrayNode = root[ pchArrayName ];
for( auto i = vecHistory.begin(); i != vecHistory.end(); i++ )
{
arrayNode.append( *i );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CVRPathRegistry_Public::ToJsonString( std::string &sJsonString )
{
std::string sRegPath = GetVRPathRegistryFilename();
if( sRegPath.empty() )
return false;
std::string sRegistryContents = Path_ReadTextFile( sRegPath );
if( sRegistryContents.empty() )
return false;
sJsonString = sRegistryContents;
return true;
}
// ---------------------------------------------------------------------------
// Purpose: Loads the config file from its well known location
// ---------------------------------------------------------------------------
bool CVRPathRegistry_Public::BLoadFromFile()
{
std::string sRegPath = GetVRPathRegistryFilename();
if( sRegPath.empty() )
{
VRLog( "Unable to determine VR Path Registry filename\n" );
return false;
}
std::string sRegistryContents = Path_ReadTextFile( sRegPath );
if( sRegistryContents.empty() )
{
VRLog( "Unable to read VR Path Registry from %s\n", sRegPath.c_str() );
return false;
}
Json::Value root;
Json::Reader reader;
if( !reader.parse( sRegistryContents, root ) )
{
VRLog( "Unable to parse %s: %s\n", sRegPath.c_str(), reader.getFormattedErrorMessages().c_str() );
return false;
}
ParseStringListFromJson( &m_vecRuntimePath, root, "runtime" );
ParseStringListFromJson( &m_vecConfigPath, root, "config" );
ParseStringListFromJson( &m_vecLogPath, root, "log" );
if (root.isMember( "external_drivers" ) && root[ "external_drivers" ].isArray() )
{
ParseStringListFromJson( &m_vecExternalDrivers, root, "external_drivers" );
}
return true;
}
// ---------------------------------------------------------------------------
// Purpose: Saves the config file to its well known location
// ---------------------------------------------------------------------------
bool CVRPathRegistry_Public::BSaveToFile() const
{
#if defined( DASHBOARD_BUILD_MODE )
return false;
#else
std::string sRegPath = GetVRPathRegistryFilename();
if( sRegPath.empty() )
return false;
Json::Value root;
root[ "version" ] = 1;
root[ "jsonid" ] = "vrpathreg";
StringListToJson( m_vecRuntimePath, root, "runtime" );
StringListToJson( m_vecConfigPath, root, "config" );
StringListToJson( m_vecLogPath, root, "log" );
StringListToJson( m_vecExternalDrivers, root, "external_drivers" );
Json::StyledWriter writer;
std::string sRegistryContents = writer.write( root );
// make sure the directory we're writing into actually exists
std::string sRegDirectory = Path_StripFilename( sRegPath );
if( !BCreateDirectoryRecursive( sRegDirectory.c_str() ) )
{
VRLog( "Unable to create path registry directory %s\n", sRegDirectory.c_str() );
return false;
}
if( !Path_WriteStringToTextFile( sRegPath, sRegistryContents.c_str() ) )
{
VRLog( "Unable to write VR path registry to %s\n", sRegPath.c_str() );
return false;
}
return true;
#endif
}
// ---------------------------------------------------------------------------
// Purpose: Returns the current runtime path or NULL if no path is configured.
// ---------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetRuntimePath() const
{
if( m_vecRuntimePath.empty() )
return "";
else
return m_vecRuntimePath.front().c_str();
}
// ---------------------------------------------------------------------------
// Purpose: Returns the current config path or NULL if no path is configured.
// ---------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetConfigPath() const
{
if( m_vecConfigPath.empty() )
return "";
else
return m_vecConfigPath.front().c_str();
}
// ---------------------------------------------------------------------------
// Purpose: Returns the current log path or NULL if no path is configured.
// ---------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetLogPath() const
{
if( m_vecLogPath.empty() )
return "";
else
return m_vecLogPath.front().c_str();
}
// ---------------------------------------------------------------------------
// Purpose: Returns paths using the path registry and the provided override
// values. Pass NULL for any paths you don't care about.
// ---------------------------------------------------------------------------
bool CVRPathRegistry_Public::GetPaths( std::string *psRuntimePath, std::string *psConfigPath, std::string *psLogPath, const char *pchConfigPathOverride, const char *pchLogPathOverride, std::vector<std::string> *pvecExternalDrivers )
{
CVRPathRegistry_Public pathReg;
bool bLoadedRegistry = pathReg.BLoadFromFile();
int nCountEnvironmentVariables = 0;
if( psRuntimePath )
{
if ( GetEnvironmentVariable( k_pchRuntimeOverrideVar ).length() != 0 )
{
*psRuntimePath = GetEnvironmentVariable( k_pchRuntimeOverrideVar );
nCountEnvironmentVariables++;
}
else if( !pathReg.GetRuntimePath().empty() )
{
*psRuntimePath = pathReg.GetRuntimePath();
}
else
{
*psRuntimePath = "";
}
}
if( psConfigPath )
{
if ( GetEnvironmentVariable( k_pchConfigOverrideVar ).length() != 0 )
{
*psConfigPath = GetEnvironmentVariable( k_pchConfigOverrideVar );
nCountEnvironmentVariables++;
}
else if( pchConfigPathOverride )
{
*psConfigPath = pchConfigPathOverride;
}
else if( !pathReg.GetConfigPath().empty() )
{
*psConfigPath = pathReg.GetConfigPath();
}
else
{
*psConfigPath = "";
}
}
if( psLogPath )
{
if ( GetEnvironmentVariable( k_pchLogOverrideVar ).length() != 0 )
{
*psLogPath = GetEnvironmentVariable( k_pchLogOverrideVar );
nCountEnvironmentVariables++;
}
else if( pchLogPathOverride )
{
*psLogPath = pchLogPathOverride;
}
else if( !pathReg.GetLogPath().empty() )
{
*psLogPath = pathReg.GetLogPath();
}
else
{
*psLogPath = "";
}
}
if ( pvecExternalDrivers )
{
*pvecExternalDrivers = pathReg.m_vecExternalDrivers;
}
if ( nCountEnvironmentVariables == 3 )
{
// all three environment variables where set, so we don't need the physical file
return true;
}
return bLoadedRegistry;
}
//========= Copyright Valve Corporation ============//
#include "vrpathregistry_public.h"
#include "json/json.h"
#include "pathtools_public.h"
#include "envvartools_public.h"
#include "strtools_public.h"
#include "dirtools_public.h"
#if defined( WIN32 )
#include <windows.h>
#include <shlobj.h>
#undef GetEnvironmentVariable
#elif defined OSX
#include <Foundation/Foundation.h>
#include <AppKit/AppKit.h>
#elif defined(LINUX)
#include <dlfcn.h>
#include <stdio.h>
#endif
#include <algorithm>
#ifndef VRLog
#if defined( __MINGW32__ )
#define VRLog(args...) fprintf(stderr, args)
#elif defined( WIN32 )
#define VRLog(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#else
#define VRLog(args...) fprintf(stderr, args)
#endif
#endif
/** Returns the root of the directory the system wants us to store user config data in */
static std::string GetAppSettingsPath()
{
#if defined( WIN32 )
WCHAR rwchPath[MAX_PATH];
if( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) )
{
return "";
}
// Convert the path to UTF-8 and store in the output
std::string sUserPath = UTF16to8( rwchPath );
return sUserPath;
#elif defined( OSX )
std::string sSettingsDir;
@autoreleasepool {
// Search for the path
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSApplicationSupportDirectory, NSUserDomainMask, YES );
if ( [paths count] == 0 )
{
return "";
}
NSString *resolvedPath = [paths objectAtIndex:0];
resolvedPath = [resolvedPath stringByAppendingPathComponent: @"OpenVR"];
if ( ![[NSFileManager defaultManager] createDirectoryAtPath: resolvedPath withIntermediateDirectories:YES attributes:nil error:nil] )
{
return "";
}
sSettingsDir.assign( [resolvedPath UTF8String] );
}
return sSettingsDir;
#elif defined( LINUX )
// As defined by XDG Base Directory Specification
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
const char *pchHome = getenv("XDG_CONFIG_HOME");
if ( ( pchHome != NULL) && ( pchHome[0] != '\0' ) )
{
return pchHome;
}
//
// XDG_CONFIG_HOME is not defined, use ~/.config instead
//
pchHome = getenv( "HOME" );
if ( pchHome == NULL )
{
return "";
}
std::string sUserPath( pchHome );
sUserPath = Path_Join( sUserPath, ".config" );
return sUserPath;
#else
#warning "Unsupported platform"
#endif
}
// ---------------------------------------------------------------------------
// Purpose: Constructor
// ---------------------------------------------------------------------------
CVRPathRegistry_Public::CVRPathRegistry_Public()
{
}
// ---------------------------------------------------------------------------
// Purpose: Computes the registry filename
// ---------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetOpenVRConfigPath()
{
std::string sConfigPath = GetAppSettingsPath();
if( sConfigPath.empty() )
return "";
#if defined( _WIN32 ) || defined( LINUX )
sConfigPath = Path_Join( sConfigPath, "openvr" );
#elif defined ( OSX )
sConfigPath = Path_Join( sConfigPath, ".openvr" );
#else
#warning "Unsupported platform"
#endif
sConfigPath = Path_FixSlashes( sConfigPath );
return sConfigPath;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetVRPathRegistryFilename()
{
std::string sPath = GetOpenVRConfigPath();
if ( sPath.empty() )
return "";
#if defined( _WIN32 )
sPath = Path_Join( sPath, "openvrpaths.vrpath" );
#elif defined ( POSIX )
sPath = Path_Join( sPath, "openvrpaths.vrpath" );
#else
#error "Unsupported platform"
#endif
sPath = Path_FixSlashes( sPath );
return sPath;
}
// ---------------------------------------------------------------------------
// Purpose: Converts JSON to a history array
// ---------------------------------------------------------------------------
static void ParseStringListFromJson( std::vector< std::string > *pvecHistory, const Json::Value & root, const char *pchArrayName )
{
if( !root.isMember( pchArrayName ) )
return;
const Json::Value & arrayNode = root[ pchArrayName ];
if( !arrayNode )
{
VRLog( "VR Path Registry node %s is not an array\n", pchArrayName );
return;
}
pvecHistory->clear();
pvecHistory->reserve( arrayNode.size() );
for( uint32_t unIndex = 0; unIndex < arrayNode.size(); unIndex++ )
{
std::string sPath( arrayNode[ unIndex ].asString() );
pvecHistory->push_back( sPath );
}
}
// ---------------------------------------------------------------------------
// Purpose: Converts a history array to JSON
// ---------------------------------------------------------------------------
static void StringListToJson( const std::vector< std::string > & vecHistory, Json::Value & root, const char *pchArrayName )
{
Json::Value & arrayNode = root[ pchArrayName ];
for( auto i = vecHistory.begin(); i != vecHistory.end(); i++ )
{
arrayNode.append( *i );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CVRPathRegistry_Public::ToJsonString( std::string &sJsonString )
{
std::string sRegPath = GetVRPathRegistryFilename();
if( sRegPath.empty() )
return false;
std::string sRegistryContents = Path_ReadTextFile( sRegPath );
if( sRegistryContents.empty() )
return false;
sJsonString = sRegistryContents;
return true;
}
// ---------------------------------------------------------------------------
// Purpose: Loads the config file from its well known location
// ---------------------------------------------------------------------------
bool CVRPathRegistry_Public::BLoadFromFile()
{
std::string sRegPath = GetVRPathRegistryFilename();
if( sRegPath.empty() )
{
VRLog( "Unable to determine VR Path Registry filename\n" );
return false;
}
std::string sRegistryContents = Path_ReadTextFile( sRegPath );
if( sRegistryContents.empty() )
{
VRLog( "Unable to read VR Path Registry from %s\n", sRegPath.c_str() );
return false;
}
Json::Value root;
Json::Reader reader;
if( !reader.parse( sRegistryContents, root ) )
{
VRLog( "Unable to parse %s: %s\n", sRegPath.c_str(), reader.getFormattedErrorMessages().c_str() );
return false;
}
ParseStringListFromJson( &m_vecRuntimePath, root, "runtime" );
ParseStringListFromJson( &m_vecConfigPath, root, "config" );
ParseStringListFromJson( &m_vecLogPath, root, "log" );
if (root.isMember( "external_drivers" ) && root[ "external_drivers" ].isArray() )
{
ParseStringListFromJson( &m_vecExternalDrivers, root, "external_drivers" );
}
return true;
}
// ---------------------------------------------------------------------------
// Purpose: Saves the config file to its well known location
// ---------------------------------------------------------------------------
bool CVRPathRegistry_Public::BSaveToFile() const
{
#if defined( DASHBOARD_BUILD_MODE )
return false;
#else
std::string sRegPath = GetVRPathRegistryFilename();
if( sRegPath.empty() )
return false;
Json::Value root;
root[ "version" ] = 1;
root[ "jsonid" ] = "vrpathreg";
StringListToJson( m_vecRuntimePath, root, "runtime" );
StringListToJson( m_vecConfigPath, root, "config" );
StringListToJson( m_vecLogPath, root, "log" );
StringListToJson( m_vecExternalDrivers, root, "external_drivers" );
Json::StyledWriter writer;
std::string sRegistryContents = writer.write( root );
// make sure the directory we're writing into actually exists
std::string sRegDirectory = Path_StripFilename( sRegPath );
if( !BCreateDirectoryRecursive( sRegDirectory.c_str() ) )
{
VRLog( "Unable to create path registry directory %s\n", sRegDirectory.c_str() );
return false;
}
if( !Path_WriteStringToTextFile( sRegPath, sRegistryContents.c_str() ) )
{
VRLog( "Unable to write VR path registry to %s\n", sRegPath.c_str() );
return false;
}
return true;
#endif
}
// ---------------------------------------------------------------------------
// Purpose: Returns the current runtime path or NULL if no path is configured.
// ---------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetRuntimePath() const
{
if( m_vecRuntimePath.empty() )
return "";
else
return m_vecRuntimePath.front().c_str();
}
// ---------------------------------------------------------------------------
// Purpose: Returns the current config path or NULL if no path is configured.
// ---------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetConfigPath() const
{
if( m_vecConfigPath.empty() )
return "";
else
return m_vecConfigPath.front().c_str();
}
// ---------------------------------------------------------------------------
// Purpose: Returns the current log path or NULL if no path is configured.
// ---------------------------------------------------------------------------
std::string CVRPathRegistry_Public::GetLogPath() const
{
if( m_vecLogPath.empty() )
return "";
else
return m_vecLogPath.front().c_str();
}
// ---------------------------------------------------------------------------
// Purpose: Returns paths using the path registry and the provided override
// values. Pass NULL for any paths you don't care about.
// ---------------------------------------------------------------------------
bool CVRPathRegistry_Public::GetPaths( std::string *psRuntimePath, std::string *psConfigPath, std::string *psLogPath, const char *pchConfigPathOverride, const char *pchLogPathOverride, std::vector<std::string> *pvecExternalDrivers )
{
CVRPathRegistry_Public pathReg;
bool bLoadedRegistry = pathReg.BLoadFromFile();
int nCountEnvironmentVariables = 0;
if( psRuntimePath )
{
if ( GetEnvironmentVariable( k_pchRuntimeOverrideVar ).length() != 0 )
{
*psRuntimePath = GetEnvironmentVariable( k_pchRuntimeOverrideVar );
nCountEnvironmentVariables++;
}
else if( !pathReg.GetRuntimePath().empty() )
{
*psRuntimePath = pathReg.GetRuntimePath();
}
else
{
*psRuntimePath = "";
}
}
if( psConfigPath )
{
if ( GetEnvironmentVariable( k_pchConfigOverrideVar ).length() != 0 )
{
*psConfigPath = GetEnvironmentVariable( k_pchConfigOverrideVar );
nCountEnvironmentVariables++;
}
else if( pchConfigPathOverride )
{
*psConfigPath = pchConfigPathOverride;
}
else if( !pathReg.GetConfigPath().empty() )
{
*psConfigPath = pathReg.GetConfigPath();
}
else
{
*psConfigPath = "";
}
}
if( psLogPath )
{
if ( GetEnvironmentVariable( k_pchLogOverrideVar ).length() != 0 )
{
*psLogPath = GetEnvironmentVariable( k_pchLogOverrideVar );
nCountEnvironmentVariables++;
}
else if( pchLogPathOverride )
{
*psLogPath = pchLogPathOverride;
}
else if( !pathReg.GetLogPath().empty() )
{
*psLogPath = pathReg.GetLogPath();
}
else
{
*psLogPath = "";
}
}
if ( pvecExternalDrivers )
{
*pvecExternalDrivers = pathReg.m_vecExternalDrivers;
}
if ( nCountEnvironmentVariables == 3 )
{
// all three environment variables where set, so we don't need the physical file
return true;
}
return bLoadedRegistry;
}

View File

@ -1,45 +1,45 @@
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
#include <vector>
#include <stdint.h>
static const char *k_pchRuntimeOverrideVar = "VR_OVERRIDE";
static const char *k_pchConfigOverrideVar = "VR_CONFIG_PATH";
static const char *k_pchLogOverrideVar = "VR_LOG_PATH";
class CVRPathRegistry_Public
{
public:
static std::string GetVRPathRegistryFilename();
static std::string GetOpenVRConfigPath();
public:
CVRPathRegistry_Public();
/** Returns paths using the path registry and the provided override values. Pass NULL for any paths you don't care about.
* Returns false if the path registry could not be read. Valid paths might still be returned based on environment variables. */
static bool GetPaths( std::string *psRuntimePath, std::string *psConfigPath, std::string *psLogPath, const char *pchConfigPathOverride, const char *pchLogPathOverride, std::vector<std::string> *pvecExternalDrivers = NULL );
bool BLoadFromFile();
bool BSaveToFile() const;
bool ToJsonString( std::string &sJsonString );
// methods to get the current values
std::string GetRuntimePath() const;
std::string GetConfigPath() const;
std::string GetLogPath() const;
protected:
typedef std::vector< std::string > StringVector_t;
// index 0 is the current setting
StringVector_t m_vecRuntimePath;
StringVector_t m_vecLogPath;
StringVector_t m_vecConfigPath;
// full list of external drivers
StringVector_t m_vecExternalDrivers;
};
//========= Copyright Valve Corporation ============//
#pragma once
#include <string>
#include <vector>
#include <stdint.h>
static const char *k_pchRuntimeOverrideVar = "VR_OVERRIDE";
static const char *k_pchConfigOverrideVar = "VR_CONFIG_PATH";
static const char *k_pchLogOverrideVar = "VR_LOG_PATH";
class CVRPathRegistry_Public
{
public:
static std::string GetVRPathRegistryFilename();
static std::string GetOpenVRConfigPath();
public:
CVRPathRegistry_Public();
/** Returns paths using the path registry and the provided override values. Pass NULL for any paths you don't care about.
* Returns false if the path registry could not be read. Valid paths might still be returned based on environment variables. */
static bool GetPaths( std::string *psRuntimePath, std::string *psConfigPath, std::string *psLogPath, const char *pchConfigPathOverride, const char *pchLogPathOverride, std::vector<std::string> *pvecExternalDrivers = NULL );
bool BLoadFromFile();
bool BSaveToFile() const;
bool ToJsonString( std::string &sJsonString );
// methods to get the current values
std::string GetRuntimePath() const;
std::string GetConfigPath() const;
std::string GetLogPath() const;
protected:
typedef std::vector< std::string > StringVector_t;
// index 0 is the current setting
StringVector_t m_vecRuntimePath;
StringVector_t m_vecLogPath;
StringVector_t m_vecConfigPath;
// full list of external drivers
StringVector_t m_vecExternalDrivers;
};

View File

@ -1 +1 @@
3a4ce4b66a7bc9bd10773744d20530c609a61e90
4de718f9ea3435c099cabafc02e8b51da539bc62

View File

@ -1046,11 +1046,18 @@ impl<'a> From<DrawTarget<'a>> for ReadTarget<'a> {
impl Device {
pub fn new(
gl: Rc<gl::Gl>,
mut gl: Rc<gl::Gl>,
resource_override_path: Option<PathBuf>,
upload_method: UploadMethod,
cached_programs: Option<Rc<ProgramCache>>,
) -> Device {
// On debug builds, assert that each GL call is error-free. We don't do
// this on release builds because the synchronous call can stall the
// pipeline.
if cfg!(debug_assertions) {
gl = gl::ErrorCheckingGl::wrap(gl);
}
let mut max_texture_size = [0];
let mut max_texture_layers = [0];
unsafe {
@ -1151,11 +1158,6 @@ impl Device {
let supports_copy_image_sub_data = supports_extension(&extensions, "GL_EXT_copy_image") ||
supports_extension(&extensions, "GL_ARB_copy_image");
// Explicitly set some global states to the values we expect.
gl.disable(gl::FRAMEBUFFER_SRGB);
gl.disable(gl::MULTISAMPLE);
gl.disable(gl::POLYGON_SMOOTH);
Device {
gl,
resource_override_path,
@ -1289,20 +1291,10 @@ impl Device {
}
}
// If an assertion is hit in this function, something outside of WebRender is likely
// messing with the GL context's global state.
pub fn check_gl_state(&self) {
debug_assert!(self.gl.is_enabled(gl::FRAMEBUFFER_SRGB) == 0);
debug_assert!(self.gl.is_enabled(gl::MULTISAMPLE) == 0);
debug_assert!(self.gl.is_enabled(gl::POLYGON_SMOOTH) == 0);
}
pub fn begin_frame(&mut self) -> GpuFrameId {
debug_assert!(!self.inside_frame);
self.inside_frame = true;
self.check_gl_state();
// Retrieve the currently set FBO.
let mut default_read_fbo = [0];
unsafe {
@ -1435,8 +1427,15 @@ impl Device {
);
}
/// Creates an unbound FBO object. Additional attachment API calls are
/// required to make it complete.
pub fn create_fbo(&mut self) -> FBOId {
FBOId(self.gl.gen_framebuffers(1)[0])
}
/// Creates an FBO with the given texture bound as the color attachment.
pub fn create_fbo_for_external_texture(&mut self, texture_id: u32) -> FBOId {
let fbo = FBOId(self.gl.gen_framebuffers(1)[0]);
let fbo = self.create_fbo();
fbo.bind(self.gl(), FBOTarget::Draw);
self.gl.framebuffer_texture_2d(
gl::DRAW_FRAMEBUFFER,
@ -1445,6 +1444,11 @@ impl Device {
texture_id,
0,
);
debug_assert_eq!(
self.gl.check_frame_buffer_status(gl::DRAW_FRAMEBUFFER),
gl::FRAMEBUFFER_COMPLETE,
"Incomplete framebuffer",
);
self.bound_draw_fbo.bind(self.gl(), FBOTarget::Draw);
fbo
}
@ -1867,6 +1871,12 @@ impl Device {
depth_rb.0,
);
}
debug_assert_eq!(
self.gl.check_frame_buffer_status(gl::DRAW_FRAMEBUFFER),
gl::FRAMEBUFFER_COMPLETE,
"Incomplete framebuffer",
);
}
self.bind_external_draw_target(original_bound_fbo);
}
@ -2886,11 +2896,24 @@ impl<'a, T> Drop for TextureUploader<'a, T> {
impl<'a, T> TextureUploader<'a, T> {
pub fn upload(
&mut self,
rect: DeviceIntRect,
mut rect: DeviceIntRect,
layer_index: i32,
stride: Option<i32>,
data: &[T],
) -> usize {
// Textures dimensions may have been clamped by the hardware. Crop the
// upload region to match.
let cropped = rect.intersection(
&DeviceIntRect::new(DeviceIntPoint::zero(), self.target.texture.get_dimensions())
);
if cfg!(debug_assertions) && cropped.map_or(true, |r| r != rect) {
warn!("Cropping texture upload {:?} to {:?}", rect, cropped);
}
rect = match cropped {
None => return 0,
Some(r) => r,
};
let bytes_pp = self.target.texture.format.bytes_per_pixel();
let upload_size = match stride {
Some(stride) => ((rect.size.height - 1) * stride + rect.size.width * bytes_pp) as usize,

View File

@ -1969,7 +1969,7 @@ impl Renderer {
let ext_debug_marker = device.supports_extension("GL_EXT_debug_marker");
let gpu_profile = GpuProfiler::new(Rc::clone(device.rc_gl()), ext_debug_marker);
#[cfg(feature = "capture")]
let read_fbo = device.create_fbo_for_external_texture(0);
let read_fbo = device.create_fbo();
let mut renderer = Renderer {
result_rx,

View File

@ -10,7 +10,7 @@
#include "gfxColor.h"
extern "C" {
#include "jpeglib.h"
#include "jpeglib.h"
}
#include <setjmp.h>
@ -32,19 +32,18 @@ class nsJPEGEncoderInternal {
*/
static void initDestination(jpeg_compress_struct* cinfo);
/**
* This is called whenever the buffer has filled (free_in_buffer reaches
* zero). In typical applications, it should write out the *entire* buffer
* (use the saved start address and buffer length; ignore the current state
* of next_output_byte and free_in_buffer). Then reset the pointer & count
* to the start of the buffer, and return TRUE indicating that the buffer
* has been dumped. free_in_buffer must be set to a positive value when
* TRUE is returned. A FALSE return should only be used when I/O suspension
* is desired (this operating mode is discussed in the next section).
*/
/**
* This is called whenever the buffer has filled (free_in_buffer reaches
* zero). In typical applications, it should write out the *entire* buffer
* (use the saved start address and buffer length; ignore the current state
* of next_output_byte and free_in_buffer). Then reset the pointer & count
* to the start of the buffer, and return TRUE indicating that the buffer
* has been dumped. free_in_buffer must be set to a positive value when
* TRUE is returned. A FALSE return should only be used when I/O suspension
* is desired (this operating mode is discussed in the next section).
*/
static boolean emptyOutputBuffer(jpeg_compress_struct* cinfo);
/**
* Terminate destination --- called by jpeg_finish_compress() after all data
* has been written. In most applications, this must flush any data
@ -390,7 +389,6 @@ void nsJPEGEncoder::ConvertRGBARow(const uint8_t* aSrc, uint8_t* aDest,
}
}
void nsJPEGEncoder::NotifyListener() {
// We might call this function on multiple threads (any threads that call
// AsyncWait and any that do encoding) so we lock to avoid notifying the
@ -420,9 +418,8 @@ void nsJPEGEncoder::NotifyListener() {
}
}
/* static */ void
nsJPEGEncoderInternal::initDestination(jpeg_compress_struct* cinfo) {
/* static */ void nsJPEGEncoderInternal::initDestination(
jpeg_compress_struct* cinfo) {
nsJPEGEncoder* that = static_cast<nsJPEGEncoder*>(cinfo->client_data);
NS_ASSERTION(!that->mImageBuffer, "Image buffer already initialized");
@ -434,8 +431,8 @@ nsJPEGEncoderInternal::initDestination(jpeg_compress_struct* cinfo) {
cinfo->dest->free_in_buffer = that->mImageBufferSize;
}
/* static */ boolean
nsJPEGEncoderInternal::emptyOutputBuffer(jpeg_compress_struct* cinfo) {
/* static */ boolean nsJPEGEncoderInternal::emptyOutputBuffer(
jpeg_compress_struct* cinfo) {
nsJPEGEncoder* that = static_cast<nsJPEGEncoder*>(cinfo->client_data);
NS_ASSERTION(that->mImageBuffer, "No buffer to empty!");
@ -470,8 +467,8 @@ nsJPEGEncoderInternal::emptyOutputBuffer(jpeg_compress_struct* cinfo) {
return 1;
}
/* static */ void
nsJPEGEncoderInternal::termDestination(jpeg_compress_struct* cinfo) {
/* static */ void nsJPEGEncoderInternal::termDestination(
jpeg_compress_struct* cinfo) {
nsJPEGEncoder* that = static_cast<nsJPEGEncoder*>(cinfo->client_data);
if (!that->mImageBuffer) {
return;
@ -482,8 +479,7 @@ nsJPEGEncoderInternal::termDestination(jpeg_compress_struct* cinfo) {
that->NotifyListener();
}
/* static */ void
nsJPEGEncoderInternal::errorExit(jpeg_common_struct* cinfo) {
/* static */ void nsJPEGEncoderInternal::errorExit(jpeg_common_struct* cinfo) {
nsresult error_code;
encoder_error_mgr* err = (encoder_error_mgr*)cinfo->err;

342
js/public/Promise.h Normal file
View File

@ -0,0 +1,342 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_Promise_h
#define js_Promise_h
#include "jspubtd.h"
#include "js/RootingAPI.h"
#include "js/TypeDecls.h"
namespace JS {
typedef JSObject* (*GetIncumbentGlobalCallback)(JSContext* cx);
typedef bool (*EnqueuePromiseJobCallback)(JSContext* cx,
JS::HandleObject promise,
JS::HandleObject job,
JS::HandleObject allocationSite,
JS::HandleObject incumbentGlobal,
void* data);
enum class PromiseRejectionHandlingState { Unhandled, Handled };
typedef void (*PromiseRejectionTrackerCallback)(
JSContext* cx, JS::HandleObject promise,
JS::PromiseRejectionHandlingState state, void* data);
/**
* Sets the callback that's invoked whenever an incumbent global is required.
*
* SpiderMonkey doesn't itself have a notion of incumbent globals as defined
* by the html spec, so we need the embedding to provide this.
* See dom/base/ScriptSettings.h for details.
*/
extern JS_PUBLIC_API void SetGetIncumbentGlobalCallback(
JSContext* cx, GetIncumbentGlobalCallback callback);
/**
* Sets the callback that's invoked whenever a Promise job should be enqeued.
*
* SpiderMonkey doesn't schedule Promise resolution jobs itself; instead,
* using this function the embedding can provide a callback to do that
* scheduling. The provided `callback` is invoked with the promise job,
* the corresponding Promise's allocation stack, and the `data` pointer
* passed here as arguments.
*/
extern JS_PUBLIC_API void SetEnqueuePromiseJobCallback(
JSContext* cx, EnqueuePromiseJobCallback callback, void* data = nullptr);
/**
* Sets the callback that's invoked whenever a Promise is rejected without
* a rejection handler, and when a Promise that was previously rejected
* without a handler gets a handler attached.
*/
extern JS_PUBLIC_API void SetPromiseRejectionTrackerCallback(
JSContext* cx, PromiseRejectionTrackerCallback callback,
void* data = nullptr);
/**
* Inform the runtime that the job queue is empty and the embedding is going to
* execute its last promise job. The runtime may now choose to skip creating
* promise jobs for asynchronous execution and instead continue execution
* synchronously. More specifically, this optimization is used to skip the
* standard job queuing behavior for `await` operations in async functions.
*
* This function may be called before executing the last job in the job queue.
* When it was called, JobQueueMayNotBeEmpty must be called in order to restore
* the default job queuing behavior before the embedding enqueues its next job
* into the job queue.
*/
extern JS_PUBLIC_API void JobQueueIsEmpty(JSContext* cx);
/**
* Inform the runtime that job queue is no longer empty. The runtime can now no
* longer skip creating promise jobs for asynchronous execution, because
* pending jobs in the job queue must be executed first to preserve the FIFO
* (first in - first out) property of the queue. This effectively undoes
* JobQueueIsEmpty and re-enables the standard job queuing behavior.
*
* This function must be called whenever enqueuing a job to the job queue when
* JobQueueIsEmpty was called previously.
*/
extern JS_PUBLIC_API void JobQueueMayNotBeEmpty(JSContext* cx);
/**
* Returns a new instance of the Promise builtin class in the current
* compartment, with the right slot layout.
*
* The `executor` can be a `nullptr`. In that case, the only way to resolve or
* reject the returned promise is via the `JS::ResolvePromise` and
* `JS::RejectPromise` JSAPI functions.
*
* If a `proto` is passed, that gets set as the instance's [[Prototype]]
* instead of the original value of `Promise.prototype`.
*/
extern JS_PUBLIC_API JSObject* NewPromiseObject(
JSContext* cx, JS::HandleObject executor, JS::HandleObject proto = nullptr);
/**
* Returns true if the given object is an unwrapped PromiseObject, false
* otherwise.
*/
extern JS_PUBLIC_API bool IsPromiseObject(JS::HandleObject obj);
/**
* Returns the current compartment's original Promise constructor.
*/
extern JS_PUBLIC_API JSObject* GetPromiseConstructor(JSContext* cx);
/**
* Returns the current compartment's original Promise.prototype.
*/
extern JS_PUBLIC_API JSObject* GetPromisePrototype(JSContext* cx);
// Keep this in sync with the PROMISE_STATE defines in SelfHostingDefines.h.
enum class PromiseState { Pending, Fulfilled, Rejected };
/**
* Returns the given Promise's state as a JS::PromiseState enum value.
*
* Returns JS::PromiseState::Pending if the given object is a wrapper that
* can't safely be unwrapped.
*/
extern JS_PUBLIC_API PromiseState GetPromiseState(JS::HandleObject promise);
/**
* Returns the given Promise's process-unique ID.
*/
JS_PUBLIC_API uint64_t GetPromiseID(JS::HandleObject promise);
/**
* Returns the given Promise's result: either the resolution value for
* fulfilled promises, or the rejection reason for rejected ones.
*/
extern JS_PUBLIC_API JS::Value GetPromiseResult(JS::HandleObject promise);
/**
* Returns whether the given promise's rejection is already handled or not.
*
* The caller must check the given promise is rejected before checking it's
* handled or not.
*/
extern JS_PUBLIC_API bool GetPromiseIsHandled(JS::HandleObject promise);
/**
* Returns a js::SavedFrame linked list of the stack that lead to the given
* Promise's allocation.
*/
extern JS_PUBLIC_API JSObject* GetPromiseAllocationSite(
JS::HandleObject promise);
extern JS_PUBLIC_API JSObject* GetPromiseResolutionSite(
JS::HandleObject promise);
#ifdef DEBUG
extern JS_PUBLIC_API void DumpPromiseAllocationSite(JSContext* cx,
JS::HandleObject promise);
extern JS_PUBLIC_API void DumpPromiseResolutionSite(JSContext* cx,
JS::HandleObject promise);
#endif
/**
* Calls the current compartment's original Promise.resolve on the original
* Promise constructor, with `resolutionValue` passed as an argument.
*/
extern JS_PUBLIC_API JSObject* CallOriginalPromiseResolve(
JSContext* cx, JS::HandleValue resolutionValue);
/**
* Calls the current compartment's original Promise.reject on the original
* Promise constructor, with `resolutionValue` passed as an argument.
*/
extern JS_PUBLIC_API JSObject* CallOriginalPromiseReject(
JSContext* cx, JS::HandleValue rejectionValue);
/**
* Resolves the given Promise with the given `resolutionValue`.
*
* Calls the `resolve` function that was passed to the executor function when
* the Promise was created.
*/
extern JS_PUBLIC_API bool ResolvePromise(JSContext* cx,
JS::HandleObject promiseObj,
JS::HandleValue resolutionValue);
/**
* Rejects the given `promise` with the given `rejectionValue`.
*
* Calls the `reject` function that was passed to the executor function when
* the Promise was created.
*/
extern JS_PUBLIC_API bool RejectPromise(JSContext* cx,
JS::HandleObject promiseObj,
JS::HandleValue rejectionValue);
/**
* Calls the current compartment's original Promise.prototype.then on the
* given `promise`, with `onResolve` and `onReject` passed as arguments.
*
* Throws a TypeError if `promise` isn't a Promise (or possibly a different
* error if it's a security wrapper or dead object proxy).
*
* Asserts that `onFulfilled` and `onRejected` are each either callable or
* null.
*/
extern JS_PUBLIC_API JSObject* CallOriginalPromiseThen(
JSContext* cx, JS::HandleObject promise, JS::HandleObject onFulfilled,
JS::HandleObject onRejected);
/**
* Unforgeable, optimized version of the JS builtin Promise.prototype.then.
*
* Takes a Promise instance and `onResolve`, `onReject` callables to enqueue
* as reactions for that promise. In difference to Promise.prototype.then,
* this doesn't create and return a new Promise instance.
*
* Throws a TypeError if `promise` isn't a Promise (or possibly a different
* error if it's a security wrapper or dead object proxy).
*
* Asserts that `onFulfilled` and `onRejected` are each either callable or
* null.
*/
extern JS_PUBLIC_API bool AddPromiseReactions(JSContext* cx,
JS::HandleObject promise,
JS::HandleObject onFulfilled,
JS::HandleObject onRejected);
// This enum specifies whether a promise is expected to keep track of
// information that is useful for embedders to implement user activation
// behavior handling as specified in the HTML spec:
// https://html.spec.whatwg.org/multipage/interaction.html#triggered-by-user-activation
// By default, promises created by SpiderMonkey do not make any attempt to keep
// track of information about whether an activation behavior was being processed
// when the original promise in a promise chain was created. If the embedder
// sets either of the HadUserInteractionAtCreation or
// DidntHaveUserInteractionAtCreation flags on a promise after creating it,
// SpiderMonkey will propagate that flag to newly created promises when
// processing Promise#then and will make it possible to query this flag off of a
// promise further down the chain later using the
// GetPromiseUserInputEventHandlingState() API.
enum class PromiseUserInputEventHandlingState {
// Don't keep track of this state (default for all promises)
DontCare,
// Keep track of this state, the original promise in the chain was created
// while an activation behavior was being processed.
HadUserInteractionAtCreation,
// Keep track of this state, the original promise in the chain was created
// while an activation behavior was not being processed.
DidntHaveUserInteractionAtCreation
};
/**
* Returns the given Promise's activation behavior state flag per above as a
* JS::PromiseUserInputEventHandlingState value. All promises are created with
* the DontCare state by default.
*
* Returns JS::PromiseUserInputEventHandlingState::DontCare if the given object
* is a wrapper that can't safely be unwrapped.
*/
extern JS_PUBLIC_API PromiseUserInputEventHandlingState
GetPromiseUserInputEventHandlingState(JS::HandleObject promise);
/**
* Sets the given Promise's activation behavior state flag per above as a
* JS::PromiseUserInputEventHandlingState value.
*
* Returns false if the given object is a wrapper that can't safely be
* unwrapped.
*/
extern JS_PUBLIC_API bool SetPromiseUserInputEventHandlingState(
JS::HandleObject promise, JS::PromiseUserInputEventHandlingState state);
/**
* Unforgeable version of the JS builtin Promise.all.
*
* Takes an AutoObjectVector of Promise objects and returns a promise that's
* resolved with an array of resolution values when all those promises have
* been resolved, or rejected with the rejection value of the first rejected
* promise.
*
* Asserts that all objects in the `promises` vector are, maybe wrapped,
* instances of `Promise` or a subclass of `Promise`.
*/
extern JS_PUBLIC_API JSObject* GetWaitForAllPromise(
JSContext* cx, const JS::AutoObjectVector& promises);
/**
* The Dispatchable interface allows the embedding to call SpiderMonkey
* on a JSContext thread when requested via DispatchToEventLoopCallback.
*/
class JS_PUBLIC_API Dispatchable {
protected:
// Dispatchables are created and destroyed by SpiderMonkey.
Dispatchable() = default;
virtual ~Dispatchable() = default;
public:
// ShuttingDown indicates that SpiderMonkey should abort async tasks to
// expedite shutdown.
enum MaybeShuttingDown { NotShuttingDown, ShuttingDown };
// Called by the embedding after DispatchToEventLoopCallback succeeds.
virtual void run(JSContext* cx, MaybeShuttingDown maybeShuttingDown) = 0;
};
/**
* DispatchToEventLoopCallback may be called from any thread, being passed the
* same 'closure' passed to InitDispatchToEventLoop() and Dispatchable from the
* same JSRuntime. If the embedding returns 'true', the embedding must call
* Dispatchable::run() on an active JSContext thread for the same JSRuntime on
* which 'closure' was registered. If DispatchToEventLoopCallback returns
* 'false', SpiderMonkey will assume a shutdown of the JSRuntime is in progress.
* This contract implies that, by the time the final JSContext is destroyed in
* the JSRuntime, the embedding must have (1) run all Dispatchables for which
* DispatchToEventLoopCallback returned true, (2) already started returning
* false from calls to DispatchToEventLoopCallback.
*/
typedef bool (*DispatchToEventLoopCallback)(void* closure,
Dispatchable* dispatchable);
extern JS_PUBLIC_API void InitDispatchToEventLoop(
JSContext* cx, DispatchToEventLoopCallback callback, void* closure);
/**
* When a JSRuntime is destroyed it implicitly cancels all async tasks in
* progress, releasing any roots held by the task. However, this is not soon
* enough for cycle collection, which needs to have roots dropped earlier so
* that the cycle collector can transitively remove roots for a future GC. For
* these and other cases, the set of pending async tasks can be canceled
* with this call earlier than JSRuntime destruction.
*/
extern JS_PUBLIC_API void ShutdownAsyncTasks(JSContext* cx);
} // namespace JS
#endif // js_Promise_h

View File

@ -1249,13 +1249,13 @@ bool ModuleBuilder::initModule() {
bool ModuleBuilder::processImport(frontend::BinaryNode* importNode) {
using namespace js::frontend;
MOZ_ASSERT(importNode->isKind(ParseNodeKind::Import));
MOZ_ASSERT(importNode->isKind(ParseNodeKind::ImportDecl));
ListNode* specList = &importNode->left()->as<ListNode>();
MOZ_ASSERT(specList->isKind(ParseNodeKind::ImportSpecList));
NameNode* moduleSpec = &importNode->right()->as<NameNode>();
MOZ_ASSERT(moduleSpec->isKind(ParseNodeKind::String));
MOZ_ASSERT(moduleSpec->isKind(ParseNodeKind::StringExpr));
RootedAtom module(cx_, moduleSpec->atom());
if (!maybeAppendRequestedModule(module, moduleSpec)) {
@ -1300,10 +1300,10 @@ bool ModuleBuilder::appendImportEntryObject(
bool ModuleBuilder::processExport(frontend::ParseNode* exportNode) {
using namespace js::frontend;
MOZ_ASSERT(exportNode->isKind(ParseNodeKind::Export) ||
exportNode->isKind(ParseNodeKind::ExportDefault));
MOZ_ASSERT(exportNode->isKind(ParseNodeKind::ExportStmt) ||
exportNode->isKind(ParseNodeKind::ExportDefaultStmt));
bool isDefault = exportNode->isKind(ParseNodeKind::ExportDefault);
bool isDefault = exportNode->isKind(ParseNodeKind::ExportDefaultStmt);
ParseNode* kid = isDefault ? exportNode->as<BinaryNode>().left()
: exportNode->as<UnaryNode>().kid();
@ -1334,7 +1334,7 @@ bool ModuleBuilder::processExport(frontend::ParseNode* exportNode) {
break;
}
case ParseNodeKind::Class: {
case ParseNodeKind::ClassDecl: {
const ClassNode& cls = kid->as<ClassNode>();
MOZ_ASSERT(cls.names());
RootedAtom localName(cx_, cls.names()->innerBinding()->atom());
@ -1346,13 +1346,13 @@ bool ModuleBuilder::processExport(frontend::ParseNode* exportNode) {
break;
}
case ParseNodeKind::Var:
case ParseNodeKind::Const:
case ParseNodeKind::Let: {
case ParseNodeKind::VarStmt:
case ParseNodeKind::ConstDecl:
case ParseNodeKind::LetDecl: {
RootedAtom localName(cx_);
RootedAtom exportName(cx_);
for (ParseNode* binding : kid->as<ListNode>().contents()) {
if (binding->isKind(ParseNodeKind::Assign)) {
if (binding->isKind(ParseNodeKind::AssignExpr)) {
binding = binding->as<AssignmentNode>().left();
} else {
MOZ_ASSERT(binding->isKind(ParseNodeKind::Name));
@ -1364,12 +1364,12 @@ bool ModuleBuilder::processExport(frontend::ParseNode* exportNode) {
if (!appendExportEntry(exportName, localName)) {
return false;
}
} else if (binding->isKind(ParseNodeKind::Array)) {
} else if (binding->isKind(ParseNodeKind::ArrayExpr)) {
if (!processExportArrayBinding(&binding->as<ListNode>())) {
return false;
}
} else {
MOZ_ASSERT(binding->isKind(ParseNodeKind::Object));
MOZ_ASSERT(binding->isKind(ParseNodeKind::ObjectExpr));
if (!processExportObjectBinding(&binding->as<ListNode>())) {
return false;
}
@ -1406,18 +1406,18 @@ bool ModuleBuilder::processExportBinding(frontend::ParseNode* binding) {
return appendExportEntry(name, name);
}
if (binding->isKind(ParseNodeKind::Array)) {
if (binding->isKind(ParseNodeKind::ArrayExpr)) {
return processExportArrayBinding(&binding->as<ListNode>());
}
MOZ_ASSERT(binding->isKind(ParseNodeKind::Object));
MOZ_ASSERT(binding->isKind(ParseNodeKind::ObjectExpr));
return processExportObjectBinding(&binding->as<ListNode>());
}
bool ModuleBuilder::processExportArrayBinding(frontend::ListNode* array) {
using namespace js::frontend;
MOZ_ASSERT(array->isKind(ParseNodeKind::Array));
MOZ_ASSERT(array->isKind(ParseNodeKind::ArrayExpr));
for (ParseNode* node : array->contents()) {
if (node->isKind(ParseNodeKind::Elision)) {
@ -1426,7 +1426,7 @@ bool ModuleBuilder::processExportArrayBinding(frontend::ListNode* array) {
if (node->isKind(ParseNodeKind::Spread)) {
node = node->as<UnaryNode>().kid();
} else if (node->isKind(ParseNodeKind::Assign)) {
} else if (node->isKind(ParseNodeKind::AssignExpr)) {
node = node->as<AssignmentNode>().left();
}
@ -1441,7 +1441,7 @@ bool ModuleBuilder::processExportArrayBinding(frontend::ListNode* array) {
bool ModuleBuilder::processExportObjectBinding(frontend::ListNode* obj) {
using namespace js::frontend;
MOZ_ASSERT(obj->isKind(ParseNodeKind::Object));
MOZ_ASSERT(obj->isKind(ParseNodeKind::ObjectExpr));
for (ParseNode* node : obj->contents()) {
MOZ_ASSERT(node->isKind(ParseNodeKind::MutateProto) ||
@ -1459,7 +1459,7 @@ bool ModuleBuilder::processExportObjectBinding(frontend::ListNode* obj) {
target = node->as<BinaryNode>().right();
}
if (target->isKind(ParseNodeKind::Assign)) {
if (target->isKind(ParseNodeKind::AssignExpr)) {
target = target->as<AssignmentNode>().left();
}
}
@ -1475,13 +1475,13 @@ bool ModuleBuilder::processExportObjectBinding(frontend::ListNode* obj) {
bool ModuleBuilder::processExportFrom(frontend::BinaryNode* exportNode) {
using namespace js::frontend;
MOZ_ASSERT(exportNode->isKind(ParseNodeKind::ExportFrom));
MOZ_ASSERT(exportNode->isKind(ParseNodeKind::ExportFromStmt));
ListNode* specList = &exportNode->left()->as<ListNode>();
MOZ_ASSERT(specList->isKind(ParseNodeKind::ExportSpecList));
NameNode* moduleSpec = &exportNode->right()->as<NameNode>();
MOZ_ASSERT(moduleSpec->isKind(ParseNodeKind::String));
MOZ_ASSERT(moduleSpec->isKind(ParseNodeKind::StringExpr));
RootedAtom module(cx_, moduleSpec->atom());
if (!maybeAppendRequestedModule(module, moduleSpec)) {
@ -1502,7 +1502,7 @@ bool ModuleBuilder::processExportFrom(frontend::BinaryNode* exportNode) {
return false;
}
} else {
MOZ_ASSERT(spec->isKind(ParseNodeKind::ExportBatchSpec));
MOZ_ASSERT(spec->isKind(ParseNodeKind::ExportBatchSpecStmt));
exportName = cx_->names().star;
if (!appendExportFromEntry(nullptr, module, exportName, spec)) {
return false;

View File

@ -7,6 +7,8 @@
#ifndef builtin_Promise_h
#define builtin_Promise_h
#include "js/Promise.h"
#include "builtin/SelfHostingDefines.h"
#include "threading/ConditionVariable.h"
#include "threading/Mutex.h"

View File

@ -1709,31 +1709,31 @@ class ASTSerializer {
AssignmentOperator ASTSerializer::aop(ParseNodeKind kind) {
switch (kind) {
case ParseNodeKind::Assign:
case ParseNodeKind::AssignExpr:
return AOP_ASSIGN;
case ParseNodeKind::AddAssign:
case ParseNodeKind::AddAssignExpr:
return AOP_PLUS;
case ParseNodeKind::SubAssign:
case ParseNodeKind::SubAssignExpr:
return AOP_MINUS;
case ParseNodeKind::MulAssign:
case ParseNodeKind::MulAssignExpr:
return AOP_STAR;
case ParseNodeKind::DivAssign:
case ParseNodeKind::DivAssignExpr:
return AOP_DIV;
case ParseNodeKind::ModAssign:
case ParseNodeKind::ModAssignExpr:
return AOP_MOD;
case ParseNodeKind::PowAssign:
case ParseNodeKind::PowAssignExpr:
return AOP_POW;
case ParseNodeKind::LshAssign:
case ParseNodeKind::LshAssignExpr:
return AOP_LSH;
case ParseNodeKind::RshAssign:
case ParseNodeKind::RshAssignExpr:
return AOP_RSH;
case ParseNodeKind::UrshAssign:
case ParseNodeKind::UrshAssignExpr:
return AOP_URSH;
case ParseNodeKind::BitOrAssign:
case ParseNodeKind::BitOrAssignExpr:
return AOP_BITOR;
case ParseNodeKind::BitXorAssign:
case ParseNodeKind::BitXorAssignExpr:
return AOP_BITXOR;
case ParseNodeKind::BitAndAssign:
case ParseNodeKind::BitAndAssignExpr:
return AOP_BITAND;
default:
return AOP_ERR;
@ -1750,17 +1750,17 @@ UnaryOperator ASTSerializer::unop(ParseNodeKind kind) {
}
switch (kind) {
case ParseNodeKind::Await:
case ParseNodeKind::AwaitExpr:
return UNOP_AWAIT;
case ParseNodeKind::Neg:
case ParseNodeKind::NegExpr:
return UNOP_NEG;
case ParseNodeKind::Pos:
case ParseNodeKind::PosExpr:
return UNOP_POS;
case ParseNodeKind::Not:
case ParseNodeKind::NotExpr:
return UNOP_NOT;
case ParseNodeKind::BitNot:
case ParseNodeKind::BitNotExpr:
return UNOP_BITNOT;
case ParseNodeKind::Void:
case ParseNodeKind::VoidExpr:
return UNOP_VOID;
default:
return UNOP_ERR;
@ -1769,51 +1769,51 @@ UnaryOperator ASTSerializer::unop(ParseNodeKind kind) {
BinaryOperator ASTSerializer::binop(ParseNodeKind kind) {
switch (kind) {
case ParseNodeKind::Lsh:
case ParseNodeKind::LshExpr:
return BINOP_LSH;
case ParseNodeKind::Rsh:
case ParseNodeKind::RshExpr:
return BINOP_RSH;
case ParseNodeKind::Ursh:
case ParseNodeKind::UrshExpr:
return BINOP_URSH;
case ParseNodeKind::Lt:
case ParseNodeKind::LtExpr:
return BINOP_LT;
case ParseNodeKind::Le:
case ParseNodeKind::LeExpr:
return BINOP_LE;
case ParseNodeKind::Gt:
case ParseNodeKind::GtExpr:
return BINOP_GT;
case ParseNodeKind::Ge:
case ParseNodeKind::GeExpr:
return BINOP_GE;
case ParseNodeKind::Eq:
case ParseNodeKind::EqExpr:
return BINOP_EQ;
case ParseNodeKind::Ne:
case ParseNodeKind::NeExpr:
return BINOP_NE;
case ParseNodeKind::StrictEq:
case ParseNodeKind::StrictEqExpr:
return BINOP_STRICTEQ;
case ParseNodeKind::StrictNe:
case ParseNodeKind::StrictNeExpr:
return BINOP_STRICTNE;
case ParseNodeKind::Add:
case ParseNodeKind::AddExpr:
return BINOP_ADD;
case ParseNodeKind::Sub:
case ParseNodeKind::SubExpr:
return BINOP_SUB;
case ParseNodeKind::Star:
case ParseNodeKind::MulExpr:
return BINOP_STAR;
case ParseNodeKind::Div:
case ParseNodeKind::DivExpr:
return BINOP_DIV;
case ParseNodeKind::Mod:
case ParseNodeKind::ModExpr:
return BINOP_MOD;
case ParseNodeKind::Pow:
case ParseNodeKind::PowExpr:
return BINOP_POW;
case ParseNodeKind::BitOr:
case ParseNodeKind::BitOrExpr:
return BINOP_BITOR;
case ParseNodeKind::BitXor:
case ParseNodeKind::BitXorExpr:
return BINOP_BITXOR;
case ParseNodeKind::BitAnd:
case ParseNodeKind::BitAndExpr:
return BINOP_BITAND;
case ParseNodeKind::In:
case ParseNodeKind::InExpr:
return BINOP_IN;
case ParseNodeKind::InstanceOf:
case ParseNodeKind::InstanceOfExpr:
return BINOP_INSTANCEOF;
case ParseNodeKind::Pipeline:
case ParseNodeKind::PipelineExpr:
return BINOP_PIPELINE;
default:
return BINOP_ERR;
@ -1886,36 +1886,39 @@ bool ASTSerializer::sourceElement(ParseNode* pn, MutableHandleValue dst) {
bool ASTSerializer::declaration(ParseNode* pn, MutableHandleValue dst) {
MOZ_ASSERT(pn->isKind(ParseNodeKind::Function) ||
pn->isKind(ParseNodeKind::Var) || pn->isKind(ParseNodeKind::Let) ||
pn->isKind(ParseNodeKind::Const));
pn->isKind(ParseNodeKind::VarStmt) ||
pn->isKind(ParseNodeKind::LetDecl) ||
pn->isKind(ParseNodeKind::ConstDecl));
switch (pn->getKind()) {
case ParseNodeKind::Function:
return function(&pn->as<CodeNode>(), AST_FUNC_DECL, dst);
case ParseNodeKind::Var:
case ParseNodeKind::VarStmt:
return variableDeclaration(&pn->as<ListNode>(), false, dst);
default:
MOZ_ASSERT(pn->isKind(ParseNodeKind::Let) ||
pn->isKind(ParseNodeKind::Const));
MOZ_ASSERT(pn->isKind(ParseNodeKind::LetDecl) ||
pn->isKind(ParseNodeKind::ConstDecl));
return variableDeclaration(&pn->as<ListNode>(), true, dst);
}
}
bool ASTSerializer::variableDeclaration(ListNode* declList, bool lexical,
MutableHandleValue dst) {
MOZ_ASSERT_IF(lexical, declList->isKind(ParseNodeKind::Let) ||
declList->isKind(ParseNodeKind::Const));
MOZ_ASSERT_IF(!lexical, declList->isKind(ParseNodeKind::Var));
MOZ_ASSERT_IF(lexical, declList->isKind(ParseNodeKind::LetDecl) ||
declList->isKind(ParseNodeKind::ConstDecl));
MOZ_ASSERT_IF(!lexical, declList->isKind(ParseNodeKind::VarStmt));
VarDeclKind kind = VARDECL_ERR;
// Treat both the toplevel const binding (secretly var-like) and the lexical
// const the same way
if (lexical) {
kind = declList->isKind(ParseNodeKind::Let) ? VARDECL_LET : VARDECL_CONST;
kind =
declList->isKind(ParseNodeKind::LetDecl) ? VARDECL_LET : VARDECL_CONST;
} else {
kind = declList->isKind(ParseNodeKind::Var) ? VARDECL_VAR : VARDECL_CONST;
kind =
declList->isKind(ParseNodeKind::VarStmt) ? VARDECL_VAR : VARDECL_CONST;
}
NodeVector dtors(cx);
@ -1940,7 +1943,7 @@ bool ASTSerializer::variableDeclarator(ParseNode* pn, MutableHandleValue dst) {
patternNode = pn;
initNode = pn->as<NameNode>().initializer();
MOZ_ASSERT_IF(initNode, pn->pn_pos.encloses(initNode->pn_pos));
} else if (pn->isKind(ParseNodeKind::Assign)) {
} else if (pn->isKind(ParseNodeKind::AssignExpr)) {
AssignmentNode* assignNode = &pn->as<AssignmentNode>();
patternNode = assignNode->left();
initNode = assignNode->right();
@ -1959,13 +1962,13 @@ bool ASTSerializer::variableDeclarator(ParseNode* pn, MutableHandleValue dst) {
bool ASTSerializer::importDeclaration(BinaryNode* importNode,
MutableHandleValue dst) {
MOZ_ASSERT(importNode->isKind(ParseNodeKind::Import));
MOZ_ASSERT(importNode->isKind(ParseNodeKind::ImportDecl));
ListNode* specList = &importNode->left()->as<ListNode>();
MOZ_ASSERT(specList->isKind(ParseNodeKind::ImportSpecList));
ParseNode* moduleSpecNode = importNode->right();
MOZ_ASSERT(moduleSpecNode->isKind(ParseNodeKind::String));
MOZ_ASSERT(moduleSpecNode->isKind(ParseNodeKind::StringExpr));
NodeVector elts(cx);
if (!elts.reserve(specList->count())) {
@ -2002,19 +2005,19 @@ bool ASTSerializer::importSpecifier(BinaryNode* importSpec,
bool ASTSerializer::exportDeclaration(ParseNode* exportNode,
MutableHandleValue dst) {
MOZ_ASSERT(exportNode->isKind(ParseNodeKind::Export) ||
exportNode->isKind(ParseNodeKind::ExportFrom) ||
exportNode->isKind(ParseNodeKind::ExportDefault));
MOZ_ASSERT_IF(exportNode->isKind(ParseNodeKind::Export),
MOZ_ASSERT(exportNode->isKind(ParseNodeKind::ExportStmt) ||
exportNode->isKind(ParseNodeKind::ExportFromStmt) ||
exportNode->isKind(ParseNodeKind::ExportDefaultStmt));
MOZ_ASSERT_IF(exportNode->isKind(ParseNodeKind::ExportStmt),
exportNode->is<UnaryNode>());
MOZ_ASSERT_IF(
exportNode->isKind(ParseNodeKind::ExportFrom),
exportNode->as<BinaryNode>().right()->isKind(ParseNodeKind::String));
exportNode->isKind(ParseNodeKind::ExportFromStmt),
exportNode->as<BinaryNode>().right()->isKind(ParseNodeKind::StringExpr));
RootedValue decl(cx, NullValue());
NodeVector elts(cx);
ParseNode* kid = exportNode->isKind(ParseNodeKind::Export)
ParseNode* kid = exportNode->isKind(ParseNodeKind::ExportStmt)
? exportNode->as<UnaryNode>().kid()
: exportNode->as<BinaryNode>().left();
switch (ParseNodeKind kind = kid->getKind()) {
@ -2046,17 +2049,17 @@ bool ASTSerializer::exportDeclaration(ParseNode* exportNode,
}
break;
case ParseNodeKind::Class:
case ParseNodeKind::ClassDecl:
if (!classDefinition(&kid->as<ClassNode>(), false, &decl)) {
return false;
}
break;
case ParseNodeKind::Var:
case ParseNodeKind::Const:
case ParseNodeKind::Let:
if (!variableDeclaration(&kid->as<ListNode>(), kind != ParseNodeKind::Var,
&decl)) {
case ParseNodeKind::VarStmt:
case ParseNodeKind::ConstDecl:
case ParseNodeKind::LetDecl:
if (!variableDeclaration(&kid->as<ListNode>(),
kind != ParseNodeKind::VarStmt, &decl)) {
return false;
}
break;
@ -2069,14 +2072,14 @@ bool ASTSerializer::exportDeclaration(ParseNode* exportNode,
}
RootedValue moduleSpec(cx, NullValue());
if (exportNode->isKind(ParseNodeKind::ExportFrom)) {
if (exportNode->isKind(ParseNodeKind::ExportFromStmt)) {
if (!literal(exportNode->as<BinaryNode>().right(), &moduleSpec)) {
return false;
}
}
RootedValue isDefault(cx, BooleanValue(false));
if (exportNode->isKind(ParseNodeKind::ExportDefault)) {
if (exportNode->isKind(ParseNodeKind::ExportDefaultStmt)) {
isDefault.setBoolean(true);
}
@ -2196,9 +2199,9 @@ bool ASTSerializer::forInit(ParseNode* pn, MutableHandleValue dst) {
return true;
}
bool lexical =
pn->isKind(ParseNodeKind::Let) || pn->isKind(ParseNodeKind::Const);
return (lexical || pn->isKind(ParseNodeKind::Var))
bool lexical = pn->isKind(ParseNodeKind::LetDecl) ||
pn->isKind(ParseNodeKind::ConstDecl);
return (lexical || pn->isKind(ParseNodeKind::VarStmt))
? variableDeclaration(&pn->as<ListNode>(), lexical, dst)
: expression(pn, dst);
}
@ -2244,25 +2247,25 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
switch (pn->getKind()) {
case ParseNodeKind::Function:
case ParseNodeKind::Var:
case ParseNodeKind::VarStmt:
return declaration(pn, dst);
case ParseNodeKind::Let:
case ParseNodeKind::Const:
case ParseNodeKind::LetDecl:
case ParseNodeKind::ConstDecl:
return declaration(pn, dst);
case ParseNodeKind::Import:
case ParseNodeKind::ImportDecl:
return importDeclaration(&pn->as<BinaryNode>(), dst);
case ParseNodeKind::Export:
case ParseNodeKind::ExportDefault:
case ParseNodeKind::ExportFrom:
case ParseNodeKind::ExportStmt:
case ParseNodeKind::ExportDefaultStmt:
case ParseNodeKind::ExportFromStmt:
return exportDeclaration(pn, dst);
case ParseNodeKind::EmptyStatement:
case ParseNodeKind::EmptyStmt:
return builder.emptyStatement(&pn->pn_pos, dst);
case ParseNodeKind::ExpressionStatement: {
case ParseNodeKind::ExpressionStmt: {
RootedValue expr(cx);
return expression(pn->as<UnaryNode>().kid(), &expr) &&
builder.expressionStatement(expr, &pn->pn_pos, dst);
@ -2278,7 +2281,7 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
case ParseNodeKind::StatementList:
return blockStatement(&pn->as<ListNode>(), dst);
case ParseNodeKind::If: {
case ParseNodeKind::IfStmt: {
TernaryNode* ifNode = &pn->as<TernaryNode>();
ParseNode* testNode = ifNode->kid1();
@ -2297,14 +2300,14 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
builder.ifStatement(test, cons, alt, &ifNode->pn_pos, dst);
}
case ParseNodeKind::Switch:
case ParseNodeKind::SwitchStmt:
return switchStatement(&pn->as<SwitchStatement>(), dst);
case ParseNodeKind::Try:
case ParseNodeKind::TryStmt:
return tryStatement(&pn->as<TryNode>(), dst);
case ParseNodeKind::With:
case ParseNodeKind::While: {
case ParseNodeKind::WithStmt:
case ParseNodeKind::WhileStmt: {
BinaryNode* node = &pn->as<BinaryNode>();
ParseNode* exprNode = node->left();
@ -2316,12 +2319,12 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
RootedValue expr(cx), stmt(cx);
return expression(exprNode, &expr) && statement(stmtNode, &stmt) &&
(node->isKind(ParseNodeKind::With)
(node->isKind(ParseNodeKind::WithStmt)
? builder.withStatement(expr, stmt, &node->pn_pos, dst)
: builder.whileStatement(expr, stmt, &node->pn_pos, dst));
}
case ParseNodeKind::DoWhile: {
case ParseNodeKind::DoWhileStmt: {
BinaryNode* node = &pn->as<BinaryNode>();
ParseNode* stmtNode = node->left();
@ -2336,7 +2339,7 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
builder.doWhileStatement(stmt, test, &node->pn_pos, dst);
}
case ParseNodeKind::For: {
case ParseNodeKind::ForStmt: {
ForNode* forNode = &pn->as<ForNode>();
TernaryNode* head = forNode->head();
@ -2368,17 +2371,18 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
true, &var)) {
return false;
}
} else if (!initNode->isKind(ParseNodeKind::Var) &&
!initNode->isKind(ParseNodeKind::Let) &&
!initNode->isKind(ParseNodeKind::Const)) {
} else if (!initNode->isKind(ParseNodeKind::VarStmt) &&
!initNode->isKind(ParseNodeKind::LetDecl) &&
!initNode->isKind(ParseNodeKind::ConstDecl)) {
if (!pattern(initNode, &var)) {
return false;
}
} else {
if (!variableDeclaration(&initNode->as<ListNode>(),
initNode->isKind(ParseNodeKind::Let) ||
initNode->isKind(ParseNodeKind::Const),
&var)) {
if (!variableDeclaration(
&initNode->as<ListNode>(),
initNode->isKind(ParseNodeKind::LetDecl) ||
initNode->isKind(ParseNodeKind::ConstDecl),
&var)) {
return false;
}
}
@ -2396,18 +2400,18 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
dst);
}
case ParseNodeKind::Break:
case ParseNodeKind::Continue: {
case ParseNodeKind::BreakStmt:
case ParseNodeKind::ContinueStmt: {
LoopControlStatement* node = &pn->as<LoopControlStatement>();
RootedValue label(cx);
RootedAtom pnAtom(cx, node->label());
return optIdentifier(pnAtom, nullptr, &label) &&
(node->isKind(ParseNodeKind::Break)
(node->isKind(ParseNodeKind::BreakStmt)
? builder.breakStatement(label, &node->pn_pos, dst)
: builder.continueStatement(label, &node->pn_pos, dst));
}
case ParseNodeKind::Label: {
case ParseNodeKind::LabelStmt: {
LabeledStatement* labelNode = &pn->as<LabeledStatement>();
ParseNode* stmtNode = labelNode->statement();
MOZ_ASSERT(labelNode->pn_pos.encloses(stmtNode->pn_pos));
@ -2419,7 +2423,7 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
builder.labeledStatement(label, stmt, &labelNode->pn_pos, dst);
}
case ParseNodeKind::Throw: {
case ParseNodeKind::ThrowStmt: {
UnaryNode* throwNode = &pn->as<UnaryNode>();
ParseNode* operand = throwNode->kid();
MOZ_ASSERT(throwNode->pn_pos.encloses(operand->pn_pos));
@ -2430,7 +2434,7 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
builder.throwStatement(arg, &throwNode->pn_pos, dst);
}
case ParseNodeKind::Return: {
case ParseNodeKind::ReturnStmt: {
UnaryNode* returnNode = &pn->as<UnaryNode>();
ParseNode* operand = returnNode->kid();
MOZ_ASSERT_IF(operand, returnNode->pn_pos.encloses(operand->pn_pos));
@ -2441,10 +2445,10 @@ bool ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst) {
builder.returnStatement(arg, &returnNode->pn_pos, dst);
}
case ParseNodeKind::Debugger:
case ParseNodeKind::DebuggerStmt:
return builder.debuggerStatement(&pn->pn_pos, dst);
case ParseNodeKind::Class:
case ParseNodeKind::ClassDecl:
return classDefinition(&pn->as<ClassNode>(), false, dst);
case ParseNodeKind::ClassMemberList: {
@ -2510,8 +2514,8 @@ bool ASTSerializer::leftAssociate(ListNode* node, MutableHandleValue dst) {
MOZ_ASSERT(!node->empty());
ParseNodeKind kind = node->getKind();
bool lor = kind == ParseNodeKind::Or;
bool logop = lor || (kind == ParseNodeKind::And);
bool lor = kind == ParseNodeKind::OrExpr;
bool logop = lor || (kind == ParseNodeKind::AndExpr);
ParseNode* head = node->head();
RootedValue left(cx);
@ -2601,13 +2605,13 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
return function(funNode, type, dst);
}
case ParseNodeKind::Comma: {
case ParseNodeKind::CommaExpr: {
NodeVector exprs(cx);
return expressions(&pn->as<ListNode>(), exprs) &&
builder.sequenceExpression(exprs, &pn->pn_pos, dst);
}
case ParseNodeKind::Conditional: {
case ParseNodeKind::ConditionalExpr: {
ConditionalExpression* condNode = &pn->as<ConditionalExpression>();
ParseNode* testNode = condNode->kid1();
ParseNode* consNode = condNode->kid2();
@ -2624,47 +2628,47 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
dst);
}
case ParseNodeKind::Or:
case ParseNodeKind::And:
case ParseNodeKind::OrExpr:
case ParseNodeKind::AndExpr:
return leftAssociate(&pn->as<ListNode>(), dst);
case ParseNodeKind::PreIncrement:
case ParseNodeKind::PreDecrement: {
case ParseNodeKind::PreIncrementExpr:
case ParseNodeKind::PreDecrementExpr: {
UnaryNode* incDec = &pn->as<UnaryNode>();
ParseNode* operand = incDec->kid();
MOZ_ASSERT(incDec->pn_pos.encloses(operand->pn_pos));
bool inc = incDec->isKind(ParseNodeKind::PreIncrement);
bool inc = incDec->isKind(ParseNodeKind::PreIncrementExpr);
RootedValue expr(cx);
return expression(operand, &expr) &&
builder.updateExpression(expr, inc, true, &incDec->pn_pos, dst);
}
case ParseNodeKind::PostIncrement:
case ParseNodeKind::PostDecrement: {
case ParseNodeKind::PostIncrementExpr:
case ParseNodeKind::PostDecrementExpr: {
UnaryNode* incDec = &pn->as<UnaryNode>();
ParseNode* operand = incDec->kid();
MOZ_ASSERT(incDec->pn_pos.encloses(operand->pn_pos));
bool inc = incDec->isKind(ParseNodeKind::PostIncrement);
bool inc = incDec->isKind(ParseNodeKind::PostIncrementExpr);
RootedValue expr(cx);
return expression(operand, &expr) &&
builder.updateExpression(expr, inc, false, &incDec->pn_pos, dst);
}
case ParseNodeKind::Assign:
case ParseNodeKind::AddAssign:
case ParseNodeKind::SubAssign:
case ParseNodeKind::BitOrAssign:
case ParseNodeKind::BitXorAssign:
case ParseNodeKind::BitAndAssign:
case ParseNodeKind::LshAssign:
case ParseNodeKind::RshAssign:
case ParseNodeKind::UrshAssign:
case ParseNodeKind::MulAssign:
case ParseNodeKind::DivAssign:
case ParseNodeKind::ModAssign:
case ParseNodeKind::PowAssign: {
case ParseNodeKind::AssignExpr:
case ParseNodeKind::AddAssignExpr:
case ParseNodeKind::SubAssignExpr:
case ParseNodeKind::BitOrAssignExpr:
case ParseNodeKind::BitXorAssignExpr:
case ParseNodeKind::BitAndAssignExpr:
case ParseNodeKind::LshAssignExpr:
case ParseNodeKind::RshAssignExpr:
case ParseNodeKind::UrshAssignExpr:
case ParseNodeKind::MulAssignExpr:
case ParseNodeKind::DivAssignExpr:
case ParseNodeKind::ModAssignExpr:
case ParseNodeKind::PowAssignExpr: {
AssignmentNode* assignNode = &pn->as<AssignmentNode>();
ParseNode* lhsNode = assignNode->left();
ParseNode* rhsNode = assignNode->right();
@ -2680,45 +2684,45 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
dst);
}
case ParseNodeKind::Pipeline:
case ParseNodeKind::Add:
case ParseNodeKind::Sub:
case ParseNodeKind::StrictEq:
case ParseNodeKind::Eq:
case ParseNodeKind::StrictNe:
case ParseNodeKind::Ne:
case ParseNodeKind::Lt:
case ParseNodeKind::Le:
case ParseNodeKind::Gt:
case ParseNodeKind::Ge:
case ParseNodeKind::Lsh:
case ParseNodeKind::Rsh:
case ParseNodeKind::Ursh:
case ParseNodeKind::Star:
case ParseNodeKind::Div:
case ParseNodeKind::Mod:
case ParseNodeKind::BitOr:
case ParseNodeKind::BitXor:
case ParseNodeKind::BitAnd:
case ParseNodeKind::In:
case ParseNodeKind::InstanceOf:
case ParseNodeKind::PipelineExpr:
case ParseNodeKind::AddExpr:
case ParseNodeKind::SubExpr:
case ParseNodeKind::StrictEqExpr:
case ParseNodeKind::EqExpr:
case ParseNodeKind::StrictNeExpr:
case ParseNodeKind::NeExpr:
case ParseNodeKind::LtExpr:
case ParseNodeKind::LeExpr:
case ParseNodeKind::GtExpr:
case ParseNodeKind::GeExpr:
case ParseNodeKind::LshExpr:
case ParseNodeKind::RshExpr:
case ParseNodeKind::UrshExpr:
case ParseNodeKind::MulExpr:
case ParseNodeKind::DivExpr:
case ParseNodeKind::ModExpr:
case ParseNodeKind::BitOrExpr:
case ParseNodeKind::BitXorExpr:
case ParseNodeKind::BitAndExpr:
case ParseNodeKind::InExpr:
case ParseNodeKind::InstanceOfExpr:
return leftAssociate(&pn->as<ListNode>(), dst);
case ParseNodeKind::Pow:
case ParseNodeKind::PowExpr:
return rightAssociate(&pn->as<ListNode>(), dst);
case ParseNodeKind::DeleteName:
case ParseNodeKind::DeleteProp:
case ParseNodeKind::DeleteElem:
case ParseNodeKind::DeleteNameExpr:
case ParseNodeKind::DeletePropExpr:
case ParseNodeKind::DeleteElemExpr:
case ParseNodeKind::DeleteExpr:
case ParseNodeKind::TypeOfName:
case ParseNodeKind::TypeOfNameExpr:
case ParseNodeKind::TypeOfExpr:
case ParseNodeKind::Void:
case ParseNodeKind::Not:
case ParseNodeKind::BitNot:
case ParseNodeKind::Pos:
case ParseNodeKind::Await:
case ParseNodeKind::Neg: {
case ParseNodeKind::VoidExpr:
case ParseNodeKind::NotExpr:
case ParseNodeKind::BitNotExpr:
case ParseNodeKind::PosExpr:
case ParseNodeKind::AwaitExpr:
case ParseNodeKind::NegExpr: {
UnaryNode* unaryNode = &pn->as<UnaryNode>();
ParseNode* operand = unaryNode->kid();
MOZ_ASSERT(unaryNode->pn_pos.encloses(operand->pn_pos));
@ -2731,17 +2735,17 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
builder.unaryExpression(op, expr, &unaryNode->pn_pos, dst);
}
case ParseNodeKind::New:
case ParseNodeKind::TaggedTemplate:
case ParseNodeKind::Call:
case ParseNodeKind::SuperCall: {
case ParseNodeKind::NewExpr:
case ParseNodeKind::TaggedTemplateExpr:
case ParseNodeKind::CallExpr:
case ParseNodeKind::SuperCallExpr: {
BinaryNode* node = &pn->as<BinaryNode>();
ParseNode* calleeNode = node->left();
ListNode* argsList = &node->right()->as<ListNode>();
MOZ_ASSERT(node->pn_pos.encloses(calleeNode->pn_pos));
RootedValue callee(cx);
if (node->isKind(ParseNodeKind::SuperCall)) {
if (node->isKind(ParseNodeKind::SuperCallExpr)) {
MOZ_ASSERT(calleeNode->isKind(ParseNodeKind::SuperBase));
if (!builder.super(&calleeNode->pn_pos, &callee)) {
return false;
@ -2767,17 +2771,17 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
args.infallibleAppend(arg);
}
if (node->getKind() == ParseNodeKind::TaggedTemplate) {
if (node->getKind() == ParseNodeKind::TaggedTemplateExpr) {
return builder.taggedTemplate(callee, args, &node->pn_pos, dst);
}
// SUPERCALL is Call(super, args)
return node->isKind(ParseNodeKind::New)
return node->isKind(ParseNodeKind::NewExpr)
? builder.newExpression(callee, args, &node->pn_pos, dst)
: builder.callExpression(callee, args, &node->pn_pos, dst);
}
case ParseNodeKind::Dot: {
case ParseNodeKind::DotExpr: {
PropertyAccess* prop = &pn->as<PropertyAccess>();
// TODO(khyperia): Implement private field access.
MOZ_ASSERT(prop->pn_pos.encloses(prop->expression().pn_pos));
@ -2801,7 +2805,7 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
dst);
}
case ParseNodeKind::Elem: {
case ParseNodeKind::ElemExpr: {
PropertyByValue* elem = &pn->as<PropertyByValue>();
MOZ_ASSERT(elem->pn_pos.encloses(elem->expression().pn_pos));
MOZ_ASSERT(elem->pn_pos.encloses(elem->key().pn_pos));
@ -2822,7 +2826,7 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
builder.memberExpression(true, expr, key, &elem->pn_pos, dst);
}
case ParseNodeKind::CallSiteObj: {
case ParseNodeKind::CallSiteObjExpr: {
CallSiteNode* callSiteObj = &pn->as<CallSiteNode>();
ListNode* rawNodes = callSiteObj->rawNodes();
NodeVector raw(cx);
@ -2848,10 +2852,10 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
MOZ_ASSERT(callSiteObj->pn_pos.encloses(cookedItem->pn_pos));
RootedValue expr(cx);
if (cookedItem->isKind(ParseNodeKind::RawUndefined)) {
if (cookedItem->isKind(ParseNodeKind::RawUndefinedExpr)) {
expr.setUndefined();
} else {
MOZ_ASSERT(cookedItem->isKind(ParseNodeKind::TemplateString));
MOZ_ASSERT(cookedItem->isKind(ParseNodeKind::TemplateStringExpr));
expr.setString(cookedItem->as<NameNode>().atom());
}
cooked.infallibleAppend(expr);
@ -2860,7 +2864,7 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
return builder.callSiteObj(raw, cooked, &callSiteObj->pn_pos, dst);
}
case ParseNodeKind::Array: {
case ParseNodeKind::ArrayExpr: {
ListNode* array = &pn->as<ListNode>();
NodeVector elts(cx);
if (!elts.reserve(array->count())) {
@ -2896,7 +2900,7 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
builder.computedName(name, &pn->pn_pos, dst);
}
case ParseNodeKind::Object: {
case ParseNodeKind::ObjectExpr: {
ListNode* obj = &pn->as<ListNode>();
NodeVector elts(cx);
if (!elts.reserve(obj->count())) {
@ -2919,10 +2923,10 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
case ParseNodeKind::Name:
return identifier(&pn->as<NameNode>(), dst);
case ParseNodeKind::This:
case ParseNodeKind::ThisExpr:
return builder.thisExpression(&pn->pn_pos, dst);
case ParseNodeKind::TemplateStringList: {
case ParseNodeKind::TemplateStringListExpr: {
ListNode* list = &pn->as<ListNode>();
NodeVector elts(cx);
if (!elts.reserve(list->count())) {
@ -2942,20 +2946,20 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
return builder.templateLiteral(elts, &list->pn_pos, dst);
}
case ParseNodeKind::TemplateString:
case ParseNodeKind::String:
case ParseNodeKind::RegExp:
case ParseNodeKind::Number:
case ParseNodeKind::TemplateStringExpr:
case ParseNodeKind::StringExpr:
case ParseNodeKind::RegExpExpr:
case ParseNodeKind::NumberExpr:
#ifdef ENABLE_BIGINT
case ParseNodeKind::BigInt:
case ParseNodeKind::BigIntExpr:
#endif
case ParseNodeKind::True:
case ParseNodeKind::False:
case ParseNodeKind::Null:
case ParseNodeKind::RawUndefined:
case ParseNodeKind::TrueExpr:
case ParseNodeKind::FalseExpr:
case ParseNodeKind::NullExpr:
case ParseNodeKind::RawUndefinedExpr:
return literal(pn, dst);
case ParseNodeKind::YieldStar: {
case ParseNodeKind::YieldStarExpr: {
UnaryNode* yieldNode = &pn->as<UnaryNode>();
ParseNode* operand = yieldNode->kid();
MOZ_ASSERT(yieldNode->pn_pos.encloses(operand->pn_pos));
@ -2965,7 +2969,7 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
builder.yieldExpression(arg, Delegating, &yieldNode->pn_pos, dst);
}
case ParseNodeKind::Yield: {
case ParseNodeKind::YieldExpr: {
UnaryNode* yieldNode = &pn->as<UnaryNode>();
ParseNode* operand = yieldNode->kid();
MOZ_ASSERT_IF(operand, yieldNode->pn_pos.encloses(operand->pn_pos));
@ -2976,11 +2980,11 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
dst);
}
case ParseNodeKind::Class:
case ParseNodeKind::ClassDecl:
return classDefinition(&pn->as<ClassNode>(), true, dst);
case ParseNodeKind::NewTarget:
case ParseNodeKind::ImportMeta: {
case ParseNodeKind::NewTargetExpr:
case ParseNodeKind::ImportMetaExpr: {
BinaryNode* node = &pn->as<BinaryNode>();
ParseNode* firstNode = node->left();
MOZ_ASSERT(firstNode->isKind(ParseNodeKind::PosHolder));
@ -2996,7 +3000,7 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
RootedAtom firstStr(cx);
RootedAtom secondStr(cx);
if (node->getKind() == ParseNodeKind::NewTarget) {
if (node->getKind() == ParseNodeKind::NewTargetExpr) {
firstStr = cx->names().new_;
secondStr = cx->names().target;
} else {
@ -3009,7 +3013,7 @@ bool ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst) {
builder.metaProperty(firstIdent, secondIdent, &node->pn_pos, dst);
}
case ParseNodeKind::CallImport: {
case ParseNodeKind::CallImportExpr: {
BinaryNode* node = &pn->as<BinaryNode>();
ParseNode* identNode = node->left();
MOZ_ASSERT(identNode->isKind(ParseNodeKind::PosHolder));
@ -3048,8 +3052,8 @@ bool ASTSerializer::propertyName(ParseNode* key, MutableHandleValue dst) {
return identifier(&key->as<NameNode>(), dst);
}
LOCAL_ASSERT(key->isKind(ParseNodeKind::String) ||
key->isKind(ParseNodeKind::Number));
LOCAL_ASSERT(key->isKind(ParseNodeKind::StringExpr) ||
key->isKind(ParseNodeKind::NumberExpr));
return literal(key, dst);
}
@ -3099,12 +3103,12 @@ bool ASTSerializer::property(ParseNode* pn, MutableHandleValue dst) {
bool ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst) {
RootedValue val(cx);
switch (pn->getKind()) {
case ParseNodeKind::TemplateString:
case ParseNodeKind::String:
case ParseNodeKind::TemplateStringExpr:
case ParseNodeKind::StringExpr:
val.setString(pn->as<NameNode>().atom());
break;
case ParseNodeKind::RegExp: {
case ParseNodeKind::RegExpExpr: {
RootedObject re1(cx, pn->as<RegExpLiteral>().objbox()->object());
LOCAL_ASSERT(re1 && re1->is<RegExpObject>());
@ -3117,7 +3121,7 @@ bool ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst) {
break;
}
case ParseNodeKind::Number:
case ParseNodeKind::NumberExpr:
val.setNumber(pn->as<NumericLiteral>().value());
break;
@ -3130,19 +3134,19 @@ bool ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst) {
}
#endif
case ParseNodeKind::Null:
case ParseNodeKind::NullExpr:
val.setNull();
break;
case ParseNodeKind::RawUndefined:
case ParseNodeKind::RawUndefinedExpr:
val.setUndefined();
break;
case ParseNodeKind::True:
case ParseNodeKind::TrueExpr:
val.setBoolean(true);
break;
case ParseNodeKind::False:
case ParseNodeKind::FalseExpr:
val.setBoolean(false);
break;
@ -3154,7 +3158,7 @@ bool ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst) {
}
bool ASTSerializer::arrayPattern(ListNode* array, MutableHandleValue dst) {
MOZ_ASSERT(array->isKind(ParseNodeKind::Array));
MOZ_ASSERT(array->isKind(ParseNodeKind::ArrayExpr));
NodeVector elts(cx);
if (!elts.reserve(array->count())) {
@ -3186,7 +3190,7 @@ bool ASTSerializer::arrayPattern(ListNode* array, MutableHandleValue dst) {
}
bool ASTSerializer::objectPattern(ListNode* obj, MutableHandleValue dst) {
MOZ_ASSERT(obj->isKind(ParseNodeKind::Object));
MOZ_ASSERT(obj->isKind(ParseNodeKind::ObjectExpr));
NodeVector elts(cx);
if (!elts.reserve(obj->count())) {
@ -3244,10 +3248,10 @@ bool ASTSerializer::pattern(ParseNode* pn, MutableHandleValue dst) {
}
switch (pn->getKind()) {
case ParseNodeKind::Object:
case ParseNodeKind::ObjectExpr:
return objectPattern(&pn->as<ListNode>(), dst);
case ParseNodeKind::Array:
case ParseNodeKind::ArrayExpr:
return arrayPattern(&pn->as<ListNode>(), dst);
default:
@ -3323,7 +3327,8 @@ bool ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args,
/* Serialize the arguments and body. */
switch (bodyNode->getKind()) {
case ParseNodeKind::Return: /* expression closure, no destructured args */
case ParseNodeKind::ReturnStmt: /* expression closure, no destructured args
*/
return functionArgs(pn, argsList, args, defaults, rest) &&
expression(bodyNode->as<UnaryNode>().kid(), body);
@ -3339,7 +3344,7 @@ bool ASTSerializer::functionArgsAndBody(ParseNode* pn, NodeVector& args,
// Async arrow with expression body is converted into STATEMENTLIST
// to insert initial yield.
if (isAsync && isExpression) {
MOZ_ASSERT(firstNode->getKind() == ParseNodeKind::Return);
MOZ_ASSERT(firstNode->getKind() == ParseNodeKind::ReturnStmt);
return functionArgs(pn, argsList, args, defaults, rest) &&
expression(firstNode->as<UnaryNode>().kid(), body);
}
@ -3369,12 +3374,13 @@ bool ASTSerializer::functionArgs(ParseNode* pn, ListNode* argsList,
for (ParseNode* arg : argsList->contentsTo(argsList->last())) {
ParseNode* pat;
ParseNode* defNode;
if (arg->isKind(ParseNodeKind::Name) || arg->isKind(ParseNodeKind::Array) ||
arg->isKind(ParseNodeKind::Object)) {
if (arg->isKind(ParseNodeKind::Name) ||
arg->isKind(ParseNodeKind::ArrayExpr) ||
arg->isKind(ParseNodeKind::ObjectExpr)) {
pat = arg;
defNode = nullptr;
} else {
MOZ_ASSERT(arg->isKind(ParseNodeKind::Assign));
MOZ_ASSERT(arg->isKind(ParseNodeKind::AssignExpr));
AssignmentNode* assignNode = &arg->as<AssignmentNode>();
pat = assignNode->left();
defNode = assignNode->right();
@ -3382,8 +3388,8 @@ bool ASTSerializer::functionArgs(ParseNode* pn, ListNode* argsList,
// Process the name or pattern.
MOZ_ASSERT(pat->isKind(ParseNodeKind::Name) ||
pat->isKind(ParseNodeKind::Array) ||
pat->isKind(ParseNodeKind::Object));
pat->isKind(ParseNodeKind::ArrayExpr) ||
pat->isKind(ParseNodeKind::ObjectExpr));
if (!pattern(pat, &node)) {
return false;
}

View File

@ -1,7 +1,7 @@
// This file was autogenerated by binjs_generate_spidermonkey,
// please DO NOT EDIT BY HAND.
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -1764,8 +1764,8 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceAssignmentExpression(
BINJS_MOZ_TRY_DECL(expression, parseExpression());
BINJS_TRY_DECL(result, factory_.newAssignment(ParseNodeKind::Assign, binding,
expression));
BINJS_TRY_DECL(result, factory_.newAssignment(ParseNodeKind::AssignExpr,
binding, expression));
return result;
}
@ -1822,86 +1822,86 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBinaryExpression(
ParseNodeKind pnk;
switch (operator_) {
case BinaryOperator::Comma:
pnk = ParseNodeKind::Comma;
pnk = ParseNodeKind::CommaExpr;
break;
case BinaryOperator::LogicalOr:
pnk = ParseNodeKind::Or;
pnk = ParseNodeKind::OrExpr;
break;
case BinaryOperator::LogicalAnd:
pnk = ParseNodeKind::And;
pnk = ParseNodeKind::AndExpr;
break;
case BinaryOperator::BitOr:
pnk = ParseNodeKind::BitOr;
pnk = ParseNodeKind::BitOrExpr;
break;
case BinaryOperator::BitXor:
pnk = ParseNodeKind::BitXor;
pnk = ParseNodeKind::BitXorExpr;
break;
case BinaryOperator::BitAnd:
pnk = ParseNodeKind::BitAnd;
pnk = ParseNodeKind::BitAndExpr;
break;
case BinaryOperator::Eq:
pnk = ParseNodeKind::Eq;
pnk = ParseNodeKind::EqExpr;
break;
case BinaryOperator::Neq:
pnk = ParseNodeKind::Ne;
pnk = ParseNodeKind::NeExpr;
break;
case BinaryOperator::StrictEq:
pnk = ParseNodeKind::StrictEq;
pnk = ParseNodeKind::StrictEqExpr;
break;
case BinaryOperator::StrictNeq:
pnk = ParseNodeKind::StrictNe;
pnk = ParseNodeKind::StrictNeExpr;
break;
case BinaryOperator::LessThan:
pnk = ParseNodeKind::Lt;
pnk = ParseNodeKind::LtExpr;
break;
case BinaryOperator::LeqThan:
pnk = ParseNodeKind::Le;
pnk = ParseNodeKind::LeExpr;
break;
case BinaryOperator::GreaterThan:
pnk = ParseNodeKind::Gt;
pnk = ParseNodeKind::GtExpr;
break;
case BinaryOperator::GeqThan:
pnk = ParseNodeKind::Ge;
pnk = ParseNodeKind::GeExpr;
break;
case BinaryOperator::In:
pnk = ParseNodeKind::In;
pnk = ParseNodeKind::InExpr;
break;
case BinaryOperator::Instanceof:
pnk = ParseNodeKind::InstanceOf;
pnk = ParseNodeKind::InstanceOfExpr;
break;
case BinaryOperator::Lsh:
pnk = ParseNodeKind::Lsh;
pnk = ParseNodeKind::LshExpr;
break;
case BinaryOperator::Rsh:
pnk = ParseNodeKind::Rsh;
pnk = ParseNodeKind::RshExpr;
break;
case BinaryOperator::Ursh:
pnk = ParseNodeKind::Ursh;
pnk = ParseNodeKind::UrshExpr;
break;
case BinaryOperator::Plus:
pnk = ParseNodeKind::Add;
pnk = ParseNodeKind::AddExpr;
break;
case BinaryOperator::Minus:
pnk = ParseNodeKind::Sub;
pnk = ParseNodeKind::SubExpr;
break;
case BinaryOperator::Mul:
pnk = ParseNodeKind::Star;
pnk = ParseNodeKind::MulExpr;
break;
case BinaryOperator::Div:
pnk = ParseNodeKind::Div;
pnk = ParseNodeKind::DivExpr;
break;
case BinaryOperator::Mod:
pnk = ParseNodeKind::Mod;
pnk = ParseNodeKind::ModExpr;
break;
case BinaryOperator::Pow:
pnk = ParseNodeKind::Pow;
pnk = ParseNodeKind::PowExpr;
break;
}
ParseNode* result;
if (left->isKind(pnk) &&
pnk !=
ParseNodeKind::Pow /* ParseNodeKind::Pow is not left-associative */) {
pnk != ParseNodeKind::
PowExpr /* ParseNodeKind::PowExpr is not left-associative */) {
// Regroup left-associative operations into lists.
left->template as<ListNode>().appendWithoutOrderAssumption(right);
result = left;
@ -2188,40 +2188,40 @@ BinASTParser<Tok>::parseInterfaceCompoundAssignmentExpression(
ParseNodeKind pnk;
switch (operator_) {
case CompoundAssignmentOperator::PlusAssign:
pnk = ParseNodeKind::AddAssign;
pnk = ParseNodeKind::AddAssignExpr;
break;
case CompoundAssignmentOperator::MinusAssign:
pnk = ParseNodeKind::SubAssign;
pnk = ParseNodeKind::SubAssignExpr;
break;
case CompoundAssignmentOperator::MulAssign:
pnk = ParseNodeKind::MulAssign;
pnk = ParseNodeKind::MulAssignExpr;
break;
case CompoundAssignmentOperator::DivAssign:
pnk = ParseNodeKind::DivAssign;
pnk = ParseNodeKind::DivAssignExpr;
break;
case CompoundAssignmentOperator::ModAssign:
pnk = ParseNodeKind::ModAssign;
pnk = ParseNodeKind::ModAssignExpr;
break;
case CompoundAssignmentOperator::PowAssign:
pnk = ParseNodeKind::PowAssign;
pnk = ParseNodeKind::PowAssignExpr;
break;
case CompoundAssignmentOperator::LshAssign:
pnk = ParseNodeKind::LshAssign;
pnk = ParseNodeKind::LshAssignExpr;
break;
case CompoundAssignmentOperator::RshAssign:
pnk = ParseNodeKind::RshAssign;
pnk = ParseNodeKind::RshAssignExpr;
break;
case CompoundAssignmentOperator::UrshAssign:
pnk = ParseNodeKind::UrshAssign;
pnk = ParseNodeKind::UrshAssignExpr;
break;
case CompoundAssignmentOperator::BitOrAssign:
pnk = ParseNodeKind::BitOrAssign;
pnk = ParseNodeKind::BitOrAssignExpr;
break;
case CompoundAssignmentOperator::BitXorAssign:
pnk = ParseNodeKind::BitXorAssign;
pnk = ParseNodeKind::BitXorAssignExpr;
break;
case CompoundAssignmentOperator::BitAndAssign:
pnk = ParseNodeKind::BitAndAssign;
pnk = ParseNodeKind::BitAndAssignExpr;
break;
}
BINJS_TRY_DECL(result, factory_.newAssignment(pnk, binding, expression));
@ -2806,7 +2806,7 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceForInOfBinding(
ParseNodeKind pnk;
switch (kind_) {
case VariableDeclarationKind::Var:
pnk = ParseNodeKind::Var;
pnk = ParseNodeKind::VarStmt;
break;
case VariableDeclarationKind::Let:
return raiseError("Let is not supported in this preview release");
@ -4092,39 +4092,39 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceUnaryExpression(
ParseNodeKind pnk;
switch (operator_) {
case UnaryOperator::Minus:
pnk = ParseNodeKind::Neg;
pnk = ParseNodeKind::NegExpr;
break;
case UnaryOperator::Plus:
pnk = ParseNodeKind::Pos;
pnk = ParseNodeKind::PosExpr;
break;
case UnaryOperator::Not:
pnk = ParseNodeKind::Not;
pnk = ParseNodeKind::NotExpr;
break;
case UnaryOperator::BitNot:
pnk = ParseNodeKind::BitNot;
pnk = ParseNodeKind::BitNotExpr;
break;
case UnaryOperator::Typeof: {
if (operand->isKind(ParseNodeKind::Name)) {
pnk = ParseNodeKind::TypeOfName;
pnk = ParseNodeKind::TypeOfNameExpr;
} else {
pnk = ParseNodeKind::TypeOfExpr;
}
break;
}
case UnaryOperator::Void:
pnk = ParseNodeKind::Void;
pnk = ParseNodeKind::VoidExpr;
break;
case UnaryOperator::Delete: {
switch (operand->getKind()) {
case ParseNodeKind::Name:
operand->setOp(JSOP_DELNAME);
pnk = ParseNodeKind::DeleteName;
pnk = ParseNodeKind::DeleteNameExpr;
break;
case ParseNodeKind::Dot:
pnk = ParseNodeKind::DeleteProp;
case ParseNodeKind::DotExpr:
pnk = ParseNodeKind::DeletePropExpr;
break;
case ParseNodeKind::Elem:
pnk = ParseNodeKind::DeleteElem;
case ParseNodeKind::ElemExpr:
pnk = ParseNodeKind::DeleteElemExpr;
break;
default:
pnk = ParseNodeKind::DeleteExpr;
@ -4157,12 +4157,12 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceUpdateExpression(
ParseNodeKind pnk;
switch (operator_) {
case UpdateOperator::Incr:
pnk =
isPrefix ? ParseNodeKind::PreIncrement : ParseNodeKind::PostIncrement;
pnk = isPrefix ? ParseNodeKind::PreIncrementExpr
: ParseNodeKind::PostIncrementExpr;
break;
case UpdateOperator::Decr:
pnk =
isPrefix ? ParseNodeKind::PreDecrement : ParseNodeKind::PostDecrement;
pnk = isPrefix ? ParseNodeKind::PreDecrementExpr
: ParseNodeKind::PostDecrementExpr;
break;
}
BINJS_TRY_DECL(result, factory_.newUnary(pnk, start, operand));
@ -4194,7 +4194,7 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceVariableDeclaration(
ParseNodeKind pnk;
switch (kind_) {
case VariableDeclarationKind::Var:
pnk = ParseNodeKind::Var;
pnk = ParseNodeKind::VarStmt;
break;
case VariableDeclarationKind::Let:
return raiseError("Let is not supported in this preview release");
@ -4265,8 +4265,8 @@ JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceVariableDeclarator(
MOZ_CRASH(
"Unimplemented: AssertedScope check for BindingPattern variable "
"declaration");
BINJS_TRY_VAR(result,
factory_.newAssignment(ParseNodeKind::Assign, binding, init));
BINJS_TRY_VAR(result, factory_.newAssignment(ParseNodeKind::AssignExpr,
binding, init));
}
return result;
}
@ -4807,9 +4807,9 @@ JS::Result<ListNode*> BinASTParser<Tok>::parseListOfVariableDeclarator() {
const auto start = tokenizer_->offset();
MOZ_TRY(tokenizer_->enterList(length, guard));
BINJS_TRY_DECL(
result, factory_.newDeclarationList(ParseNodeKind::Const /*Placeholder*/,
tokenizer_->pos(start)));
BINJS_TRY_DECL(result, factory_.newDeclarationList(
ParseNodeKind::ConstDecl /*Placeholder*/,
tokenizer_->pos(start)));
for (uint32_t i = 0; i < length; ++i) {
BINJS_MOZ_TRY_DECL(item, parseVariableDeclarator());

View File

@ -1,7 +1,7 @@
// This file was autogenerated by binjs_generate_spidermonkey,
// please DO NOT EDIT BY HAND.
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

View File

@ -512,7 +512,7 @@ JS::Result<Ok> BinASTParserPerTokenizer<Tok>::checkPositionalParameterIndices(
uint32_t i = 0;
const bool hasRest = parseContext_->functionBox()->hasRest();
for (ParseNode* param : params->contents()) {
if (param->isKind(ParseNodeKind::Assign)) {
if (param->isKind(ParseNodeKind::AssignExpr)) {
param = param->as<AssignmentNode>().left();
}
@ -562,8 +562,8 @@ JS::Result<Ok> BinASTParserPerTokenizer<Tok>::checkPositionalParameterIndices(
} else {
// Destructuring parameter.
MOZ_ASSERT(param->isKind(ParseNodeKind::Object) ||
param->isKind(ParseNodeKind::Array));
MOZ_ASSERT(param->isKind(ParseNodeKind::ObjectExpr) ||
param->isKind(ParseNodeKind::ArrayExpr));
// Step 3.
if (i >= positionalParams.get().length()) {

View File

@ -350,7 +350,7 @@ hpp:
Arguments:
init:
BINJS_TRY_DECL(result, factory_.newList(ParseNodeKind::Arguments, tokenizer_->pos(start)));
BINJS_TRY_DECL(result, factory_.newList(ParseNodeKind::ArgumentsExpr, tokenizer_->pos(start)));
append:
factory_.addList(/* list = */ result, /* kid = */ item);
@ -485,7 +485,7 @@ AssertedVarScope:
AssignmentExpression:
build: |
BINJS_TRY_DECL(result, factory_.newAssignment(ParseNodeKind::Assign, binding, expression));
BINJS_TRY_DECL(result, factory_.newAssignment(ParseNodeKind::AssignExpr, binding, expression));
AssignmentTargetIdentifier:
build: |
@ -507,85 +507,85 @@ BinaryExpression:
ParseNodeKind pnk;
switch (operator_) {
case BinaryOperator::Comma:
pnk = ParseNodeKind::Comma;
pnk = ParseNodeKind::CommaExpr;
break;
case BinaryOperator::LogicalOr:
pnk = ParseNodeKind::Or;
pnk = ParseNodeKind::OrExpr;
break;
case BinaryOperator::LogicalAnd:
pnk = ParseNodeKind::And;
pnk = ParseNodeKind::AndExpr;
break;
case BinaryOperator::BitOr:
pnk = ParseNodeKind::BitOr;
pnk = ParseNodeKind::BitOrExpr;
break;
case BinaryOperator::BitXor:
pnk = ParseNodeKind::BitXor;
pnk = ParseNodeKind::BitXorExpr;
break;
case BinaryOperator::BitAnd:
pnk = ParseNodeKind::BitAnd;
pnk = ParseNodeKind::BitAndExpr;
break;
case BinaryOperator::Eq:
pnk = ParseNodeKind::Eq;
pnk = ParseNodeKind::EqExpr;
break;
case BinaryOperator::Neq:
pnk = ParseNodeKind::Ne;
pnk = ParseNodeKind::NeExpr;
break;
case BinaryOperator::StrictEq:
pnk = ParseNodeKind::StrictEq;
pnk = ParseNodeKind::StrictEqExpr;
break;
case BinaryOperator::StrictNeq:
pnk = ParseNodeKind::StrictNe;
pnk = ParseNodeKind::StrictNeExpr;
break;
case BinaryOperator::LessThan:
pnk = ParseNodeKind::Lt;
pnk = ParseNodeKind::LtExpr;
break;
case BinaryOperator::LeqThan:
pnk = ParseNodeKind::Le;
pnk = ParseNodeKind::LeExpr;
break;
case BinaryOperator::GreaterThan:
pnk = ParseNodeKind::Gt;
pnk = ParseNodeKind::GtExpr;
break;
case BinaryOperator::GeqThan:
pnk = ParseNodeKind::Ge;
pnk = ParseNodeKind::GeExpr;
break;
case BinaryOperator::In:
pnk = ParseNodeKind::In;
pnk = ParseNodeKind::InExpr;
break;
case BinaryOperator::Instanceof:
pnk = ParseNodeKind::InstanceOf;
pnk = ParseNodeKind::InstanceOfExpr;
break;
case BinaryOperator::Lsh:
pnk = ParseNodeKind::Lsh;
pnk = ParseNodeKind::LshExpr;
break;
case BinaryOperator::Rsh:
pnk = ParseNodeKind::Rsh;
pnk = ParseNodeKind::RshExpr;
break;
case BinaryOperator::Ursh:
pnk = ParseNodeKind::Ursh;
pnk = ParseNodeKind::UrshExpr;
break;
case BinaryOperator::Plus:
pnk = ParseNodeKind::Add;
pnk = ParseNodeKind::AddExpr;
break;
case BinaryOperator::Minus:
pnk = ParseNodeKind::Sub;
pnk = ParseNodeKind::SubExpr;
break;
case BinaryOperator::Mul:
pnk = ParseNodeKind::Star;
pnk = ParseNodeKind::MulExpr;
break;
case BinaryOperator::Div:
pnk = ParseNodeKind::Div;
pnk = ParseNodeKind::DivExpr;
break;
case BinaryOperator::Mod:
pnk = ParseNodeKind::Mod;
pnk = ParseNodeKind::ModExpr;
break;
case BinaryOperator::Pow:
pnk = ParseNodeKind::Pow;
pnk = ParseNodeKind::PowExpr;
break;
}
ParseNode* result;
if (left->isKind(pnk) &&
pnk != ParseNodeKind::Pow /* ParseNodeKind::Pow is not left-associative */)
pnk != ParseNodeKind::PowExpr /* ParseNodeKind::PowExpr is not left-associative */)
{
// Regroup left-associative operations into lists.
left->template as<ListNode>().appendWithoutOrderAssumption(right);
@ -686,40 +686,40 @@ CompoundAssignmentExpression:
ParseNodeKind pnk;
switch (operator_){
case CompoundAssignmentOperator::PlusAssign:
pnk = ParseNodeKind::AddAssign;
pnk = ParseNodeKind::AddAssignExpr;
break;
case CompoundAssignmentOperator::MinusAssign:
pnk = ParseNodeKind::SubAssign;
pnk = ParseNodeKind::SubAssignExpr;
break;
case CompoundAssignmentOperator::MulAssign:
pnk = ParseNodeKind::MulAssign;
pnk = ParseNodeKind::MulAssignExpr;
break;
case CompoundAssignmentOperator::DivAssign:
pnk = ParseNodeKind::DivAssign;
pnk = ParseNodeKind::DivAssignExpr;
break;
case CompoundAssignmentOperator::ModAssign:
pnk = ParseNodeKind::ModAssign;
pnk = ParseNodeKind::ModAssignExpr;
break;
case CompoundAssignmentOperator::PowAssign:
pnk = ParseNodeKind::PowAssign;
pnk = ParseNodeKind::PowAssignExpr;
break;
case CompoundAssignmentOperator::LshAssign:
pnk = ParseNodeKind::LshAssign;
pnk = ParseNodeKind::LshAssignExpr;
break;
case CompoundAssignmentOperator::RshAssign:
pnk = ParseNodeKind::RshAssign;
pnk = ParseNodeKind::RshAssignExpr;
break;
case CompoundAssignmentOperator::UrshAssign:
pnk = ParseNodeKind::UrshAssign;
pnk = ParseNodeKind::UrshAssignExpr;
break;
case CompoundAssignmentOperator::BitOrAssign:
pnk = ParseNodeKind::BitOrAssign;
pnk = ParseNodeKind::BitOrAssignExpr;
break;
case CompoundAssignmentOperator::BitXorAssign:
pnk = ParseNodeKind::BitXorAssign;
pnk = ParseNodeKind::BitXorAssignExpr;
break;
case CompoundAssignmentOperator::BitAndAssign:
pnk = ParseNodeKind::BitAndAssign;
pnk = ParseNodeKind::BitAndAssignExpr;
break;
}
BINJS_TRY_DECL(result, factory_.newAssignment(pnk, binding, expression));
@ -771,7 +771,7 @@ DataProperty:
ParseNode* result;
if (name->template is<NameNode>() && name->template as<NameNode>().atom() == cx_->names().proto) {
BINJS_TRY_VAR(result, factory_.newUnary(ParseNodeKind::MutateProto, start, expression));
BINJS_TRY_VAR(result, factory_.newUnary(ParseNodeKind::MutateProtoExpr, start, expression));
} else {
BINJS_TRY_VAR(result, factory_.newObjectMethodOrPropertyDefinition(name, expression, AccessorType::None));
}
@ -990,7 +990,7 @@ ForInOfBinding:
ParseNodeKind pnk;
switch (kind_) {
case VariableDeclarationKind::Var:
pnk = ParseNodeKind::Var;
pnk = ParseNodeKind::VarStmt;
break;
case VariableDeclarationKind::Let:
return raiseError("Let is not supported in this preview release");
@ -1175,7 +1175,7 @@ ListOfVariableDeclarator:
type-ok:
ListNode*
init: |
BINJS_TRY_DECL(result, factory_.newDeclarationList(ParseNodeKind::Const /*Placeholder*/,
BINJS_TRY_DECL(result, factory_.newDeclarationList(ParseNodeKind::ConstStmt /*Placeholder*/,
tokenizer_->pos(start)));
LiteralBooleanExpression:
@ -1289,7 +1289,7 @@ ShorthandProperty:
BINJS_TRY_DECL(propName, factory_.newObjectLiteralPropertyName(name->template as<NameNode>().name(), tokenizer_->pos(start)));
BINJS_TRY_DECL(result, factory_.newObjectMethodOrPropertyDefinition(propName, name, AccessorType::None));
result->setKind(ParseNodeKind::Shorthand);
result->setKind(ParseNodeKind::ShorthandExpr);
SwitchCase:
type-ok:
@ -1403,39 +1403,39 @@ UnaryExpression:
ParseNodeKind pnk;
switch (operator_) {
case UnaryOperator::Minus:
pnk = ParseNodeKind::Neg;
pnk = ParseNodeKind::NegExpr;
break;
case UnaryOperator::Plus:
pnk = ParseNodeKind::Pos;
pnk = ParseNodeKind::PosExpr;
break;
case UnaryOperator::Not:
pnk = ParseNodeKind::Not;
pnk = ParseNodeKind::NotExpr;
break;
case UnaryOperator::BitNot:
pnk = ParseNodeKind::BitNot;
pnk = ParseNodeKind::BitNotExpr;
break;
case UnaryOperator::Typeof: {
if (operand->isKind(ParseNodeKind::Name)) {
pnk = ParseNodeKind::TypeOfName;
pnk = ParseNodeKind::TypeOfNameExpr;
} else {
pnk = ParseNodeKind::TypeOfExpr;
}
break;
}
case UnaryOperator::Void:
pnk = ParseNodeKind::Void;
pnk = ParseNodeKind::VoidExpr;
break;
case UnaryOperator::Delete: {
switch (operand->getKind()) {
case ParseNodeKind::Name:
operand->setOp(JSOP_DELNAME);
pnk = ParseNodeKind::DeleteName;
pnk = ParseNodeKind::DeleteNameExpr;
break;
case ParseNodeKind::Dot:
pnk = ParseNodeKind::DeleteProp;
case ParseNodeKind::DotExpr:
pnk = ParseNodeKind::DeletePropExpr;
break;
case ParseNodeKind::Elem:
pnk = ParseNodeKind::DeleteElem;
case ParseNodeKind::ElemExpr:
pnk = ParseNodeKind::DeleteElemExpr;
break;
default:
pnk = ParseNodeKind::DeleteExpr;
@ -1450,12 +1450,12 @@ UpdateExpression:
ParseNodeKind pnk;
switch (operator_) {
case UpdateOperator::Incr:
pnk = isPrefix ? ParseNodeKind::PreIncrement
: ParseNodeKind::PostIncrement;
pnk = isPrefix ? ParseNodeKind::PreIncrementExpr
: ParseNodeKind::PostIncrementExpr;
break;
case UpdateOperator::Decr:
pnk = isPrefix ? ParseNodeKind::PreDecrement
: ParseNodeKind::PostDecrement;
pnk = isPrefix ? ParseNodeKind::PreDecrementExpr
: ParseNodeKind::PostDecrementExpr;
break;
}
BINJS_TRY_DECL(result, factory_.newUnary(pnk, start, operand));
@ -1479,7 +1479,7 @@ VariableDeclaration:
ParseNodeKind pnk;
switch (kind_) {
case VariableDeclarationKind::Var:
pnk = ParseNodeKind::Var;
pnk = ParseNodeKind::VarStmt;
break;
case VariableDeclarationKind::Let:
return raiseError("Let is not supported in this preview release");
@ -1508,7 +1508,7 @@ VariableDeclarator:
}
MOZ_CRASH("Unimplemented: AssertedScope check for BindingPattern variable declaration");
BINJS_TRY_VAR(result, factory_.newAssignment(ParseNodeKind::Assign, binding, init));
BINJS_TRY_VAR(result, factory_.newAssignment(ParseNodeKind::AssignExpr, binding, init));
}
WhileStatement:

View File

@ -1,7 +1,7 @@
// This file was autogenerated by binjs_generate_spidermonkey,
// please DO NOT EDIT BY HAND.
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -66,18 +66,18 @@ class FullParseHandler {
using NullNode = std::nullptr_t;
bool isPropertyAccess(Node node) {
return node->isKind(ParseNodeKind::Dot) ||
node->isKind(ParseNodeKind::Elem);
return node->isKind(ParseNodeKind::DotExpr) ||
node->isKind(ParseNodeKind::ElemExpr);
}
bool isFunctionCall(Node node) {
// Note: super() is a special form, *not* a function call.
return node->isKind(ParseNodeKind::Call);
return node->isKind(ParseNodeKind::CallExpr);
}
static bool isUnparenthesizedDestructuringPattern(Node node) {
return !node->isInParens() && (node->isKind(ParseNodeKind::Object) ||
node->isKind(ParseNodeKind::Array));
return !node->isInParens() && (node->isKind(ParseNodeKind::ObjectExpr) ||
node->isKind(ParseNodeKind::ArrayExpr));
}
static bool isParenthesizedDestructuringPattern(Node node) {
@ -85,8 +85,8 @@ class FullParseHandler {
// doesn't treat it as such. But we need to know when this happens to
// consider it a SyntaxError rather than an invalid-left-hand-side
// ReferenceError.
return node->isInParens() && (node->isKind(ParseNodeKind::Object) ||
node->isKind(ParseNodeKind::Array));
return node->isInParens() && (node->isKind(ParseNodeKind::ObjectExpr) ||
node->isKind(ParseNodeKind::ArrayExpr));
}
FullParseHandler(JSContext* cx, LifoAlloc& alloc,
@ -150,11 +150,12 @@ class FullParseHandler {
}
NameNodeType newStringLiteral(JSAtom* atom, const TokenPos& pos) {
return new_<NameNode>(ParseNodeKind::String, JSOP_NOP, atom, pos);
return new_<NameNode>(ParseNodeKind::StringExpr, JSOP_NOP, atom, pos);
}
NameNodeType newTemplateStringLiteral(JSAtom* atom, const TokenPos& pos) {
return new_<NameNode>(ParseNodeKind::TemplateString, JSOP_NOP, atom, pos);
return new_<NameNode>(ParseNodeKind::TemplateStringExpr, JSOP_NOP, atom,
pos);
}
CallSiteNodeType newCallSiteObject(uint32_t begin) {
@ -175,7 +176,7 @@ class FullParseHandler {
void addToCallSiteObject(CallSiteNodeType callSiteObj, Node rawNode,
Node cookedNode) {
MOZ_ASSERT(callSiteObj->isKind(ParseNodeKind::CallSiteObj));
MOZ_ASSERT(callSiteObj->isKind(ParseNodeKind::CallSiteObjExpr));
addArrayElement(callSiteObj, cookedNode);
addArrayElement(callSiteObj->rawNodes(), rawNode);
@ -220,15 +221,15 @@ class FullParseHandler {
UnaryNodeType newDelete(uint32_t begin, Node expr) {
if (expr->isKind(ParseNodeKind::Name)) {
expr->setOp(JSOP_DELNAME);
return newUnary(ParseNodeKind::DeleteName, begin, expr);
return newUnary(ParseNodeKind::DeleteNameExpr, begin, expr);
}
if (expr->isKind(ParseNodeKind::Dot)) {
return newUnary(ParseNodeKind::DeleteProp, begin, expr);
if (expr->isKind(ParseNodeKind::DotExpr)) {
return newUnary(ParseNodeKind::DeletePropExpr, begin, expr);
}
if (expr->isKind(ParseNodeKind::Elem)) {
return newUnary(ParseNodeKind::DeleteElem, begin, expr);
if (expr->isKind(ParseNodeKind::ElemExpr)) {
return newUnary(ParseNodeKind::DeleteElemExpr, begin, expr);
}
return newUnary(ParseNodeKind::DeleteExpr, begin, expr);
@ -236,7 +237,7 @@ class FullParseHandler {
UnaryNodeType newTypeof(uint32_t begin, Node kid) {
ParseNodeKind pnk = kid->isKind(ParseNodeKind::Name)
? ParseNodeKind::TypeOfName
? ParseNodeKind::TypeOfNameExpr
: ParseNodeKind::TypeOfExpr;
return newUnary(pnk, begin, kid);
}
@ -272,11 +273,11 @@ class FullParseHandler {
// Expressions
ListNodeType newArrayLiteral(uint32_t begin) {
return new_<ListNode>(ParseNodeKind::Array, TokenPos(begin, begin + 1));
return new_<ListNode>(ParseNodeKind::ArrayExpr, TokenPos(begin, begin + 1));
}
MOZ_MUST_USE bool addElision(ListNodeType literal, const TokenPos& pos) {
MOZ_ASSERT(literal->isKind(ParseNodeKind::Array));
MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr));
NullaryNode* elision = new_<NullaryNode>(ParseNodeKind::Elision, pos);
if (!elision) {
@ -290,7 +291,7 @@ class FullParseHandler {
MOZ_MUST_USE bool addSpreadElement(ListNodeType literal, uint32_t begin,
Node inner) {
MOZ_ASSERT(literal->isKind(ParseNodeKind::Array));
MOZ_ASSERT(literal->isKind(ParseNodeKind::ArrayExpr));
ParseNode* spread = newSpread(begin, inner);
if (!spread) {
@ -310,7 +311,7 @@ class FullParseHandler {
}
BinaryNodeType newCall(Node callee, Node args) {
return new_<BinaryNode>(ParseNodeKind::Call, JSOP_CALL, callee, args);
return new_<BinaryNode>(ParseNodeKind::CallExpr, JSOP_CALL, callee, args);
}
ListNodeType newArguments(const TokenPos& pos) {
@ -318,17 +319,18 @@ class FullParseHandler {
}
BinaryNodeType newSuperCall(Node callee, Node args) {
return new_<BinaryNode>(ParseNodeKind::SuperCall, JSOP_SUPERCALL, callee,
args);
return new_<BinaryNode>(ParseNodeKind::SuperCallExpr, JSOP_SUPERCALL,
callee, args);
}
BinaryNodeType newTaggedTemplate(Node tag, Node args) {
return new_<BinaryNode>(ParseNodeKind::TaggedTemplate, JSOP_CALL, tag,
return new_<BinaryNode>(ParseNodeKind::TaggedTemplateExpr, JSOP_CALL, tag,
args);
}
ListNodeType newObjectLiteral(uint32_t begin) {
return new_<ListNode>(ParseNodeKind::Object, TokenPos(begin, begin + 1));
return new_<ListNode>(ParseNodeKind::ObjectExpr,
TokenPos(begin, begin + 1));
}
ClassNodeType newClass(Node name, Node heritage, Node memberBlock,
@ -344,7 +346,7 @@ class FullParseHandler {
}
BinaryNodeType newNewTarget(NullaryNodeType newHolder,
NullaryNodeType targetHolder) {
return new_<BinaryNode>(ParseNodeKind::NewTarget, JSOP_NOP, newHolder,
return new_<BinaryNode>(ParseNodeKind::NewTargetExpr, JSOP_NOP, newHolder,
targetHolder);
}
NullaryNodeType newPosHolder(const TokenPos& pos) {
@ -355,7 +357,7 @@ class FullParseHandler {
}
MOZ_MUST_USE bool addPrototypeMutation(ListNodeType literal, uint32_t begin,
Node expr) {
MOZ_ASSERT(literal->isKind(ParseNodeKind::Object));
MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
// Object literals with mutated [[Prototype]] are non-constant so that
// singleton objects will have Object.prototype as their [[Prototype]].
@ -376,7 +378,7 @@ class FullParseHandler {
}
void addPropertyDefinition(ListNodeType literal, BinaryNodeType propdef) {
MOZ_ASSERT(literal->isKind(ParseNodeKind::Object));
MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
MOZ_ASSERT(propdef->isKind(ParseNodeKind::Colon));
if (!propdef->right()->isConstant()) {
@ -398,7 +400,7 @@ class FullParseHandler {
MOZ_MUST_USE bool addShorthand(ListNodeType literal, NameNodeType name,
NameNodeType expr) {
MOZ_ASSERT(literal->isKind(ParseNodeKind::Object));
MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
MOZ_ASSERT(name->isKind(ParseNodeKind::ObjectPropertyName));
MOZ_ASSERT(expr->isKind(ParseNodeKind::Name));
MOZ_ASSERT(name->atom() == expr->atom());
@ -415,7 +417,7 @@ class FullParseHandler {
MOZ_MUST_USE bool addSpreadProperty(ListNodeType literal, uint32_t begin,
Node inner) {
MOZ_ASSERT(literal->isKind(ParseNodeKind::Object));
MOZ_ASSERT(literal->isKind(ParseNodeKind::ObjectExpr));
literal->setHasNonConstInitializer();
ParseNode* spread = newSpread(begin, inner);
@ -482,17 +484,17 @@ class FullParseHandler {
UnaryNodeType newYieldExpression(uint32_t begin, Node value) {
TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
return new_<UnaryNode>(ParseNodeKind::Yield, pos, value);
return new_<UnaryNode>(ParseNodeKind::YieldExpr, pos, value);
}
UnaryNodeType newYieldStarExpression(uint32_t begin, Node value) {
TokenPos pos(begin, value->pn_pos.end);
return new_<UnaryNode>(ParseNodeKind::YieldStar, pos, value);
return new_<UnaryNode>(ParseNodeKind::YieldStarExpr, pos, value);
}
UnaryNodeType newAwaitExpression(uint32_t begin, Node value) {
TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
return new_<UnaryNode>(ParseNodeKind::Await, pos, value);
return new_<UnaryNode>(ParseNodeKind::AwaitExpr, pos, value);
}
// Statements
@ -502,7 +504,7 @@ class FullParseHandler {
}
MOZ_MUST_USE bool isFunctionStmt(Node stmt) {
while (stmt->isKind(ParseNodeKind::Label)) {
while (stmt->isKind(ParseNodeKind::LabelStmt)) {
stmt = stmt->as<LabeledStatement>().statement();
}
return stmt->isKind(ParseNodeKind::Function);
@ -548,7 +550,7 @@ class FullParseHandler {
MOZ_ASSERT(genName->getOp() == JSOP_GETNAME);
genName->setOp(JSOP_SETNAME);
ParseNode* genInit =
newAssignment(ParseNodeKind::Assign, /* lhs = */ genName,
newAssignment(ParseNodeKind::AssignExpr, /* lhs = */ genName,
/* rhs = */ makeGen);
if (!genInit) {
return false;
@ -571,13 +573,13 @@ class FullParseHandler {
}
NullaryNodeType newEmptyStatement(const TokenPos& pos) {
return new_<NullaryNode>(ParseNodeKind::EmptyStatement, pos);
return new_<NullaryNode>(ParseNodeKind::EmptyStmt, pos);
}
BinaryNodeType newImportDeclaration(Node importSpecSet, Node moduleSpec,
const TokenPos& pos) {
return new_<BinaryNode>(ParseNodeKind::Import, JSOP_NOP, pos, importSpecSet,
moduleSpec);
return new_<BinaryNode>(ParseNodeKind::ImportDecl, JSOP_NOP, pos,
importSpecSet, moduleSpec);
}
BinaryNodeType newImportSpec(Node importNameNode, Node bindingName) {
@ -585,12 +587,12 @@ class FullParseHandler {
}
UnaryNodeType newExportDeclaration(Node kid, const TokenPos& pos) {
return new_<UnaryNode>(ParseNodeKind::Export, pos, kid);
return new_<UnaryNode>(ParseNodeKind::ExportStmt, pos, kid);
}
BinaryNodeType newExportFromDeclaration(uint32_t begin, Node exportSpecSet,
Node moduleSpec) {
BinaryNode* decl = new_<BinaryNode>(ParseNodeKind::ExportFrom, JSOP_NOP,
BinaryNode* decl = new_<BinaryNode>(ParseNodeKind::ExportFromStmt, JSOP_NOP,
exportSpecSet, moduleSpec);
if (!decl) {
return nullptr;
@ -608,8 +610,8 @@ class FullParseHandler {
checkAndSetIsDirectRHSAnonFunction(kid);
}
return new_<BinaryNode>(ParseNodeKind::ExportDefault, JSOP_NOP, pos, kid,
maybeBinding);
return new_<BinaryNode>(ParseNodeKind::ExportDefaultStmt, JSOP_NOP, pos,
kid, maybeBinding);
}
BinaryNodeType newExportSpec(Node bindingName, Node exportName) {
@ -617,30 +619,30 @@ class FullParseHandler {
}
NullaryNodeType newExportBatchSpec(const TokenPos& pos) {
return new_<NullaryNode>(ParseNodeKind::ExportBatchSpec, JSOP_NOP, pos);
return new_<NullaryNode>(ParseNodeKind::ExportBatchSpecStmt, JSOP_NOP, pos);
}
BinaryNodeType newImportMeta(NullaryNodeType importHolder,
NullaryNodeType metaHolder) {
return new_<BinaryNode>(ParseNodeKind::ImportMeta, JSOP_NOP, importHolder,
metaHolder);
return new_<BinaryNode>(ParseNodeKind::ImportMetaExpr, JSOP_NOP,
importHolder, metaHolder);
}
BinaryNodeType newCallImport(NullaryNodeType importHolder, Node singleArg) {
return new_<BinaryNode>(ParseNodeKind::CallImport, JSOP_DYNAMIC_IMPORT,
return new_<BinaryNode>(ParseNodeKind::CallImportExpr, JSOP_DYNAMIC_IMPORT,
importHolder, singleArg);
}
UnaryNodeType newExprStatement(Node expr, uint32_t end) {
MOZ_ASSERT(expr->pn_pos.end <= end);
return new_<UnaryNode>(ParseNodeKind::ExpressionStatement,
return new_<UnaryNode>(ParseNodeKind::ExpressionStmt,
TokenPos(expr->pn_pos.begin, end), expr);
}
TernaryNodeType newIfStatement(uint32_t begin, Node cond, Node thenBranch,
Node elseBranch) {
TernaryNode* node =
new_<TernaryNode>(ParseNodeKind::If, cond, thenBranch, elseBranch);
new_<TernaryNode>(ParseNodeKind::IfStmt, cond, thenBranch, elseBranch);
if (!node) {
return nullptr;
}
@ -650,12 +652,14 @@ class FullParseHandler {
BinaryNodeType newDoWhileStatement(Node body, Node cond,
const TokenPos& pos) {
return new_<BinaryNode>(ParseNodeKind::DoWhile, JSOP_NOP, pos, body, cond);
return new_<BinaryNode>(ParseNodeKind::DoWhileStmt, JSOP_NOP, pos, body,
cond);
}
BinaryNodeType newWhileStatement(uint32_t begin, Node cond, Node body) {
TokenPos pos(begin, body->pn_pos.end);
return new_<BinaryNode>(ParseNodeKind::While, JSOP_NOP, pos, cond, body);
return new_<BinaryNode>(ParseNodeKind::WhileStmt, JSOP_NOP, pos, cond,
body);
}
ForNodeType newForStatement(uint32_t begin, TernaryNodeType forHead,
@ -698,15 +702,15 @@ class FullParseHandler {
UnaryNodeType newReturnStatement(Node expr, const TokenPos& pos) {
MOZ_ASSERT_IF(expr, pos.encloses(expr->pn_pos));
return new_<UnaryNode>(ParseNodeKind::Return, pos, expr);
return new_<UnaryNode>(ParseNodeKind::ReturnStmt, pos, expr);
}
UnaryNodeType newExpressionBody(Node expr) {
return new_<UnaryNode>(ParseNodeKind::Return, expr->pn_pos, expr);
return new_<UnaryNode>(ParseNodeKind::ReturnStmt, expr->pn_pos, expr);
}
BinaryNodeType newWithStatement(uint32_t begin, Node expr, Node body) {
return new_<BinaryNode>(ParseNodeKind::With, JSOP_NOP,
return new_<BinaryNode>(ParseNodeKind::WithStmt, JSOP_NOP,
TokenPos(begin, body->pn_pos.end), expr, body);
}
@ -717,7 +721,7 @@ class FullParseHandler {
UnaryNodeType newThrowStatement(Node expr, const TokenPos& pos) {
MOZ_ASSERT(pos.encloses(expr->pn_pos));
return new_<UnaryNode>(ParseNodeKind::Throw, pos, expr);
return new_<UnaryNode>(ParseNodeKind::ThrowStmt, pos, expr);
}
TernaryNodeType newTryStatement(uint32_t begin, Node body,
@ -731,7 +735,7 @@ class FullParseHandler {
}
NameNodeType newPropertyName(PropertyName* name, const TokenPos& pos) {
return new_<NameNode>(ParseNodeKind::PropertyName, JSOP_NOP, name, pos);
return new_<NameNode>(ParseNodeKind::PropertyNameExpr, JSOP_NOP, name, pos);
}
PropertyAccessType newPropertyAccess(Node expr, NameNodeType key) {
@ -818,12 +822,12 @@ class FullParseHandler {
}
BinaryNodeType newNewExpression(uint32_t begin, Node ctor, Node args) {
return new_<BinaryNode>(ParseNodeKind::New, JSOP_NEW,
return new_<BinaryNode>(ParseNodeKind::NewExpr, JSOP_NEW,
TokenPos(begin, args->pn_pos.end), ctor, args);
}
AssignmentNodeType newAssignment(ParseNodeKind kind, Node lhs, Node rhs) {
if (kind == ParseNodeKind::Assign && lhs->isKind(ParseNodeKind::Name) &&
if (kind == ParseNodeKind::AssignExpr && lhs->isKind(ParseNodeKind::Name) &&
!lhs->isInParens()) {
checkAndSetIsDirectRHSAnonFunction(rhs);
}
@ -832,7 +836,7 @@ class FullParseHandler {
}
bool isUnparenthesizedAssignment(Node node) {
if (node->isKind(ParseNodeKind::Assign) && !node->isInParens()) {
if (node->isKind(ParseNodeKind::AssignExpr) && !node->isInParens()) {
// ParseNodeKind::Assign is also (mis)used for things like
// |var name = expr;|. But this method is only called on actual
// expressions, so we can just assert the node's op is the one used
@ -847,31 +851,32 @@ class FullParseHandler {
bool isUnparenthesizedUnaryExpression(Node node) {
if (!node->isInParens()) {
ParseNodeKind kind = node->getKind();
return kind == ParseNodeKind::Void || kind == ParseNodeKind::Not ||
kind == ParseNodeKind::BitNot || kind == ParseNodeKind::Pos ||
kind == ParseNodeKind::Neg || IsTypeofKind(kind) ||
IsDeleteKind(kind);
return kind == ParseNodeKind::VoidExpr ||
kind == ParseNodeKind::NotExpr ||
kind == ParseNodeKind::BitNotExpr ||
kind == ParseNodeKind::PosExpr || kind == ParseNodeKind::NegExpr ||
IsTypeofKind(kind) || IsDeleteKind(kind);
}
return false;
}
bool isReturnStatement(Node node) {
return node->isKind(ParseNodeKind::Return);
return node->isKind(ParseNodeKind::ReturnStmt);
}
bool isStatementPermittedAfterReturnStatement(Node node) {
ParseNodeKind kind = node->getKind();
return kind == ParseNodeKind::Function || kind == ParseNodeKind::Var ||
kind == ParseNodeKind::Break || kind == ParseNodeKind::Throw ||
kind == ParseNodeKind::EmptyStatement;
return kind == ParseNodeKind::Function || kind == ParseNodeKind::VarStmt ||
kind == ParseNodeKind::BreakStmt ||
kind == ParseNodeKind::ThrowStmt || kind == ParseNodeKind::EmptyStmt;
}
bool isSuperBase(Node node) { return node->isKind(ParseNodeKind::SuperBase); }
bool isUsableAsObjectPropertyName(Node node) {
return node->isKind(ParseNodeKind::Number) ||
return node->isKind(ParseNodeKind::NumberExpr) ||
node->isKind(ParseNodeKind::ObjectPropertyName) ||
node->isKind(ParseNodeKind::String) ||
node->isKind(ParseNodeKind::StringExpr) ||
node->isKind(ParseNodeKind::ComputedName);
}
@ -899,8 +904,8 @@ class FullParseHandler {
}
bool isDeclarationKind(ParseNodeKind kind) {
return kind == ParseNodeKind::Var || kind == ParseNodeKind::Let ||
kind == ParseNodeKind::Const;
return kind == ParseNodeKind::VarStmt || kind == ParseNodeKind::LetDecl ||
kind == ParseNodeKind::ConstDecl;
}
ListNodeType newList(ParseNodeKind kind, const TokenPos& pos) {
@ -930,7 +935,7 @@ class FullParseHandler {
}
ListNodeType newCommaExpressionList(Node kid) {
return new_<ListNode>(ParseNodeKind::Comma, JSOP_NOP, kid);
return new_<ListNode>(ParseNodeKind::CommaExpr, JSOP_NOP, kid);
}
void addList(ListNodeType list, Node kid) {
@ -1015,7 +1020,7 @@ inline bool FullParseHandler::setLastFunctionFormalParameterDefault(
MOZ_ASSERT(funNode->isKind(ParseNodeKind::Function));
ListNode* body = funNode->body();
ParseNode* arg = body->last();
ParseNode* pn = newAssignment(ParseNodeKind::Assign, arg, defaultValue);
ParseNode* pn = newAssignment(ParseNodeKind::AssignExpr, arg, defaultValue);
if (!pn) {
return false;
}

View File

@ -31,7 +31,7 @@ class NameResolver {
StringBuffer* buf; /* when resolving, buffer to append to */
/* Test whether a ParseNode represents a function invocation */
bool call(ParseNode* pn) { return pn && pn->isKind(ParseNodeKind::Call); }
bool call(ParseNode* pn) { return pn && pn->isKind(ParseNodeKind::CallExpr); }
/*
* Append a reference to a property named |name| to |buf|. If |name| is
@ -74,7 +74,7 @@ class NameResolver {
*/
bool nameExpression(ParseNode* n, bool* foundName) {
switch (n->getKind()) {
case ParseNodeKind::Dot: {
case ParseNodeKind::DotExpr: {
PropertyAccess* prop = &n->as<PropertyAccess>();
if (!nameExpression(&prop->expression(), foundName)) {
return false;
@ -90,11 +90,11 @@ class NameResolver {
*foundName = true;
return buf->append(n->as<NameNode>().atom());
case ParseNodeKind::This:
case ParseNodeKind::ThisExpr:
*foundName = true;
return buf->append("this");
case ParseNodeKind::Elem: {
case ParseNodeKind::ElemExpr: {
PropertyByValue* elem = &n->as<PropertyByValue>();
if (!nameExpression(&elem->expression(), foundName)) {
return false;
@ -111,7 +111,7 @@ class NameResolver {
return buf->append(']');
}
case ParseNodeKind::Number:
case ParseNodeKind::NumberExpr:
*foundName = true;
return appendNumber(n->as<NumericLiteral>().value());
@ -148,12 +148,12 @@ class NameResolver {
case ParseNodeKind::PrivateName:
case ParseNodeKind::Name:
return cur; /* found the initialized declaration */
case ParseNodeKind::This:
case ParseNodeKind::ThisExpr:
return cur; /* Setting a property of 'this'. */
case ParseNodeKind::Function:
return nullptr; /* won't find an assignment or declaration */
case ParseNodeKind::Return:
case ParseNodeKind::ReturnStmt:
/*
* Normally the relevant parent of a node is its direct parent, but
* sometimes with code like:
@ -264,11 +264,11 @@ class NameResolver {
node->isKind(ParseNodeKind::Shorthand)) {
ParseNode* left = node->as<BinaryNode>().left();
if (left->isKind(ParseNodeKind::ObjectPropertyName) ||
left->isKind(ParseNodeKind::String)) {
left->isKind(ParseNodeKind::StringExpr)) {
if (!appendPropertyReference(left->as<NameNode>().atom())) {
return false;
}
} else if (left->isKind(ParseNodeKind::Number)) {
} else if (left->isKind(ParseNodeKind::NumberExpr)) {
if (!appendNumericPropertyReference(
left->as<NumericLiteral>().value())) {
return false;
@ -326,10 +326,10 @@ class NameResolver {
}
bool resolveTemplateLiteral(ListNode* node, HandleAtom prefix) {
MOZ_ASSERT(node->isKind(ParseNodeKind::TemplateStringList));
MOZ_ASSERT(node->isKind(ParseNodeKind::TemplateStringListExpr));
ParseNode* element = node->head();
while (true) {
MOZ_ASSERT(element->isKind(ParseNodeKind::TemplateString));
MOZ_ASSERT(element->isKind(ParseNodeKind::TemplateStringExpr));
element = element->pn_next;
if (!element) {
@ -345,7 +345,7 @@ class NameResolver {
}
bool resolveTaggedTemplate(BinaryNode* taggedTemplate, HandleAtom prefix) {
MOZ_ASSERT(taggedTemplate->isKind(ParseNodeKind::TaggedTemplate));
MOZ_ASSERT(taggedTemplate->isKind(ParseNodeKind::TaggedTemplateExpr));
ParseNode* tag = taggedTemplate->left();
@ -363,13 +363,13 @@ class NameResolver {
#ifdef DEBUG
{
ListNode* rawNodes = &element->head()->as<ListNode>();
MOZ_ASSERT(rawNodes->isKind(ParseNodeKind::Array));
MOZ_ASSERT(rawNodes->isKind(ParseNodeKind::ArrayExpr));
for (ParseNode* raw : rawNodes->contents()) {
MOZ_ASSERT(raw->isKind(ParseNodeKind::TemplateString));
MOZ_ASSERT(raw->isKind(ParseNodeKind::TemplateStringExpr));
}
for (ParseNode* cooked : element->contentsFrom(rawNodes->pn_next)) {
MOZ_ASSERT(cooked->isKind(ParseNodeKind::TemplateString) ||
cooked->isKind(ParseNodeKind::RawUndefined));
MOZ_ASSERT(cooked->isKind(ParseNodeKind::TemplateStringExpr) ||
cooked->isKind(ParseNodeKind::RawUndefinedExpr));
}
}
#endif
@ -427,43 +427,43 @@ class NameResolver {
switch (cur->getKind()) {
// Nodes with no children that might require name resolution need no
// further work.
case ParseNodeKind::EmptyStatement:
case ParseNodeKind::True:
case ParseNodeKind::False:
case ParseNodeKind::Null:
case ParseNodeKind::RawUndefined:
case ParseNodeKind::EmptyStmt:
case ParseNodeKind::TrueExpr:
case ParseNodeKind::FalseExpr:
case ParseNodeKind::NullExpr:
case ParseNodeKind::RawUndefinedExpr:
case ParseNodeKind::Elision:
case ParseNodeKind::Generator:
case ParseNodeKind::ExportBatchSpec:
case ParseNodeKind::ExportBatchSpecStmt:
case ParseNodeKind::PosHolder:
MOZ_ASSERT(cur->is<NullaryNode>());
break;
case ParseNodeKind::Debugger:
case ParseNodeKind::DebuggerStmt:
MOZ_ASSERT(cur->is<DebuggerStatement>());
break;
case ParseNodeKind::Break:
case ParseNodeKind::BreakStmt:
MOZ_ASSERT(cur->is<BreakStatement>());
break;
case ParseNodeKind::Continue:
case ParseNodeKind::ContinueStmt:
MOZ_ASSERT(cur->is<ContinueStatement>());
break;
case ParseNodeKind::ObjectPropertyName:
case ParseNodeKind::PrivateName: // TODO(khyperia): Implement private
// field access.
case ParseNodeKind::String:
case ParseNodeKind::TemplateString:
case ParseNodeKind::StringExpr:
case ParseNodeKind::TemplateStringExpr:
MOZ_ASSERT(cur->is<NameNode>());
break;
case ParseNodeKind::RegExp:
case ParseNodeKind::RegExpExpr:
MOZ_ASSERT(cur->is<RegExpLiteral>());
break;
case ParseNodeKind::Number:
case ParseNodeKind::NumberExpr:
MOZ_ASSERT(cur->is<NumericLiteral>());
break;
@ -473,14 +473,14 @@ class NameResolver {
break;
#endif
case ParseNodeKind::TypeOfName:
case ParseNodeKind::TypeOfNameExpr:
case ParseNodeKind::SuperBase:
MOZ_ASSERT(cur->as<UnaryNode>().kid()->isKind(ParseNodeKind::Name));
MOZ_ASSERT(!cur->as<UnaryNode>().kid()->as<NameNode>().initializer());
break;
case ParseNodeKind::NewTarget:
case ParseNodeKind::ImportMeta: {
case ParseNodeKind::NewTargetExpr:
case ParseNodeKind::ImportMetaExpr: {
MOZ_ASSERT(
cur->as<BinaryNode>().left()->isKind(ParseNodeKind::PosHolder));
MOZ_ASSERT(
@ -489,33 +489,33 @@ class NameResolver {
}
// Nodes with a single non-null child requiring name resolution.
case ParseNodeKind::ExpressionStatement:
case ParseNodeKind::ExpressionStmt:
case ParseNodeKind::TypeOfExpr:
case ParseNodeKind::Void:
case ParseNodeKind::Not:
case ParseNodeKind::BitNot:
case ParseNodeKind::Throw:
case ParseNodeKind::DeleteName:
case ParseNodeKind::DeleteProp:
case ParseNodeKind::DeleteElem:
case ParseNodeKind::VoidExpr:
case ParseNodeKind::NotExpr:
case ParseNodeKind::BitNotExpr:
case ParseNodeKind::ThrowStmt:
case ParseNodeKind::DeleteNameExpr:
case ParseNodeKind::DeletePropExpr:
case ParseNodeKind::DeleteElemExpr:
case ParseNodeKind::DeleteExpr:
case ParseNodeKind::Neg:
case ParseNodeKind::Pos:
case ParseNodeKind::PreIncrement:
case ParseNodeKind::PostIncrement:
case ParseNodeKind::PreDecrement:
case ParseNodeKind::PostDecrement:
case ParseNodeKind::NegExpr:
case ParseNodeKind::PosExpr:
case ParseNodeKind::PreIncrementExpr:
case ParseNodeKind::PostIncrementExpr:
case ParseNodeKind::PreDecrementExpr:
case ParseNodeKind::PostDecrementExpr:
case ParseNodeKind::ComputedName:
case ParseNodeKind::Spread:
case ParseNodeKind::MutateProto:
case ParseNodeKind::Export:
case ParseNodeKind::ExportStmt:
if (!resolve(cur->as<UnaryNode>().kid(), prefix)) {
return false;
}
break;
// Nodes with a single nullable child.
case ParseNodeKind::This:
case ParseNodeKind::ThisExpr:
if (ParseNode* expr = cur->as<ThisLiteral>().kid()) {
if (!resolve(expr, prefix)) {
return false;
@ -524,25 +524,25 @@ class NameResolver {
break;
// Binary nodes with two non-null children.
case ParseNodeKind::Assign:
case ParseNodeKind::AddAssign:
case ParseNodeKind::SubAssign:
case ParseNodeKind::BitOrAssign:
case ParseNodeKind::BitXorAssign:
case ParseNodeKind::BitAndAssign:
case ParseNodeKind::LshAssign:
case ParseNodeKind::RshAssign:
case ParseNodeKind::UrshAssign:
case ParseNodeKind::MulAssign:
case ParseNodeKind::DivAssign:
case ParseNodeKind::ModAssign:
case ParseNodeKind::PowAssign:
case ParseNodeKind::AssignExpr:
case ParseNodeKind::AddAssignExpr:
case ParseNodeKind::SubAssignExpr:
case ParseNodeKind::BitOrAssignExpr:
case ParseNodeKind::BitXorAssignExpr:
case ParseNodeKind::BitAndAssignExpr:
case ParseNodeKind::LshAssignExpr:
case ParseNodeKind::RshAssignExpr:
case ParseNodeKind::UrshAssignExpr:
case ParseNodeKind::MulAssignExpr:
case ParseNodeKind::DivAssignExpr:
case ParseNodeKind::ModAssignExpr:
case ParseNodeKind::PowAssignExpr:
case ParseNodeKind::Colon:
case ParseNodeKind::Shorthand:
case ParseNodeKind::DoWhile:
case ParseNodeKind::While:
case ParseNodeKind::Switch:
case ParseNodeKind::For:
case ParseNodeKind::DoWhileStmt:
case ParseNodeKind::WhileStmt:
case ParseNodeKind::SwitchStmt:
case ParseNodeKind::ForStmt:
case ParseNodeKind::ClassMethod:
case ParseNodeKind::SetThis: {
BinaryNode* node = &cur->as<BinaryNode>();
@ -570,7 +570,7 @@ class NameResolver {
break;
}
case ParseNodeKind::Elem: {
case ParseNodeKind::ElemExpr: {
PropertyByValue* elem = &cur->as<PropertyByValue>();
if (!elem->isSuper() && !resolve(&elem->expression(), prefix)) {
return false;
@ -581,7 +581,7 @@ class NameResolver {
break;
}
case ParseNodeKind::With: {
case ParseNodeKind::WithStmt: {
BinaryNode* node = &cur->as<BinaryNode>();
if (!resolve(node->left(), prefix)) {
return false;
@ -615,14 +615,14 @@ class NameResolver {
break;
}
case ParseNodeKind::YieldStar:
case ParseNodeKind::YieldStarExpr:
if (!resolve(cur->as<UnaryNode>().kid(), prefix)) {
return false;
}
break;
case ParseNodeKind::Yield:
case ParseNodeKind::Await:
case ParseNodeKind::YieldExpr:
case ParseNodeKind::AwaitExpr:
if (ParseNode* expr = cur->as<UnaryNode>().kid()) {
if (!resolve(expr, prefix)) {
return false;
@ -630,7 +630,7 @@ class NameResolver {
}
break;
case ParseNodeKind::Return:
case ParseNodeKind::ReturnStmt:
if (ParseNode* returnValue = cur->as<UnaryNode>().kid()) {
if (!resolve(returnValue, prefix)) {
return false;
@ -638,9 +638,9 @@ class NameResolver {
}
break;
case ParseNodeKind::Import:
case ParseNodeKind::ExportFrom:
case ParseNodeKind::ExportDefault: {
case ParseNodeKind::ImportDecl:
case ParseNodeKind::ExportFromStmt:
case ParseNodeKind::ExportDefaultStmt: {
BinaryNode* node = &cur->as<BinaryNode>();
// The left halves of Import and ExportFrom don't contain any
// unconstrained expressions, but it's very hard to assert this to
@ -648,13 +648,13 @@ class NameResolver {
if (!resolve(node->left(), prefix)) {
return false;
}
MOZ_ASSERT_IF(!node->isKind(ParseNodeKind::ExportDefault),
node->right()->isKind(ParseNodeKind::String));
MOZ_ASSERT_IF(!node->isKind(ParseNodeKind::ExportDefaultStmt),
node->right()->isKind(ParseNodeKind::StringExpr));
break;
}
// Ternary nodes with three expression children.
case ParseNodeKind::Conditional: {
case ParseNodeKind::ConditionalExpr: {
TernaryNode* condNode = &cur->as<TernaryNode>();
if (!resolve(condNode->kid1(), prefix)) {
return false;
@ -712,7 +712,7 @@ class NameResolver {
// The first child of a class is a pair of names referring to it,
// inside and outside the class. The second is the class's heritage,
// if any. The third is the class body.
case ParseNodeKind::Class: {
case ParseNodeKind::ClassDecl: {
ClassNode* classNode = &cur->as<ClassNode>();
#ifdef DEBUG
if (classNode->names()) {
@ -740,7 +740,7 @@ class NameResolver {
// The condition and consequent are non-optional, but the alternative
// might be omitted.
case ParseNodeKind::If: {
case ParseNodeKind::IfStmt: {
TernaryNode* ifNode = &cur->as<TernaryNode>();
if (!resolve(ifNode->kid1(), prefix)) {
return false;
@ -759,7 +759,7 @@ class NameResolver {
// The statements in the try-block are mandatory. The catch-blocks
// and finally block are optional (but at least one or the other must
// be present).
case ParseNodeKind::Try: {
case ParseNodeKind::TryStmt: {
TryNode* tryNode = &cur->as<TryNode>();
if (!resolve(tryNode->body(), prefix)) {
return false;
@ -798,40 +798,40 @@ class NameResolver {
}
// Nodes with arbitrary-expression children.
case ParseNodeKind::Or:
case ParseNodeKind::And:
case ParseNodeKind::BitOr:
case ParseNodeKind::BitXor:
case ParseNodeKind::BitAnd:
case ParseNodeKind::StrictEq:
case ParseNodeKind::Eq:
case ParseNodeKind::StrictNe:
case ParseNodeKind::Ne:
case ParseNodeKind::Lt:
case ParseNodeKind::Le:
case ParseNodeKind::Gt:
case ParseNodeKind::Ge:
case ParseNodeKind::InstanceOf:
case ParseNodeKind::In:
case ParseNodeKind::Lsh:
case ParseNodeKind::Rsh:
case ParseNodeKind::Ursh:
case ParseNodeKind::Add:
case ParseNodeKind::Sub:
case ParseNodeKind::Star:
case ParseNodeKind::Div:
case ParseNodeKind::Mod:
case ParseNodeKind::Pow:
case ParseNodeKind::Pipeline:
case ParseNodeKind::Comma:
case ParseNodeKind::Array:
case ParseNodeKind::OrExpr:
case ParseNodeKind::AndExpr:
case ParseNodeKind::BitOrExpr:
case ParseNodeKind::BitXorExpr:
case ParseNodeKind::BitAndExpr:
case ParseNodeKind::StrictEqExpr:
case ParseNodeKind::EqExpr:
case ParseNodeKind::StrictNeExpr:
case ParseNodeKind::NeExpr:
case ParseNodeKind::LtExpr:
case ParseNodeKind::LeExpr:
case ParseNodeKind::GtExpr:
case ParseNodeKind::GeExpr:
case ParseNodeKind::InstanceOfExpr:
case ParseNodeKind::InExpr:
case ParseNodeKind::LshExpr:
case ParseNodeKind::RshExpr:
case ParseNodeKind::UrshExpr:
case ParseNodeKind::AddExpr:
case ParseNodeKind::SubExpr:
case ParseNodeKind::MulExpr:
case ParseNodeKind::DivExpr:
case ParseNodeKind::ModExpr:
case ParseNodeKind::PowExpr:
case ParseNodeKind::PipelineExpr:
case ParseNodeKind::CommaExpr:
case ParseNodeKind::ArrayExpr:
case ParseNodeKind::StatementList:
case ParseNodeKind::ParamsBody:
// Initializers for individual variables, and computed property names
// within destructuring patterns, may contain unnamed functions.
case ParseNodeKind::Var:
case ParseNodeKind::Const:
case ParseNodeKind::Let:
case ParseNodeKind::VarStmt:
case ParseNodeKind::ConstDecl:
case ParseNodeKind::LetDecl:
for (ParseNode* element : cur->as<ListNode>().contents()) {
if (!resolve(element, prefix)) {
return false;
@ -839,7 +839,7 @@ class NameResolver {
}
break;
case ParseNodeKind::Object:
case ParseNodeKind::ObjectExpr:
case ParseNodeKind::ClassMemberList:
for (ParseNode* element : cur->as<ListNode>().contents()) {
if (!resolve(element, prefix)) {
@ -850,21 +850,21 @@ class NameResolver {
// A template string list's contents alternate raw template string
// contents with expressions interpolated into the overall literal.
case ParseNodeKind::TemplateStringList:
case ParseNodeKind::TemplateStringListExpr:
if (!resolveTemplateLiteral(&cur->as<ListNode>(), prefix)) {
return false;
}
break;
case ParseNodeKind::TaggedTemplate:
case ParseNodeKind::TaggedTemplateExpr:
if (!resolveTaggedTemplate(&cur->as<BinaryNode>(), prefix)) {
return false;
}
break;
case ParseNodeKind::New:
case ParseNodeKind::Call:
case ParseNodeKind::SuperCall: {
case ParseNodeKind::NewExpr:
case ParseNodeKind::CallExpr:
case ParseNodeKind::SuperCallExpr: {
BinaryNode* callNode = &cur->as<BinaryNode>();
if (!resolve(callNode->left(), prefix)) {
return false;
@ -895,7 +895,8 @@ class NameResolver {
bool isImport = cur->isKind(ParseNodeKind::ImportSpecList);
ListNode* list = &cur->as<ListNode>();
ParseNode* item = list->head();
if (!isImport && item && item->isKind(ParseNodeKind::ExportBatchSpec)) {
if (!isImport && item &&
item->isKind(ParseNodeKind::ExportBatchSpecStmt)) {
MOZ_ASSERT(item->is<NullaryNode>());
break;
}
@ -912,7 +913,7 @@ class NameResolver {
break;
}
case ParseNodeKind::CallImport: {
case ParseNodeKind::CallImportExpr: {
BinaryNode* node = &cur->as<BinaryNode>();
if (!resolve(node->right(), prefix)) {
return false;
@ -920,7 +921,7 @@ class NameResolver {
break;
}
case ParseNodeKind::Dot: {
case ParseNodeKind::DotExpr: {
// Super prop nodes do not have a meaningful LHS
PropertyAccess* prop = &cur->as<PropertyAccess>();
if (prop->isSuper()) {
@ -932,7 +933,7 @@ class NameResolver {
break;
}
case ParseNodeKind::Label:
case ParseNodeKind::LabelStmt:
if (!resolve(cur->as<LabeledStatement>().statement(), prefix)) {
return false;
}
@ -963,11 +964,11 @@ class NameResolver {
// Kinds that should be handled by parent node resolution.
case ParseNodeKind::ImportSpec: // by ParseNodeKind::ImportSpecList
case ParseNodeKind::ExportSpec: // by ParseNodeKind::ExportSpecList
case ParseNodeKind::CallSiteObj: // by ParseNodeKind::TaggedTemplate
case ParseNodeKind::ClassNames: // by ParseNodeKind::Class
case ParseNodeKind::PropertyName: // by ParseNodeKind::Dot
case ParseNodeKind::ImportSpec: // by ParseNodeKind::ImportSpecList
case ParseNodeKind::ExportSpec: // by ParseNodeKind::ExportSpecList
case ParseNodeKind::CallSiteObjExpr: // by ParseNodeKind::TaggedTemplate
case ParseNodeKind::ClassNames: // by ParseNodeKind::ClassDecl
case ParseNodeKind::PropertyNameExpr: // by ParseNodeKind::Dot
MOZ_CRASH("should have been handled by a parent node");
case ParseNodeKind::Limit: // invalid sentinel value

View File

@ -78,8 +78,8 @@ ParseNode* ParseNode::appendOrCreateList(ParseNodeKind kind, ParseNode* left,
// processed with a left fold because (+) is left-associative.
//
if (left->isKind(kind) &&
(kind == ParseNodeKind::Pow ? !left->pn_parens
: left->isBinaryOperation())) {
(kind == ParseNodeKind::PowExpr ? !left->pn_parens
: left->isBinaryOperation())) {
ListNode* list = &left->as<ListNode>();
list->append(right);
@ -99,7 +99,7 @@ ParseNode* ParseNode::appendOrCreateList(ParseNodeKind kind, ParseNode* left,
}
const ParseNodeArity js::frontend::ParseNodeKindArity[] = {
#define ARITY(_name, arity) arity,
#define ARITY(_name, type) type::arity(),
FOR_EACH_PARSE_NODE_KIND(ARITY)
#undef ARITY
};
@ -107,7 +107,7 @@ const ParseNodeArity js::frontend::ParseNodeKindArity[] = {
#ifdef DEBUG
static const char* const parseNodeNames[] = {
#define STRINGIFY(name, _arity) #name,
#define STRINGIFY(name, _type) #name,
FOR_EACH_PARSE_NODE_KIND(STRINGIFY)
#undef STRINGIFY
};
@ -186,16 +186,16 @@ void ParseNode::dump(GenericPrinter& out, int indent) {
void NullaryNode::dump(GenericPrinter& out) {
switch (getKind()) {
case ParseNodeKind::True:
case ParseNodeKind::TrueExpr:
out.put("#true");
break;
case ParseNodeKind::False:
case ParseNodeKind::FalseExpr:
out.put("#false");
break;
case ParseNodeKind::Null:
case ParseNodeKind::NullExpr:
out.put("#null");
break;
case ParseNodeKind::RawUndefined:
case ParseNodeKind::RawUndefinedExpr:
out.put("#undefined");
break;
@ -246,7 +246,7 @@ void UnaryNode::dump(GenericPrinter& out, int indent) {
}
void BinaryNode::dump(GenericPrinter& out, int indent) {
if (isKind(ParseNodeKind::Dot)) {
if (isKind(ParseNodeKind::DotExpr)) {
out.put("(.");
DumpParseTree(right(), out, indent + 2);
@ -325,8 +325,8 @@ static void DumpName(GenericPrinter& out, const CharT* s, size_t len) {
void NameNode::dump(GenericPrinter& out, int indent) {
switch (getKind()) {
case ParseNodeKind::String:
case ParseNodeKind::TemplateString:
case ParseNodeKind::StringExpr:
case ParseNodeKind::TemplateStringExpr:
case ParseNodeKind::ObjectPropertyName:
atom()->dumpCharsNoNewline(out);
return;
@ -334,7 +334,7 @@ void NameNode::dump(GenericPrinter& out, int indent) {
case ParseNodeKind::Name:
case ParseNodeKind::PrivateName: // atom() already includes the '#', no
// need to specially include it.
case ParseNodeKind::PropertyName:
case ParseNodeKind::PropertyNameExpr:
if (!atom()) {
out.put("#<null name>");
} else if (getOp() == JSOP_GETARG && atom()->length() == 0) {
@ -355,7 +355,7 @@ void NameNode::dump(GenericPrinter& out, int indent) {
}
return;
case ParseNodeKind::Label: {
case ParseNodeKind::LabelStmt: {
const char* name = parseNodeNames[size_t(getKind())];
out.printf("(%s ", name);
atom()->dumpCharsNoNewline(out);
@ -476,7 +476,7 @@ bool js::frontend::IsAnonymousFunctionDefinition(ParseNode* pn) {
// ES 2017 draft
// 12.15.2 (ArrowFunction, AsyncArrowFunction).
// 14.1.12 (FunctionExpression).
// 14.4.8 (GeneratorExpression).
// 14.4.8 (Generatoression).
// 14.6.8 (AsyncFunctionExpression)
if (pn->isKind(ParseNodeKind::Function) &&
!pn->as<CodeNode>().funbox()->function()->explicitName()) {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef frontend_ParseNodeVisitor_h
#define frontend_ParseNodeVisitor_h
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "jsfriendapi.h"
#include "frontend/ParseNode.h"
namespace js {
namespace frontend {
/**
* Utility class for walking a JS AST.
*
* Simple usage:
*
* class HowTrueVisitor : public ParseNodeVisitor<HowTrueVisitor> {
* public:
* bool visitTrue(ParseNode*& pn) {
* std::cout << "How true.\n";
* return true;
* }
* bool visitClass(ParseNode*& pn) {
* // The base-class implementation of each visit method
* // simply visits the node's children. So the subclass
* // gets to decide whether to descend into a subtree
* // and can do things either before or after:
* std::cout << "How classy.\n";
* return ParseNodeVisitor::visitClass(pn);
* }
* };
*
* HowTrueVisitor v;
* v.visit(programRootNode); // walks the entire tree
*
* Note that the Curiously Recurring Template Pattern is used for performance,
* as it eliminates the need for virtual method calls. Some rough testing shows
* about a 12% speedup in the FoldConstants.cpp pass.
* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
*/
template <typename Super>
class ParseNodeVisitor {
public:
JSContext* cx;
explicit ParseNodeVisitor(JSContext* cx) : cx(cx) {}
MOZ_MUST_USE bool visit(ParseNode*& pn) {
if (!CheckRecursionLimit(cx)) {
return false;
}
switch (pn->getKind()) {
#define VISIT_CASE(KIND, _type) \
case ParseNodeKind::KIND: \
return static_cast<Super*>(this)->visit##KIND(pn);
FOR_EACH_PARSE_NODE_KIND(VISIT_CASE)
#undef VISIT_CASE
default:
MOZ_CRASH("invalid node kind");
}
}
// using static_cast<Super*> here allows plain visit() to be overridden.
#define VISIT_METHOD(KIND, TYPE) \
MOZ_MUST_USE bool visit##KIND(ParseNode*& pn) { \
MOZ_ASSERT(pn->is<TYPE>(), \
"Node of kind " #KIND " was not of type " #TYPE); \
return pn->as<TYPE>().accept(*static_cast<Super*>(this)); \
}
FOR_EACH_PARSE_NODE_KIND(VISIT_METHOD)
#undef VISIT_METHOD
};
} // namespace frontend
} // namespace js
#endif // frontend_ParseNodeVisitor_h

View File

@ -2792,7 +2792,7 @@ GeneralParser<ParseHandler, Unit>::templateLiteral(
}
ListNodeType nodeList =
handler.newList(ParseNodeKind::TemplateStringList, literal);
handler.newList(ParseNodeKind::TemplateStringListExpr, literal);
if (!nodeList) {
return null();
}
@ -3929,7 +3929,7 @@ GeneralParser<ParseHandler, Unit>::bindingInitializer(
}
BinaryNodeType assign =
handler.newAssignment(ParseNodeKind::Assign, lhs, rhs);
handler.newAssignment(ParseNodeKind::AssignExpr, lhs, rhs);
if (!assign) {
return null();
}
@ -4370,7 +4370,7 @@ GeneralParser<ParseHandler, Unit>::declarationPattern(
return null();
}
return handler.newAssignment(ParseNodeKind::Assign, pattern, init);
return handler.newAssignment(ParseNodeKind::AssignExpr, pattern, init);
}
template <class ParseHandler, typename Unit>
@ -4532,18 +4532,18 @@ GeneralParser<ParseHandler, Unit>::declarationList(
YieldHandling yieldHandling, ParseNodeKind kind,
ParseNodeKind* forHeadKind /* = nullptr */,
Node* forInOrOfExpression /* = nullptr */) {
MOZ_ASSERT(kind == ParseNodeKind::Var || kind == ParseNodeKind::Let ||
kind == ParseNodeKind::Const);
MOZ_ASSERT(kind == ParseNodeKind::VarStmt || kind == ParseNodeKind::LetDecl ||
kind == ParseNodeKind::ConstDecl);
DeclarationKind declKind;
switch (kind) {
case ParseNodeKind::Var:
case ParseNodeKind::VarStmt:
declKind = DeclarationKind::Var;
break;
case ParseNodeKind::Const:
case ParseNodeKind::ConstDecl:
declKind = DeclarationKind::Const;
break;
case ParseNodeKind::Let:
case ParseNodeKind::LetDecl:
declKind = DeclarationKind::Let;
break;
default:
@ -4614,8 +4614,8 @@ GeneralParser<ParseHandler, Unit>::lexicalDeclaration(
* See 8.1.1.1.6 and the note in 13.2.1.
*/
ListNodeType decl = declarationList(
yieldHandling, kind == DeclarationKind::Const ? ParseNodeKind::Const
: ParseNodeKind::Let);
yieldHandling, kind == DeclarationKind::Const ? ParseNodeKind::ConstDecl
: ParseNodeKind::LetDecl);
if (!decl || !matchOrInsertSemicolon()) {
return null();
}
@ -4937,7 +4937,7 @@ inline bool GeneralParser<ParseHandler, Unit>::checkExportedName(
template <typename Unit>
bool Parser<FullParseHandler, Unit>::checkExportedNamesForArrayBinding(
ListNode* array) {
MOZ_ASSERT(array->isKind(ParseNodeKind::Array));
MOZ_ASSERT(array->isKind(ParseNodeKind::ArrayExpr));
for (ParseNode* node : array->contents()) {
if (node->isKind(ParseNodeKind::Elision)) {
@ -4947,7 +4947,7 @@ bool Parser<FullParseHandler, Unit>::checkExportedNamesForArrayBinding(
ParseNode* binding;
if (node->isKind(ParseNodeKind::Spread)) {
binding = node->as<UnaryNode>().kid();
} else if (node->isKind(ParseNodeKind::Assign)) {
} else if (node->isKind(ParseNodeKind::AssignExpr)) {
binding = node->as<AssignmentNode>().left();
} else {
binding = node;
@ -4978,7 +4978,7 @@ GeneralParser<ParseHandler, Unit>::checkExportedNamesForArrayBinding(
template <typename Unit>
bool Parser<FullParseHandler, Unit>::checkExportedNamesForObjectBinding(
ListNode* obj) {
MOZ_ASSERT(obj->isKind(ParseNodeKind::Object));
MOZ_ASSERT(obj->isKind(ParseNodeKind::ObjectExpr));
for (ParseNode* node : obj->contents()) {
MOZ_ASSERT(node->isKind(ParseNodeKind::MutateProto) ||
@ -4996,7 +4996,7 @@ bool Parser<FullParseHandler, Unit>::checkExportedNamesForObjectBinding(
target = node->as<BinaryNode>().right();
}
if (target->isKind(ParseNodeKind::Assign)) {
if (target->isKind(ParseNodeKind::AssignExpr)) {
target = target->as<AssignmentNode>().left();
}
}
@ -5030,12 +5030,12 @@ bool Parser<FullParseHandler, Unit>::checkExportedNamesForDeclaration(
if (!checkExportedName(node->as<NameNode>().atom())) {
return false;
}
} else if (node->isKind(ParseNodeKind::Array)) {
} else if (node->isKind(ParseNodeKind::ArrayExpr)) {
if (!checkExportedNamesForArrayBinding(&node->as<ListNode>())) {
return false;
}
} else {
MOZ_ASSERT(node->isKind(ParseNodeKind::Object));
MOZ_ASSERT(node->isKind(ParseNodeKind::ObjectExpr));
if (!checkExportedNamesForObjectBinding(&node->as<ListNode>())) {
return false;
}
@ -5061,7 +5061,7 @@ template <typename Unit>
bool Parser<FullParseHandler, Unit>::checkExportedNamesForDeclarationList(
ListNode* node) {
for (ParseNode* binding : node->contents()) {
if (binding->isKind(ParseNodeKind::Assign)) {
if (binding->isKind(ParseNodeKind::AssignExpr)) {
binding = binding->as<AssignmentNode>().left();
} else {
MOZ_ASSERT(binding->isKind(ParseNodeKind::Name));
@ -5402,7 +5402,7 @@ GeneralParser<ParseHandler, Unit>::exportVariableStatement(uint32_t begin) {
MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Var));
ListNodeType kid = declarationList(YieldIsName, ParseNodeKind::Var);
ListNodeType kid = declarationList(YieldIsName, ParseNodeKind::VarStmt);
if (!kid) {
return null();
}
@ -5982,7 +5982,7 @@ bool GeneralParser<ParseHandler, Unit>::forHeadStart(
tokenStream.consumeKnownToken(tt, TokenStream::Operand);
// Pass null for block object because |var| declarations don't use one.
*forInitialPart = declarationList(yieldHandling, ParseNodeKind::Var,
*forInitialPart = declarationList(yieldHandling, ParseNodeKind::VarStmt,
forHeadKind, forInOrOfExpression);
return *forInitialPart != null();
}
@ -6027,10 +6027,11 @@ bool GeneralParser<ParseHandler, Unit>::forHeadStart(
// statements.
ParseContext::Statement forHeadStmt(pc, StatementKind::ForLoopLexicalHead);
*forInitialPart = declarationList(
yieldHandling,
tt == TokenKind::Const ? ParseNodeKind::Const : ParseNodeKind::Let,
forHeadKind, forInOrOfExpression);
*forInitialPart =
declarationList(yieldHandling,
tt == TokenKind::Const ? ParseNodeKind::ConstDecl
: ParseNodeKind::LetDecl,
forHeadKind, forInOrOfExpression);
return *forInitialPart != null();
}
@ -6565,7 +6566,7 @@ GeneralParser<ParseHandler, Unit>::yieldExpression(InHandling inHandling) {
pc->lastYieldOffset = begin;
Node exprNode;
ParseNodeKind kind = ParseNodeKind::Yield;
ParseNodeKind kind = ParseNodeKind::YieldExpr;
TokenKind tt = TokenKind::Eof;
if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand)) {
return null();
@ -6591,7 +6592,7 @@ GeneralParser<ParseHandler, Unit>::yieldExpression(InHandling inHandling) {
anyChars.addModifierException(TokenStream::NoneIsOperand);
break;
case TokenKind::Mul:
kind = ParseNodeKind::YieldStar;
kind = ParseNodeKind::YieldStarExpr;
tokenStream.consumeKnownToken(TokenKind::Mul, TokenStream::Operand);
MOZ_FALLTHROUGH;
default:
@ -6600,7 +6601,7 @@ GeneralParser<ParseHandler, Unit>::yieldExpression(InHandling inHandling) {
return null();
}
}
if (kind == ParseNodeKind::YieldStar) {
if (kind == ParseNodeKind::YieldStarExpr) {
return handler.newYieldStarExpression(begin, exprNode);
}
return handler.newYieldExpression(begin, exprNode);
@ -7344,7 +7345,7 @@ template <class ParseHandler, typename Unit>
typename ParseHandler::Node
GeneralParser<ParseHandler, Unit>::variableStatement(
YieldHandling yieldHandling) {
ListNodeType vars = declarationList(yieldHandling, ParseNodeKind::Var);
ListNodeType vars = declarationList(yieldHandling, ParseNodeKind::VarStmt);
if (!vars) {
return null();
}
@ -8234,43 +8235,43 @@ typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::assignExpr(
ParseNodeKind kind;
switch (tokenAfterLHS) {
case TokenKind::Assign:
kind = ParseNodeKind::Assign;
kind = ParseNodeKind::AssignExpr;
break;
case TokenKind::AddAssign:
kind = ParseNodeKind::AddAssign;
kind = ParseNodeKind::AddAssignExpr;
break;
case TokenKind::SubAssign:
kind = ParseNodeKind::SubAssign;
kind = ParseNodeKind::SubAssignExpr;
break;
case TokenKind::BitOrAssign:
kind = ParseNodeKind::BitOrAssign;
kind = ParseNodeKind::BitOrAssignExpr;
break;
case TokenKind::BitXorAssign:
kind = ParseNodeKind::BitXorAssign;
kind = ParseNodeKind::BitXorAssignExpr;
break;
case TokenKind::BitAndAssign:
kind = ParseNodeKind::BitAndAssign;
kind = ParseNodeKind::BitAndAssignExpr;
break;
case TokenKind::LshAssign:
kind = ParseNodeKind::LshAssign;
kind = ParseNodeKind::LshAssignExpr;
break;
case TokenKind::RshAssign:
kind = ParseNodeKind::RshAssign;
kind = ParseNodeKind::RshAssignExpr;
break;
case TokenKind::UrshAssign:
kind = ParseNodeKind::UrshAssign;
kind = ParseNodeKind::UrshAssignExpr;
break;
case TokenKind::MulAssign:
kind = ParseNodeKind::MulAssign;
kind = ParseNodeKind::MulAssignExpr;
break;
case TokenKind::DivAssign:
kind = ParseNodeKind::DivAssign;
kind = ParseNodeKind::DivAssignExpr;
break;
case TokenKind::ModAssign:
kind = ParseNodeKind::ModAssign;
kind = ParseNodeKind::ModAssignExpr;
break;
case TokenKind::PowAssign:
kind = ParseNodeKind::PowAssign;
kind = ParseNodeKind::PowAssignExpr;
break;
default:
@ -8289,7 +8290,7 @@ typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::assignExpr(
// Verify the left-hand side expression doesn't have a forbidden form.
if (handler.isUnparenthesizedDestructuringPattern(lhs)) {
if (kind != ParseNodeKind::Assign) {
if (kind != ParseNodeKind::AssignExpr) {
error(JSMSG_BAD_DESTRUCT_ASS);
return null();
}
@ -8435,15 +8436,15 @@ typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::unaryExpr(
uint32_t begin = pos().begin;
switch (tt) {
case TokenKind::Void:
return unaryOpExpr(yieldHandling, ParseNodeKind::Void, begin);
return unaryOpExpr(yieldHandling, ParseNodeKind::VoidExpr, begin);
case TokenKind::Not:
return unaryOpExpr(yieldHandling, ParseNodeKind::Not, begin);
return unaryOpExpr(yieldHandling, ParseNodeKind::NotExpr, begin);
case TokenKind::BitNot:
return unaryOpExpr(yieldHandling, ParseNodeKind::BitNot, begin);
return unaryOpExpr(yieldHandling, ParseNodeKind::BitNotExpr, begin);
case TokenKind::Add:
return unaryOpExpr(yieldHandling, ParseNodeKind::Pos, begin);
return unaryOpExpr(yieldHandling, ParseNodeKind::PosExpr, begin);
case TokenKind::Sub:
return unaryOpExpr(yieldHandling, ParseNodeKind::Neg, begin);
return unaryOpExpr(yieldHandling, ParseNodeKind::NegExpr, begin);
case TokenKind::TypeOf: {
// The |typeof| operator is specially parsed to distinguish its
@ -8477,8 +8478,9 @@ typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::unaryExpr(
if (!operand || !checkIncDecOperand(operand, operandOffset)) {
return null();
}
ParseNodeKind pnk = (tt == TokenKind::Inc) ? ParseNodeKind::PreIncrement
: ParseNodeKind::PreDecrement;
ParseNodeKind pnk = (tt == TokenKind::Inc)
? ParseNodeKind::PreIncrementExpr
: ParseNodeKind::PreDecrementExpr;
return handler.newUpdate(pnk, begin, operand);
}
@ -8546,8 +8548,9 @@ typename ParseHandler::Node GeneralParser<ParseHandler, Unit>::unaryExpr(
return null();
}
ParseNodeKind pnk = (tt == TokenKind::Inc) ? ParseNodeKind::PostIncrement
: ParseNodeKind::PostDecrement;
ParseNodeKind pnk = (tt == TokenKind::Inc)
? ParseNodeKind::PostIncrementExpr
: ParseNodeKind::PostDecrementExpr;
return handler.newUpdate(pnk, begin, expr);
}
}
@ -9908,7 +9911,7 @@ GeneralParser<ParseHandler, Unit>::objectLiteral(YieldHandling yieldHandling,
}
BinaryNodeType propExpr =
handler.newAssignment(ParseNodeKind::Assign, lhs, rhs);
handler.newAssignment(ParseNodeKind::AssignExpr, lhs, rhs);
if (!propExpr) {
return null();
}

View File

@ -540,9 +540,9 @@ class SyntaxParseHandler {
}
ListNodeType newList(ParseNodeKind kind, const TokenPos& pos) {
MOZ_ASSERT(kind != ParseNodeKind::Var);
MOZ_ASSERT(kind != ParseNodeKind::Let);
MOZ_ASSERT(kind != ParseNodeKind::Const);
MOZ_ASSERT(kind != ParseNodeKind::VarStmt);
MOZ_ASSERT(kind != ParseNodeKind::LetDecl);
MOZ_ASSERT(kind != ParseNodeKind::ConstDecl);
return NodeGeneric;
}
@ -551,10 +551,11 @@ class SyntaxParseHandler {
}
ListNodeType newDeclarationList(ParseNodeKind kind, const TokenPos& pos) {
if (kind == ParseNodeKind::Var) {
if (kind == ParseNodeKind::VarStmt) {
return NodeVarDeclaration;
}
MOZ_ASSERT(kind == ParseNodeKind::Let || kind == ParseNodeKind::Const);
MOZ_ASSERT(kind == ParseNodeKind::LetDecl ||
kind == ParseNodeKind::ConstDecl);
return NodeLexicalDeclaration;
}
@ -579,8 +580,8 @@ class SyntaxParseHandler {
}
AssignmentNodeType newAssignment(ParseNodeKind kind, Node lhs, Node rhs) {
return kind == ParseNodeKind::Assign ? NodeUnparenthesizedAssignment
: NodeGeneric;
return kind == ParseNodeKind::AssignExpr ? NodeUnparenthesizedAssignment
: NodeGeneric;
}
bool isUnparenthesizedAssignment(Node node) {

View File

@ -7926,8 +7926,13 @@ Realm* js::NewRealm(JSContext* cx, JSPrincipals* principals,
zone = zoneHolder.get();
}
if (!comp) {
compHolder = cx->make_unique<JS::Compartment>(zone);
bool invisibleToDebugger = options.creationOptions().invisibleToDebugger();
if (comp) {
// Debugger visibility is per-compartment, not per-realm, so make sure the
// new realm's visibility matches its compartment's.
MOZ_ASSERT(comp->invisibleToDebugger() == invisibleToDebugger);
} else {
compHolder = cx->make_unique<JS::Compartment>(zone, invisibleToDebugger);
if (!compHolder) {
return nullptr;
}

View File

@ -1,8 +0,0 @@
function checkMethods(proto) {
var names = Object.getOwnPropertyNames(proto);
for (var i = 0; i < names.length; i++) {
var name = names[i];
var prop = proto[name];
}
}
checkMethods(Function.prototype);

View File

@ -1,2 +1,2 @@
assertEq(Function.prototype.toString(), "function () {\n}");
assertEq(Function.prototype.toSource(), "function () {\n}");
assertEq(Function.prototype.toString(), "function () {\n [native code]\n}");
assertEq(Function.prototype.toSource(), "function () {\n [native code]\n}");

View File

@ -10,7 +10,7 @@ var allScripts = dbg.findScripts();
var scripts = dbg.findScripts({
source: o.script.source
});
assertEq(scripts.length < allScripts.length, true);
assertEq(scripts.length, allScripts.length);
assertEq(scripts.indexOf(o.script) !== -1, true);
scripts = dbg.findScripts({

View File

@ -59,7 +59,6 @@ Pattern({
JSString: { count: Pattern.NATURAL },
'js::Shape': { count: Pattern.NATURAL },
JSObject: { count: Pattern.NATURAL },
JSScript: { count: Pattern.NATURAL }
})
.assert(dbg.memory.takeCensus({ breakdown: { by: 'internalType' } }));
@ -77,7 +76,6 @@ Pattern({
JSString: coarse_type_pattern,
'js::Shape': coarse_type_pattern,
JSObject: coarse_type_pattern,
JSScript: coarse_type_pattern,
})
.assert(dbg.memory.takeCensus({
breakdown: { by: 'internalType',

View File

@ -1,8 +0,0 @@
// Function.prototype's script source should be fully initialized.
var g = newGlobal();
var dbg = new Debugger;
var gw = dbg.addDebuggee(g);
var DOfp = gw.getOwnPropertyDescriptor('Function').value.proto;
// This should not crash.
print(DOfp.script.source.introductionScript);

View File

@ -1,11 +0,0 @@
// Source.prototype.url is null for Function.prototype.
var g = newGlobal();
var dbg = new Debugger;
var gw = dbg.addDebuggee(g);
var Fpw = gw.getOwnPropertyDescriptor('Function').value.proto;
assertEq(Fpw.script.source.url, null);

View File

@ -1,11 +0,0 @@
// In a debuggee, the Function.prototype script source has the introductionType
// property set to "Function.prototype".
var g = newGlobal();
var dbg = new Debugger(g);
var scripts = dbg.findScripts();
assertEq(scripts.length > 0, true);
var fpScripts = scripts.filter(s => s.source.introductionType == "Function.prototype");
assertEq(fpScripts.length, 1);
var source = fpScripts[0].source;
assertEq(source.text, "function () {\n}");

View File

@ -3855,19 +3855,19 @@ JS_PUBLIC_API void JS_ResetInterruptCallback(JSContext* cx, bool enable) {
* Promises.
*/
JS_PUBLIC_API void JS::SetGetIncumbentGlobalCallback(
JSContext* cx, JSGetIncumbentGlobalCallback callback) {
JSContext* cx, GetIncumbentGlobalCallback callback) {
cx->getIncumbentGlobalCallback = callback;
}
JS_PUBLIC_API void JS::SetEnqueuePromiseJobCallback(
JSContext* cx, JSEnqueuePromiseJobCallback callback,
JSContext* cx, EnqueuePromiseJobCallback callback,
void* data /* = nullptr */) {
cx->enqueuePromiseJobCallback = callback;
cx->enqueuePromiseJobCallbackData = data;
}
extern JS_PUBLIC_API void JS::SetPromiseRejectionTrackerCallback(
JSContext* cx, JSPromiseRejectionTrackerCallback callback,
JSContext* cx, PromiseRejectionTrackerCallback callback,
void* data /* = nullptr */) {
cx->promiseRejectionTrackerCallback = callback;
cx->promiseRejectionTrackerCallbackData = data;

View File

@ -169,25 +169,6 @@ class HandleValueArray {
typedef bool (*JSInterruptCallback)(JSContext* cx);
typedef JSObject* (*JSGetIncumbentGlobalCallback)(JSContext* cx);
typedef bool (*JSEnqueuePromiseJobCallback)(JSContext* cx,
JS::HandleObject promise,
JS::HandleObject job,
JS::HandleObject allocationSite,
JS::HandleObject incumbentGlobal,
void* data);
namespace JS {
enum class PromiseRejectionHandlingState { Unhandled, Handled };
} /* namespace JS */
typedef void (*JSPromiseRejectionTrackerCallback)(
JSContext* cx, JS::HandleObject promise,
JS::PromiseRejectionHandlingState state, void* data);
/**
* Callback used to ask the embedding for the cross compartment wrapper handler
* that implements the desired prolicy for this kind of object in the
@ -1549,10 +1530,15 @@ class JS_PUBLIC_API RealmCreationOptions {
RealmCreationOptions& setNewCompartmentAndZone();
RealmCreationOptions& setExistingCompartment(JSObject* obj);
// Certain scopes (i.e. XBL compilation scopes) are implementation details
// of the embedding, and references to them should never leak out to script.
// This flag causes the this realm to skip firing onNewGlobalObject and
// makes addDebuggee a no-op for this global.
// Certain compartments are implementation details of the embedding, and
// references to them should never leak out to script. This flag causes this
// realm to skip firing onNewGlobalObject and makes addDebuggee a no-op for
// this global.
//
// Debugger visibility is per-compartment, not per-realm (it's only practical
// to enforce visibility on compartment boundaries), so if a realm is being
// created in an extant compartment, its requested visibility must match that
// of the compartment.
bool invisibleToDebugger() const { return invisibleToDebugger_; }
RealmCreationOptions& setInvisibleToDebugger(bool flag) {
invisibleToDebugger_ = flag;
@ -3283,304 +3269,6 @@ extern JS_PUBLIC_API void JS_RequestInterruptCallbackCanWait(JSContext* cx);
namespace JS {
/**
* Sets the callback that's invoked whenever an incumbent global is required.
*
* SpiderMonkey doesn't itself have a notion of incumbent globals as defined
* by the html spec, so we need the embedding to provide this.
* See dom/base/ScriptSettings.h for details.
*/
extern JS_PUBLIC_API void SetGetIncumbentGlobalCallback(
JSContext* cx, JSGetIncumbentGlobalCallback callback);
/**
* Sets the callback that's invoked whenever a Promise job should be enqeued.
*
* SpiderMonkey doesn't schedule Promise resolution jobs itself; instead,
* using this function the embedding can provide a callback to do that
* scheduling. The provided `callback` is invoked with the promise job,
* the corresponding Promise's allocation stack, and the `data` pointer
* passed here as arguments.
*/
extern JS_PUBLIC_API void SetEnqueuePromiseJobCallback(
JSContext* cx, JSEnqueuePromiseJobCallback callback, void* data = nullptr);
/**
* Sets the callback that's invoked whenever a Promise is rejected without
* a rejection handler, and when a Promise that was previously rejected
* without a handler gets a handler attached.
*/
extern JS_PUBLIC_API void SetPromiseRejectionTrackerCallback(
JSContext* cx, JSPromiseRejectionTrackerCallback callback,
void* data = nullptr);
/**
* Inform the runtime that the job queue is empty and the embedding is going to
* execute its last promise job. The runtime may now choose to skip creating
* promise jobs for asynchronous execution and instead continue execution
* synchronously. More specifically, this optimization is used to skip the
* standard job queuing behavior for `await` operations in async functions.
*
* This function may be called before executing the last job in the job queue.
* When it was called, JobQueueMayNotBeEmpty must be called in order to restore
* the default job queuing behavior before the embedding enqueues its next job
* into the job queue.
*/
extern JS_PUBLIC_API void JobQueueIsEmpty(JSContext* cx);
/**
* Inform the runtime that job queue is no longer empty. The runtime can now no
* longer skip creating promise jobs for asynchronous execution, because
* pending jobs in the job queue must be executed first to preserve the FIFO
* (first in - first out) property of the queue. This effectively undoes
* JobQueueIsEmpty and re-enables the standard job queuing behavior.
*
* This function must be called whenever enqueuing a job to the job queue when
* JobQueueIsEmpty was called previously.
*/
extern JS_PUBLIC_API void JobQueueMayNotBeEmpty(JSContext* cx);
/**
* Returns a new instance of the Promise builtin class in the current
* compartment, with the right slot layout.
*
* The `executor` can be a `nullptr`. In that case, the only way to resolve or
* reject the returned promise is via the `JS::ResolvePromise` and
* `JS::RejectPromise` JSAPI functions.
*
* If a `proto` is passed, that gets set as the instance's [[Prototype]]
* instead of the original value of `Promise.prototype`.
*/
extern JS_PUBLIC_API JSObject* NewPromiseObject(
JSContext* cx, JS::HandleObject executor, JS::HandleObject proto = nullptr);
/**
* Returns true if the given object is an unwrapped PromiseObject, false
* otherwise.
*/
extern JS_PUBLIC_API bool IsPromiseObject(JS::HandleObject obj);
/**
* Returns the current compartment's original Promise constructor.
*/
extern JS_PUBLIC_API JSObject* GetPromiseConstructor(JSContext* cx);
/**
* Returns the current compartment's original Promise.prototype.
*/
extern JS_PUBLIC_API JSObject* GetPromisePrototype(JSContext* cx);
// Keep this in sync with the PROMISE_STATE defines in SelfHostingDefines.h.
enum class PromiseState { Pending, Fulfilled, Rejected };
/**
* Returns the given Promise's state as a JS::PromiseState enum value.
*
* Returns JS::PromiseState::Pending if the given object is a wrapper that
* can't safely be unwrapped.
*/
extern JS_PUBLIC_API PromiseState GetPromiseState(JS::HandleObject promise);
/**
* Returns the given Promise's process-unique ID.
*/
JS_PUBLIC_API uint64_t GetPromiseID(JS::HandleObject promise);
/**
* Returns the given Promise's result: either the resolution value for
* fulfilled promises, or the rejection reason for rejected ones.
*/
extern JS_PUBLIC_API JS::Value GetPromiseResult(JS::HandleObject promise);
/**
* Returns whether the given promise's rejection is already handled or not.
*
* The caller must check the given promise is rejected before checking it's
* handled or not.
*/
extern JS_PUBLIC_API bool GetPromiseIsHandled(JS::HandleObject promise);
/**
* Returns a js::SavedFrame linked list of the stack that lead to the given
* Promise's allocation.
*/
extern JS_PUBLIC_API JSObject* GetPromiseAllocationSite(
JS::HandleObject promise);
extern JS_PUBLIC_API JSObject* GetPromiseResolutionSite(
JS::HandleObject promise);
#ifdef DEBUG
extern JS_PUBLIC_API void DumpPromiseAllocationSite(JSContext* cx,
JS::HandleObject promise);
extern JS_PUBLIC_API void DumpPromiseResolutionSite(JSContext* cx,
JS::HandleObject promise);
#endif
/**
* Calls the current compartment's original Promise.resolve on the original
* Promise constructor, with `resolutionValue` passed as an argument.
*/
extern JS_PUBLIC_API JSObject* CallOriginalPromiseResolve(
JSContext* cx, JS::HandleValue resolutionValue);
/**
* Calls the current compartment's original Promise.reject on the original
* Promise constructor, with `resolutionValue` passed as an argument.
*/
extern JS_PUBLIC_API JSObject* CallOriginalPromiseReject(
JSContext* cx, JS::HandleValue rejectionValue);
/**
* Resolves the given Promise with the given `resolutionValue`.
*
* Calls the `resolve` function that was passed to the executor function when
* the Promise was created.
*/
extern JS_PUBLIC_API bool ResolvePromise(JSContext* cx,
JS::HandleObject promiseObj,
JS::HandleValue resolutionValue);
/**
* Rejects the given `promise` with the given `rejectionValue`.
*
* Calls the `reject` function that was passed to the executor function when
* the Promise was created.
*/
extern JS_PUBLIC_API bool RejectPromise(JSContext* cx,
JS::HandleObject promiseObj,
JS::HandleValue rejectionValue);
/**
* Calls the current compartment's original Promise.prototype.then on the
* given `promise`, with `onResolve` and `onReject` passed as arguments.
*
* Throws a TypeError if `promise` isn't a Promise (or possibly a different
* error if it's a security wrapper or dead object proxy).
*
* Asserts that `onFulfilled` and `onRejected` are each either callable or
* null.
*/
extern JS_PUBLIC_API JSObject* CallOriginalPromiseThen(
JSContext* cx, JS::HandleObject promise, JS::HandleObject onFulfilled,
JS::HandleObject onRejected);
/**
* Unforgeable, optimized version of the JS builtin Promise.prototype.then.
*
* Takes a Promise instance and `onResolve`, `onReject` callables to enqueue
* as reactions for that promise. In difference to Promise.prototype.then,
* this doesn't create and return a new Promise instance.
*
* Throws a TypeError if `promise` isn't a Promise (or possibly a different
* error if it's a security wrapper or dead object proxy).
*
* Asserts that `onFulfilled` and `onRejected` are each either callable or
* null.
*/
extern JS_PUBLIC_API bool AddPromiseReactions(JSContext* cx,
JS::HandleObject promise,
JS::HandleObject onFulfilled,
JS::HandleObject onRejected);
// This enum specifies whether a promise is expected to keep track of
// information that is useful for embedders to implement user activation
// behavior handling as specified in the HTML spec:
// https://html.spec.whatwg.org/multipage/interaction.html#triggered-by-user-activation
// By default, promises created by SpiderMonkey do not make any attempt to keep
// track of information about whether an activation behavior was being processed
// when the original promise in a promise chain was created. If the embedder
// sets either of the HadUserInteractionAtCreation or
// DidntHaveUserInteractionAtCreation flags on a promise after creating it,
// SpiderMonkey will propagate that flag to newly created promises when
// processing Promise#then and will make it possible to query this flag off of a
// promise further down the chain later using the
// GetPromiseUserInputEventHandlingState() API.
enum class PromiseUserInputEventHandlingState {
// Don't keep track of this state (default for all promises)
DontCare,
// Keep track of this state, the original promise in the chain was created
// while an activation behavior was being processed.
HadUserInteractionAtCreation,
// Keep track of this state, the original promise in the chain was created
// while an activation behavior was not being processed.
DidntHaveUserInteractionAtCreation
};
/**
* Returns the given Promise's activation behavior state flag per above as a
* JS::PromiseUserInputEventHandlingState value. All promises are created with
* the DontCare state by default.
*
* Returns JS::PromiseUserInputEventHandlingState::DontCare if the given object
* is a wrapper that can't safely be unwrapped.
*/
extern JS_PUBLIC_API PromiseUserInputEventHandlingState
GetPromiseUserInputEventHandlingState(JS::HandleObject promise);
/**
* Sets the given Promise's activation behavior state flag per above as a
* JS::PromiseUserInputEventHandlingState value.
*
* Returns false if the given object is a wrapper that can't safely be
* unwrapped.
*/
extern JS_PUBLIC_API bool SetPromiseUserInputEventHandlingState(
JS::HandleObject promise, JS::PromiseUserInputEventHandlingState state);
/**
* Unforgeable version of the JS builtin Promise.all.
*
* Takes an AutoObjectVector of Promise objects and returns a promise that's
* resolved with an array of resolution values when all those promises have
* been resolved, or rejected with the rejection value of the first rejected
* promise.
*
* Asserts that all objects in the `promises` vector are, maybe wrapped,
* instances of `Promise` or a subclass of `Promise`.
*/
extern JS_PUBLIC_API JSObject* GetWaitForAllPromise(
JSContext* cx, const JS::AutoObjectVector& promises);
/**
* The Dispatchable interface allows the embedding to call SpiderMonkey
* on a JSContext thread when requested via DispatchToEventLoopCallback.
*/
class JS_PUBLIC_API Dispatchable {
protected:
// Dispatchables are created and destroyed by SpiderMonkey.
Dispatchable() = default;
virtual ~Dispatchable() = default;
public:
// ShuttingDown indicates that SpiderMonkey should abort async tasks to
// expedite shutdown.
enum MaybeShuttingDown { NotShuttingDown, ShuttingDown };
// Called by the embedding after DispatchToEventLoopCallback succeeds.
virtual void run(JSContext* cx, MaybeShuttingDown maybeShuttingDown) = 0;
};
/**
* DispatchToEventLoopCallback may be called from any thread, being passed the
* same 'closure' passed to InitDispatchToEventLoop() and Dispatchable from the
* same JSRuntime. If the embedding returns 'true', the embedding must call
* Dispatchable::run() on an active JSContext thread for the same JSRuntime on
* which 'closure' was registered. If DispatchToEventLoopCallback returns
* 'false', SpiderMonkey will assume a shutdown of the JSRuntime is in progress.
* This contract implies that, by the time the final JSContext is destroyed in
* the JSRuntime, the embedding must have (1) run all Dispatchables for which
* DispatchToEventLoopCallback returned true, (2) already started returning
* false from calls to DispatchToEventLoopCallback.
*/
typedef bool (*DispatchToEventLoopCallback)(void* closure,
Dispatchable* dispatchable);
extern JS_PUBLIC_API void InitDispatchToEventLoop(
JSContext* cx, DispatchToEventLoopCallback callback, void* closure);
/* Vector of characters used for holding build ids. */
typedef js::Vector<char, 0, js::SystemAllocPolicy> BuildIdCharVector;
@ -3677,17 +3365,6 @@ extern JS_PUBLIC_API void InitConsumeStreamCallback(
JSContext* cx, ConsumeStreamCallback consume,
ReportStreamErrorCallback report);
/**
* When a JSRuntime is destroyed it implicitly cancels all async tasks in
* progress, releasing any roots held by the task. However, this is not soon
* enough for cycle collection, which needs to have roots dropped earlier so
* that the cycle collector can transitively remove roots for a future GC. For
* these and other cases, the set of pending async tasks can be canceled
* with this call earlier than JSRuntime destruction.
*/
extern JS_PUBLIC_API void ShutdownAsyncTasks(JSContext* cx);
/**
* Supply an alternative stack to incorporate into captured SavedFrame
* backtraces as the imputed caller of asynchronous JavaScript calls, like async

Some files were not shown because too many files have changed in this diff Show More