Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable noUncheckedIndexedAccess for ODSP driver (#21664) #23068

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/drivers/odsp-driver/src/ReadBufferUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ export class ReadBuffer {
let length = lengthArg;
while (length > 0) {
assert(!this.eof, 0x223 /* "unexpected end of buffer" */);
res += this.data[this.index] * multiplier;
// TODO Why are we non null asserting here?
res += this.data[this.index]! * multiplier;
this.index++;
multiplier *= 256;
length--;
Expand Down
6 changes: 4 additions & 2 deletions packages/drivers/odsp-driver/src/WriteBufferUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ export class WriteBuffer {
let index = 0;
const oldData = this.data;
while (index < length) {
newData[index] = oldData[index];
// TODO Why are we non null asserting here?
newData[index] = oldData[index]!;
index++;
}
this.data = newData;
Expand Down Expand Up @@ -252,7 +253,8 @@ function serializeNodeCore(
buffer.write(child, len);
}
} else if (typeof child === "boolean") {
buffer.write(boolToCodeMap[child ? 1 : 0]);
// TODO Why are we non null asserting here?
buffer.write(boolToCodeMap[child ? 1 : 0]!);
} else {
assert(child._stringElement, 0x3dd /* Unsupported node type */);
if (child.dictionary) {
Expand Down
39 changes: 26 additions & 13 deletions packages/drivers/odsp-driver/src/compactSnapshotParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ function readBlobSection(node: NodeTypes): {
*/
slowBlobStructureCount += 1;
const records = getNodeProps(blob);
assertBlobCoreInstance(records.data, "data should be of BlobCore type");
const id = getStringInstance(records.id, "blob id should be string");
// TODO why are we non null asserting here?
assertBlobCoreInstance(records.data!, "data should be of BlobCore type");
// TODO why are we non null asserting here?
const id = getStringInstance(records.id!, "blob id should be string");
blobContents.set(id, records.data.arrayBuffer);
}
}
Expand All @@ -86,8 +88,10 @@ function readOpsSection(node: NodeTypes): ISequencedDocumentMessage[] {
assertNodeCoreInstance(node, "Deltas should be of type NodeCore");
const ops: ISequencedDocumentMessage[] = [];
const records = getNodeProps(node);
assertNumberInstance(records.firstSequenceNumber, "Seq number should be a number");
assertNodeCoreInstance(records.deltas, "Deltas should be a Node");
// TODO Why are we non null asserting here?
assertNumberInstance(records.firstSequenceNumber!, "Seq number should be a number");
// TODO Why are we non null asserting here?
assertNodeCoreInstance(records.deltas!, "Deltas should be a Node");
for (let i = 0; i < records.deltas.length; ++i) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
ops.push(JSON.parse(records.deltas.getString(i)));
Expand All @@ -96,7 +100,8 @@ function readOpsSection(node: NodeTypes): ISequencedDocumentMessage[] {
// when there are no ops. So just make the code resilient to that bug. Service has also
// fixed that bug.
assert(
ops.length === 0 || records.firstSequenceNumber.valueOf() === ops[0].sequenceNumber,
// Non null asserting here because of the length check
ops.length === 0 || records.firstSequenceNumber.valueOf() === ops[0]!.sequenceNumber,
0x280 /* "Validate first op seq number" */,
);
return ops;
Expand Down Expand Up @@ -201,7 +206,8 @@ function readTreeSection(node: NodeCore): {
snapshotTree.unreferenced = true;
}

const path = getStringInstance(records.name, "Path name should be string");
// TODO Why are we non null asserting here?
const path = getStringInstance(records.name!, "Path name should be string");
if (records.value !== undefined) {
snapshotTree.blobs[path] = getStringInstance(
records.value,
Expand Down Expand Up @@ -239,11 +245,14 @@ function readSnapshotSection(node: NodeTypes): {
assertNodeCoreInstance(node, "Snapshot should be of type NodeCore");
const records = getNodeProps(node);

assertNodeCoreInstance(records.treeNodes, "TreeNodes should be of type NodeCore");
assertNumberInstance(records.sequenceNumber, "sequenceNumber should be of type number");
// TODO Why are we non null asserting here?
assertNodeCoreInstance(records.treeNodes!, "TreeNodes should be of type NodeCore");
// TODO Why are we non null asserting here?
assertNumberInstance(records.sequenceNumber!, "sequenceNumber should be of type number");
const { snapshotTree, slowTreeStructureCount, treeStructureCountWithGroupId } =
readTreeSection(records.treeNodes);
snapshotTree.id = getStringInstance(records.id, "snapshotId should be string");
// TODO Why are we non null asserting here?
snapshotTree.id = getStringInstance(records.id!, "snapshotId should be string");
const sequenceNumber = records.sequenceNumber.valueOf();
return {
sequenceNumber,
Expand All @@ -269,8 +278,10 @@ export function parseCompactSnapshotResponse(

const records = getNodeProps(root);

const mrv = getStringInstance(records.mrv, "minReadVersion should be string");
const cv = getStringInstance(records.cv, "createVersion should be string");
// TODO Why are we non null asserting here?
const mrv = getStringInstance(records.mrv!, "minReadVersion should be string");
// TODO Why are we non null asserting here?
const cv = getStringInstance(records.cv!, "createVersion should be string");
if (records.lsn !== undefined) {
assertNumberInstance(records.lsn, "lsn should be a number");
}
Expand All @@ -289,9 +300,11 @@ export function parseCompactSnapshotResponse(
);

const [snapshot, durationSnapshotTree] = measure(() =>
readSnapshotSection(records.snapshot),
// TODO Why are we non null asserting here?
readSnapshotSection(records.snapshot!),
);
const [blobContents, durationBlobs] = measure(() => readBlobSection(records.blobs));
// TODO Why are we non null asserting here?
const [blobContents, durationBlobs] = measure(() => readBlobSection(records.blobs!));

return {
...snapshot,
Expand Down
6 changes: 4 additions & 2 deletions packages/drivers/odsp-driver/src/compactSnapshotWriter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ function writeSnapshotSection(
function writeOpsSection(rootNode: NodeCore, ops: ISequencedDocumentMessage[]): void {
let firstSequenceNumber: number | undefined;
if (ops.length > 0) {
firstSequenceNumber = ops[0].sequenceNumber;
// Non null asserting here because of the length check above
firstSequenceNumber = ops[0]!.sequenceNumber;
}
if (firstSequenceNumber !== undefined) {
rootNode.addDictionaryString("deltas");
Expand Down Expand Up @@ -162,7 +163,8 @@ export function convertToCompactSnapshot(snapshotContents: ISnapshot): Uint8Arra
if (latestSequenceNumber === undefined) {
latestSequenceNumber =
snapshotContents.ops.length > 0
? snapshotContents.ops[snapshotContents.ops.length - 1].sequenceNumber
? // Non null asserting here because of the length check above
snapshotContents.ops[snapshotContents.ops.length - 1]!.sequenceNumber
: snapshotContents.sequenceNumber;
}

Expand Down
3 changes: 2 additions & 1 deletion packages/drivers/odsp-driver/src/createNewUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ function convertCreateNewSummaryTreeToTreeAndBlobsCore(
};
const keys = Object.keys(summary.tree);
for (const key of keys) {
const summaryObject = summary.tree[key];
// Non null asserting for now this should change to Object.entries
const summaryObject = summary.tree[key]!;

switch (summaryObject.type) {
case SummaryType.Tree: {
Expand Down
3 changes: 2 additions & 1 deletion packages/drivers/odsp-driver/src/fetchSnapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,8 @@ async function fetchLatestSnapshotCore(
const sequenceNumber: number = snapshot.sequenceNumber ?? 0;
const seqNumberFromOps =
snapshot.ops && snapshot.ops.length > 0
? snapshot.ops[0].sequenceNumber - 1
? // Non null asserting here because of the length check above
snapshot.ops[0]!.sequenceNumber - 1
: undefined;

if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ export class LocalOdspDeltaStorageService implements IDocumentDeltaStorageServic
);
validateMessages("cached", messages, from, this.logger);

if (messages.length === 0 || messages[0].sequenceNumber !== from) {
// Non null asserting here because of the length check
if (messages.length === 0 || messages[0]!.sequenceNumber !== from) {
this.snapshotOps = [];
}
this.snapshotOps = this.snapshotOps.filter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ export class OdspDelayLoadedDeltaStream {
}

private emitMetaDataUpdateEvent(metadata: Record<string, string>): void {
const label = JSON.parse(metadata.sensitivityLabelsInfo) as {
// TODO Why are we non null asserting here?
const label = JSON.parse(metadata.sensitivityLabelsInfo!) as {
labels: unknown;
timestamp: number;
};
Expand All @@ -481,7 +482,8 @@ export class OdspDelayLoadedDeltaStream {
if (time > this.labelUpdateTimestamp) {
this.labelUpdateTimestamp = time;
this.metadataUpdateHandler({
sensitivityLabelsInfo: metadata.sensitivityLabelsInfo,
// TODO Why are we non null asserting here?
sensitivityLabelsInfo: metadata.sensitivityLabelsInfo!,
});
}
}
Expand Down
6 changes: 4 additions & 2 deletions packages/drivers/odsp-driver/src/odspDeltaStorageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ export class OdspDeltaStorageService {
clearTimeout(timer);
const deltaStorageResponse = response.content;
const messages =
deltaStorageResponse.value.length > 0 && "op" in deltaStorageResponse.value[0]
// Non null asserting here because of the length check
deltaStorageResponse.value.length > 0 && "op" in deltaStorageResponse.value[0]!
? (deltaStorageResponse.value as ISequencedDeltaOpMessage[]).map(
(operation) => operation.op,
)
Expand Down Expand Up @@ -187,7 +188,8 @@ export class OdspDeltaStorageWithCache implements IDocumentDeltaStorageService {
(op) => op.sequenceNumber >= from && op.sequenceNumber < to,
);
validateMessages("cached", messages, from, this.logger);
if (messages.length > 0 && messages[0].sequenceNumber === from) {
// Non null asserting here because of the length check
if (messages.length > 0 && messages[0]!.sequenceNumber === from) {
this.snapshotOps = this.snapshotOps.filter((op) => op.sequenceNumber >= to);
opsFromSnapshot += messages.length;
return { messages, partialResult: true };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -588,8 +588,10 @@ export class OdspDocumentDeltaConnection extends DocumentDeltaConnection {
if (messages !== undefined && messages.length > 0) {
this.logger.sendPerformanceEvent({
...common,
first: messages[0].sequenceNumber,
last: messages[messages.length - 1].sequenceNumber,
// Non null asserting here because of the length check above
first: messages[0]!.sequenceNumber,
// Non null asserting here because of the length check above
last: messages[messages.length - 1]!.sequenceNumber,
length: messages.length,
});
this.emit("op", this.documentId, messages);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ export abstract class OdspDocumentStorageServiceBase implements IDocumentStorage
// eslint-disable-next-line unicorn/no-null
return null;
}
id = versions[0].id;
// Non null asserting here because of the length check above
id = versions[0]!.id;
}

const snapshotTree = await this.readTree(id, scenarioName);
Expand Down Expand Up @@ -257,7 +258,8 @@ export abstract class OdspDocumentStorageServiceBase implements IDocumentStorage
protected combineProtocolAndAppSnapshotTree(snapshotTree: ISnapshotTree): ISnapshotTree {
// When we upload the container snapshot, we upload appTree in ".app" and protocol tree in ".protocol"
// So when we request the snapshot we get ".app" as tree and not as commit node as in the case just above.
const hierarchicalAppTree = snapshotTree.trees[".app"];
// TODO Why are we non null asserting here?
const hierarchicalAppTree = snapshotTree.trees[".app"]!;
const hierarchicalProtocolTree = snapshotTree.trees[".protocol"];
const summarySnapshotTree: ISnapshotTree = {
blobs: {
Expand Down
3 changes: 2 additions & 1 deletion packages/drivers/odsp-driver/src/odspDriverUrlResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ export function decodeOdspUrl(url: string): {
}

return {
siteUrl,
// TODO Why are we non null asserting here?
siteUrl: siteUrl!,
driveId: decodeURIComponent(driveId),
itemId: decodeURIComponent(itemId),
path: decodeURIComponent(path),
Expand Down
12 changes: 8 additions & 4 deletions packages/drivers/odsp-driver/src/odspSnapshotParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ function buildHierarchy(flatTree: IOdspSnapshotCommit): ISnapshotTree {
const entryPathBase = entry.path.slice(lastIndex + 1);

// ODSP snapshots are created breadth-first so we can assume we see tree nodes prior to their contents
const node = lookup[entryPathDir];
// TODO Why are we non null asserting here?
const node = lookup[entryPathDir]!;

// Add in either the blob or tree
if (entry.type === "tree") {
Expand Down Expand Up @@ -69,16 +70,19 @@ export function convertOdspSnapshotToSnapshotTreeAndBlobs(
}
}

const sequenceNumber = odspSnapshot?.trees[0].sequenceNumber;
// TODO Why are we non null asserting here?
const sequenceNumber = odspSnapshot?.trees[0]!.sequenceNumber;

const val: ISnapshot = {
blobContents: blobsWithBufferContent,
ops: odspSnapshot.ops?.map((op) => op.op) ?? [],
sequenceNumber,
snapshotTree: buildHierarchy(odspSnapshot.trees[0]),
// TODO Why are we non null asserting here?
snapshotTree: buildHierarchy(odspSnapshot.trees[0]!),
latestSequenceNumber:
odspSnapshot.ops && odspSnapshot.ops.length > 0
? odspSnapshot.ops[odspSnapshot.ops.length - 1].sequenceNumber
? // Non null asserting here because of the length check above
odspSnapshot.ops[odspSnapshot.ops.length - 1]!.sequenceNumber
: sequenceNumber,
snapshotFormatV: 1,
};
Expand Down
5 changes: 1 addition & 4 deletions packages/drivers/odsp-driver/src/odspSummaryUploadManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,8 @@ export class OdspSummaryUploadManager {
};

let blobs = 0;
const keys = Object.keys(tree.tree);
for (const key of keys) {
for (const [key, summaryObject] of Object.entries(tree.tree)) {
assert(!key.includes("/"), 0x9cd /* id should not include slashes */);
const summaryObject = tree.tree[key];

let id: string | undefined;
let value: OdspSummaryTreeValue | undefined;

Expand Down
12 changes: 8 additions & 4 deletions packages/drivers/odsp-driver/src/odspUrlHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,10 @@ export async function getOdspUrlParts(url: URL): Promise<IOdspUrlParts | undefin
}
}

const driveId = joinSessionMatch[3] || joinSessionMatch[5];
const itemId = joinSessionMatch[4];
// TODO Why are we non null asserting here?
const driveId = joinSessionMatch[3] ?? joinSessionMatch[5]!;
// TODO Why are we non null asserting here?
const itemId = joinSessionMatch[4]!;

return { siteUrl: `${url.origin}${url.pathname}`, driveId, itemId };
} else {
Expand All @@ -120,8 +122,10 @@ export async function getOdspUrlParts(url: URL): Promise<IOdspUrlParts | undefin
if (joinSessionMatch === null) {
return undefined;
}
const driveId = joinSessionMatch[2];
const itemId = joinSessionMatch[3];
// TODO Why are we non null asserting here?
const driveId = joinSessionMatch[2]!;
// TODO Why are we non null asserting here?
const itemId = joinSessionMatch[3]!;

return { siteUrl: `${url.origin}${url.pathname}`, driveId, itemId };
}
Expand Down
27 changes: 18 additions & 9 deletions packages/drivers/odsp-driver/src/zipItDataRepresentationUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,39 +301,46 @@ export class NodeCore {
}

public get(index: number): NodeTypes {
return this.children[index];
// TODO Why are we non null asserting here?
return this.children[index]!;
}

public getString(index: number): string {
const node = this.children[index];
// TODO Why are we non null asserting here?
const node = this.children[index]!;
return getStringInstance(node, "getString should return string");
}

public getMaybeString(index: number): string | undefined {
const node = this.children[index];
// TODO Why are we non null asserting here?
const node = this.children[index]!;
return getMaybeStringInstance(node);
}

public getBlob(index: number): BlobCore {
const node = this.children[index];
// TODO Why are we non null asserting here?
const node = this.children[index]!;
assertBlobCoreInstance(node, "getBlob should return a blob");
return node;
}

public getNode(index: number): NodeCore {
const node = this.children[index];
// TODO Why are we non null asserting here?
const node = this.children[index]!;
assertNodeCoreInstance(node, "getNode should return a node");
return node;
}

public getNumber(index: number): number {
const node = this.children[index];
// TODO Why are we non null asserting here?
const node = this.children[index]!;
assertNumberInstance(node, "getNumber should return a number");
return node;
}

public getBool(index: number): boolean {
const node = this.children[index];
// TODO Why are we non null asserting here?
const node = this.children[index]!;
assertBoolInstance(node, "getBool should return a boolean");
return node;
}
Expand Down Expand Up @@ -549,7 +556,8 @@ export class NodeCore {

for (const el of stringsToResolve) {
for (let it = el.startPos; it < el.endPos; it++) {
stringBuffer[length] = input[it];
// Non null asserting here because we are iterating over startPos
stringBuffer[length] = input[it]!;
length++;
}
stringBuffer[length] = 0;
Expand All @@ -561,7 +569,8 @@ export class NodeCore {
if (result.length === stringsToResolve.length + 1) {
// All is good, we expect all the cases to get here
for (let i = 0; i < stringsToResolve.length; i++) {
stringsToResolve[i].content = result[i];
// Non null asserting here because we are iterating over stringsToResolve
stringsToResolve[i]!.content = result[i];
}
} else {
// String content has \0 chars!
Expand Down
Loading
Loading