mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 15:55:36 +00:00
Merge mozilla-central to mozilla-inbound
This commit is contained in:
commit
f1762a3667
4
.gitignore
vendored
4
.gitignore
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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]
|
||||
|
@ -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);
|
||||
});
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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::
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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__);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
31
dom/media/test/test_vp9_superframes.html
Normal file
31
dom/media/test/test_vp9_superframes.html
Normal 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>
|
BIN
dom/media/test/vp9-superframes.webm
Normal file
BIN
dom/media/test/vp9-superframes.webm
Normal file
Binary file not shown.
1
dom/media/test/vp9-superframes.webm^headers^
Normal file
1
dom/media/test/vp9-superframes.webm^headers^
Normal file
@ -0,0 +1 @@
|
||||
Cache-Control: no-store
|
@ -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)) ||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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]),
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
@ -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();
|
||||
|
298
gfx/vr/service/binding/OpenVRKnucklesBinding.h
Normal file
298
gfx/vr/service/binding/OpenVRKnucklesBinding.h
Normal 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
|
172
gfx/vr/service/binding/OpenVRViveBinding.h
Normal file
172
gfx/vr/service/binding/OpenVRViveBinding.h
Normal 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
|
192
gfx/vr/service/binding/OpenVRWMRBinding.h
Normal file
192
gfx/vr/service/binding/OpenVRWMRBinding.h
Normal 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
|
@ -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
|
||||
|
@ -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
@ -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`
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 );
|
||||
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 );
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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";
|
||||
|
||||
|
||||
}
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 );
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -1 +1 @@
|
||||
3a4ce4b66a7bc9bd10773744d20530c609a61e90
|
||||
4de718f9ea3435c099cabafc02e8b51da539bc62
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
342
js/public/Promise.h
Normal 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
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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/. */
|
||||
|
@ -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()) {
|
||||
|
@ -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:
|
||||
|
@ -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
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
86
js/src/frontend/ParseNodeVisitor.h
Normal file
86
js/src/frontend/ParseNodeVisitor.h
Normal 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
|
@ -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();
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
@ -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}");
|
||||
|
@ -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({
|
||||
|
@ -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',
|
||||
|
@ -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);
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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}");
|
@ -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;
|
||||
|
341
js/src/jsapi.h
341
js/src/jsapi.h
@ -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
Loading…
Reference in New Issue
Block a user