Commit 172bca0e authored by Ken Rockot's avatar Ken Rockot Committed by Commit Bot

Reland "Reland "Mojo JS: Use BigInt consistently for 64-bit int fields""

This is a reland of 0092862f

Original change's description:
> Reland "Mojo JS: Use BigInt consistently for 64-bit int fields"
>
> This is a reland of ea79bdd2
>
> Fix is in the delta from PS1 -> PS3
>
> Original change's description:
> > Mojo JS: Use BigInt consistently for 64-bit int fields
> >
> > This changes 64-bit integer fields to be deserialized as
> > BigInt values consistently, rather than sometimes being
> > BigInts and sometimes being Numbers.
> >
> > Fixed: 1102217,1009262
> > Change-Id: I9cc8d767058938e9c39f62f139737e512f47cdb2
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2466398
> > Reviewed-by: Ryan Sturm <ryansturm@chromium.org>
> > Reviewed-by: Moe Ahmadi <mahmadi@chromium.org>
> > Reviewed-by: François Doray <fdoray@chromium.org>
> > Reviewed-by: Becca Hughes <beccahughes@chromium.org>
> > Reviewed-by: Shik Chen <shik@chromium.org>
> > Reviewed-by: Oksana Zhuravlova <oksamyt@chromium.org>
> > Reviewed-by: Giovanni Ortuño Urquidi <ortuno@chromium.org>
> > Commit-Queue: Ken Rockot <rockot@google.com>
> > Cr-Commit-Position: refs/heads/master@{#818611}
>
> Change-Id: I393a33b44b1a3e1746f7b9ee021dbe06c3ff7b07
> Tbr: shik@chromium.org
> Tbr: fdoray@chromium.org
> Tbr: ryansturm@chromium.org
> Tbr: mahmadi@chromium.org
> Tbr: beccahughes@chromium.org
> Tbr: oksamyt@chromium.org
> Tbr: ortuno@chromium.org
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2485749
> Reviewed-by: François Doray <fdoray@chromium.org>
> Reviewed-by: Moe Ahmadi <mahmadi@chromium.org>
> Reviewed-by: Dan H <harringtond@chromium.org>
> Reviewed-by: Oksana Zhuravlova <oksamyt@chromium.org>
> Reviewed-by: Ryan Sturm <ryansturm@chromium.org>
> Reviewed-by: Becca Hughes <beccahughes@chromium.org>
> Commit-Queue: Ken Rockot <rockot@google.com>
> Auto-Submit: Ken Rockot <rockot@google.com>
> Cr-Commit-Position: refs/heads/master@{#819004}

NOPRESUBMIT=True

Change-Id: I51f628aa5898f66d26ff1d8c7ef3ade3d0f91045
Tbr: shik@chromium.org
Tbr: fdoray@chromium.org
Tbr: ryansturm@chromium.org
Tbr: mahmadi@chromium.org
Tbr: beccahughes@chromium.org
Tbr: oksamyt@chromium.org
Tbr: ortuno@chromium.org
Tbr: harringtond@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2489666
Commit-Queue: Ken Rockot <rockot@google.com>
Reviewed-by: default avatarThomas Lukaszewicz <tluk@chromium.org>
Reviewed-by: default avatarOksana Zhuravlova <oksamyt@chromium.org>
Reviewed-by: default avatarMoe Ahmadi <mahmadi@chromium.org>
Reviewed-by: default avatarShik Chen <shik@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Reviewed-by: default avatarDan H <harringtond@chromium.org>
Reviewed-by: default avatarBecca Hughes <beccahughes@chromium.org>
Auto-Submit: Ken Rockot <rockot@google.com>
Cr-Commit-Position: refs/heads/master@{#821026}
parent aaa14f97
......@@ -399,11 +399,12 @@ Polymer({
if (feature.useTimestamp) {
const nowSecondsFromEpoch = Math.round(Date.now() / 1000);
return 'Used ' +
durationToString(nowSecondsFromEpoch - feature.useTimestamp);
durationToString(
Number(BigInt(nowSecondsFromEpoch) - feature.useTimestamp));
}
if (feature.observationDuration) {
return secondsToString(feature.observationDuration);
return secondsToString(Number(feature.observationDuration));
}
return 'N/A';
......
......@@ -225,8 +225,8 @@ Polymer({
((reason === LifecycleUnitDiscardReason.URGENT) ? ' at ' +
// Must convert since Date constructor takes
// milliseconds.
(new Date(stateChangeTime.microseconds / 1000))
.toLocaleString() :
(new Date(Number(stateChangeTime.microseconds) / 1000)
.toLocaleString()) :
'');
}
assertNotReached('Unknown lifecycle state: ' + state);
......
......@@ -235,7 +235,7 @@ class ToolTip {
/** @implements {d3.ForceNode} */
class GraphNode {
constructor(id) {
/** @type {number} */
/** @type {bigint} */
this.id = id;
/** @type {string} */
this.color = 'black';
......@@ -320,7 +320,7 @@ class GraphNode {
return -200;
}
/** @return {!Array<number>} an array of node ids. */
/** @return {!Array<bigint>} an array of node ids. */
get linkTargets() {
return [];
}
......@@ -330,7 +330,7 @@ class GraphNode {
* things, but be owned by exactly one (per relationship type). As such, the
* relationship is expressed on the *owned* object. These links are drawn with
* an arrow at the beginning of the link, pointing to the owned object.
* @return {!Array<number>} an array of node ids.
* @return {!Array<bigint>} an array of node ids.
*/
get dashedLinkTargets() {
return [];
......@@ -338,11 +338,14 @@ class GraphNode {
/**
* Selects a color string from an id.
* @param {number} id The id the returned color is selected from.
* @param {bigint} id The id the returned color is selected from.
* @return {string}
*/
selectColor(id) {
return d3.schemeSet3[Math.abs(id) % 12];
if (id < 0) {
id = -id;
}
return d3.schemeSet3[Number(id % BigInt(12))];
}
}
......@@ -631,7 +634,7 @@ class Graph {
*/
this.dashedLinkGroup_ = null;
/** @private {!Map<number, !GraphNode>} */
/** @private {!Map<bigint, !GraphNode>} */
this.nodes_ = new Map();
/**
......@@ -850,7 +853,7 @@ class Graph {
*/
nodeDescriptions_(nodeDescriptions) {
for (const nodeId in nodeDescriptions) {
const node = this.nodes_.get(Number.parseInt(nodeId, 10));
const node = this.nodes_.get(BigInt(nodeId));
if (node && node.tooltip) {
node.tooltip.onDescription(nodeDescriptions[nodeId]);
}
......@@ -893,7 +896,7 @@ class Graph {
}
const type = /** @type {string} */ (event.data[0]);
const data = /** @type {Object|number} */ (event.data[1]);
const data = /** @type {Object|number|bigint} */ (event.data[1]);
switch (type) {
case 'frameCreated':
this.frameCreated(
......@@ -932,7 +935,7 @@ class Graph {
/** @type {!WorkerInfo} */ (data));
break;
case 'nodeDeleted':
this.nodeDeleted(/** @type {number} */ (data));
this.nodeDeleted(/** @type {bigint} */ (data));
break;
case 'nodeDescriptions':
this.nodeDescriptions_(/** @type {!Object<string>} */ (data));
......
......@@ -18,7 +18,7 @@ class DiscardsGraphChangeStreamImpl {
/**
* @param {string} type
* @param {Object|number} data
* @param {Object|number|bigint} data
*/
postMessage_(type, data) {
this.contentWindow_.postMessage([type, data], '*');
......@@ -118,12 +118,12 @@ Polymer({
*/
onMessage_(event) {
const type = /** @type {string} */ (event.data[0]);
const data = /** @type {Object|number} */ (event.data[1]);
const data = /** @type {Object|number|bigint} */ (event.data[1]);
switch (type) {
case 'requestNodeDescriptions':
// Forward the request through the mojoms and bounce the reply back.
this.graphDump_
.requestNodeDescriptions(/** @type {!Array<number>} */ (data))
.requestNodeDescriptions(/** @type {!Array<bigint>} */ (data))
.then(
(descriptions) => this.contentWindow_.postMessage(
['nodeDescriptions', descriptions.nodeDescriptionsJson],
......
......@@ -111,9 +111,9 @@ function setLinkNode(node, url) {
* @return {string}
*/
function toDateString(timeSinceEpoch) {
return timeSinceEpoch.microseconds === 0 ?
'' :
new Date(timeSinceEpoch.microseconds / 1000).toLocaleString();
const microseconds = Number(timeSinceEpoch.microseconds);
return microseconds === 0 ? '' :
new Date(microseconds / 1000).toLocaleString();
}
/**
......
......@@ -465,7 +465,7 @@ InterventionsInternalPageImpl.prototype = {
*/
logNewMessage(log) {
insertMessageRowToMessageLogTable(
log.time, log.type, log.description, log.url.url, log.pageId);
Number(log.time), log.type, log.description, log.url.url, log.pageId);
},
/**
......@@ -473,7 +473,7 @@ InterventionsInternalPageImpl.prototype = {
*
* @override
* @param {!string} host The blocklisted host.
* @param {number} time The time when the host was blocklisted in milliseconds
* @param {bigint} time The time when the host was blocklisted in milliseconds
* since Unix epoch.
*/
onBlocklistedHost(host, time) {
......@@ -487,7 +487,7 @@ InterventionsInternalPageImpl.prototype = {
const timeTd = document.createElement('td');
timeTd.setAttribute('class', 'host-blocklisted-time');
timeTd.textContent = getTimeFormat(time);
timeTd.textContent = getTimeFormat(Number(time));
row.appendChild(timeTd);
// TODO(thanhdle): Insert row at correct index. crbug.com/776105.
......@@ -511,12 +511,12 @@ InterventionsInternalPageImpl.prototype = {
* Update the blocklist cleared status on the page.
*
* @override
* @param {number} time The time of the event in milliseconds since Unix
* @param {bigint} time The time of the event in milliseconds since Unix
* epoch.
*/
onBlocklistCleared(time) {
const blocklistClearedStatus = $('blocklist-last-cleared-time');
blocklistClearedStatus.textContent = getTimeFormat(time);
blocklistClearedStatus.textContent = getTimeFormat(Number(time));
// Remove hosts from table.
const blocklistedHostsTable = $('blocklisted-hosts-table');
......@@ -529,7 +529,8 @@ InterventionsInternalPageImpl.prototype = {
// Log event message.
insertMessageRowToMessageLogTable(
time, 'Blocklist', 'Blocklist Cleared', '' /* URL */, 0 /* pageId */);
Number(time), 'Blocklist', 'Blocklist Cleared', '' /* URL */,
0 /* pageId */);
},
/**
......
......@@ -377,7 +377,7 @@ class MediaFeedsTableDelegate {
* @returns {number}
*/
function timeDeltaToSeconds(timeDelta) {
return timeDelta.microseconds / 1000 / 1000;
return Number(timeDelta.microseconds) / 1000 / 1000;
}
/**
......
......@@ -65,7 +65,7 @@ export function mojoString16(str) {
* @returns {!mojoBase.mojom.TimeDelta}
*/
export function mojoTimeDelta(timeDelta) {
return {microseconds: Math.floor(timeDelta * 1000)};
return {microseconds: BigInt(Math.floor(timeDelta * 1000))};
}
/**
......
......@@ -10,7 +10,7 @@ import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
import 'chrome://resources/polymer/v3_0/iron-iconset-svg/iron-iconset-svg.js';
import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
import './tab_search_item.js';
import './tab_search_search_field.js'
import './tab_search_search_field.js';
import './strings.js';
import {assert} from 'chrome://resources/js/assert.m.js';
......@@ -111,9 +111,9 @@ export class TabSearchAppElement extends PolymerElement {
/** @override */
ready() {
super.ready();
this.addEventListener(
'keydown',
(e) => {this.onKeyDown_(/** @type {!KeyboardEvent} **/ (e))});
this.addEventListener('keydown', (e) => {
this.onKeyDown_(/** @type {!KeyboardEvent} */ (e));
});
// Update option values for fuzzy search from feature params.
this.fuzzySearchOptions_ = Object.assign({}, this.fuzzySearchOptions_, {
......@@ -438,8 +438,9 @@ export class TabSearchAppElement extends PolymerElement {
});
result.sort(
(a, b) => (b.tab.lastActiveTimeTicks && a.tab.lastActiveTimeTicks) ?
b.tab.lastActiveTimeTicks.internalValue -
a.tab.lastActiveTimeTicks.internalValue :
Number(
b.tab.lastActiveTimeTicks.internalValue -
a.tab.lastActiveTimeTicks.internalValue) :
0);
this.filteredOpenTabs_ =
fuzzySearch(this.searchText_, result, this.fuzzySearchOptions_);
......
......@@ -21,7 +21,7 @@ class FakePageHandler extends TestBrowserProxy {
/** @override */
install(diskSize, username) {
this.methodCalled('install', [diskSize, username]);
this.methodCalled('install', [Number(diskSize), username]);
}
/** @override */
......@@ -236,7 +236,7 @@ suite('<crostini-installer-app>', () => {
await clickInstall();
await fakeBrowserProxy.handler.whenCalled('install').then(
([diskSize, username]) => {
assertEquals(diskSize, diskTicks[defaultIndex].value);
assertEquals(Number(diskSize), diskTicks[defaultIndex].value);
});
expectEquals(fakeBrowserProxy.handler.getCallCount('install'), 1);
});
......@@ -261,7 +261,7 @@ suite('<crostini-installer-app>', () => {
await clickInstall();
await fakeBrowserProxy.handler.whenCalled('install').then(
([diskSize, username]) => {
assertEquals(diskSize, diskTicks[1].value);
assertEquals(Number(diskSize), diskTicks[1].value);
});
expectEquals(fakeBrowserProxy.handler.getCallCount('install'), 1);
});
......
......@@ -89,7 +89,7 @@ suite('ConfirmatonPageTest', function() {
test('renders share target name', function() {
const name = 'Device Name';
confirmationPageElement.shareTarget = {
id: {high: 0, low: 0},
id: {high: BigInt(0), low: BigInt(0)},
name,
type: nearbyShare.mojom.ShareTargetType.kPhone,
};
......
......@@ -85,7 +85,7 @@ suite('DiscoveryPageTest', function() {
*/
function createShareTarget(name) {
return {
id: {high: 0, low: nextId++},
id: {high: BigInt(0), low: BigInt(nextId++)},
name,
type: nearbyShare.mojom.ShareTargetType.kPhone,
};
......
......@@ -61,7 +61,7 @@ suite('NewTabPageMostVisitedTest', () => {
source: i,
titleSource: i,
isQueryTile: false,
dataGenerationTime: {internalValue: 0},
dataGenerationTime: {internalValue: BigInt(0)},
};
});
const tilesRendered = eventToPromise('dom-change', mostVisited.$.tiles);
......@@ -897,7 +897,7 @@ suite('NewTabPageMostVisitedTest', () => {
source: 0,
titleSource: 0,
isQueryTile: false,
dataGenerationTime: {internalValue: 0},
dataGenerationTime: {internalValue: BigInt(0)},
});
assertDeepEquals(tiles[1], {
title: 'b',
......@@ -906,7 +906,7 @@ suite('NewTabPageMostVisitedTest', () => {
source: 1,
titleSource: 1,
isQueryTile: false,
dataGenerationTime: {internalValue: 0},
dataGenerationTime: {internalValue: BigInt(0)},
});
});
......@@ -931,7 +931,7 @@ suite('NewTabPageMostVisitedTest', () => {
source: 0,
titleSource: 0,
isQueryTile: false,
dataGenerationTime: {internalValue: 0},
dataGenerationTime: {internalValue: BigInt(0)},
});
});
......
......@@ -218,7 +218,7 @@ suite('TabSearchAppTest', () => {
tabId: 1,
title: 'Example',
url: 'https://example.com',
lastActiveTimeTicks: { internalValue: 1 },
lastActiveTimeTicks: {internalValue: BigInt(1)},
});
testProxy.getCallbackRouterRemote().tabUpdated(updatedTab);
await flushTasks();
......@@ -351,27 +351,28 @@ suite('TabSearchAppTest', () => {
test('Sort by most recent active tabs', async () => {
const tabs = [
{
index: 0,
tabId: 1,
title: 'Google',
url: 'https://www.google.com',
lastActiveTimeTicks: { internalValue: 2 },
},
{
index: 1,
tabId: 2,
title: 'Bing',
url: 'https://www.bing.com',
lastActiveTimeTicks: { internalValue: 4 },
},
{
index: 2,
tabId: 3,
title: 'Yahoo',
url: 'https://www.yahoo.com',
lastActiveTimeTicks: { internalValue: 3 },
}];
{
index: 0,
tabId: 1,
title: 'Google',
url: 'https://www.google.com',
lastActiveTimeTicks: {internalValue: BigInt(2)},
},
{
index: 1,
tabId: 2,
title: 'Bing',
url: 'https://www.bing.com',
lastActiveTimeTicks: {internalValue: BigInt(4)},
},
{
index: 2,
tabId: 3,
title: 'Yahoo',
url: 'https://www.yahoo.com',
lastActiveTimeTicks: {internalValue: BigInt(3)},
}
];
await setupTest({windows: [{active: true, tabs}]});
verifyTabIds(queryRows(), [2, 3, 1]);
......
......@@ -26,7 +26,7 @@ suite('TabSearchItemTest', () => {
active: true,
index: 0,
isDefaultFavicon: true,
lastActiveTimeTicks: {internalValue: 0},
lastActiveTimeTicks: {internalValue: BigInt(0)},
pinned: false,
showIcon: true,
tabId: 0,
......@@ -69,4 +69,4 @@ suite('TabSearchItemTest', () => {
await assertTabSearchItemHighlights(
text, [{start: 5, length: 4}], ['work']);
});
});
\ No newline at end of file
});
......@@ -204,8 +204,12 @@ export class ChromeHelper {
});
const idleManager = blink.mojom.IdleManager.getRemote();
// Set a large threshold since we don't care about user idle.
const threshold = {microseconds: 86400000000};
// Set a large threshold since we don't care about user idle. Note that
// ESLint does not yet seem to know about BigInt, so it complains about an
// uppercase "function" being used as something other than a constructor,
// and about BigInt not existing.
// eslint-disable-next-line new-cap, no-undef
const threshold = {microseconds: BigInt(86400000000)};
const {state} = await idleManager.addMonitor(
threshold, monitorCallbackRouter.$.bindNewPipeAndPassRemote());
callback(state.screen === blink.mojom.ScreenIdleState.kLocked);
......
......@@ -562,7 +562,7 @@ class DiagnosticsProxy {
(message);
this.assertNumberIsPositive(request.lengthSeconds);
return await getOrCreateDiagnosticsService().runPrimeSearchRoutine(
request.lengthSeconds, request.maximumNumber);
request.lengthSeconds, BigInt(request.maximumNumber));
};
/**
......@@ -813,9 +813,10 @@ class TelemetryProxy {
// At this point, closure compiler knows that the input is {!Object}.
// Rule #2: convert objects like { value: X } to X, where X is either a
// number or a boolean.
// number, a bigint, or a boolean.
if (Object.entries(input).length === 1 &&
(typeof input['value'] === 'number' ||
typeof input['value'] === typeof BigInt(0) ||
typeof input['value'] === 'boolean')) {
return input['value'];
}
......
......@@ -85,6 +85,8 @@ js_library("untrusted_browsertest") {
"untrusted_test_handlers.js",
]
deps = [ "//chromeos/components/telemetry_extension_ui/resources:untrusted" ]
externs_list =
[ "//chromeos/components/web_applications/js2gtest_support.externs.js" ]
externs_list = [
"$externs_path/pending.js",
"//chromeos/components/web_applications/js2gtest_support.externs.js",
]
}
......@@ -548,13 +548,13 @@ UNTRUSTED_TEST('UntrustedRequestTelemetryInfo', async () => {
]);
// Rounded down to the nearest 100MiB due to privacy requirement.
const availableSpace =
Math.floor(1125899906842624 / (100 * 1024 * 1024)) * (100 * 1024 * 1024);
const availableSpace = BigInt(
Math.floor(1125899906842624 / (100 * 1024 * 1024)) * (100 * 1024 * 1024));
assertDeepEquals(response, {
batteryResult: {
batteryInfo: {
cycleCount: 100000000000000,
cycleCount: BigInt(100000000000000),
voltageNow: 1234567890.123456,
vendor: 'Google',
serialNumber: 'abcdef',
......@@ -567,23 +567,23 @@ UNTRUSTED_TEST('UntrustedRequestTelemetryInfo', async () => {
technology: 'Li-ion',
status: 'Charging',
manufactureDate: '2020-07-30',
temperature: 7777777777777777,
temperature: BigInt(7777777777777777),
}
},
blockDeviceResult: {
blockDeviceInfo: [{
path: '/dev/device1',
size: 5555555555555555,
size: BigInt(5555555555555555),
type: 'NVMe',
manufacturerId: 200,
name: 'goog',
serial: '4287654321',
bytesReadSinceLastBoot: 9000000000000000,
bytesWrittenSinceLastBoot: 8000000000000000,
readTimeSecondsSinceLastBoot: 7000000000000000,
writeTimeSecondsSinceLastBoot: 6666666666666666,
ioTimeSecondsSinceLastBoot: 1111111111111,
discardTimeSecondsSinceLastBoot: 77777777777777
bytesReadSinceLastBoot: BigInt(9000000000000000),
bytesWrittenSinceLastBoot: BigInt(8000000000000000),
readTimeSecondsSinceLastBoot: BigInt(7000000000000000),
writeTimeSecondsSinceLastBoot: BigInt(6666666666666666),
ioTimeSecondsSinceLastBoot: BigInt(1111111111111),
discardTimeSecondsSinceLastBoot: BigInt(77777777777777)
}]
},
vpdResult: {vpdInfo: {skuNumber: 'sku-18'}},
......@@ -599,17 +599,23 @@ UNTRUSTED_TEST('UntrustedRequestTelemetryInfo', async () => {
maxClockSpeedKhz: 2147494759,
scalingMaxFrequencyKhz: 1073764046,
scalingCurrentFrequencyKhz: 536904245,
idleTimeMs: 0,
idleTimeMs: BigInt(0),
cStates: [
{name: 'C1', timeInStateSinceLastBootUs: 1125899906875957},
{name: 'C2', timeInStateSinceLastBootUs: 1125899906877777}
{
name: 'C1',
timeInStateSinceLastBootUs: BigInt(1125899906875957)
},
{
name: 'C2',
timeInStateSinceLastBootUs: BigInt(1125899906877777)
}
]
},
{
maxClockSpeedKhz: 1147494759,
scalingMaxFrequencyKhz: 1063764046,
scalingCurrentFrequencyKhz: 936904246,
idleTimeMs: 0,
idleTimeMs: BigInt(0),
cStates: []
}
]
......@@ -629,7 +635,7 @@ UNTRUSTED_TEST('UntrustedRequestTelemetryInfo', async () => {
totalMemoryKib: 2147483648,
freeMemoryKib: 2147573648,
availableMemoryKib: 2147571148,
pageFaultsSinceLastBoot: 2199971148
pageFaultsSinceLastBoot: BigInt(2199971148),
}
},
backlightResult: {
......@@ -647,7 +653,7 @@ UNTRUSTED_TEST('UntrustedRequestTelemetryInfo', async () => {
statefulPartitionResult: {
partitionInfo: {
availableSpace: availableSpace,
totalSpace: 1125900006842624,
totalSpace: BigInt(1125900006842624),
}
},
bluetoothResult: {
......
......@@ -58,7 +58,7 @@ mojo.internal.align = function(size, alignment) {
/**
* @param {!DataView} dataView
* @param {number} byteOffset
* @param {number} value
* @param {number|bigint} value
*/
mojo.internal.setInt64 = function(dataView, byteOffset, value) {
if (mojo.internal.kHostLittleEndian) {
......@@ -66,11 +66,12 @@ mojo.internal.setInt64 = function(dataView, byteOffset, value) {
byteOffset, Number(BigInt(value) & BigInt(0xffffffff)),
mojo.internal.kHostLittleEndian);
dataView.setInt32(
byteOffset + 4, Number(BigInt(value) >> BigInt(32)),
byteOffset + 4,
Number((BigInt(value) >> BigInt(32)) & BigInt(0xffffffff)),
mojo.internal.kHostLittleEndian);
} else {
dataView.setInt32(
byteOffset, Number(BigInt(value) >> BigInt(32)),
byteOffset, Number((BigInt(value) >> BigInt(32)) & BigInt(0xffffffff)),
mojo.internal.kHostLittleEndian);
dataView.setUint32(
byteOffset + 4, Number(BigInt(value) & BigInt(0xffffffff)),
......@@ -81,7 +82,7 @@ mojo.internal.setInt64 = function(dataView, byteOffset, value) {
/**
* @param {!DataView} dataView
* @param {number} byteOffset
* @param {number} value
* @param {number|bigint} value
*/
mojo.internal.setUint64 = function(dataView, byteOffset, value) {
if (mojo.internal.kHostLittleEndian) {
......@@ -89,11 +90,12 @@ mojo.internal.setUint64 = function(dataView, byteOffset, value) {
byteOffset, Number(BigInt(value) & BigInt(0xffffffff)),
mojo.internal.kHostLittleEndian);
dataView.setUint32(
byteOffset + 4, Number(BigInt(value) >> BigInt(32)),
byteOffset + 4,
Number((BigInt(value) >> BigInt(32)) & BigInt(0xffffffff)),
mojo.internal.kHostLittleEndian);
} else {
dataView.setUint32(
byteOffset, Number(BigInt(value) >> BigInt(32)),
byteOffset, Number((BigInt(value) >> BigInt(32)) & BigInt(0xffffffff)),
mojo.internal.kHostLittleEndian);
dataView.setUint32(
byteOffset + 4, Number(BigInt(value) & BigInt(0xffffffff)),
......@@ -104,7 +106,7 @@ mojo.internal.setUint64 = function(dataView, byteOffset, value) {
/**
* @param {!DataView} dataView
* @param {number} byteOffset
* @return {bigint|number}
* @return {bigint}
*/
mojo.internal.getInt64 = function(dataView, byteOffset) {
let low, high;
......@@ -115,12 +117,24 @@ mojo.internal.getInt64 = function(dataView, byteOffset) {
low = dataView.getUint32(byteOffset + 4, mojo.internal.kHostLittleEndian);
high = dataView.getInt32(byteOffset, mojo.internal.kHostLittleEndian);
}
const value = (BigInt(high) << BigInt(32)) | BigInt(low);
if (value <= BigInt(Number.MAX_SAFE_INTEGER) &&
value >= BigInt(Number.MIN_SAFE_INTEGER)) {
return Number(value);
return (BigInt(high) << BigInt(32)) | BigInt(low);
};
/**
* @param {!DataView} dataView
* @param {number} byteOffset
* @return {bigint}
*/
mojo.internal.getUint64 = function(dataView, byteOffset) {
let low, high;
if (mojo.internal.kHostLittleEndian) {
low = dataView.getUint32(byteOffset, mojo.internal.kHostLittleEndian);
high = dataView.getUint32(byteOffset + 4, mojo.internal.kHostLittleEndian);
} else {
low = dataView.getUint32(byteOffset + 4, mojo.internal.kHostLittleEndian);
high = dataView.getUint32(byteOffset, mojo.internal.kHostLittleEndian);
}
return value;
return (BigInt(high) << BigInt(32)) | BigInt(low);
};
/**
......@@ -222,26 +236,6 @@ mojo.internal.computeTotalArraySize = function(arraySpec, value) {
return totalSize;
};
/**
* @param {!DataView} dataView
* @param {number} byteOffset
* @return {bigint|number}
*/
mojo.internal.getUint64 = function(dataView, byteOffset) {
let low, high;
if (mojo.internal.kHostLittleEndian) {
low = dataView.getUint32(byteOffset, mojo.internal.kHostLittleEndian);
high = dataView.getUint32(byteOffset + 4, mojo.internal.kHostLittleEndian);
} else {
low = dataView.getUint32(byteOffset + 4, mojo.internal.kHostLittleEndian);
high = dataView.getUint32(byteOffset, mojo.internal.kHostLittleEndian);
}
const value = (BigInt(high) << BigInt(32)) | BigInt(low);
if (value <= BigInt(Number.MAX_SAFE_INTEGER))
return Number(value);
return value;
};
/** Owns an outgoing message buffer and facilitates serialization. */
mojo.internal.Message = class {
/**
......@@ -656,7 +650,9 @@ mojo.internal.Decoder = class {
const relativeOffset = this.decodeUint64(offset);
if (relativeOffset == 0)
return 0;
return this.data_.byteOffset + offset + relativeOffset;
if (relativeOffset > BigInt(Number.MAX_SAFE_INTEGER))
throw new Error('Mesage offset too large');
return this.data_.byteOffset + offset + Number(relativeOffset);
}
/**
......
{% macro generateMethodAnnotation(method) %}
/**
{%- for param in method.parameters %}
* @param { {{param.kind|type_in_js_module_with_nullability}} } {{param.name|sanitize_identifier}}
* @param { {{param.kind|param_type_in_js_module}} } {{param.name|sanitize_identifier}}
{%- endfor -%}
{%- if method.response_parameters != None %}
{%- if method.response_parameters|length == 0 %}
......@@ -9,7 +9,7 @@
{%- else %}
* @return {!Promise<{
{%- for response_parameter in method.response_parameters %}
{{response_parameter.name}}: {{response_parameter.kind|type_in_js_module_with_nullability}},
{{response_parameter.name}}: {{response_parameter.kind|param_type_in_js_module}},
{%- endfor %}
* }>}
{%- endif %}
......
......@@ -8,8 +8,7 @@ goog.provide('{{module.namespace}}.{{constant.name}}');
* @const { {{constant.kind|lite_closure_type_with_nullability}} }
* @export
*/
{{module.namespace}}.{{constant.name}} =
{{constant.value|expression_to_text_lite}};
{{module.namespace}}.{{constant.name}} = {{constant|constant_value}};
{%- endfor %}
{#--- Enums #}
......
......@@ -22,8 +22,7 @@ import {
/**
* @const { {{constant.kind|type_in_js_module_with_nullability}} }
*/
export const {{constant.name}} =
{{constant.value|expression_to_text_lite}};
export const {{constant.name}} = {{constant|constant_value_in_js_module}};
{% endfor -%}
......
......@@ -4,7 +4,7 @@
* @export
*/
{{module.namespace}}.{{struct.name}}_{{constant.name}} =
{{constant.value|expression_to_text_lite}};
{{constant|constant_value}};
{% endfor %}
{%- from "lite/enum_definition.tmpl" import enum_def with context %}
......
......@@ -3,7 +3,7 @@
* @const { {{constant.kind|type_in_js_module_with_nullability}} }
*/
export const {{struct.name}}_{{constant.name}} =
{{constant.value|expression_to_text_lite}};
{{constant|constant_value_in_js_module}};
{% endfor %}
{%- from "lite/enum_definition_for_module.tmpl" import enum_def with context %}
......
......@@ -318,12 +318,13 @@ class Generator(generator.Generator):
def GetFilters(self):
js_filters = {
"closure_type": self._ClosureType,
"constant_value": self._GetConstantValue,
"constant_value_in_js_module": self._GetConstantValueInJsModule,
"decode_snippet": self._JavaScriptDecodeSnippet,
"default_value": self._JavaScriptDefaultValue,
"default_value_in_js_module": self._DefaultValueInJsModule,
"encode_snippet": self._JavaScriptEncodeSnippet,
"expression_to_text": self._ExpressionToText,
"expression_to_text_lite": self._ExpressionToTextLite,
"field_offset": JavaScriptFieldOffset,
"field_type_in_js_module": self._GetFieldTypeInJsModule,
"get_relative_url": GetRelativeUrl,
......@@ -507,6 +508,10 @@ class Generator(generator.Generator):
# Indicates whether a kind of suitable to stringify and use as an Object
# property name. This is checked for map key types to allow most kinds of
# mojom maps to be represented as either a Map or an Object.
if kind == mojom.INT64 or kind == mojom.UINT64:
# JS BigInts are not stringable and cannot be used as Object property
# names.
return False
return (mojom.IsIntegralKind(kind) or mojom.IsFloatKind(kind)
or mojom.IsDoubleKind(kind) or mojom.IsStringKind(kind)
or mojom.IsEnumKind(kind))
......@@ -521,6 +526,8 @@ class Generator(generator.Generator):
for_module=for_module)
def get_type_name(kind):
if kind == mojom.INT64 or kind == mojom.UINT64:
return "bigint"
if kind in mojom.PRIMITIVES:
return _kind_to_closure_type[kind]
if mojom.IsArrayKind(kind):
......@@ -778,6 +785,8 @@ class Generator(generator.Generator):
assert field.default == "default"
return "null"
return self._ExpressionToTextLite(field.default, for_module=for_module)
if field.kind == mojom.INT64 or field.kind == mojom.UINT64:
return "BigInt(0)"
if field.kind in mojom.PRIMITIVES:
return _kind_to_javascript_default_value[field.kind]
if mojom.IsEnumKind(field.kind):
......@@ -979,6 +988,16 @@ class Generator(generator.Generator):
return self._ExpressionToText(token)
def _GetConstantValue(self, constant, for_module=False):
assert isinstance(constant, mojom.Constant)
text = self._ExpressionToTextLite(constant.value, for_module=for_module)
if constant.kind == mojom.INT64 or constant.kind == mojom.UINT64:
return "BigInt('{}')".format(text)
return text
def _GetConstantValueInJsModule(self, constant):
return self._GetConstantValue(constant, for_module=True)
def _GenerateHtmlImports(self):
result = []
for full_import in self.module.imports:
......
......@@ -77,7 +77,6 @@ mojom_parser_sources = [
"$_mojom_library_root/__init__.py",
"$_mojom_library_root/error.py",
"$_mojom_library_root/generate/__init__.py",
"$_mojom_library_root/generate/constant_resolver.py",
"$_mojom_library_root/generate/generator.py",
"$_mojom_library_root/generate/module.py",
"$_mojom_library_root/generate/pack.py",
......
......@@ -8,7 +8,6 @@ group("mojom") {
"error.py",
"fileutil.py",
"generate/__init__.py",
"generate/constant_resolver.py",
"generate/generator.py",
"generate/module.py",
"generate/pack.py",
......
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Resolves the values used for constants and enums."""
from itertools import ifilter
from mojom.generate import module as mojom
def ResolveConstants(module, expression_to_text):
in_progress = set()
computed = set()
def GetResolvedValue(named_value):
assert isinstance(named_value, (mojom.EnumValue, mojom.ConstantValue))
if isinstance(named_value, mojom.EnumValue):
field = next(
ifilter(lambda field: field.name == named_value.name,
named_value.enum.fields), None)
if not field:
raise RuntimeError(
'Unable to get computed value for field %s of enum %s' %
(named_value.name, named_value.enum.name))
if field not in computed:
ResolveEnum(named_value.enum)
return field.resolved_value
else:
ResolveConstant(named_value.constant)
named_value.resolved_value = named_value.constant.resolved_value
return named_value.resolved_value
def ResolveConstant(constant):
if constant in computed:
return
if constant in in_progress:
raise RuntimeError('Circular dependency for constant: %s' % constant.name)
in_progress.add(constant)
if isinstance(constant.value, (mojom.EnumValue, mojom.ConstantValue)):
resolved_value = GetResolvedValue(constant.value)
else:
resolved_value = expression_to_text(constant.value)
constant.resolved_value = resolved_value
in_progress.remove(constant)
computed.add(constant)
def ResolveEnum(enum):
def ResolveEnumField(enum, field, default_value):
if field in computed:
return
if field in in_progress:
raise RuntimeError('Circular dependency for enum: %s' % enum.name)
in_progress.add(field)
if field.value:
if isinstance(field.value, mojom.EnumValue):
resolved_value = GetResolvedValue(field.value)
elif isinstance(field.value, str):
resolved_value = int(field.value, 0)
else:
raise RuntimeError('Unexpected value: %s' % field.value)
else:
resolved_value = default_value
field.resolved_value = resolved_value
in_progress.remove(field)
computed.add(field)
current_value = 0
for field in enum.fields:
ResolveEnumField(enum, field, current_value)
current_value = field.resolved_value + 1
for constant in module.constants:
ResolveConstant(constant)
for enum in module.enums:
ResolveEnum(enum)
for struct in module.structs:
for constant in struct.constants:
ResolveConstant(constant)
for enum in struct.enums:
ResolveEnum(enum)
for field in struct.fields:
if isinstance(field.default, (mojom.ConstantValue, mojom.EnumValue)):
field.default.resolved_value = GetResolvedValue(field.default)
for interface in module.interfaces:
for constant in interface.constants:
ResolveConstant(constant)
for enum in interface.enums:
ResolveEnum(enum)
return module
......@@ -17,7 +17,7 @@ test(() => {
const s = deserializer.TestStruct_Deserialize(dataview);
assert_equals(s.v1, 8899);
assert_equals(s.v2, 9988);
assert_equals(s.v3, 7777);
assert_equals(s.v3, 7777n);
}, 'deserializer');
</script>
......@@ -35,17 +35,14 @@
expectedValue: 4294967295,
type: 'uint32'
}, {
// TODO(crbug.com/1009262): Re-enable once we generate the right value for
// 64-bit constants.
//
// constant: mojo.tstest.kInt64Value,
// expectedValue: -9223372036854775807n,
// type: 'int64'
//}, {
// constant: mojo.tstest.kUint64Value,
// expectedValue: 9999999999999999999n,
// type: 'uint64'
//}, {
constant: mojo.tstest.INT64_VALUE,
expectedValue: -9223372036854775807n,
type: 'int64'
}, {
constant: mojo.tstest.UINT64_VALUE,
expectedValue: 9999999999999999999n,
type: 'uint64'
}, {
constant: mojo.tstest.DOUBLE_VALUE,
expectedValue: 3.14159,
type: 'double'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment