From 8eee4789aa4c251fb27e2b786dea0568277a3363 Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Thu, 8 Jun 2023 10:14:49 -0700 Subject: [PATCH 01/15] Provide different layers' APIs to describeCompat suites --- .../{.eslintrc.js => .eslintrc.cjs} | 4 + .../test/test-end-to-end-tests/package.json | 15 +- .../src/test/{.mocharc.js => .mocharc.cjs} | 3 +- .../src/test/SummarizeFetchValidation.spec.ts | 2 +- ...WithOutOfOrderDataStoreRealization.spec.ts | 2 +- ....mocharc.memory.js => .mocharc.memory.cjs} | 0 .../{.mocharc.time.js => .mocharc.time.cjs} | 0 .../src/test/benchmark/DocumentCreator.ts | 4 +- .../src/test/benchmark/DocumentMap.ts | 6 +- .../benchmark/DocumentMultipleDataStores.ts | 6 +- .../test/benchmark/LoadDocument.all.spec.ts | 2 +- .../src/test/benchmark/PasTable.all.spec.ts | 2 +- .../src/test/benchmark/SimpleTest.all.spec.ts | 2 +- .../summarizationDocument.all.spec.ts | 2 +- .../src/test/blobs.spec.ts | 2 +- .../src/test/compression.spec.ts | 2 +- .../test/deRehydrateContainerTests.spec.ts | 2 +- .../src/test/gc/gcAttachmentBlobs.spec.ts | 6 +- .../test/gc/gcContainerRuntimeCompat.spec.ts | 4 +- .../src/test/gc/gcDatastoreAliased.spec.ts | 4 +- .../gc/gcDatastoreDuplicateRoutes.spec.ts | 4 +- .../test/gc/gcDeleteObjectsInTestMode.spec.ts | 4 +- .../src/test/gc/gcInactiveNodes.spec.ts | 2 +- .../test/gc/gcIncrementalSummaries.spec.ts | 2 +- .../gc/gcLoadingFromOlderSummaries.spec.ts | 4 +- .../gc/gcReferenceUpdatesInSummary.spec.ts | 88 +++--- .../test/gc/gcStateResetInSummaries.spec.ts | 4 +- .../src/test/gc/gcStats.spec.ts | 4 +- .../test/gc/gcSweepAttachmentBlobs.spec.ts | 6 +- .../src/test/gc/gcSweepDataStores.spec.ts | 2 +- .../test/gc/gcSweepUnreferencePhases.spec.ts | 2 +- .../src/test/gc/gcTestSummaryUtils.ts | 2 +- .../gc/gcTombstoneAttachmentBlobs.spec.ts | 4 +- .../src/test/gc/gcTombstoneDataStores.spec.ts | 2 +- .../gc/gcTombstoneUnreferencePhases.spec.ts | 2 +- .../src/test/gc/gcTrailingOps.spec.ts | 4 +- .../src/test/gc/gcUnknownHandles.spec.ts | 4 +- .../gc/gcUnreferencedFlagInSnapshot.spec.ts | 2 +- .../test/gc/gcUnreferencedTimestamp.spec.ts | 4 +- .../src/test/gc/gcVersionUpdate.spec.ts | 2 +- .../test/incrementalSummaryContext.spec.ts | 2 +- .../src/test/sharedInterval.spec.ts | 2 +- .../src/test/sharedStringLoading.spec.ts | 2 +- .../src/test/tsconfig.json | 1 + .../{.eslintrc.js => .eslintrc.cjs} | 4 + .../{mocharc-common.js => mocharc-common.cjs} | 9 +- packages/test/test-version-utils/package.json | 1 + .../test-version-utils/src/compatConfig.ts | 44 ++- .../test-version-utils/src/compatOptions.ts | 4 +- .../test-version-utils/src/compatUtils.ts | 68 ++-- .../test-version-utils/src/describeCompat.ts | 47 +-- .../test-version-utils/src/describeE2eDocs.ts | 8 +- .../src/describeWithVersions.ts | 10 +- packages/test/test-version-utils/src/index.ts | 16 +- .../test/test-version-utils/src/testApi.ts | 291 +++++++++++++----- .../test-version-utils/src/versionUtils.ts | 17 +- .../test/test-version-utils/tsconfig.json | 1 + 57 files changed, 467 insertions(+), 278 deletions(-) rename packages/test/test-end-to-end-tests/{.eslintrc.js => .eslintrc.cjs} (75%) rename packages/test/test-end-to-end-tests/src/test/{.mocharc.js => .mocharc.cjs} (91%) rename packages/test/test-end-to-end-tests/src/test/benchmark/{.mocharc.memory.js => .mocharc.memory.cjs} (100%) rename packages/test/test-end-to-end-tests/src/test/benchmark/{.mocharc.time.js => .mocharc.time.cjs} (100%) rename packages/test/test-version-utils/{.eslintrc.js => .eslintrc.cjs} (62%) rename packages/test/test-version-utils/{mocharc-common.js => mocharc-common.cjs} (84%) diff --git a/packages/test/test-end-to-end-tests/.eslintrc.js b/packages/test/test-end-to-end-tests/.eslintrc.cjs similarity index 75% rename from packages/test/test-end-to-end-tests/.eslintrc.js rename to packages/test/test-end-to-end-tests/.eslintrc.cjs index 72e84913adce..c97c86eb75af 100644 --- a/packages/test/test-end-to-end-tests/.eslintrc.js +++ b/packages/test/test-end-to-end-tests/.eslintrc.cjs @@ -22,6 +22,10 @@ module.exports = { rules: { // Test files are run in node only so additional node libraries can be used. "import/no-nodejs-modules": ["error", { allow: ["assert", "url"] }], + // ESLint's resolver doesn't resolve relative imports of ESNext modules correctly, since + // it resolves the path relative to the .ts file (and assumes a file with a .js extension + // should exist there) + "import/no-unresolved": ["error", { ignore: ["^\\.(.*)\\.js$"] }], }, }, ], diff --git a/packages/test/test-end-to-end-tests/package.json b/packages/test/test-end-to-end-tests/package.json index 269f21720699..669375860942 100644 --- a/packages/test/test-end-to-end-tests/package.json +++ b/packages/test/test-end-to-end-tests/package.json @@ -11,6 +11,7 @@ "license": "MIT", "author": "Microsoft and contributors", "sideEffects": false, + "type": "module", "scripts": { "build": "npm run build:genver && concurrently npm:build:compile npm:lint", "build:compile": "npm run build:test", @@ -28,12 +29,12 @@ "prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore", "start:tinylicious:test": "tinylicious > tinylicious.log 2>&1", "test": "npm run test:realsvc", - "test:benchmark:report": "mocha --config src/test/benchmark/.mocharc.time.js -- --driver=local --e2eConfigFile='src/test/benchmark/e2eDocsConfig.json'", - "test:benchmark:report:frs": "mocha --config src/test/benchmark/.mocharc.time.js -- --driver=r11s --r11sEndpointName=frs --e2eConfigFile='src/test/benchmark/e2eDocsConfig.json'", - "test:benchmark:report:odsp": "mocha --config src/test/benchmark/.mocharc.time.js -- --driver=odsp --e2eConfigFile='src/test/benchmark/e2eDocsConfig.json'", - "test:memory-profiling:report": "mocha --config src/test/benchmark/.mocharc.memory.js -- --driver=local --e2eConfigFile='src/test/benchmark/e2eDocsConfig.json'", - "test:memory-profiling:report:frs": "mocha --config src/test/benchmark/.mocharc.memory.js -- --driver=r11s --r11sEndpointName=frs --e2eConfigFile='src/test/benchmark/e2eDocsConfig.json'", - "test:memory-profiling:report:odsp": "mocha --config src/test/benchmark/.mocharc.memory.js -- --driver=odsp --e2eConfigFile='src/test/benchmark/e2eDocsConfig.json'", + "test:benchmark:report": "mocha --config src/test/benchmark/.mocharc.time.cjs -- --driver=local --e2eConfigFile='src/test/benchmark/e2eDocsConfig.json'", + "test:benchmark:report:frs": "mocha --config src/test/benchmark/.mocharc.time.cjs -- --driver=r11s --r11sEndpointName=frs --e2eConfigFile='src/test/benchmark/e2eDocsConfig.json'", + "test:benchmark:report:odsp": "mocha --config src/test/benchmark/.mocharc.time.cjs -- --driver=odsp --e2eConfigFile='src/test/benchmark/e2eDocsConfig.json'", + "test:memory-profiling:report": "mocha --config src/test/benchmark/.mocharc.memory.cjs -- --driver=local --e2eConfigFile='src/test/benchmark/e2eDocsConfig.json'", + "test:memory-profiling:report:frs": "mocha --config src/test/benchmark/.mocharc.memory.cjs -- --driver=r11s --r11sEndpointName=frs --e2eConfigFile='src/test/benchmark/e2eDocsConfig.json'", + "test:memory-profiling:report:odsp": "mocha --config src/test/benchmark/.mocharc.memory.cjs -- --driver=odsp --e2eConfigFile='src/test/benchmark/e2eDocsConfig.json'", "test:realsvc": "npm run test:realsvc:local && npm run test:realsvc:tinylicious", "test:realsvc:frs": "npm run test:realsvc:run -- --driver=r11s --r11sEndpointName=frs --timeout=20s", "test:realsvc:frs:report": "cross-env FLUID_TEST_REPORT=1 npm run test:realsvc:frs --", @@ -45,7 +46,7 @@ "test:realsvc:r11s": "npm run test:realsvc:run -- --driver=r11s --timeout=5s --use-openssl-ca", "test:realsvc:routerlicious": "npm run test:realsvc:r11s", "test:realsvc:routerlicious:report": "cross-env FLUID_TEST_REPORT=1 npm run test:realsvc:r11s --", - "test:realsvc:run": "mocha dist/test --config src/test/.mocharc.js --exclude dist/test/benchmark/**/*", + "test:realsvc:run": "mocha dist/test --config src/test/.mocharc.cjs --exclude dist/test/benchmark/**/*", "test:realsvc:t9s": "start-server-and-test start:tinylicious:test 7070 test:realsvc:tinylicious:run", "test:realsvc:tinylicious": "npm run test:realsvc:t9s", "test:realsvc:tinylicious:report": "cross-env FLUID_TEST_REPORT=1 npm run test:realsvc:t9s", diff --git a/packages/test/test-end-to-end-tests/src/test/.mocharc.js b/packages/test/test-end-to-end-tests/src/test/.mocharc.cjs similarity index 91% rename from packages/test/test-end-to-end-tests/src/test/.mocharc.js rename to packages/test/test-end-to-end-tests/src/test/.mocharc.cjs index 02362889f26e..f2d98f497d97 100644 --- a/packages/test/test-end-to-end-tests/src/test/.mocharc.js +++ b/packages/test/test-end-to-end-tests/src/test/.mocharc.cjs @@ -6,7 +6,6 @@ "use strict"; const packageDir = `${__dirname}/../..`; - -const getFluidTestMochaConfig = require("@fluid-internal/test-version-utils/mocharc-common.js"); +const getFluidTestMochaConfig = require("@fluid-internal/test-version-utils/mocharc-common.cjs"); const config = getFluidTestMochaConfig(packageDir, ["source-map-support/register"]); module.exports = config; diff --git a/packages/test/test-end-to-end-tests/src/test/SummarizeFetchValidation.spec.ts b/packages/test/test-end-to-end-tests/src/test/SummarizeFetchValidation.spec.ts index 1cfc37a710c2..8bb4aefc5da9 100644 --- a/packages/test/test-end-to-end-tests/src/test/SummarizeFetchValidation.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/SummarizeFetchValidation.spec.ts @@ -27,7 +27,7 @@ import { MockLogger } from "@fluidframework/telemetry-utils"; import { ISummaryContext } from "@fluidframework/driver-definitions"; import { SharedMatrix } from "@fluidframework/matrix"; import { ISnapshotTree, ISummaryTree, IVersion } from "@fluidframework/protocol-definitions"; -import { pkgVersion } from "../packageVersion"; +import { pkgVersion } from "../packageVersion.js"; // Note GC needs to be disabled. const runtimeOptions: IContainerRuntimeOptions = { diff --git a/packages/test/test-end-to-end-tests/src/test/SummarizerWithOutOfOrderDataStoreRealization.spec.ts b/packages/test/test-end-to-end-tests/src/test/SummarizerWithOutOfOrderDataStoreRealization.spec.ts index 9003439b7cb6..b9fb0bc52d52 100644 --- a/packages/test/test-end-to-end-tests/src/test/SummarizerWithOutOfOrderDataStoreRealization.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/SummarizerWithOutOfOrderDataStoreRealization.spec.ts @@ -20,7 +20,7 @@ import { } from "@fluidframework/test-utils"; import { describeNoCompat, getContainerRuntimeApi } from "@fluid-internal/test-version-utils"; import { IContainerRuntimeBase, IFluidDataStoreFactory } from "@fluidframework/runtime-definitions"; -import { pkgVersion } from "../packageVersion"; +import { pkgVersion } from "../packageVersion.js"; interface ProvideSearchContent { SearchContent: SearchContent; diff --git a/packages/test/test-end-to-end-tests/src/test/benchmark/.mocharc.memory.js b/packages/test/test-end-to-end-tests/src/test/benchmark/.mocharc.memory.cjs similarity index 100% rename from packages/test/test-end-to-end-tests/src/test/benchmark/.mocharc.memory.js rename to packages/test/test-end-to-end-tests/src/test/benchmark/.mocharc.memory.cjs diff --git a/packages/test/test-end-to-end-tests/src/test/benchmark/.mocharc.time.js b/packages/test/test-end-to-end-tests/src/test/benchmark/.mocharc.time.cjs similarity index 100% rename from packages/test/test-end-to-end-tests/src/test/benchmark/.mocharc.time.js rename to packages/test/test-end-to-end-tests/src/test/benchmark/.mocharc.time.cjs diff --git a/packages/test/test-end-to-end-tests/src/test/benchmark/DocumentCreator.ts b/packages/test/test-end-to-end-tests/src/test/benchmark/DocumentCreator.ts index 9e982ac3a76d..e6dfafe8bc9a 100644 --- a/packages/test/test-end-to-end-tests/src/test/benchmark/DocumentCreator.ts +++ b/packages/test/test-end-to-end-tests/src/test/benchmark/DocumentCreator.ts @@ -20,8 +20,8 @@ import { IMemoryTestObject, } from "@fluid-tools/benchmark"; import { ISummarizer } from "@fluidframework/container-runtime"; -import { DocumentMap } from "./DocumentMap"; -import { DocumentMultipleDds } from "./DocumentMultipleDataStores"; +import { DocumentMap } from "./DocumentMap.js"; +import { DocumentMultipleDds } from "./DocumentMultipleDataStores.js"; export interface IDocumentCreatorProps { testName: string; diff --git a/packages/test/test-end-to-end-tests/src/test/benchmark/DocumentMap.ts b/packages/test/test-end-to-end-tests/src/test/benchmark/DocumentMap.ts index e92eeac59322..2e2043b0415a 100644 --- a/packages/test/test-end-to-end-tests/src/test/benchmark/DocumentMap.ts +++ b/packages/test/test-end-to-end-tests/src/test/benchmark/DocumentMap.ts @@ -24,7 +24,11 @@ import { IRequest } from "@fluidframework/core-interfaces"; import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils"; import { CompressionAlgorithms, ISummarizer } from "@fluidframework/container-runtime"; import { assertDocumentTypeInfo, isDocumentMapInfo } from "@fluid-internal/test-version-utils"; -import { IDocumentLoaderAndSummarizer, IDocumentProps, ISummarizeResult } from "./DocumentCreator"; +import { + IDocumentLoaderAndSummarizer, + IDocumentProps, + ISummarizeResult, +} from "./DocumentCreator.js"; const defaultDataStoreId = "default"; const mapId = "mapId"; diff --git a/packages/test/test-end-to-end-tests/src/test/benchmark/DocumentMultipleDataStores.ts b/packages/test/test-end-to-end-tests/src/test/benchmark/DocumentMultipleDataStores.ts index 915c457df709..eaec4883c3b2 100644 --- a/packages/test/test-end-to-end-tests/src/test/benchmark/DocumentMultipleDataStores.ts +++ b/packages/test/test-end-to-end-tests/src/test/benchmark/DocumentMultipleDataStores.ts @@ -24,7 +24,11 @@ import { isDocumentMultipleDataStoresInfo, } from "@fluid-internal/test-version-utils"; import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils"; -import { IDocumentLoaderAndSummarizer, IDocumentProps, ISummarizeResult } from "./DocumentCreator"; +import { + IDocumentLoaderAndSummarizer, + IDocumentProps, + ISummarizeResult, +} from "./DocumentCreator.js"; // Tests usually make use of the default data object provided by the test object provider. // However, it only creates a single DDS and in these tests we create multiple (3) DDSes per data store. diff --git a/packages/test/test-end-to-end-tests/src/test/benchmark/LoadDocument.all.spec.ts b/packages/test/test-end-to-end-tests/src/test/benchmark/LoadDocument.all.spec.ts index aea69b797a4e..7545f57dc9ef 100644 --- a/packages/test/test-end-to-end-tests/src/test/benchmark/LoadDocument.all.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/benchmark/LoadDocument.all.spec.ts @@ -11,7 +11,7 @@ import { createDocument, IBenchmarkParameters, IDocumentLoader, -} from "./DocumentCreator"; +} from "./DocumentCreator.js"; describeE2EDocRun("Load Document", (getTestObjectProvider, getDocumentInfo) => { let documentWrapper: IDocumentLoader; diff --git a/packages/test/test-end-to-end-tests/src/test/benchmark/PasTable.all.spec.ts b/packages/test/test-end-to-end-tests/src/test/benchmark/PasTable.all.spec.ts index 230d7da26a25..57830e33a9ba 100644 --- a/packages/test/test-end-to-end-tests/src/test/benchmark/PasTable.all.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/benchmark/PasTable.all.spec.ts @@ -10,7 +10,7 @@ import { } from "@fluidframework/test-runtime-utils"; import { SharedMatrix, SharedMatrixFactory } from "@fluidframework/matrix"; import { SharedString, SharedStringFactory } from "@fluidframework/sequence"; -import { benchmarkAll, IBenchmarkParameters } from "./DocumentCreator"; +import { benchmarkAll, IBenchmarkParameters } from "./DocumentCreator.js"; function createLocalMatrix(id: string, dataStoreRuntime: MockFluidDataStoreRuntime) { return new SharedMatrix(dataStoreRuntime, "matrix1", SharedMatrixFactory.Attributes); diff --git a/packages/test/test-end-to-end-tests/src/test/benchmark/SimpleTest.all.spec.ts b/packages/test/test-end-to-end-tests/src/test/benchmark/SimpleTest.all.spec.ts index 0ce9ba934fd9..c29956dd445d 100644 --- a/packages/test/test-end-to-end-tests/src/test/benchmark/SimpleTest.all.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/benchmark/SimpleTest.all.spec.ts @@ -6,7 +6,7 @@ import { strict as assert } from "assert"; import { IContainer } from "@fluidframework/container-definitions"; import { ITestObjectProvider } from "@fluidframework/test-utils"; import { describeNoCompat } from "@fluid-internal/test-version-utils"; -import { benchmarkAll, IBenchmarkParameters } from "./DocumentCreator"; +import { benchmarkAll, IBenchmarkParameters } from "./DocumentCreator.js"; describeNoCompat("Simple Scenario Title", (getTestObjectProvider) => { let provider: ITestObjectProvider; diff --git a/packages/test/test-end-to-end-tests/src/test/benchmark/summarizationDocument.all.spec.ts b/packages/test/test-end-to-end-tests/src/test/benchmark/summarizationDocument.all.spec.ts index d8876d0c29bd..87c02f0e0e59 100644 --- a/packages/test/test-end-to-end-tests/src/test/benchmark/summarizationDocument.all.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/benchmark/summarizationDocument.all.spec.ts @@ -12,7 +12,7 @@ import { IBenchmarkParameters, IDocumentLoaderAndSummarizer, ISummarizeResult, -} from "./DocumentCreator"; +} from "./DocumentCreator.js"; const scenarioTitle = "Summarize Document"; describeE2EDocRun(scenarioTitle, (getTestObjectProvider, getDocumentInfo) => { diff --git a/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts b/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts index a7841419b869..269e2412d222 100644 --- a/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts @@ -27,7 +27,7 @@ import { driverSupportsBlobs, getUrlFromDetachedBlobStorage, MockDetachedBlobStorage, -} from "./mockDetachedBlobStorage"; +} from "./mockDetachedBlobStorage.js"; const testContainerConfig: ITestContainerConfig = { runtimeOptions: { diff --git a/packages/test/test-end-to-end-tests/src/test/compression.spec.ts b/packages/test/test-end-to-end-tests/src/test/compression.spec.ts index 14c295d984c9..08e536440c1d 100644 --- a/packages/test/test-end-to-end-tests/src/test/compression.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/compression.spec.ts @@ -20,7 +20,7 @@ import { getVersionedTestObjectProvider, } from "@fluid-internal/test-version-utils"; import { CompressionAlgorithms } from "@fluidframework/container-runtime"; -import { pkgVersion } from "../packageVersion"; +import { pkgVersion } from "../packageVersion.js"; const compressionSuite = (getProvider) => { describe("Compression", () => { diff --git a/packages/test/test-end-to-end-tests/src/test/deRehydrateContainerTests.spec.ts b/packages/test/test-end-to-end-tests/src/test/deRehydrateContainerTests.spec.ts index b9dfeec518f0..5281cf000ed2 100644 --- a/packages/test/test-end-to-end-tests/src/test/deRehydrateContainerTests.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/deRehydrateContainerTests.spec.ts @@ -41,7 +41,7 @@ import { describeFullCompat } from "@fluid-internal/test-version-utils"; import { getSnapshotTreeFromSerializedContainer, // eslint-disable-next-line import/no-internal-modules -} from "@fluidframework/container-loader/dist/utils"; +} from "@fluidframework/container-loader/dist/utils.js"; import { SparseMatrix } from "@fluid-experimental/sequence-deprecated"; const detachedContainerRefSeqNumber = 0; diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcAttachmentBlobs.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcAttachmentBlobs.spec.ts index 5cf76f2ccf82..c7493b4c0028 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcAttachmentBlobs.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcAttachmentBlobs.spec.ts @@ -17,16 +17,16 @@ import { } from "@fluidframework/test-utils"; import { describeNoCompat, ITestDataObject } from "@fluid-internal/test-version-utils"; // eslint-disable-next-line import/no-internal-modules -import { BlobManager } from "@fluidframework/container-runtime/dist/blobManager"; +import { BlobManager } from "@fluidframework/container-runtime/dist/blobManager.js"; import { driverSupportsBlobs, getUrlFromDetachedBlobStorage, MockDetachedBlobStorage, -} from "../mockDetachedBlobStorage"; +} from "../mockDetachedBlobStorage.js"; import { getGCStateFromSummary, waitForContainerWriteModeConnectionWrite, -} from "./gcTestSummaryUtils"; +} from "./gcTestSummaryUtils.js"; /** * Validates that unreferenced blobs are marked as unreferenced and deleted correctly. diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcContainerRuntimeCompat.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcContainerRuntimeCompat.spec.ts index 564ad5d3c11c..0346be6db795 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcContainerRuntimeCompat.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcContainerRuntimeCompat.spec.ts @@ -21,8 +21,8 @@ import { summarizeNow, } from "@fluidframework/test-utils"; import { describeFullCompat, getContainerRuntimeApi } from "@fluid-internal/test-version-utils"; -import { pkgVersion } from "../../packageVersion"; -import { getGCStateFromSummary } from "./gcTestSummaryUtils"; +import { pkgVersion } from "../../packageVersion.js"; +import { getGCStateFromSummary } from "./gcTestSummaryUtils.js"; /** * These tests validate the compatibility of the GC data in the summary tree across the past 2 container runtime diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcDatastoreAliased.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcDatastoreAliased.spec.ts index 3a4d4dc8c569..763940100e80 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcDatastoreAliased.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcDatastoreAliased.spec.ts @@ -23,8 +23,8 @@ import { ITestDataObject, TestDataObjectType, } from "@fluid-internal/test-version-utils"; -import { defaultGCConfig } from "./gcTestConfigs"; -import { getGCStateFromSummary } from "./gcTestSummaryUtils"; +import { defaultGCConfig } from "./gcTestConfigs.js"; +import { getGCStateFromSummary } from "./gcTestSummaryUtils.js"; /** * Validates this scenario: When a datastore is aliased that it is considered a root datastore and always referenced diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcDatastoreDuplicateRoutes.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcDatastoreDuplicateRoutes.spec.ts index ea8e58b624e3..0f61fc38600d 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcDatastoreDuplicateRoutes.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcDatastoreDuplicateRoutes.spec.ts @@ -22,8 +22,8 @@ import { ISummaryBlob, SummaryType } from "@fluidframework/protocol-definitions" import { SharedMap } from "@fluidframework/map"; import { gcTreeKey, gcBlobPrefix } from "@fluidframework/runtime-definitions"; // eslint-disable-next-line import/no-internal-modules -import { IGarbageCollectionState } from "@fluidframework/container-runtime/dist/gc"; -import { defaultGCConfig } from "./gcTestConfigs"; +import type { IGarbageCollectionState } from "@fluidframework/container-runtime/dist/gc/index.js"; +import { defaultGCConfig } from "./gcTestConfigs.js"; /** * Validates this scenario: When two DDSes in the same datastore has one change, gets summarized, and then gc is called diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcDeleteObjectsInTestMode.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcDeleteObjectsInTestMode.spec.ts index f4bc06dbf621..7ada5d62ac43 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcDeleteObjectsInTestMode.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcDeleteObjectsInTestMode.spec.ts @@ -24,8 +24,8 @@ import { TestDataObjectType, } from "@fluid-internal/test-version-utils"; -import { defaultGCConfig } from "./gcTestConfigs"; -import { getGCStateFromSummary } from "./gcTestSummaryUtils"; +import { defaultGCConfig } from "./gcTestConfigs.js"; +import { getGCStateFromSummary } from "./gcTestSummaryUtils.js"; /** * Validates the state of the given node in the GC summary tree: diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcInactiveNodes.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcInactiveNodes.spec.ts index 92f48a60c786..cbc1862899b7 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcInactiveNodes.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcInactiveNodes.spec.ts @@ -25,7 +25,7 @@ import { itExpects, TestDataObjectType, } from "@fluid-internal/test-version-utils"; -import { waitForContainerWriteModeConnectionWrite } from "./gcTestSummaryUtils"; +import { waitForContainerWriteModeConnectionWrite } from "./gcTestSummaryUtils.js"; /** * Validates this scenario: When a GC node (data store or attachment blob) becomes inactive, i.e, it has been diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcIncrementalSummaries.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcIncrementalSummaries.spec.ts index 8f874e45aab4..ea492bda2b9f 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcIncrementalSummaries.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcIncrementalSummaries.spec.ts @@ -22,7 +22,7 @@ import { TestDataObjectType, } from "@fluid-internal/test-version-utils"; import { channelsTreeName } from "@fluidframework/runtime-definitions"; -import { defaultGCConfig } from "./gcTestConfigs"; +import { defaultGCConfig } from "./gcTestConfigs.js"; /** * Validates that unchanged Fluid objects are not summarized again. Basically, only objects that have changed since diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcLoadingFromOlderSummaries.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcLoadingFromOlderSummaries.spec.ts index 1af86adbe2b6..17d37946b471 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcLoadingFromOlderSummaries.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcLoadingFromOlderSummaries.spec.ts @@ -25,8 +25,8 @@ import { ITestDataObject, TestDataObjectType, } from "@fluid-internal/test-version-utils"; -import { defaultGCConfig } from "./gcTestConfigs"; -import { getGCStateFromSummary } from "./gcTestSummaryUtils"; +import { defaultGCConfig } from "./gcTestConfigs.js"; +import { getGCStateFromSummary } from "./gcTestSummaryUtils.js"; /** * Validates that that reference state of nodes is correct irrespective of whether a summarizer loads from the latest diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcReferenceUpdatesInSummary.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcReferenceUpdatesInSummary.spec.ts index c4a3df6967ee..67e4202dff14 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcReferenceUpdatesInSummary.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcReferenceUpdatesInSummary.spec.ts @@ -4,12 +4,6 @@ */ import { strict as assert } from "assert"; - -import { - ContainerRuntimeFactoryWithDefaultDataStore, - DataObject, - DataObjectFactory, -} from "@fluidframework/aqueduct"; import { IContainer } from "@fluidframework/container-definitions"; import { ContainerRuntime, IContainerRuntimeOptions } from "@fluidframework/container-runtime"; import { IFluidHandle } from "@fluidframework/core-interfaces"; @@ -23,56 +17,58 @@ import { ITestObjectProvider, waitForContainerConnection } from "@fluidframework import { describeFullCompat } from "@fluid-internal/test-version-utils"; import { UndoRedoStackManager } from "@fluidframework/undo-redo"; -class TestDataObject extends DataObject { - public get _root() { - return this.root; - } +/** + * Validates this scenario: When all references to a data store are deleted, the data store is marked as unreferenced + * in the next summary. When a reference to the data store is re-added, it is marked as referenced in the next summary. + * Basically, if the handle to a data store is not stored in any DDS, its summary tree will have the "unreferenced" + * property set to true. If the handle to a data store exists or it's a root data store, its summary tree does not have + * the "unreferenced" property. + */ +describeFullCompat("GC reference updates in local summary", (getTestObjectProvider, apis) => { + class TestDataObject extends apis.dataRuntime.DataObject { + public get _root() { + return this.root; + } - public get _context() { - return this.context; - } + public get _context() { + return this.context; + } - private readonly matrixKey = "matrix"; - public matrix!: SharedMatrix; - public undoRedoStackManager!: UndoRedoStackManager; + private readonly matrixKey = "matrix"; + public matrix!: SharedMatrix; + public undoRedoStackManager!: UndoRedoStackManager; - private readonly sharedStringKey = "sharedString"; - public sharedString!: SharedString; + private readonly sharedStringKey = "sharedString"; + public sharedString!: SharedString; - protected async initializingFirstTime() { - const sharedMatrix = SharedMatrix.create(this.runtime); - this.root.set(this.matrixKey, sharedMatrix.handle); + protected async initializingFirstTime() { + const sharedMatrix = SharedMatrix.create(this.runtime); + this.root.set(this.matrixKey, sharedMatrix.handle); - const sharedString = SharedString.create(this.runtime); - this.root.set(this.sharedStringKey, sharedString.handle); - } + const sharedString = SharedString.create(this.runtime); + this.root.set(this.sharedStringKey, sharedString.handle); + } - protected async hasInitialized() { - const matrixHandle = this.root.get>(this.matrixKey); - assert(matrixHandle !== undefined, "SharedMatrix not found"); - this.matrix = await matrixHandle.get(); + protected async hasInitialized() { + const matrixHandle = this.root.get>(this.matrixKey); + assert(matrixHandle !== undefined, "SharedMatrix not found"); + this.matrix = await matrixHandle.get(); - this.undoRedoStackManager = new UndoRedoStackManager(); - this.matrix.insertRows(0, 3); - this.matrix.insertCols(0, 3); - this.matrix.openUndo(this.undoRedoStackManager); + this.undoRedoStackManager = new UndoRedoStackManager(); + this.matrix.insertRows(0, 3); + this.matrix.insertCols(0, 3); + this.matrix.openUndo(this.undoRedoStackManager); - const sharedStringHandle = this.root.get>(this.sharedStringKey); - assert(sharedStringHandle !== undefined, "SharedMatrix not found"); - this.sharedString = await sharedStringHandle.get(); + const sharedStringHandle = this.root.get>( + this.sharedStringKey, + ); + assert(sharedStringHandle !== undefined, "SharedMatrix not found"); + this.sharedString = await sharedStringHandle.get(); + } } -} -/** - * Validates this scenario: When all references to a data store are deleted, the data store is marked as unreferenced - * in the next summary. When a reference to the data store is re-added, it is marked as referenced in the next summary. - * Basically, if the handle to a data store is not stored in any DDS, its summary tree will have the "unreferenced" - * property set to true. If the handle to a data store exists or it's a root data store, its summary tree does not have - * the "unreferenced" property. - */ -describeFullCompat("GC reference updates in local summary", (getTestObjectProvider) => { let provider: ITestObjectProvider; - const factory = new DataObjectFactory( + const factory = new apis.dataRuntime.DataObjectFactory( "TestDataObject", TestDataObject, [SharedMatrix.getFactory(), SharedString.getFactory()], @@ -87,7 +83,7 @@ describeFullCompat("GC reference updates in local summary", (getTestObjectProvid }, gcOptions: { gcAllowed: true }, }; - const runtimeFactory = new ContainerRuntimeFactoryWithDefaultDataStore( + const runtimeFactory = new apis.containerRuntime.ContainerRuntimeFactoryWithDefaultDataStore( factory, [[factory.type, Promise.resolve(factory)]], undefined, diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcStateResetInSummaries.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcStateResetInSummaries.spec.ts index 2514e2f44441..7eddc4847a18 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcStateResetInSummaries.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcStateResetInSummaries.spec.ts @@ -20,8 +20,8 @@ import { ITestDataObject, TestDataObjectType, } from "@fluid-internal/test-version-utils"; -import { defaultGCConfig } from "./gcTestConfigs"; -import { getGCStateFromSummary } from "./gcTestSummaryUtils"; +import { defaultGCConfig } from "./gcTestConfigs.js"; +import { getGCStateFromSummary } from "./gcTestSummaryUtils.js"; /** * Validates that when GC is disabled on a document that had run GC previously, the GC state is removed from summary diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcStats.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcStats.spec.ts index f4a5ca5c339a..ab60409005bf 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcStats.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcStats.spec.ts @@ -18,8 +18,8 @@ import { TestDataObjectType, } from "@fluid-internal/test-version-utils"; import { IContainer } from "@fluidframework/container-definitions"; -import { defaultGCConfig } from "./gcTestConfigs"; -import { waitForContainerWriteModeConnectionWrite } from "./gcTestSummaryUtils"; +import { defaultGCConfig } from "./gcTestConfigs.js"; +import { waitForContainerWriteModeConnectionWrite } from "./gcTestSummaryUtils.js"; /** * Validates that we generate correct garbage collection stats, such as total number of nodes, number of unreferenced diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcSweepAttachmentBlobs.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcSweepAttachmentBlobs.spec.ts index 227dc1bce3e3..e5c4f95cef78 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcSweepAttachmentBlobs.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcSweepAttachmentBlobs.spec.ts @@ -19,17 +19,17 @@ import { describeNoCompat, ITestDataObject, itExpects } from "@fluid-internal/te import { delay, stringToBuffer } from "@fluidframework/common-utils"; import { IContainer, LoaderHeader } from "@fluidframework/container-definitions"; // eslint-disable-next-line import/no-internal-modules -import { blobsTreeName } from "@fluidframework/container-runtime/dist/summary"; +import { blobsTreeName } from "@fluidframework/container-runtime/dist/summary/index.js"; import { driverSupportsBlobs, getUrlFromDetachedBlobStorage, MockDetachedBlobStorage, -} from "../mockDetachedBlobStorage"; +} from "../mockDetachedBlobStorage.js"; import { getGCDeletedStateFromSummary, getGCStateFromSummary, waitForContainerWriteModeConnectionWrite, -} from "./gcTestSummaryUtils"; +} from "./gcTestSummaryUtils.js"; /** * These tests validate that SweepReady attachment blobs are correctly swept. Swept attachment blobs should be diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcSweepDataStores.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcSweepDataStores.spec.ts index 8b51813cd0f2..3180731cda6a 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcSweepDataStores.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcSweepDataStores.spec.ts @@ -29,7 +29,7 @@ import { import { delay } from "@fluidframework/common-utils"; import { IContainer, LoaderHeader } from "@fluidframework/container-definitions"; import { IRequest, IResponse } from "@fluidframework/core-interfaces"; -import { getGCDeletedStateFromSummary, getGCStateFromSummary } from "./gcTestSummaryUtils"; +import { getGCDeletedStateFromSummary, getGCStateFromSummary } from "./gcTestSummaryUtils.js"; /** * These tests validate that SweepReady data stores are correctly swept. Swept datastores should be diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcSweepUnreferencePhases.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcSweepUnreferencePhases.spec.ts index 245051b52954..1e1e2a5e6cf9 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcSweepUnreferencePhases.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcSweepUnreferencePhases.spec.ts @@ -27,7 +27,7 @@ import { getGCStateFromSummary, getGCDeletedStateFromSummary, getGCTombstoneStateFromSummary, -} from "./gcTestSummaryUtils"; +} from "./gcTestSummaryUtils.js"; /** * Validates that an unreferenced datastore and blob goes through all the GC sweep phases without overlapping. diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcTestSummaryUtils.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcTestSummaryUtils.ts index 194cb08bfcf3..4e2ce2f31cb0 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcTestSummaryUtils.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcTestSummaryUtils.ts @@ -15,7 +15,7 @@ import { concatGarbageCollectionStates, IGarbageCollectionState, // eslint-disable-next-line import/no-internal-modules -} from "@fluidframework/container-runtime/dist/gc"; +} from "@fluidframework/container-runtime/dist/gc/index.js"; import { IContainer } from "@fluidframework/container-definitions"; /** diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneAttachmentBlobs.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneAttachmentBlobs.spec.ts index d253e4c09ed8..b63af1d78bd8 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneAttachmentBlobs.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneAttachmentBlobs.spec.ts @@ -22,8 +22,8 @@ import { driverSupportsBlobs, getUrlFromDetachedBlobStorage, MockDetachedBlobStorage, -} from "../mockDetachedBlobStorage"; -import { waitForContainerWriteModeConnectionWrite } from "./gcTestSummaryUtils"; +} from "../mockDetachedBlobStorage.js"; +import { waitForContainerWriteModeConnectionWrite } from "./gcTestSummaryUtils.js"; /** * These tests validate that SweepReady attachment blobs are correctly marked as tombstones. Tombstones should be added diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneDataStores.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneDataStores.spec.ts index 757f617a0b54..eff5b2fbd71e 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneDataStores.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneDataStores.spec.ts @@ -34,7 +34,7 @@ import { validateAssertionError } from "@fluidframework/test-runtime-utils"; import { IFluidDataStoreChannel } from "@fluidframework/runtime-definitions"; import { MockLogger } from "@fluidframework/telemetry-utils"; import { FluidSerializer, parseHandles } from "@fluidframework/shared-object-base"; -import { getGCStateFromSummary, getGCTombstoneStateFromSummary } from "./gcTestSummaryUtils"; +import { getGCStateFromSummary, getGCTombstoneStateFromSummary } from "./gcTestSummaryUtils.js"; /** * These tests validate that SweepReady data stores are correctly marked as tombstones. Tombstones should be added diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneUnreferencePhases.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneUnreferencePhases.spec.ts index 4cb1aa12aafb..cd2f1085a6d8 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneUnreferencePhases.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcTombstoneUnreferencePhases.spec.ts @@ -22,7 +22,7 @@ import { IGCRuntimeOptions } from "@fluidframework/container-runtime"; import { delay, stringToBuffer } from "@fluidframework/common-utils"; import { gcTreeKey } from "@fluidframework/runtime-definitions"; import { SummaryType } from "@fluidframework/protocol-definitions"; -import { getGCStateFromSummary, getGCTombstoneStateFromSummary } from "./gcTestSummaryUtils"; +import { getGCStateFromSummary, getGCTombstoneStateFromSummary } from "./gcTestSummaryUtils.js"; /** * Validates that an unreferenced datastore and blob goes through all the GC phases without overlapping. diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcTrailingOps.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcTrailingOps.spec.ts index 40167fdfdefd..bc638b255fdd 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcTrailingOps.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcTrailingOps.spec.ts @@ -22,8 +22,8 @@ import { requestFluidObject } from "@fluidframework/runtime-utils"; import { stringToBuffer } from "@fluidframework/common-utils"; import { ISummaryTree } from "@fluidframework/protocol-definitions"; import { IGCRuntimeOptions } from "@fluidframework/container-runtime"; -import { getGCStateFromSummary } from "./gcTestSummaryUtils"; -import { defaultGCConfig } from "./gcTestConfigs"; +import { getGCStateFromSummary } from "./gcTestSummaryUtils.js"; +import { defaultGCConfig } from "./gcTestConfigs.js"; describeNoCompat("GC trailing ops tests", (getTestObjectProvider) => { const tests = (tombstoneEnabled: boolean = false) => { diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcUnknownHandles.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcUnknownHandles.spec.ts index c74914daf07e..e5e97a48ae44 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcUnknownHandles.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcUnknownHandles.spec.ts @@ -16,8 +16,8 @@ import { IRequest, IResponse, } from "@fluidframework/core-interfaces"; -import { defaultGCConfig } from "./gcTestConfigs"; -import { getGCStateFromSummary } from "./gcTestSummaryUtils"; +import { defaultGCConfig } from "./gcTestConfigs.js"; +import { getGCStateFromSummary } from "./gcTestSummaryUtils.js"; /** * An IFluidHandle implementation that has a random path / url. This is used to test that adding this handle to diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcUnreferencedFlagInSnapshot.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcUnreferencedFlagInSnapshot.spec.ts index 74e54fd80487..0a2c58543aee 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcUnreferencedFlagInSnapshot.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcUnreferencedFlagInSnapshot.spec.ts @@ -22,7 +22,7 @@ import { TestDataObjectType, } from "@fluid-internal/test-version-utils"; import { IContainer } from "@fluidframework/container-definitions"; -import { defaultGCConfig } from "./gcTestConfigs"; +import { defaultGCConfig } from "./gcTestConfigs.js"; /** * Validates that the 'unreferenced' property in the summary tree of unreferenced data stores is present diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcUnreferencedTimestamp.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcUnreferencedTimestamp.spec.ts index 95f2d4194627..ff8990019999 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcUnreferencedTimestamp.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcUnreferencedTimestamp.spec.ts @@ -22,8 +22,8 @@ import { ITestDataObject, TestDataObjectType, } from "@fluid-internal/test-version-utils"; -import { defaultGCConfig } from "./gcTestConfigs"; -import { getGCStateFromSummary } from "./gcTestSummaryUtils"; +import { defaultGCConfig } from "./gcTestConfigs.js"; +import { getGCStateFromSummary } from "./gcTestSummaryUtils.js"; /** * Validates that the unreferenced timestamp is correctly set in the GC summary tree. Also, the timestamp is removed diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcVersionUpdate.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcVersionUpdate.spec.ts index 32b97f0d753c..f2be585ccc84 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcVersionUpdate.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcVersionUpdate.spec.ts @@ -29,7 +29,7 @@ import { IGCMetadata, IGarbageCollector, // eslint-disable-next-line import/no-internal-modules -} from "@fluidframework/container-runtime/dist/gc"; +} from "@fluidframework/container-runtime/dist/gc/index.js"; // IContainerRuntime type that exposes garbage collector which is a private property. type IContainerRuntimeWithPrivates = IContainerRuntime & { diff --git a/packages/test/test-end-to-end-tests/src/test/incrementalSummaryContext.spec.ts b/packages/test/test-end-to-end-tests/src/test/incrementalSummaryContext.spec.ts index d2a2bd3c6769..9535cde76957 100644 --- a/packages/test/test-end-to-end-tests/src/test/incrementalSummaryContext.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/incrementalSummaryContext.spec.ts @@ -37,7 +37,7 @@ import { SummaryType, } from "@fluidframework/protocol-definitions"; import { readAndParse } from "@fluidframework/driver-utils"; -import { pkgVersion } from "../packageVersion"; +import { pkgVersion } from "../packageVersion.js"; // Test DDS factory for the blob dds class TestBlobDDSFactory implements IChannelFactory { diff --git a/packages/test/test-end-to-end-tests/src/test/sharedInterval.spec.ts b/packages/test/test-end-to-end-tests/src/test/sharedInterval.spec.ts index 7b5a92b90954..23e0a8e43552 100644 --- a/packages/test/test-end-to-end-tests/src/test/sharedInterval.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/sharedInterval.spec.ts @@ -17,7 +17,7 @@ import { } from "@fluidframework/sequence"; // This is not in sequence's public API, but an e2e test in this file sniffs the summary. // eslint-disable-next-line import/no-internal-modules -import { ISerializedIntervalCollectionV2 } from "@fluidframework/sequence/dist/intervalCollection"; +import { ISerializedIntervalCollectionV2 } from "@fluidframework/sequence/dist/intervalCollection.js"; import { ITestObjectProvider, ITestContainerConfig, diff --git a/packages/test/test-end-to-end-tests/src/test/sharedStringLoading.spec.ts b/packages/test/test-end-to-end-tests/src/test/sharedStringLoading.spec.ts index e95b1ef21ed4..262fbe75a06b 100644 --- a/packages/test/test-end-to-end-tests/src/test/sharedStringLoading.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/sharedStringLoading.spec.ts @@ -25,7 +25,7 @@ import { NonRetryableError, readAndParse } from "@fluidframework/driver-utils"; import { IFluidHandle } from "@fluidframework/core-interfaces"; import { ReferenceType, TextSegment } from "@fluidframework/merge-tree"; import { describeNoCompat, itExpects } from "@fluid-internal/test-version-utils"; -import { pkgVersion } from "../packageVersion"; +import { pkgVersion } from "../packageVersion.js"; // REVIEW: enable compat testing? describeNoCompat("SharedString", (getTestObjectProvider) => { diff --git a/packages/test/test-end-to-end-tests/src/test/tsconfig.json b/packages/test/test-end-to-end-tests/src/test/tsconfig.json index dccb135cb08d..ca0efdc7a8fd 100644 --- a/packages/test/test-end-to-end-tests/src/test/tsconfig.json +++ b/packages/test/test-end-to-end-tests/src/test/tsconfig.json @@ -7,6 +7,7 @@ "outDir": "../../dist", "types": ["mocha", "@fluidframework/test-driver-definitions"], "noUnusedLocals": false, // Needed for memory tests to be able to declare local variables just for the purpose of keeping stuff in memory + "module": "ESNext", }, "include": ["./**/*"], } diff --git a/packages/test/test-version-utils/.eslintrc.js b/packages/test/test-version-utils/.eslintrc.cjs similarity index 62% rename from packages/test/test-version-utils/.eslintrc.js rename to packages/test/test-version-utils/.eslintrc.cjs index e520388420dc..2218f5eaf158 100644 --- a/packages/test/test-version-utils/.eslintrc.js +++ b/packages/test/test-version-utils/.eslintrc.cjs @@ -8,6 +8,10 @@ module.exports = { rules: { "@typescript-eslint/strict-boolean-expressions": "off", // requires strictNullChecks=true in tsconfig "import/no-nodejs-modules": "off", + // ESLint's resolver doesn't resolve relative imports of ESNext modules correctly, since + // it resolves the path relative to the .ts file (and assumes a file with a .js extension + // should exist there) + "import/no-unresolved": ["error", { ignore: ["^\\.(.*)\\.js$"] }], }, parserOptions: { project: ["./tsconfig.json", "./src/test/tsconfig.json"], diff --git a/packages/test/test-version-utils/mocharc-common.js b/packages/test/test-version-utils/mocharc-common.cjs similarity index 84% rename from packages/test/test-version-utils/mocharc-common.js rename to packages/test/test-version-utils/mocharc-common.cjs index e84818d20e62..dd7388df850d 100644 --- a/packages/test/test-version-utils/mocharc-common.js +++ b/packages/test/test-version-utils/mocharc-common.cjs @@ -4,8 +4,7 @@ */ "use strict"; - -const options = require("./dist/compatOptions"); +const options = import("./dist/compatOptions.js"); const getFluidTestMochaConfig = require("@fluidframework/mocha-test-setup/mocharc-common.js"); function getFluidTestVariant() { @@ -32,11 +31,7 @@ function getFluidTestMochaConfigWithCompat(packageDir, additionalRequiredModules testReportPrefix += `_${options.compatKind.join("_")}`; } - return getFluidTestMochaConfig( - packageDir, - ["@fluid-internal/test-version-utils", ...additionalRequiredModules], - testReportPrefix, - ); + return getFluidTestMochaConfig(packageDir, additionalRequiredModules, testReportPrefix); } module.exports = getFluidTestMochaConfigWithCompat; diff --git a/packages/test/test-version-utils/package.json b/packages/test/test-version-utils/package.json index 54128380ed96..c1afef634c19 100644 --- a/packages/test/test-version-utils/package.json +++ b/packages/test/test-version-utils/package.json @@ -14,6 +14,7 @@ "main": "dist/index.js", "module": "lib/index.js", "types": "dist/index.d.ts", + "type": "module", "scripts": { "build": "npm run build:genver && concurrently npm:build:compile npm:lint", "build:compile": "npm run tsc && npm run build:test", diff --git a/packages/test/test-version-utils/src/compatConfig.ts b/packages/test/test-version-utils/src/compatConfig.ts index ff6a42499475..fd0f8f60b87c 100644 --- a/packages/test/test-version-utils/src/compatConfig.ts +++ b/packages/test/test-version-utils/src/compatConfig.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. */ import { Lazy, assert } from "@fluidframework/common-utils"; -import { ensurePackageInstalled } from "./testApi"; -import { pkgVersion } from "./packageVersion"; +import { ensurePackageInstalled } from "./testApi.js"; +import { pkgVersion } from "./packageVersion.js"; import { CompatKind, compatKind, @@ -14,7 +14,7 @@ import { tenantIndex, baseVersion, reinstall, -} from "./compatOptions"; +} from "./compatOptions.js"; /* * Generate configuration combinations for a particular compat version @@ -229,8 +229,41 @@ export const configList = new Lazy(() => { return _configList; }); -/* +/** * Mocha start up to ensure legacy versions are installed + * @privateRemarks + * This isn't currently used in a global setup hook due to https://github.com/mochajs/mocha/issues/4508. + * Instead, we ensure that all requested compatibility versions are loaded at `describeCompat` module import time by + * leveraging top-level await. + * + * This makes compatibility layer APIs (e.g. DDSes, data object, etc.) available at mocha suite creation time rather than + * hook/test execution time, which is convenient for test authors: this sort of code can be used + * ```ts + * describeCompat("my suite", (getTestObjectProvider, apis) => { + * class MyDataObject extends apis.dataRuntime.DataObject { + * // ... + * } + * }); + * ``` + * + * instead of code like this: + * + * ```ts + * describeCompat("my suite", (getTestObjectProvider, getApis) => { + * + * const makeDataObjectClass = (apis: CompatApis) => class MyDataObject extends apis.dataRuntime.DataObject { + * // ... + * } + * + * before(() => { + * // `getApis` can only be invoked from inside a hook or test + * const MyDataObject = makeDataObjectClass(getApis()) + * }); + * }); + * ``` + * + * If the linked github issue is ever fixed, the module load logic in `./testApi.js` can be simplified considerably + * and this can be once again used as a global setup fixture. */ export async function mochaGlobalSetup() { const versions = new Set(configList.value.map((value) => value.compatVersion)); @@ -246,7 +279,8 @@ export async function mochaGlobalSetup() { let error: unknown | undefined; for (const p of installP) { try { - await p; + const pkg = await p; + console.log(pkg?.modulePath, pkg?.version); } catch (e) { error = e; } diff --git a/packages/test/test-version-utils/src/compatOptions.ts b/packages/test/test-version-utils/src/compatOptions.ts index ad9acf1a829c..011914f527f2 100644 --- a/packages/test/test-version-utils/src/compatOptions.ts +++ b/packages/test/test-version-utils/src/compatOptions.ts @@ -5,8 +5,8 @@ import nconf from "nconf"; import { RouterliciousEndpoint, TestDriverTypes } from "@fluidframework/test-driver-definitions"; -import { resolveVersion } from "./versionUtils"; -import { pkgVersion } from "./packageVersion"; +import { resolveVersion } from "./versionUtils.js"; +import { pkgVersion } from "./packageVersion.js"; /** * Different kind of compat version config diff --git a/packages/test/test-version-utils/src/compatUtils.ts b/packages/test/test-version-utils/src/compatUtils.ts index 97d0f464055a..133e7f05fe83 100644 --- a/packages/test/test-version-utils/src/compatUtils.ts +++ b/packages/test/test-version-utils/src/compatUtils.ts @@ -22,8 +22,14 @@ import { } from "@fluidframework/test-utils"; import { TestDriverTypes } from "@fluidframework/test-driver-definitions"; import { mixinAttributor } from "@fluid-experimental/attributor"; -import { pkgVersion } from "./packageVersion"; -import { getLoaderApi, getContainerRuntimeApi, getDataRuntimeApi, getDriverApi } from "./testApi"; +import { pkgVersion } from "./packageVersion.js"; +import { + getLoaderApi, + getContainerRuntimeApi, + getDataRuntimeApi, + getDriverApi, + CompatApis, +} from "./testApi.js"; export const TestDataObjectType = "@fluid-example/test-dataStore"; @@ -90,43 +96,28 @@ function createGetDataStoreFactoryFunction(api: ReturnType { - const loaderApi = getLoaderApi(baseVersion, loaderVersion); - const containerRuntimeApi = getContainerRuntimeApi(baseVersion, runtimeVersion); - const dataRuntimeApi = getDataRuntimeApi(baseVersion, dataRuntimeVersion); - const driver = await createVersionedFluidTestDriver(baseVersion, driverConfig); + const driver = await createFluidTestDriver( + driverConfig?.type ?? "local", + driverConfig?.config, + apis.driver, + ); const innerRequestHandler = async (request: IRequest, runtime: IContainerRuntimeBase) => runtime.IFluidHandleContext.resolveHandle(request); - const getDataStoreFactoryFn = createGetDataStoreFactoryFunction(dataRuntimeApi); + const getDataStoreFactoryFn = createGetDataStoreFactoryFunction(apis.dataRuntime); const containerFactoryFn = (containerOptions?: ITestContainerConfig) => { const dataStoreFactory = getDataStoreFactoryFn(containerOptions); const runtimeCtor = containerOptions?.enableAttribution === true - ? mixinAttributor(containerRuntimeApi.ContainerRuntime) - : containerRuntimeApi.ContainerRuntime; + ? mixinAttributor(apis.containerRuntime.ContainerRuntime) + : apis.containerRuntime.ContainerRuntime; const factoryCtor = createTestContainerRuntimeFactory(runtimeCtor); return new factoryCtor( TestDataObjectType, @@ -136,5 +127,26 @@ export async function getVersionedTestObjectProvider( ); }; - return new TestObjectProvider(loaderApi.Loader, driver, containerFactoryFn); + return new TestObjectProvider(apis.loader.Loader, driver, containerFactoryFn); +} + +export async function getVersionedTestObjectProvider( + baseVersion: string, + loaderVersion?: number | string, + driverConfig?: { + type?: TestDriverTypes; + config?: FluidTestDriverConfig; + version?: number | string; + }, + runtimeVersion?: number | string, + dataRuntimeVersion?: number | string, +): Promise { + const apis: CompatApis = { + loader: getLoaderApi(baseVersion, loaderVersion), + containerRuntime: getContainerRuntimeApi(baseVersion, runtimeVersion), + dataRuntime: getDataRuntimeApi(baseVersion, dataRuntimeVersion), + driver: getDriverApi(baseVersion, driverConfig?.version), + }; + + return getVersionedTestObjectProviderFromApis(apis, driverConfig); } diff --git a/packages/test/test-version-utils/src/describeCompat.ts b/packages/test/test-version-utils/src/describeCompat.ts index b1a2764ec1d1..d844b3313e36 100644 --- a/packages/test/test-version-utils/src/describeCompat.ts +++ b/packages/test/test-version-utils/src/describeCompat.ts @@ -9,15 +9,24 @@ import { ITestObjectProvider, TestObjectProvider, } from "@fluidframework/test-utils"; -import { configList } from "./compatConfig"; -import { CompatKind, baseVersion, driver, r11sEndpointName, tenantIndex } from "./compatOptions"; -import { getVersionedTestObjectProvider } from "./compatUtils"; +import { configList, mochaGlobalSetup } from "./compatConfig.js"; +import { CompatKind, baseVersion, driver, r11sEndpointName, tenantIndex } from "./compatOptions.js"; +import { getVersionedTestObjectProviderFromApis } from "./compatUtils.js"; +import { + getContainerRuntimeApi, + getDataRuntimeApi, + getLoaderApi, + CompatApis, + getDriverApi, +} from "./testApi.js"; + +await mochaGlobalSetup(); /* * Mocha Utils for test to generate the compat variants. */ function createCompatSuite( - tests: (this: Mocha.Suite, provider: () => ITestObjectProvider) => void, + tests: (this: Mocha.Suite, provider: () => ITestObjectProvider, apis: CompatApis) => void, compatFilter?: CompatKind[], ) { return function (this: Mocha.Suite) { @@ -30,22 +39,22 @@ function createCompatSuite( describe(config.name, function () { let provider: TestObjectProvider; let resetAfterEach: boolean; + const apis: CompatApis = { + containerRuntime: getContainerRuntimeApi(baseVersion, config.containerRuntime), + dataRuntime: getDataRuntimeApi(baseVersion, config.dataRuntime), + driver: getDriverApi(baseVersion, config.driver), + loader: getLoaderApi(baseVersion, config.loader), + }; + before(async function () { try { - provider = await getVersionedTestObjectProvider( - baseVersion, - config.loader, - { - type: driver, - version: config.driver, - config: { - r11s: { r11sEndpointName }, - odsp: { tenantIndex }, - }, + provider = await getVersionedTestObjectProviderFromApis(apis, { + type: driver, + config: { + r11s: { r11sEndpointName }, + odsp: { tenantIndex }, }, - config.containerRuntime, - config.dataRuntime, - ); + }); } catch (error) { const logger = ChildLogger.create(getTestLogger?.(), "DescribeCompatSetup"); logger.sendErrorEvent( @@ -60,13 +69,14 @@ function createCompatSuite( Object.defineProperty(this, "__fluidTestProvider", { get: () => provider }); }); + tests.bind(this)((options?: ITestObjectProviderOptions) => { resetAfterEach = options?.resetAfterEach ?? true; if (options?.syncSummarizer === true) { provider.resetLoaderContainerTracker(true /* syncSummarizerClients */); } return provider; - }); + }, apis); afterEach(function (done: Mocha.Done) { const logErrors = getUnexpectedLogErrorException(provider.logger); @@ -99,6 +109,7 @@ export type DescribeCompatSuite = ( tests: ( this: Mocha.Suite, provider: (options?: ITestObjectProviderOptions) => ITestObjectProvider, + apis: CompatApis, ) => void, ) => Mocha.Suite | void; diff --git a/packages/test/test-version-utils/src/describeE2eDocs.ts b/packages/test/test-version-utils/src/describeE2eDocs.ts index 95fc0f6d8e65..3177f6ff2c9c 100644 --- a/packages/test/test-version-utils/src/describeE2eDocs.ts +++ b/packages/test/test-version-utils/src/describeE2eDocs.ts @@ -11,10 +11,10 @@ import { ITestObjectProvider, TestObjectProvider, } from "@fluidframework/test-utils"; -import { configList } from "./compatConfig"; -import { CompatKind, baseVersion, driver, r11sEndpointName, tenantIndex } from "./compatOptions"; -import { getVersionedTestObjectProvider } from "./compatUtils"; -import { ITestObjectProviderOptions } from "./describeCompat"; +import { configList } from "./compatConfig.js"; +import { CompatKind, baseVersion, driver, r11sEndpointName, tenantIndex } from "./compatOptions.js"; +import { getVersionedTestObjectProvider } from "./compatUtils.js"; +import { ITestObjectProviderOptions } from "./describeCompat.js"; /* * Types of documents to be used during the performance runs. diff --git a/packages/test/test-version-utils/src/describeWithVersions.ts b/packages/test/test-version-utils/src/describeWithVersions.ts index 2146738da453..d7f463e91f2b 100644 --- a/packages/test/test-version-utils/src/describeWithVersions.ts +++ b/packages/test/test-version-utils/src/describeWithVersions.ts @@ -8,11 +8,11 @@ import { ITestObjectProvider, TestObjectProvider, } from "@fluidframework/test-utils"; -import { driver, r11sEndpointName, tenantIndex } from "./compatOptions"; -import { getVersionedTestObjectProvider } from "./compatUtils"; -import { ITestObjectProviderOptions } from "./describeCompat"; -import { pkgVersion } from "./packageVersion"; -import { ensurePackageInstalled, InstalledPackage } from "./testApi"; +import { driver, r11sEndpointName, tenantIndex } from "./compatOptions.js"; +import { getVersionedTestObjectProvider } from "./compatUtils.js"; +import { ITestObjectProviderOptions } from "./describeCompat.js"; +import { pkgVersion } from "./packageVersion.js"; +import { ensurePackageInstalled, InstalledPackage } from "./testApi.js"; /** * Interface to hold the requested versions which should be installed diff --git a/packages/test/test-version-utils/src/index.ts b/packages/test/test-version-utils/src/index.ts index 98ed67f4815b..7535fba3426e 100644 --- a/packages/test/test-version-utils/src/index.ts +++ b/packages/test/test-version-utils/src/index.ts @@ -2,14 +2,15 @@ * Copyright (c) Microsoft Corporation and contributors. All rights reserved. * Licensed under the MIT License. */ -export { mochaGlobalSetup } from "./compatConfig"; +export { mochaGlobalSetup } from "./compatConfig.js"; export { getDataStoreFactory, getVersionedTestObjectProvider, + getVersionedTestObjectProviderFromApis, ITestDataObject, TestDataObjectType, -} from "./compatUtils"; -export { describeInstallVersions } from "./describeWithVersions"; +} from "./compatUtils.js"; +export { describeInstallVersions } from "./describeWithVersions.js"; export { DescribeCompat, DescribeCompatSuite, @@ -17,7 +18,7 @@ export { describeLoaderCompat, describeNoCompat, ITestObjectProviderOptions, -} from "./describeCompat"; +} from "./describeCompat.js"; export { describeE2EDocs, DocumentType, @@ -34,12 +35,13 @@ export { assertDocumentTypeInfo, isDocumentMapInfo, isDocumentMultipleDataStoresInfo, -} from "./describeE2eDocs"; -export { ExpectedEvents, ExpectsTest, itExpects } from "./itExpects"; +} from "./describeE2eDocs.js"; +export { ExpectedEvents, ExpectsTest, itExpects } from "./itExpects.js"; export { + CompatApis, ensurePackageInstalled, getContainerRuntimeApi, getDataRuntimeApi, getDriverApi, getLoaderApi, -} from "./testApi"; +} from "./testApi.js"; diff --git a/packages/test/test-version-utils/src/testApi.ts b/packages/test/test-version-utils/src/testApi.ts index a612481083cb..4e2261ffda73 100644 --- a/packages/test/test-version-utils/src/testApi.ts +++ b/packages/test/test-version-utils/src/testApi.ts @@ -32,14 +32,14 @@ import { import { SparseMatrix } from "@fluid-experimental/sequence-deprecated"; import * as semver from "semver"; -import { pkgVersion } from "./packageVersion"; +import { pkgVersion } from "./packageVersion.js"; import { checkInstalled, ensureInstalled, getRequestedRange, loadPackage, versionHasMovedSparsedMatrix, -} from "./versionUtils"; +} from "./versionUtils.js"; // List of package that needs to be install for legacy versions const packageList = [ @@ -69,8 +69,21 @@ export const ensurePackageInstalled = async ( baseVersion: string, version: number | string, force: boolean, -): Promise => - ensureInstalled(getRequestedRange(baseVersion, version), packageList, force); +): Promise => { + const pkg = await ensureInstalled(getRequestedRange(baseVersion, version), packageList, force); + await Promise.all([ + loadContainerRuntime(baseVersion, version), + loadDataRuntime(baseVersion, version), + loadLoader(baseVersion, version), + loadDriver(baseVersion, version), + ]); + return pkg; +}; + +const loaderCache = new Map(); +const containerRuntimeCache = new Map(); +const dataRuntimeCache = new Map(); +const driverCache = new Map(); // Current versions of the APIs const LoaderApi = { @@ -103,78 +116,214 @@ const DataRuntimeApi = { }, }; -export function getLoaderApi(baseVersion: string, requested?: number | string): typeof LoaderApi { +async function loadLoader( + baseVersion: string, + requested?: number | string, +): Promise { const requestedStr = getRequestedRange(baseVersion, requested); - - // If the current version satisfies the range, use it. if (semver.satisfies(pkgVersion, requestedStr)) { return LoaderApi; } const { version, modulePath } = checkInstalled(requestedStr); - return { - version, - Loader: loadPackage(modulePath, "@fluidframework/container-loader").Loader, - }; + if (!loaderCache.has(version)) { + const loader = { + version, + Loader: (await loadPackage(modulePath, "@fluidframework/container-loader")).Loader, + }; + loaderCache.set(version, loader); + } + return loaderCache.get(version) ?? throwNotFound("Loader", version); } -export function getContainerRuntimeApi( +async function loadContainerRuntime( baseVersion: string, requested?: number | string, -): typeof ContainerRuntimeApi { +): Promise { const requestedStr = getRequestedRange(baseVersion, requested); if (semver.satisfies(pkgVersion, requestedStr)) { return ContainerRuntimeApi; } + const { version, modulePath } = checkInstalled(requestedStr); - return { - version, - ContainerRuntime: loadPackage(modulePath, "@fluidframework/container-runtime") - .ContainerRuntime, - ContainerRuntimeFactoryWithDefaultDataStore: loadPackage( - modulePath, - "@fluidframework/aqueduct", - ).ContainerRuntimeFactoryWithDefaultDataStore, - }; + if (!containerRuntimeCache.has(version)) { + const containerRuntime = { + version, + ContainerRuntime: (await loadPackage(modulePath, "@fluidframework/container-runtime")) + .ContainerRuntime, + ContainerRuntimeFactoryWithDefaultDataStore: ( + await loadPackage(modulePath, "@fluidframework/aqueduct") + ).ContainerRuntimeFactoryWithDefaultDataStore, + }; + containerRuntimeCache.set(version, containerRuntime); + } + return containerRuntimeCache.get(version) ?? throwNotFound("ContainerRuntime", version); } -export function getDataRuntimeApi( +async function loadDataRuntime( baseVersion: string, requested?: number | string, -): typeof DataRuntimeApi { +): Promise { const requestedStr = getRequestedRange(baseVersion, requested); if (semver.satisfies(pkgVersion, requestedStr)) { return DataRuntimeApi; } const { version, modulePath } = checkInstalled(requestedStr); - return { - version, - DataObject: loadPackage(modulePath, "@fluidframework/aqueduct").DataObject, - DataObjectFactory: loadPackage(modulePath, "@fluidframework/aqueduct").DataObjectFactory, - TestFluidObjectFactory: loadPackage(modulePath, "@fluidframework/test-utils") - .TestFluidObjectFactory, - dds: { - SharedCell: loadPackage(modulePath, "@fluidframework/cell").SharedCell, - SharedCounter: loadPackage(modulePath, "@fluidframework/counter").SharedCounter, - Ink: loadPackage(modulePath, "@fluidframework/ink").Ink, - SharedDirectory: loadPackage(modulePath, "@fluidframework/map").SharedDirectory, - SharedMap: loadPackage(modulePath, "@fluidframework/map").SharedMap, - SharedMatrix: loadPackage(modulePath, "@fluidframework/matrix").SharedMatrix, - ConsensusQueue: loadPackage(modulePath, "@fluidframework/ordered-collection") - .ConsensusQueue, - ConsensusRegisterCollection: loadPackage( - modulePath, - "@fluidframework/register-collection", - ).ConsensusRegisterCollection, - SharedString: loadPackage(modulePath, "@fluidframework/sequence").SharedString, - SparseMatrix: loadPackage( + if (!dataRuntimeCache.has(version)) { + /* eslint-disable @typescript-eslint/no-shadow */ + const [ + { DataObject, DataObjectFactory }, + { TestFluidObjectFactory }, + { SharedMap, SharedDirectory }, + { SharedString }, + { SharedCell }, + { SharedCounter }, + { SharedMatrix }, + { Ink }, + { ConsensusQueue }, + { ConsensusRegisterCollection }, + { SparseMatrix }, + ] = await Promise.all([ + loadPackage(modulePath, "@fluidframework/aqueduct"), + loadPackage(modulePath, "@fluidframework/test-utils"), + loadPackage(modulePath, "@fluidframework/map"), + loadPackage(modulePath, "@fluidframework/sequence"), + loadPackage(modulePath, "@fluidframework/cell"), + loadPackage(modulePath, "@fluidframework/counter"), + loadPackage(modulePath, "@fluidframework/matrix"), + loadPackage(modulePath, "@fluidframework/ink"), + loadPackage(modulePath, "@fluidframework/ordered-collection"), + loadPackage(modulePath, "@fluidframework/register-collection"), + loadPackage( modulePath, versionHasMovedSparsedMatrix(version) ? "@fluid-experimental/sequence-deprecated" : "@fluidframework/sequence", - ).SparseMatrix, - }, - }; + ), + ]); + /* eslint-enable @typescript-eslint/no-shadow */ + + const dataRuntime = { + version, + DataObject, + DataObjectFactory, + TestFluidObjectFactory, + dds: { + SharedCell, + SharedCounter, + Ink, + SharedDirectory, + SharedMap, + SharedMatrix, + ConsensusQueue, + ConsensusRegisterCollection, + SharedString, + SparseMatrix, + }, + }; + dataRuntimeCache.set(version, dataRuntime); + } + return dataRuntimeCache.get(version) ?? throwNotFound("DataRuntime", version); +} + +async function loadDriver( + baseVersion: string, + requested?: number | string, +): Promise { + const requestedStr = getRequestedRange(baseVersion, requested); + if (semver.satisfies(pkgVersion, requestedStr)) { + return DriverApi; + } + + const { version, modulePath } = checkInstalled(requestedStr); + if (!driverCache.has(version)) { + const [ + { LocalDocumentServiceFactory, LocalResolver, createLocalResolverCreateNewRequest }, + { LocalDeltaConnectionServer }, + { + OdspDocumentServiceFactory, + OdspDriverUrlResolver, + createOdspCreateContainerRequest, + createOdspUrl, + }, + { RouterliciousDocumentServiceFactory }, + ] = await Promise.all([ + loadPackage(modulePath, "@fluidframework/local-driver"), + loadPackage(modulePath, "@fluidframework/server-local-server"), + loadPackage(modulePath, "@fluidframework/odsp-driver"), + loadPackage(modulePath, "@fluidframework/routerlicious-driver"), + ]); + + const LocalDriverApi: typeof DriverApi.LocalDriverApi = { + version, + LocalDocumentServiceFactory, + LocalResolver, + LocalDeltaConnectionServer, + createLocalResolverCreateNewRequest, + }; + + const OdspDriverApi: typeof DriverApi.OdspDriverApi = { + version, + OdspDocumentServiceFactory, + OdspDriverUrlResolver, + createOdspCreateContainerRequest, + createOdspUrl, + }; + + const RouterliciousDriverApi: typeof DriverApi.RouterliciousDriverApi = { + version, + modulePath, + RouterliciousDocumentServiceFactory, + }; + + driverCache.set(version, { + LocalDriverApi, + OdspDriverApi, + RouterliciousDriverApi, + }); + } + return driverCache.get(version) ?? throwNotFound("Driver", version); +} + +function throwNotFound(layer: string, version: string): never { + throw new Error(`${layer}@${version} not found. Missing install step?`); +} + +export function getLoaderApi(baseVersion: string, requested?: number | string): typeof LoaderApi { + const requestedStr = getRequestedRange(baseVersion, requested); + + // If the current version satisfies the range, use it. + if (semver.satisfies(pkgVersion, requestedStr)) { + return LoaderApi; + } + + const { version } = checkInstalled(requestedStr); + const loaderApi = loaderCache.get(version); + return loaderApi ?? throwNotFound("Loader", version); +} + +export function getContainerRuntimeApi( + baseVersion: string, + requested?: number | string, +): typeof ContainerRuntimeApi { + const requestedStr = getRequestedRange(baseVersion, requested); + if (semver.satisfies(pkgVersion, requestedStr)) { + return ContainerRuntimeApi; + } + const { version } = checkInstalled(requestedStr); + return containerRuntimeCache.get(version) ?? throwNotFound("ContainerRuntime", version); +} + +export function getDataRuntimeApi( + baseVersion: string, + requested?: number | string, +): typeof DataRuntimeApi { + const requestedStr = getRequestedRange(baseVersion, requested); + if (semver.satisfies(pkgVersion, requestedStr)) { + return DataRuntimeApi; + } + const { version } = checkInstalled(requestedStr); + return dataRuntimeCache.get(version) ?? throwNotFound("DataRuntime", version); } export function getDriverApi(baseVersion: string, requested?: number | string): typeof DriverApi { @@ -185,41 +334,13 @@ export function getDriverApi(baseVersion: string, requested?: number | string): return DriverApi; } - const { version, modulePath } = checkInstalled(requestedStr); - const localDriverApi: typeof DriverApi.LocalDriverApi = { - version, - LocalDocumentServiceFactory: loadPackage(modulePath, "@fluidframework/local-driver") - .LocalDocumentServiceFactory, - LocalResolver: loadPackage(modulePath, "@fluidframework/local-driver").LocalResolver, - LocalDeltaConnectionServer: loadPackage(modulePath, "@fluidframework/server-local-server") - .LocalDeltaConnectionServer, - createLocalResolverCreateNewRequest: loadPackage(modulePath, "@fluidframework/local-driver") - .createLocalResolverCreateNewRequest, - }; - - const odspDriverApi: typeof DriverApi.OdspDriverApi = { - version, - OdspDocumentServiceFactory: loadPackage(modulePath, "@fluidframework/odsp-driver") - .OdspDocumentServiceFactory, - OdspDriverUrlResolver: loadPackage(modulePath, "@fluidframework/odsp-driver") - .OdspDriverUrlResolver, - createOdspCreateContainerRequest: loadPackage(modulePath, "@fluidframework/odsp-driver") - .createOdspCreateContainerRequest, - createOdspUrl: loadPackage(modulePath, "@fluidframework/odsp-driver").createOdspUrl, - }; - - const routerliciousDriverApi: typeof DriverApi.RouterliciousDriverApi = { - version, - modulePath, - RouterliciousDocumentServiceFactory: loadPackage( - modulePath, - "@fluidframework/routerlicious-driver", - ).RouterliciousDocumentServiceFactory, - }; - - return { - LocalDriverApi: localDriverApi, - OdspDriverApi: odspDriverApi, - RouterliciousDriverApi: routerliciousDriverApi, - }; + const { version } = checkInstalled(requestedStr); + return driverCache.get(version) ?? throwNotFound("Driver", version); +} + +export interface CompatApis { + containerRuntime: ReturnType; + dataRuntime: ReturnType; + driver: ReturnType; + loader: ReturnType; } diff --git a/packages/test/test-version-utils/src/versionUtils.ts b/packages/test/test-version-utils/src/versionUtils.ts index 78cd2b5d8d73..7d982f853474 100644 --- a/packages/test/test-version-utils/src/versionUtils.ts +++ b/packages/test/test-version-utils/src/versionUtils.ts @@ -7,15 +7,16 @@ import { exec, execSync } from "child_process"; import * as path from "path"; +import { fileURLToPath, pathToFileURL } from "node:url"; import { existsSync, mkdirSync, rmdirSync, readdirSync, readFileSync, writeFileSync } from "fs"; import { lock } from "proper-lockfile"; import * as semver from "semver"; -import { pkgVersion } from "./packageVersion"; -import { InstalledPackage } from "./testApi"; +import { pkgVersion } from "./packageVersion.js"; +import { InstalledPackage } from "./testApi.js"; // Assuming this file is in dist\test, so go to ..\node_modules\.legacy as the install location -const baseModulePath = path.join(__dirname, "..", "node_modules", ".legacy"); +const baseModulePath = fileURLToPath(new URL("../node_modules/.legacy", import.meta.url)); const installedJsonPath = path.join(baseModulePath, "installed.json"); const getModulePath = (version: string) => path.join(baseModulePath, version); @@ -33,7 +34,7 @@ async function ensureInstalledJson() { if (existsSync(installedJsonPath)) { return; } - const release = await lock(__dirname, { retries: { forever: true } }); + const release = await lock(fileURLToPath(import.meta.url), { retries: { forever: true } }); try { // Check it again under the lock if (existsSync(installedJsonPath)) { @@ -190,7 +191,7 @@ export async function ensureInstalled( adjustedPackageList.push("@fluid-experimental/sequence-deprecated"); } - // Release the __dirname but lock the modulePath so we can do parallel installs + // Release the base path but lock the modulePath so we can do parallel installs const release = await lock(modulePath, { retries: { forever: true } }); try { if (force) { @@ -252,10 +253,8 @@ export function checkInstalled(requested: string) { ); } -export const loadPackage = (modulePath: string, pkg: string) => - // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-return - require(path.join(modulePath, "node_modules", pkg)); - +export const loadPackage = async (modulePath: string, pkg: string): Promise => + import(pathToFileURL(path.join(modulePath, "node_modules", pkg, "dist", "index.js")).href); /** * Used to get the major version number above or below the baseVersion. * @param baseVersion - The base version to move from (eg. "0.60.0") diff --git a/packages/test/test-version-utils/tsconfig.json b/packages/test/test-version-utils/tsconfig.json index 9f03e2b6e02c..64fbda69638b 100644 --- a/packages/test/test-version-utils/tsconfig.json +++ b/packages/test/test-version-utils/tsconfig.json @@ -5,6 +5,7 @@ "rootDir": "./src", "outDir": "./dist", "composite": true, + "module": "ESNext", }, "include": ["src/**/*"], } From 0bed6f6f71e057e81eaccafc45ec48bcd91f2f71 Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Thu, 8 Jun 2023 16:37:08 -0700 Subject: [PATCH 02/15] convert table-document tests to esnext --- examples/data-objects/table-document/.eslintrc.js | 12 ++++++++++++ examples/data-objects/table-document/README.md | 1 + .../data-objects/table-document/src/test/.mocharc.js | 2 +- .../src/test/{table.spec.ts => table.spec.mts} | 6 +++--- ...eption.spec.ts => tableWithInterception.spec.mts} | 6 +++--- .../table-document/src/test/tsconfig.json | 1 + 6 files changed, 21 insertions(+), 7 deletions(-) rename examples/data-objects/table-document/src/test/{table.spec.ts => table.spec.mts} (98%) rename examples/data-objects/table-document/src/test/{tableWithInterception.spec.ts => tableWithInterception.spec.mts} (98%) diff --git a/examples/data-objects/table-document/.eslintrc.js b/examples/data-objects/table-document/.eslintrc.js index c3573c72dc1d..31eca03a0423 100644 --- a/examples/data-objects/table-document/.eslintrc.js +++ b/examples/data-objects/table-document/.eslintrc.js @@ -11,4 +11,16 @@ module.exports = { rules: { "@typescript-eslint/strict-boolean-expressions": "off", }, + overrides: [ + { + // Rules only for test files + files: ["*.spec.ts", "src/test/**"], + rules: { + // ESLint's resolver doesn't resolve relative imports of ESNext modules correctly, since + // it resolves the path relative to the .ts file (and assumes a file with a .js extension + // should exist there) + "import/no-unresolved": ["error", { ignore: ["^\\.(.*)\\.js$"] }], + }, + }, + ], }; diff --git a/examples/data-objects/table-document/README.md b/examples/data-objects/table-document/README.md index bff4549d0dde..8eb09a00d582 100644 --- a/examples/data-objects/table-document/README.md +++ b/examples/data-objects/table-document/README.md @@ -20,3 +20,4 @@ For example, to support a feature like simple user attribution, the app can appe Being an example, this package should have `private: true` in `package.json` but alas there's one consumer of Fluid taking a dependency on it, so we can't do that yet. +Once it can be converted, or once that consumer confirms they don't need both ESNext and CommonJS modules, it should also drop the CommonJS build (this has already been done for the package's tests, but not its public API). diff --git a/examples/data-objects/table-document/src/test/.mocharc.js b/examples/data-objects/table-document/src/test/.mocharc.js index 7bb530ceecdb..a92b7ba302bb 100644 --- a/examples/data-objects/table-document/src/test/.mocharc.js +++ b/examples/data-objects/table-document/src/test/.mocharc.js @@ -7,6 +7,6 @@ const packageDir = `${__dirname}/../..`; -const getFluidTestMochaConfig = require("@fluid-internal/test-version-utils/mocharc-common.js"); +const getFluidTestMochaConfig = require("@fluid-internal/test-version-utils/mocharc-common.cjs"); const config = getFluidTestMochaConfig(packageDir); module.exports = config; diff --git a/examples/data-objects/table-document/src/test/table.spec.ts b/examples/data-objects/table-document/src/test/table.spec.mts similarity index 98% rename from examples/data-objects/table-document/src/test/table.spec.ts rename to examples/data-objects/table-document/src/test/table.spec.mts index 0ac8c83c0026..959309a0a4cf 100644 --- a/examples/data-objects/table-document/src/test/table.spec.ts +++ b/examples/data-objects/table-document/src/test/table.spec.mts @@ -7,9 +7,9 @@ import { strict as assert } from "assert"; import { requestFluidObject } from "@fluidframework/runtime-utils"; import { ITestObjectProvider } from "@fluidframework/test-utils"; import { describeLoaderCompat } from "@fluid-internal/test-version-utils"; -import { TableDocument } from "../document"; -import { TableSlice } from "../slice"; -import { TableDocumentItem } from "../table"; +import { TableDocument } from "../document.js"; +import { TableSlice } from "../slice.js"; +import { TableDocumentItem } from "../table.js"; describeLoaderCompat("TableDocument", (getTestObjectProvider) => { let tableDocument: TableDocument; diff --git a/examples/data-objects/table-document/src/test/tableWithInterception.spec.ts b/examples/data-objects/table-document/src/test/tableWithInterception.spec.mts similarity index 98% rename from examples/data-objects/table-document/src/test/tableWithInterception.spec.ts rename to examples/data-objects/table-document/src/test/tableWithInterception.spec.mts index a44bb2692605..9fc645d122e1 100644 --- a/examples/data-objects/table-document/src/test/tableWithInterception.spec.ts +++ b/examples/data-objects/table-document/src/test/tableWithInterception.spec.mts @@ -9,9 +9,9 @@ import { IFluidDataStoreContext } from "@fluidframework/runtime-definitions"; import { requestFluidObject } from "@fluidframework/runtime-utils"; import { ITestObjectProvider } from "@fluidframework/test-utils"; import { describeLoaderCompat } from "@fluid-internal/test-version-utils"; -import { ITable } from "../table"; -import { TableDocument } from "../document"; -import { createTableWithInterception } from "../interception"; +import { ITable } from "../table.js"; +import { TableDocument } from "../document.js"; +import { createTableWithInterception } from "../interception/index.js"; describeLoaderCompat("Table Document with Interception", (getTestObjectProvider) => { describe("Simple User Attribution", () => { diff --git a/examples/data-objects/table-document/src/test/tsconfig.json b/examples/data-objects/table-document/src/test/tsconfig.json index b58e17f1917f..e34d0becab11 100644 --- a/examples/data-objects/table-document/src/test/tsconfig.json +++ b/examples/data-objects/table-document/src/test/tsconfig.json @@ -6,6 +6,7 @@ "types": ["node", "mocha"], "declaration": false, "declarationMap": false, + "module": "esnext", }, "include": ["./**/*"], "references": [ From c0202f8fee25c602033e77c466c88e8e293910e7 Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Thu, 8 Jun 2023 18:14:21 -0700 Subject: [PATCH 03/15] Update webflow to use esm --- .../webflow/{.eslintrc.js => .eslintrc.cjs} | 0 .../data-objects/webflow/ignore-loader.mjs | 20 +++++++++++++ examples/data-objects/webflow/package.json | 28 +++++++++---------- .../webflow/src/clipboard/debug.ts | 2 +- .../webflow/src/clipboard/paste.ts | 6 ++-- .../webflow/src/document/debug.ts | 2 +- .../webflow/src/document/index.ts | 10 +++---- .../data-objects/webflow/src/editor/caret.ts | 10 +++---- .../data-objects/webflow/src/editor/debug.ts | 2 +- .../data-objects/webflow/src/editor/editor.ts | 14 +++++----- .../data-objects/webflow/src/editor/index.ts | 2 +- .../data-objects/webflow/src/host/debug.ts | 2 +- .../data-objects/webflow/src/host/index.ts | 4 +-- .../webflow/src/host/searchmenu/index.ts | 6 ++-- .../data-objects/webflow/src/host/webFlow.ts | 4 +-- .../webflow/src/host/webflowView.tsx | 14 +++++----- examples/data-objects/webflow/src/html/css.ts | 4 +-- .../data-objects/webflow/src/html/debug.ts | 2 +- .../webflow/src/html/formatters.ts | 16 +++++------ examples/data-objects/webflow/src/index.ts | 8 +++--- examples/data-objects/webflow/src/package.ts | 7 ++--- .../webflow/src/packageVersion.ts | 9 ++++++ .../src/test/{.mocharc.js => .mocharc.cjs} | 9 ++++-- .../webflow/src/test/direction.spec.ts | 2 +- .../webflow/src/test/flowdocument.spec.ts | 4 +-- .../webflow/src/test/layout.spec.ts | 9 +++--- .../webflow/src/test/segmentspan.spec.ts | 4 +-- .../webflow/src/test/strings.spec.ts | 2 +- .../webflow/src/test/tokenlist.spec.ts | 2 +- .../webflow/src/test/tsconfig.json | 1 + .../data-objects/webflow/src/util/attr.ts | 4 +-- .../data-objects/webflow/src/util/caret.ts | 4 +-- .../data-objects/webflow/src/util/index.ts | 22 +++++++-------- .../data-objects/webflow/src/util/localref.ts | 4 +-- examples/data-objects/webflow/src/util/tag.ts | 4 +-- .../webflow/src/util/tokenlist.ts | 2 +- .../data-objects/webflow/src/view/debug.ts | 2 +- .../webflow/src/view/formatter.ts | 4 +-- .../data-objects/webflow/src/view/layout.ts | 10 +++---- .../data-objects/webflow/tsconfig.esnext.json | 7 ----- examples/data-objects/webflow/tsconfig.json | 2 ++ .../{webpack.config.js => webpack.config.cjs} | 8 +++++- .../{webpack.dev.js => webpack.dev.cjs} | 0 .../{webpack.prod.js => webpack.prod.cjs} | 0 44 files changed, 154 insertions(+), 124 deletions(-) rename examples/data-objects/webflow/{.eslintrc.js => .eslintrc.cjs} (100%) create mode 100644 examples/data-objects/webflow/ignore-loader.mjs create mode 100644 examples/data-objects/webflow/src/packageVersion.ts rename examples/data-objects/webflow/src/test/{.mocharc.js => .mocharc.cjs} (58%) delete mode 100644 examples/data-objects/webflow/tsconfig.esnext.json rename examples/data-objects/webflow/{webpack.config.js => webpack.config.cjs} (84%) rename examples/data-objects/webflow/{webpack.dev.js => webpack.dev.cjs} (100%) rename examples/data-objects/webflow/{webpack.prod.js => webpack.prod.cjs} (100%) diff --git a/examples/data-objects/webflow/.eslintrc.js b/examples/data-objects/webflow/.eslintrc.cjs similarity index 100% rename from examples/data-objects/webflow/.eslintrc.js rename to examples/data-objects/webflow/.eslintrc.cjs diff --git a/examples/data-objects/webflow/ignore-loader.mjs b/examples/data-objects/webflow/ignore-loader.mjs new file mode 100644 index 000000000000..dcda2426c184 --- /dev/null +++ b/examples/data-objects/webflow/ignore-loader.mjs @@ -0,0 +1,20 @@ +const extensionsRegex = /\.css$/; + +/** + * This uses the node loader API (see https://nodejs.org/docs/latest-v16.x/api/esm.html#loaders) + * to enable webpack-style imports of .css modules. + * + * This is the recommended successor to `require.extensions`, which was used by https://www.npmjs.com/package/ignore-styles + * to accomplish the same thing. + */ +export async function load(url, context, nextLoad) { + if (extensionsRegex.test(url)) { + return { + format: "json", + source: "{}", + }; + } + + // Defer to the next hook in the chain. + return nextLoad(url, context); +} diff --git a/examples/data-objects/webflow/package.json b/examples/data-objects/webflow/package.json index 9f4cfd415e32..1ccbbb060c20 100644 --- a/examples/data-objects/webflow/package.json +++ b/examples/data-objects/webflow/package.json @@ -13,16 +13,17 @@ "author": "Microsoft and contributors", "sideEffects": false, "main": "dist/index.js", - "module": "lib/index.js", + "module": "dist/index.js", "types": "dist/index.d.ts", + "type": "module", "scripts": { - "build": "concurrently npm:build:compile npm:lint", + "build": "npm run build:genver && concurrently npm:build:compile npm:lint", "build:commonjs": "npm run tsc && npm run build:test", - "build:compile": "concurrently npm:build:commonjs npm:build:esnext npm:build:copy", - "build:copy": "copyfiles -u 1 \"src/**/*.css\" dist/ && copyfiles -u 1 \"src/**/*.css\" lib/", - "build:esnext": "tsc --project ./tsconfig.esnext.json", + "build:compile": "concurrently npm:build:commonjs npm:build:copy", + "build:copy": "copyfiles -u 1 \"src/**/*.css\" dist/", "build:full": "concurrently npm:build npm:webpack", "build:full:compile": "concurrently npm:build:compile npm:webpack", + "build:genver": "gen-version", "build:test": "tsc --project ./src/test/tsconfig.json", "clean": "rimraf dist lib *.tsbuildinfo *.build.log", "dev": "npm run build:esnext -- --watch", @@ -34,16 +35,16 @@ "prepack": "npm run webpack", "prettier": "prettier --check . --ignore-path ../../../.prettierignore", "prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore", - "start": "webpack serve --config webpack.config.js", - "start:docker": "webpack serve --config webpack.config.js --env mode=docker", - "start:r11s": "webpack serve --config webpack.config.js --env mode=r11s", - "start:single": "webpack serve --config webpack.config.js --env.single true", - "start:spo": "webpack serve --config webpack.config.js --env mode=spo", - "start:spo-df": "webpack serve --config webpack.config.js --env mode=spo-df", - "start:tinylicious": "webpack serve --config webpack.config.js --env mode=tinylicious", + "start": "webpack serve --config webpack.config.cjs", + "start:docker": "webpack serve --config webpack.config.cjs --env mode=docker", + "start:r11s": "webpack serve --config webpack.config.cjs --env mode=r11s", + "start:single": "webpack serve --config webpack.config.cjs --env.single true", + "start:spo": "webpack serve --config webpack.config.cjs --env mode=spo", + "start:spo-df": "webpack serve --config webpack.config.cjs --env mode=spo-df", + "start:tinylicious": "webpack serve --config webpack.config.cjs --env mode=tinylicious", "test": "npm run test:mocha", "test:coverage": "nyc npm test -- --reporter xunit --reporter-option output=nyc/junit-report.xml --exit", - "test:mocha": "mocha --config src/test/.mocharc.js dist/test/**/*.spec.js", + "test:mocha": "cross-env NODE_OPTIONS=\"--experimental-loader ./ignore-loader.mjs\" mocha --config src/test/.mocharc.cjs dist/test/**/*.spec.js", "test:mocha:multireport": "cross-env FLUID_TEST_MULTIREPORT=1 npm run test:mocha", "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha", "tsc": "tsc", @@ -113,7 +114,6 @@ "eslint": "~8.6.0", "file-loader": "^3.0.1", "html-loader": "^3.1.0", - "ignore-styles": "^5.0.1", "jsdom": "^16.7.0", "jsdom-global": "^3.0.2", "mocha": "^10.2.0", diff --git a/examples/data-objects/webflow/src/clipboard/debug.ts b/examples/data-objects/webflow/src/clipboard/debug.ts index f448f252da6d..b5e8d54f622c 100644 --- a/examples/data-objects/webflow/src/clipboard/debug.ts +++ b/examples/data-objects/webflow/src/clipboard/debug.ts @@ -4,6 +4,6 @@ */ import { IDebugger } from "debug"; -import { debug as parent } from "../debug"; +import { debug as parent } from "../debug.js"; export const debug: IDebugger = parent.extend("clipboard"); diff --git a/examples/data-objects/webflow/src/clipboard/paste.ts b/examples/data-objects/webflow/src/clipboard/paste.ts index dc2f2c62c378..3df400e23418 100644 --- a/examples/data-objects/webflow/src/clipboard/paste.ts +++ b/examples/data-objects/webflow/src/clipboard/paste.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. */ -import { FlowDocument } from "../document"; -import { TagName } from "../util"; -import { debug } from "./debug"; +import { FlowDocument } from "../document/index.js"; +import { TagName } from "../util/index.js"; +import { debug } from "./debug.js"; const enum ClipboardFormat { html = "text/html", diff --git a/examples/data-objects/webflow/src/document/debug.ts b/examples/data-objects/webflow/src/document/debug.ts index 951bb28721f8..9db8df23ec35 100644 --- a/examples/data-objects/webflow/src/document/debug.ts +++ b/examples/data-objects/webflow/src/document/debug.ts @@ -4,6 +4,6 @@ */ import { IDebugger } from "debug"; -import { debug as parent } from "../debug"; +import { debug as parent } from "../debug.js"; export const debug: IDebugger = parent.extend("document"); diff --git a/examples/data-objects/webflow/src/document/index.ts b/examples/data-objects/webflow/src/document/index.ts index 897fed28ab26..c3a2a7ecbbe1 100644 --- a/examples/data-objects/webflow/src/document/index.ts +++ b/examples/data-objects/webflow/src/document/index.ts @@ -41,11 +41,11 @@ import { } from "@fluidframework/sequence"; import { ISharedDirectory, SharedDirectory } from "@fluidframework/map"; import { IEvent } from "@fluidframework/common-definitions"; -import { clamp, emptyArray, randomId, TagName, TokenList } from "../util"; -import { IHTMLAttributes } from "../util/attr"; -import { documentType } from "../package"; -import { debug } from "./debug"; -import { SegmentSpan } from "./segmentspan"; +import { clamp, emptyArray, randomId, TagName, TokenList } from "../util/index.js"; +import { IHTMLAttributes } from "../util/attr.js"; +import { documentType } from "../package.js"; +import { debug } from "./debug.js"; +import { SegmentSpan } from "./segmentspan.js"; export const enum DocSegmentKind { text = "text", diff --git a/examples/data-objects/webflow/src/editor/caret.ts b/examples/data-objects/webflow/src/editor/caret.ts index 2c99ea2893e8..eddfa9ad6243 100644 --- a/examples/data-objects/webflow/src/editor/caret.ts +++ b/examples/data-objects/webflow/src/editor/caret.ts @@ -4,12 +4,12 @@ */ import { LocalReferencePosition, ReferencePosition } from "@fluidframework/merge-tree"; -import { DocSegmentKind, getDocSegmentKind } from "../document"; -import { clamp, Dom, hasTagName, TagName } from "../util"; -import { updateRef } from "../util/localref"; +import { DocSegmentKind, getDocSegmentKind } from "../document/index.js"; +import { clamp, Dom, hasTagName, TagName } from "../util/index.js"; +import { updateRef } from "../util/localref.js"; -import { eotSegment, Layout } from "../view/layout"; -import { debug } from "./debug"; +import { eotSegment, Layout } from "../view/layout.js"; +import { debug } from "./debug.js"; export class Caret { private get doc() { diff --git a/examples/data-objects/webflow/src/editor/debug.ts b/examples/data-objects/webflow/src/editor/debug.ts index 9609645704ea..3630b0af117e 100644 --- a/examples/data-objects/webflow/src/editor/debug.ts +++ b/examples/data-objects/webflow/src/editor/debug.ts @@ -4,6 +4,6 @@ */ import { IDebugger } from "debug"; -import { debug as parent } from "../debug"; +import { debug as parent } from "../debug.js"; export const debug: IDebugger = parent.extend("editor"); diff --git a/examples/data-objects/webflow/src/editor/editor.ts b/examples/data-objects/webflow/src/editor/editor.ts index 2c50f0f66d7b..30c94b8932e9 100644 --- a/examples/data-objects/webflow/src/editor/editor.ts +++ b/examples/data-objects/webflow/src/editor/editor.ts @@ -4,13 +4,13 @@ */ import { FluidObject } from "@fluidframework/core-interfaces"; -import { paste } from "../clipboard/paste"; -import { FlowDocument } from "../document"; -import { Direction, getDeltaX, KeyCode } from "../util"; -import { IFormatterState, RootFormatter } from "../view/formatter"; -import { Layout } from "../view/layout"; -import { Caret } from "./caret"; -import { debug } from "./debug"; +import { paste } from "../clipboard/paste.js"; +import { FlowDocument } from "../document/index.js"; +import { Direction, getDeltaX, KeyCode } from "../util/index.js"; +import { IFormatterState, RootFormatter } from "../view/formatter.js"; +import { Layout } from "../view/layout.js"; +import { Caret } from "./caret.js"; +import { debug } from "./debug.js"; export class Editor { private readonly layout: Layout; diff --git a/examples/data-objects/webflow/src/editor/index.ts b/examples/data-objects/webflow/src/editor/index.ts index f61ec26030bc..1f3748d77b1d 100644 --- a/examples/data-objects/webflow/src/editor/index.ts +++ b/examples/data-objects/webflow/src/editor/index.ts @@ -3,4 +3,4 @@ * Licensed under the MIT License. */ -export { Editor } from "./editor"; +export { Editor } from "./editor.js"; diff --git a/examples/data-objects/webflow/src/host/debug.ts b/examples/data-objects/webflow/src/host/debug.ts index 18c86fbd19bd..59c070dbf325 100644 --- a/examples/data-objects/webflow/src/host/debug.ts +++ b/examples/data-objects/webflow/src/host/debug.ts @@ -4,6 +4,6 @@ */ import { IDebugger } from "debug"; -import { debug as parent } from "../debug"; +import { debug as parent } from "../debug.js"; export const debug: IDebugger = parent.extend("host"); diff --git a/examples/data-objects/webflow/src/host/index.ts b/examples/data-objects/webflow/src/host/index.ts index 53ed7a02f113..ecd73ec1b322 100644 --- a/examples/data-objects/webflow/src/host/index.ts +++ b/examples/data-objects/webflow/src/host/index.ts @@ -3,5 +3,5 @@ * Licensed under the MIT License. */ -export { WebFlow } from "./webFlow"; -export { WebflowView } from "./webflowView"; +export { WebFlow } from "./webFlow.js"; +export { WebflowView } from "./webflowView.js"; diff --git a/examples/data-objects/webflow/src/host/searchmenu/index.ts b/examples/data-objects/webflow/src/host/searchmenu/index.ts index aced41ddd702..a4d0397dc466 100644 --- a/examples/data-objects/webflow/src/host/searchmenu/index.ts +++ b/examples/data-objects/webflow/src/host/searchmenu/index.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. */ -import { Dom, ICommand, KeyCode, randomId } from "../../util"; -import { debug } from "../debug"; -import { View } from "./view"; +import { Dom, ICommand, KeyCode, randomId } from "../../util/index.js"; +import { debug } from "../debug.js"; +import { View } from "./view.js"; // eslint-disable-next-line import/no-unassigned-import import "./index.css"; diff --git a/examples/data-objects/webflow/src/host/webFlow.ts b/examples/data-objects/webflow/src/host/webFlow.ts index df9272a2708d..d9de802385a0 100644 --- a/examples/data-objects/webflow/src/host/webFlow.ts +++ b/examples/data-objects/webflow/src/host/webFlow.ts @@ -13,8 +13,8 @@ import { LazyLoadedDataObject, } from "@fluidframework/data-object-base"; import { ISharedDirectory, SharedDirectory } from "@fluidframework/map"; -import { FlowDocument } from "../document"; -import { hostType } from "../package"; +import { FlowDocument } from "../document/index.js"; +import { hostType } from "../package.js"; export class WebFlow extends LazyLoadedDataObject { private static readonly factory = new LazyLoadedDataObjectFactory( diff --git a/examples/data-objects/webflow/src/host/webflowView.tsx b/examples/data-objects/webflow/src/host/webflowView.tsx index cbfa1c20d4c4..e088c7bf735c 100644 --- a/examples/data-objects/webflow/src/host/webflowView.tsx +++ b/examples/data-objects/webflow/src/host/webflowView.tsx @@ -5,17 +5,17 @@ import React, { KeyboardEventHandler, useEffect, useRef, useState } from "react"; -import { FlowDocument } from "../document"; -import { Editor } from "../editor"; -import { htmlFormatter } from "../html/formatters"; -import { ICommand, TagName } from "../util"; -import { IFormatterState, RootFormatter } from "../view/formatter"; -import { debug } from "./debug"; +import { FlowDocument } from "../document/index.js"; +import { Editor } from "../editor/index.js"; +import { htmlFormatter } from "../html/formatters.js"; +import { ICommand, TagName } from "../util/index.js"; +import { IFormatterState, RootFormatter } from "../view/formatter.js"; +import { debug } from "./debug.js"; // eslint-disable-next-line import/no-unassigned-import import "./index.css"; // eslint-disable-next-line import/no-unassigned-import import "./debug.css"; -import { SearchMenuView } from "./searchmenu"; +import { SearchMenuView } from "./searchmenu/index.js"; const always = () => true; diff --git a/examples/data-objects/webflow/src/html/css.ts b/examples/data-objects/webflow/src/html/css.ts index 4da7da953170..93ee23f1f7b5 100644 --- a/examples/data-objects/webflow/src/html/css.ts +++ b/examples/data-objects/webflow/src/html/css.ts @@ -4,8 +4,8 @@ */ import { ISegment } from "@fluidframework/merge-tree"; -import { getCss } from "../document"; -import { areStringsEquivalent } from "../util"; +import { getCss } from "../document/index.js"; +import { areStringsEquivalent } from "../util/index.js"; // Note: Similar to TokenList.set(..), but elides the search for duplicate tokens. const concat = (leftTokens: string, rightTokens: string) => diff --git a/examples/data-objects/webflow/src/html/debug.ts b/examples/data-objects/webflow/src/html/debug.ts index ddbef5a4ab23..715435e80019 100644 --- a/examples/data-objects/webflow/src/html/debug.ts +++ b/examples/data-objects/webflow/src/html/debug.ts @@ -4,6 +4,6 @@ */ import { IDebugger } from "debug"; -import { debug as parent } from "../debug"; +import { debug as parent } from "../debug.js"; export const debug: IDebugger = parent.extend("html"); diff --git a/examples/data-objects/webflow/src/html/formatters.ts b/examples/data-objects/webflow/src/html/formatters.ts index 693c5c8d4930..0ea43341c2a1 100644 --- a/examples/data-objects/webflow/src/html/formatters.ts +++ b/examples/data-objects/webflow/src/html/formatters.ts @@ -5,14 +5,14 @@ import { assert } from "@fluidframework/common-utils"; import { Marker, TextSegment } from "@fluidframework/merge-tree"; -import { DocSegmentKind, getCss, getDocSegmentKind } from "../document"; -import { emptyObject, TagName } from "../util"; -import { getAttrs, syncAttrs } from "../util/attr"; - -import { Formatter, IFormatterState, RootFormatter } from "../view/formatter"; -import { Layout } from "../view/layout"; -import { ICssProps, sameCss, syncCss } from "./css"; -import { debug } from "./debug"; +import { DocSegmentKind, getCss, getDocSegmentKind } from "../document/index.js"; +import { emptyObject, TagName } from "../util/index.js"; +import { getAttrs, syncAttrs } from "../util/attr.js"; + +import { Formatter, IFormatterState, RootFormatter } from "../view/formatter.js"; +import { Layout } from "../view/layout.js"; +import { ICssProps, sameCss, syncCss } from "./css.js"; +import { debug } from "./debug.js"; class HtmlFormatter extends RootFormatter { public begin(layout: Layout) { diff --git a/examples/data-objects/webflow/src/index.ts b/examples/data-objects/webflow/src/index.ts index a86d365d0631..89e0d345da72 100644 --- a/examples/data-objects/webflow/src/index.ts +++ b/examples/data-objects/webflow/src/index.ts @@ -6,10 +6,10 @@ import { ContainerViewRuntimeFactory } from "@fluid-example/example-utils"; import React from "react"; -export { FlowDocument } from "./document"; -export { Editor } from "./editor"; -import { WebFlow, WebflowView } from "./host"; -export { htmlFormatter } from "./html/formatters"; +export { FlowDocument } from "./document/index.js"; +export { Editor } from "./editor/index.js"; +import { WebFlow, WebflowView } from "./host/index.js"; +export { htmlFormatter } from "./html/formatters.js"; const webFlowViewCallback = (webFlow: WebFlow) => React.createElement(WebflowView, { docP: webFlow.getFlowDocument() }); diff --git a/examples/data-objects/webflow/src/package.ts b/examples/data-objects/webflow/src/package.ts index 1aacba61194b..88d07d81fa1a 100644 --- a/examples/data-objects/webflow/src/package.ts +++ b/examples/data-objects/webflow/src/package.ts @@ -3,12 +3,9 @@ * Licensed under the MIT License. */ -/* eslint-disable @typescript-eslint/no-var-requires */ -// eslint-disable-next-line @typescript-eslint/no-require-imports -const { name, version } = require("../package.json"); -/* eslint-enable @typescript-eslint/no-var-requires */ +import { pkgName, pkgVersion } from "./packageVersion.js"; -const makeTypeName = (type: string) => `${name}/${type}@${version}`; +const makeTypeName = (type: string) => `${pkgName}/${type}@${pkgVersion}`; export const hostType = makeTypeName("host"); export const documentType = makeTypeName("flow-document"); diff --git a/examples/data-objects/webflow/src/packageVersion.ts b/examples/data-objects/webflow/src/packageVersion.ts new file mode 100644 index 000000000000..020852ec61bb --- /dev/null +++ b/examples/data-objects/webflow/src/packageVersion.ts @@ -0,0 +1,9 @@ +/*! + * Copyright (c) Microsoft Corporation and contributors. All rights reserved. + * Licensed under the MIT License. + * + * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY + */ + +export const pkgName = "@fluid-example/webflow"; +export const pkgVersion = "2.0.0-internal.5.1.0"; diff --git a/examples/data-objects/webflow/src/test/.mocharc.js b/examples/data-objects/webflow/src/test/.mocharc.cjs similarity index 58% rename from examples/data-objects/webflow/src/test/.mocharc.js rename to examples/data-objects/webflow/src/test/.mocharc.cjs index 24d877223ed9..254b24568a5c 100644 --- a/examples/data-objects/webflow/src/test/.mocharc.js +++ b/examples/data-objects/webflow/src/test/.mocharc.cjs @@ -7,6 +7,9 @@ const packageDir = `${__dirname}/../..`; -const getFluidTestMochaConfig = require("@fluid-internal/test-version-utils/mocharc-common.js"); -const config = getFluidTestMochaConfig(packageDir, ["ignore-styles"]); -module.exports = config; +const getFluidTestMochaConfig = require("@fluid-internal/test-version-utils/mocharc-common.cjs"); +const config = getFluidTestMochaConfig(packageDir); +module.exports = { + ...config, + "experimental-loader": "../../ignore-loader.mjs", +}; diff --git a/examples/data-objects/webflow/src/test/direction.spec.ts b/examples/data-objects/webflow/src/test/direction.spec.ts index a9677c81d790..6ce7cea2fc15 100644 --- a/examples/data-objects/webflow/src/test/direction.spec.ts +++ b/examples/data-objects/webflow/src/test/direction.spec.ts @@ -4,7 +4,7 @@ */ import { strict as assert } from "assert"; -import { Direction, getDeltaX, getDeltaY } from "../util"; +import { Direction, getDeltaX, getDeltaY } from "../util/index.js"; const cases = [ { name: "none", direction: Direction.none, expectedX: 0, expectedY: 0 }, diff --git a/examples/data-objects/webflow/src/test/flowdocument.spec.ts b/examples/data-objects/webflow/src/test/flowdocument.spec.ts index 29901fe0fd07..34265b0aede3 100644 --- a/examples/data-objects/webflow/src/test/flowdocument.spec.ts +++ b/examples/data-objects/webflow/src/test/flowdocument.spec.ts @@ -8,8 +8,8 @@ import { Marker, ReferenceType } from "@fluidframework/merge-tree"; import { requestFluidObject } from "@fluidframework/runtime-utils"; import { ITestObjectProvider } from "@fluidframework/test-utils"; import { describeLoaderCompat } from "@fluid-internal/test-version-utils"; -import { FlowDocument } from "../document"; -import { TagName } from "../util"; +import { FlowDocument } from "../document/index.js"; +import { TagName } from "../util/index.js"; describeLoaderCompat("FlowDocument", (getTestObjectProvider) => { let doc: FlowDocument; diff --git a/examples/data-objects/webflow/src/test/layout.spec.ts b/examples/data-objects/webflow/src/test/layout.spec.ts index d4653289a418..920eb556a1a8 100644 --- a/examples/data-objects/webflow/src/test/layout.spec.ts +++ b/examples/data-objects/webflow/src/test/layout.spec.ts @@ -3,8 +3,7 @@ * Licensed under the MIT License. */ -// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports -require("jsdom-global")("", { url: "http://localhost" }); +import "jsdom-global/register.js"; window.performance.mark ??= () => undefined as PerformanceMark; window.performance.measure ??= () => undefined as PerformanceMeasure; @@ -12,9 +11,9 @@ import { strict as assert } from "assert"; import { requestFluidObject } from "@fluidframework/runtime-utils"; import { ITestObjectProvider } from "@fluidframework/test-utils"; import { describeLoaderCompat } from "@fluid-internal/test-version-utils"; -import { htmlFormatter } from ".."; -import { FlowDocument } from "../document"; -import { Layout } from "../view/layout"; +import { htmlFormatter } from "../index.js"; +import { FlowDocument } from "../document/index.js"; +import { Layout } from "../view/layout.js"; interface ISnapshotNode { node: Node; diff --git a/examples/data-objects/webflow/src/test/segmentspan.spec.ts b/examples/data-objects/webflow/src/test/segmentspan.spec.ts index ae2a49e70c12..6a67995a03c5 100644 --- a/examples/data-objects/webflow/src/test/segmentspan.spec.ts +++ b/examples/data-objects/webflow/src/test/segmentspan.spec.ts @@ -8,8 +8,8 @@ import { TextSegment } from "@fluidframework/merge-tree"; import { requestFluidObject } from "@fluidframework/runtime-utils"; import { ITestObjectProvider } from "@fluidframework/test-utils"; import { describeLoaderCompat } from "@fluid-internal/test-version-utils"; -import { FlowDocument } from "../document"; -import { SegmentSpan } from "../document/segmentspan"; +import { FlowDocument } from "../document/index.js"; +import { SegmentSpan } from "../document/segmentspan.js"; describeLoaderCompat("SegmentSpan", (getTestObjectProvider) => { let doc: FlowDocument; diff --git a/examples/data-objects/webflow/src/test/strings.spec.ts b/examples/data-objects/webflow/src/test/strings.spec.ts index 46a359da9e95..78585470173d 100644 --- a/examples/data-objects/webflow/src/test/strings.spec.ts +++ b/examples/data-objects/webflow/src/test/strings.spec.ts @@ -4,7 +4,7 @@ */ import { strict as assert } from "assert"; -import { areStringsEquivalent } from "../util"; +import { areStringsEquivalent } from "../util/index.js"; function test(left: string | undefined | null, right: string | undefined | null) { const isLeftEmpty = left === "" || left === null || left === undefined; diff --git a/examples/data-objects/webflow/src/test/tokenlist.spec.ts b/examples/data-objects/webflow/src/test/tokenlist.spec.ts index 7c0cef773d1c..cc79e62fb08e 100644 --- a/examples/data-objects/webflow/src/test/tokenlist.spec.ts +++ b/examples/data-objects/webflow/src/test/tokenlist.spec.ts @@ -4,7 +4,7 @@ */ import { strict as assert } from "assert"; -import { findToken, TokenList } from "../util"; +import { findToken, TokenList } from "../util/index.js"; describe("TokenList", () => { describe("findToken", () => { diff --git a/examples/data-objects/webflow/src/test/tsconfig.json b/examples/data-objects/webflow/src/test/tsconfig.json index 25d764cecba1..c2515626f396 100644 --- a/examples/data-objects/webflow/src/test/tsconfig.json +++ b/examples/data-objects/webflow/src/test/tsconfig.json @@ -8,6 +8,7 @@ "declaration": false, "declarationMap": false, "strictNullChecks": false, + "module": "esnext", }, "include": ["./**/*"], "references": [ diff --git a/examples/data-objects/webflow/src/util/attr.ts b/examples/data-objects/webflow/src/util/attr.ts index 45f58da016bd..f769a1c697f3 100644 --- a/examples/data-objects/webflow/src/util/attr.ts +++ b/examples/data-objects/webflow/src/util/attr.ts @@ -4,8 +4,8 @@ */ import { ISegment } from "@fluidframework/merge-tree"; -import { areStringsEquivalent } from "./string"; -import { emptyObject } from "./"; +import { areStringsEquivalent } from "./string.js"; +import { emptyObject } from "./index.js"; export interface IHTMLAttributes { src?: string; diff --git a/examples/data-objects/webflow/src/util/caret.ts b/examples/data-objects/webflow/src/util/caret.ts index b4f0f32f3eef..d6c3ace39a04 100644 --- a/examples/data-objects/webflow/src/util/caret.ts +++ b/examples/data-objects/webflow/src/util/caret.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. */ -import { Direction, getTabDirection } from "./direction"; -import { IRect } from "./rect"; +import { Direction, getTabDirection } from "./direction.js"; +import { IRect } from "./rect.js"; export type ICaretBounds = Pick; diff --git a/examples/data-objects/webflow/src/util/index.ts b/examples/data-objects/webflow/src/util/index.ts index 0f4e01376417..8f5943d93cb5 100644 --- a/examples/data-objects/webflow/src/util/index.ts +++ b/examples/data-objects/webflow/src/util/index.ts @@ -3,17 +3,17 @@ * Licensed under the MIT License. */ -export { ICaretBounds, ICaretEvent, CaretEventType, caretEnter, caretLeave } from "./caret"; -export { ICommand } from "./command"; -export { Direction, getDeltaX, getDeltaY, getTabDirection, TabDirection } from "./direction"; -export { Dom } from "./dom"; -export { KeyCode } from "./keycode"; -export { randomId } from "./random"; -export { IRect, Rect } from "./rect"; -export { getSegmentRange } from "./segment"; -export { areStringsEquivalent } from "./string"; -export { hasTagName, isElementNode, isTextNode, TagName } from "./tagName"; -export { findToken, TokenList } from "./tokenlist"; +export { ICaretBounds, ICaretEvent, CaretEventType, caretEnter, caretLeave } from "./caret.js"; +export { ICommand } from "./command.js"; +export { Direction, getDeltaX, getDeltaY, getTabDirection, TabDirection } from "./direction.js"; +export { Dom } from "./dom.js"; +export { KeyCode } from "./keycode.js"; +export { randomId } from "./random.js"; +export { IRect, Rect } from "./rect.js"; +export { getSegmentRange } from "./segment.js"; +export { areStringsEquivalent } from "./string.js"; +export { hasTagName, isElementNode, isTextNode, TagName } from "./tagName.js"; +export { findToken, TokenList } from "./tokenlist.js"; export const done = Promise.resolve(); export const emptyObject = Object.freeze({}); diff --git a/examples/data-objects/webflow/src/util/localref.ts b/examples/data-objects/webflow/src/util/localref.ts index be883d5f4063..747619a68550 100644 --- a/examples/data-objects/webflow/src/util/localref.ts +++ b/examples/data-objects/webflow/src/util/localref.ts @@ -4,8 +4,8 @@ */ import { LocalReferencePosition } from "@fluidframework/merge-tree"; -import { debug } from "../document/debug"; -import { FlowDocument } from "../document/index"; +import { debug } from "../document/debug.js"; +import { FlowDocument } from "../document/index.js"; export function updateRef(doc: FlowDocument, ref: LocalReferencePosition, position: number) { if (isNaN(position)) { diff --git a/examples/data-objects/webflow/src/util/tag.ts b/examples/data-objects/webflow/src/util/tag.ts index 1da18e17336b..93a5f8ebb84f 100644 --- a/examples/data-objects/webflow/src/util/tag.ts +++ b/examples/data-objects/webflow/src/util/tag.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. */ -import { DocSegmentKind } from "../document"; -import { TagName } from "./tagName"; +import { DocSegmentKind } from "../document/index.js"; +import { TagName } from "./tagName.js"; const segmentKindToIdPrefix = { [DocSegmentKind.beginTags]: "b:", diff --git a/examples/data-objects/webflow/src/util/tokenlist.ts b/examples/data-objects/webflow/src/util/tokenlist.ts index dae53f5e2267..8d8bd610a169 100644 --- a/examples/data-objects/webflow/src/util/tokenlist.ts +++ b/examples/data-objects/webflow/src/util/tokenlist.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. */ -import { CharCode } from "./charcode"; +import { CharCode } from "./charcode.js"; export function findToken(tokenList: string, token: string) { if (tokenList) { diff --git a/examples/data-objects/webflow/src/view/debug.ts b/examples/data-objects/webflow/src/view/debug.ts index cab7c5be3ad5..b4b5e516cc1c 100644 --- a/examples/data-objects/webflow/src/view/debug.ts +++ b/examples/data-objects/webflow/src/view/debug.ts @@ -4,6 +4,6 @@ */ import { IDebugger } from "debug"; -import { debug as parent } from "../debug"; +import { debug as parent } from "../debug.js"; export const debug: IDebugger = parent.extend("view"); diff --git a/examples/data-objects/webflow/src/view/formatter.ts b/examples/data-objects/webflow/src/view/formatter.ts index 77f3ed7cc1af..3d879d08b31f 100644 --- a/examples/data-objects/webflow/src/view/formatter.ts +++ b/examples/data-objects/webflow/src/view/formatter.ts @@ -4,8 +4,8 @@ */ import { SequenceEvent } from "@fluidframework/sequence"; -import { emptyObject } from "../util"; -import { Layout } from "./layout"; +import { emptyObject } from "../util/index.js"; +import { Layout } from "./layout.js"; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface IFormatterState {} diff --git a/examples/data-objects/webflow/src/view/layout.ts b/examples/data-objects/webflow/src/view/layout.ts index 491ef4e218c2..d25c88bdf90f 100644 --- a/examples/data-objects/webflow/src/view/layout.ts +++ b/examples/data-objects/webflow/src/view/layout.ts @@ -13,7 +13,7 @@ import { LocalReferencePosition, } from "@fluidframework/merge-tree"; import { SequenceEvent } from "@fluidframework/sequence"; -import { FlowDocument } from "../document"; +import { FlowDocument } from "../document/index.js"; import { clamp, Dom, @@ -23,10 +23,10 @@ import { hasTagName, isTextNode, TagName, -} from "../util"; -import { extractRef, updateRef } from "../util/localref"; -import { debug } from "./debug"; -import { BootstrapFormatter, Formatter, IFormatterState, RootFormatter } from "./formatter"; +} from "../util/index.js"; +import { extractRef, updateRef } from "../util/localref.js"; +import { debug } from "./debug.js"; +import { BootstrapFormatter, Formatter, IFormatterState, RootFormatter } from "./formatter.js"; interface ILayoutCursor { parent: Node; diff --git a/examples/data-objects/webflow/tsconfig.esnext.json b/examples/data-objects/webflow/tsconfig.esnext.json deleted file mode 100644 index 1ea62d46b20b..000000000000 --- a/examples/data-objects/webflow/tsconfig.esnext.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./lib", - "module": "esnext", - }, -} diff --git a/examples/data-objects/webflow/tsconfig.json b/examples/data-objects/webflow/tsconfig.json index 10f80581ad10..81b341a1644b 100644 --- a/examples/data-objects/webflow/tsconfig.json +++ b/examples/data-objects/webflow/tsconfig.json @@ -8,6 +8,8 @@ "rootDir": "./src", "outDir": "./dist", "types": ["node", "react", "react-dom"], + "module": "esnext", + "resolveJsonModule": true, }, "include": ["src/**/*"], } diff --git a/examples/data-objects/webflow/webpack.config.js b/examples/data-objects/webflow/webpack.config.cjs similarity index 84% rename from examples/data-objects/webflow/webpack.config.js rename to examples/data-objects/webflow/webpack.config.cjs index 2c51e33db7af..4eca9a9f2943 100644 --- a/examples/data-objects/webflow/webpack.config.js +++ b/examples/data-objects/webflow/webpack.config.cjs @@ -17,6 +17,12 @@ module.exports = (env) => { entry: "./src/index.ts", resolve: { extensions: [".mjs", ".ts", ".tsx", ".js"], + // This ensures that webpack understands fully-specified relative module imports. + // See https://github.com/webpack/webpack/issues/13252 for more discussion. + extensionAlias: { + ".js": [".ts", ".tsx", ".js"], + ".mjs": [".mts", ".mtsx", ".mjs"], + }, fallback: { dgram: false, fs: false, @@ -64,7 +70,7 @@ module.exports = (env) => { ignored: "**/node_modules/**", }, }, - isProduction ? require("./webpack.prod") : require("./webpack.dev"), + isProduction ? require("./webpack.prod.cjs") : require("./webpack.dev.cjs"), fluidRoute.devServerConfig(__dirname, env), ); }; diff --git a/examples/data-objects/webflow/webpack.dev.js b/examples/data-objects/webflow/webpack.dev.cjs similarity index 100% rename from examples/data-objects/webflow/webpack.dev.js rename to examples/data-objects/webflow/webpack.dev.cjs diff --git a/examples/data-objects/webflow/webpack.prod.js b/examples/data-objects/webflow/webpack.prod.cjs similarity index 100% rename from examples/data-objects/webflow/webpack.prod.js rename to examples/data-objects/webflow/webpack.prod.cjs From 88f297357a3758fdd7bf487c2165165db159b8c6 Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Fri, 9 Jun 2023 09:14:37 -0700 Subject: [PATCH 04/15] Update test-gc-sweep-tests --- .../{.eslintrc.js => .eslintrc.cjs} | 4 ++++ .../test-gc-sweep-tests/{.mocharc.js => .mocharc.cjs} | 0 packages/test/test-gc-sweep-tests/package.json | 1 + .../src/dataObjectWithChildDataObject.ts | 2 +- .../test-gc-sweep-tests/src/test/autoRunTest.spec.ts | 10 +++++----- .../test/test-gc-sweep-tests/src/test/tsconfig.json | 1 + 6 files changed, 12 insertions(+), 6 deletions(-) rename packages/test/test-gc-sweep-tests/{.eslintrc.js => .eslintrc.cjs} (63%) rename packages/test/test-gc-sweep-tests/{.mocharc.js => .mocharc.cjs} (100%) diff --git a/packages/test/test-gc-sweep-tests/.eslintrc.js b/packages/test/test-gc-sweep-tests/.eslintrc.cjs similarity index 63% rename from packages/test/test-gc-sweep-tests/.eslintrc.js rename to packages/test/test-gc-sweep-tests/.eslintrc.cjs index 67da7004678e..91eaddb1c430 100644 --- a/packages/test/test-gc-sweep-tests/.eslintrc.js +++ b/packages/test/test-gc-sweep-tests/.eslintrc.cjs @@ -9,6 +9,10 @@ module.exports = { "prefer-arrow-callback": "off", "@typescript-eslint/strict-boolean-expressions": "off", // requires strictNullChecks=true in tsconfig "import/no-nodejs-modules": "off", + // ESLint's resolver doesn't resolve relative imports of ESNext modules correctly, since + // it resolves the path relative to the .ts file (and assumes a file with a .js extension + // should exist there) + "import/no-unresolved": ["error", { ignore: ["^\\.(.*)\\.js$"] }], }, parserOptions: { project: ["./src/test/tsconfig.json"], diff --git a/packages/test/test-gc-sweep-tests/.mocharc.js b/packages/test/test-gc-sweep-tests/.mocharc.cjs similarity index 100% rename from packages/test/test-gc-sweep-tests/.mocharc.js rename to packages/test/test-gc-sweep-tests/.mocharc.cjs diff --git a/packages/test/test-gc-sweep-tests/package.json b/packages/test/test-gc-sweep-tests/package.json index a72c49973694..d5c76677a63c 100644 --- a/packages/test/test-gc-sweep-tests/package.json +++ b/packages/test/test-gc-sweep-tests/package.json @@ -12,6 +12,7 @@ "license": "MIT", "author": "Microsoft and contributors", "sideEffects": false, + "type": "module", "scripts": { "build": "concurrently npm:build:compile npm:lint", "build:compile": "npm run build:test", diff --git a/packages/test/test-gc-sweep-tests/src/dataObjectWithChildDataObject.ts b/packages/test/test-gc-sweep-tests/src/dataObjectWithChildDataObject.ts index c857712cea96..f57e8244dfa1 100644 --- a/packages/test/test-gc-sweep-tests/src/dataObjectWithChildDataObject.ts +++ b/packages/test/test-gc-sweep-tests/src/dataObjectWithChildDataObject.ts @@ -7,7 +7,7 @@ import { makeRandom } from "@fluid-internal/stochastic-test-utils"; import { DataObjectFactory } from "@fluidframework/aqueduct"; import { assert, delay } from "@fluidframework/common-utils"; import { SharedCounter } from "@fluidframework/counter"; -import { DataObjectWithCounter, dataObjectWithCounterFactory } from "./dataObjectWithCounter"; +import { DataObjectWithCounter, dataObjectWithCounterFactory } from "./dataObjectWithCounter.js"; /** * A root dataObject that repeatedly sends a series of ops, and then references a new child or diff --git a/packages/test/test-gc-sweep-tests/src/test/autoRunTest.spec.ts b/packages/test/test-gc-sweep-tests/src/test/autoRunTest.spec.ts index 0b976653d9a0..6c9e31917bf5 100644 --- a/packages/test/test-gc-sweep-tests/src/test/autoRunTest.spec.ts +++ b/packages/test/test-gc-sweep-tests/src/test/autoRunTest.spec.ts @@ -16,11 +16,11 @@ import { import { IContainerRuntimeBase } from "@fluidframework/runtime-definitions"; import { makeRandom } from "@fluid-internal/stochastic-test-utils"; import { delay } from "@fluidframework/common-utils"; -import { mockConfigProvider } from "../mockConfigProvider"; -import { IgnoreErrorLogger } from "../ignoreErrorLogger"; -import { ContainerManager } from "../containerManager"; -import { rootDataObjectWithChildDataObjectFactory } from "../dataObjectWithChildDataObject"; -import { dataObjectWithCounterFactory } from "../dataObjectWithCounter"; +import { mockConfigProvider } from "../mockConfigProvider.js"; +import { IgnoreErrorLogger } from "../ignoreErrorLogger.js"; +import { ContainerManager } from "../containerManager.js"; +import { rootDataObjectWithChildDataObjectFactory } from "../dataObjectWithChildDataObject.js"; +import { dataObjectWithCounterFactory } from "../dataObjectWithCounter.js"; describeNoCompat("GC InactiveObjectX tests", (getTestObjectProvider) => { let provider: ITestObjectProvider; diff --git a/packages/test/test-gc-sweep-tests/src/test/tsconfig.json b/packages/test/test-gc-sweep-tests/src/test/tsconfig.json index 8d9c997d58b7..4aeaf874c081 100644 --- a/packages/test/test-gc-sweep-tests/src/test/tsconfig.json +++ b/packages/test/test-gc-sweep-tests/src/test/tsconfig.json @@ -6,6 +6,7 @@ "rootDir": "../", "outDir": "../../dist", "types": ["mocha", "@fluidframework/test-driver-definitions"], + "module": "esnext", }, "include": ["./**/*", "../*"], } From 4b9de5b0242b39f54ec77514f3856f2030ad9590 Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Fri, 9 Jun 2023 09:59:04 -0700 Subject: [PATCH 05/15] Update webflow to build and make build scripts correct post-flub merge --- examples/data-objects/webflow/.eslintrc.cjs | 4 ++++ examples/data-objects/webflow/package.json | 2 +- examples/data-objects/webflow/src/test/layout.spec.ts | 1 + pnpm-lock.yaml | 7 ------- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/examples/data-objects/webflow/.eslintrc.cjs b/examples/data-objects/webflow/.eslintrc.cjs index 3a5a22d5ad7c..dfcfc4ddf0a6 100644 --- a/examples/data-objects/webflow/.eslintrc.cjs +++ b/examples/data-objects/webflow/.eslintrc.cjs @@ -12,6 +12,10 @@ module.exports = { "max-len": "off", "no-bitwise": "off", "no-case-declarations": "off", + // ESLint's resolver doesn't resolve relative imports of ESNext modules correctly, since + // it resolves the path relative to the .ts file (and assumes a file with a .js extension + // should exist there) + "import/no-unresolved": ["error", { ignore: ["^\\.(.*)\\.js$"] }], }, parserOptions: { project: ["./tsconfig.json", "./src/test/tsconfig.json"], diff --git a/examples/data-objects/webflow/package.json b/examples/data-objects/webflow/package.json index 9f0f0eaeef87..ea78336af5c9 100644 --- a/examples/data-objects/webflow/package.json +++ b/examples/data-objects/webflow/package.json @@ -18,8 +18,8 @@ "type": "module", "scripts": { "build": "fluid-build . --task build", - "build:commonjs": "fluid-build . --task commonjs", "build:compile": "fluid-build . --task compile", + "build:esnext": "tsc", "build:copy": "copyfiles -u 1 \"src/**/*.css\" dist/", "build:test": "tsc --project ./src/test/tsconfig.json", "clean": "rimraf dist lib *.tsbuildinfo *.build.log", diff --git a/examples/data-objects/webflow/src/test/layout.spec.ts b/examples/data-objects/webflow/src/test/layout.spec.ts index 920eb556a1a8..68770722d334 100644 --- a/examples/data-objects/webflow/src/test/layout.spec.ts +++ b/examples/data-objects/webflow/src/test/layout.spec.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. */ +// eslint-disable-next-line import/no-unassigned-import import "jsdom-global/register.js"; window.performance.mark ??= () => undefined as PerformanceMark; window.performance.measure ??= () => undefined as PerformanceMeasure; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bd674c0f02bc..b0ca917896e5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4591,9 +4591,6 @@ importers: html-loader: specifier: ^3.1.0 version: 3.1.2(webpack@5.83.0) - ignore-styles: - specifier: ^5.0.1 - version: 5.0.1 jsdom: specifier: ^16.7.0 version: 16.7.0 @@ -36088,10 +36085,6 @@ packages: resolution: {integrity: sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==} dev: true - /ignore-styles@5.0.1: - resolution: {integrity: sha512-gQQmIznCETPLEzfg1UH4Cs2oRq+HBPl8quroEUNXT8oybEG7/0lqI3dGgDSRry6B9HcCXw3PVkFFS0FF3CMddg==} - dev: true - /ignore-walk@4.0.1: resolution: {integrity: sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==} engines: {node: '>=10'} From 023da54596ab1b6cf7d490354c0bf62a9ab46490 Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Fri, 9 Jun 2023 10:24:03 -0700 Subject: [PATCH 06/15] Sort package.json and add engine field to webflow example --- examples/data-objects/webflow/package.json | 7 +++++-- packages/test/test-version-utils/package.json | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/data-objects/webflow/package.json b/examples/data-objects/webflow/package.json index ea78336af5c9..24f8d67fa9ed 100644 --- a/examples/data-objects/webflow/package.json +++ b/examples/data-objects/webflow/package.json @@ -12,15 +12,15 @@ "license": "MIT", "author": "Microsoft and contributors", "sideEffects": false, + "type": "module", "main": "dist/index.js", "module": "dist/index.js", "types": "dist/index.d.ts", - "type": "module", "scripts": { "build": "fluid-build . --task build", "build:compile": "fluid-build . --task compile", - "build:esnext": "tsc", "build:copy": "copyfiles -u 1 \"src/**/*.css\" dist/", + "build:esnext": "tsc", "build:test": "tsc --project ./src/test/tsconfig.json", "clean": "rimraf dist lib *.tsbuildinfo *.build.log", "dev": "npm run build:esnext -- --watch", @@ -133,6 +133,9 @@ "webpack-dev-server": "~4.6.0", "webpack-merge": "^5.8.0" }, + "engines": { + "node": ">=16.12.0" + }, "fluid": { "browser": { "umd": { diff --git a/packages/test/test-version-utils/package.json b/packages/test/test-version-utils/package.json index d90abdf9c6b4..4d33659789fd 100644 --- a/packages/test/test-version-utils/package.json +++ b/packages/test/test-version-utils/package.json @@ -11,10 +11,10 @@ "license": "MIT", "author": "Microsoft and contributors", "sideEffects": false, + "type": "module", "main": "dist/index.js", "module": "lib/index.js", "types": "dist/index.d.ts", - "type": "module", "scripts": { "build": "fluid-build . --task build", "build:compile": "fluid-build . --task compile", From 2096a7ae8e4d83672cbd25dd1e88321b11ca693b Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Fri, 9 Jun 2023 10:49:29 -0700 Subject: [PATCH 07/15] Fix test-version-utils tests --- packages/test/test-version-utils/src/test/tsconfig.json | 1 + packages/test/test-version-utils/src/test/versionUtils.spec.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/test/test-version-utils/src/test/tsconfig.json b/packages/test/test-version-utils/src/test/tsconfig.json index f48772395330..312c7f582e9a 100644 --- a/packages/test/test-version-utils/src/test/tsconfig.json +++ b/packages/test/test-version-utils/src/test/tsconfig.json @@ -7,6 +7,7 @@ "declaration": false, "declarationMap": false, "skipLibCheck": true, + "module": "esnext", }, "include": ["./**/*"], "references": [ diff --git a/packages/test/test-version-utils/src/test/versionUtils.spec.ts b/packages/test/test-version-utils/src/test/versionUtils.spec.ts index a052e096a6f2..3e7393ac40a5 100644 --- a/packages/test/test-version-utils/src/test/versionUtils.spec.ts +++ b/packages/test/test-version-utils/src/test/versionUtils.spec.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. */ import { strict as assert } from "assert"; -import { getRequestedRange, versionHasMovedSparsedMatrix } from "../versionUtils"; +import { getRequestedRange, versionHasMovedSparsedMatrix } from "../versionUtils.js"; describe("versionUtils", () => { it("Get the major version number above or below the baseVersion", () => { From 9f8f0c9159581cca55e21a400e21403002fddf8d Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Fri, 9 Jun 2023 10:51:23 -0700 Subject: [PATCH 08/15] Remove unnecessary reference to node loader --- examples/data-objects/webflow/src/test/.mocharc.cjs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/data-objects/webflow/src/test/.mocharc.cjs b/examples/data-objects/webflow/src/test/.mocharc.cjs index 254b24568a5c..a92b7ba302bb 100644 --- a/examples/data-objects/webflow/src/test/.mocharc.cjs +++ b/examples/data-objects/webflow/src/test/.mocharc.cjs @@ -9,7 +9,4 @@ const packageDir = `${__dirname}/../..`; const getFluidTestMochaConfig = require("@fluid-internal/test-version-utils/mocharc-common.cjs"); const config = getFluidTestMochaConfig(packageDir); -module.exports = { - ...config, - "experimental-loader": "../../ignore-loader.mjs", -}; +module.exports = config; From a2dadd42689ffba672ea58a7becf8ed29c4519e6 Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Fri, 9 Jun 2023 11:58:10 -0700 Subject: [PATCH 09/15] remove engines declaration as root already specifies >=16.16 --- examples/data-objects/webflow/package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/data-objects/webflow/package.json b/examples/data-objects/webflow/package.json index 24f8d67fa9ed..4f566d04be15 100644 --- a/examples/data-objects/webflow/package.json +++ b/examples/data-objects/webflow/package.json @@ -133,9 +133,6 @@ "webpack-dev-server": "~4.6.0", "webpack-merge": "^5.8.0" }, - "engines": { - "node": ">=16.12.0" - }, "fluid": { "browser": { "umd": { From 9a3b9520045f4f6fcabf8edee4ca509a38c9ca94 Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Thu, 15 Jun 2023 15:15:20 -0700 Subject: [PATCH 10/15] Update packages/test/test-version-utils/src/compatConfig.ts --- packages/test/test-version-utils/src/compatConfig.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/test/test-version-utils/src/compatConfig.ts b/packages/test/test-version-utils/src/compatConfig.ts index fd0f8f60b87c..725c03affa8e 100644 --- a/packages/test/test-version-utils/src/compatConfig.ts +++ b/packages/test/test-version-utils/src/compatConfig.ts @@ -280,7 +280,6 @@ export async function mochaGlobalSetup() { for (const p of installP) { try { const pkg = await p; - console.log(pkg?.modulePath, pkg?.version); } catch (e) { error = e; } From 64f72ad3e1eccea504f6384fa5fab2497fdb53d5 Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Fri, 16 Jun 2023 10:03:04 -0700 Subject: [PATCH 11/15] PR feedback and minor cleanup --- .../data-objects/webflow/ignore-loader.mjs | 20 ------------------- .../gc/gcReferenceUpdatesInSummary.spec.ts | 5 +++-- .../test-version-utils/src/compatConfig.ts | 5 ++--- .../test-version-utils/src/compatUtils.ts | 19 +++++++++--------- .../test-version-utils/src/describeCompat.ts | 5 ++++- .../test/test-version-utils/src/testApi.ts | 3 +++ 6 files changed, 22 insertions(+), 35 deletions(-) delete mode 100644 examples/data-objects/webflow/ignore-loader.mjs diff --git a/examples/data-objects/webflow/ignore-loader.mjs b/examples/data-objects/webflow/ignore-loader.mjs deleted file mode 100644 index dcda2426c184..000000000000 --- a/examples/data-objects/webflow/ignore-loader.mjs +++ /dev/null @@ -1,20 +0,0 @@ -const extensionsRegex = /\.css$/; - -/** - * This uses the node loader API (see https://nodejs.org/docs/latest-v16.x/api/esm.html#loaders) - * to enable webpack-style imports of .css modules. - * - * This is the recommended successor to `require.extensions`, which was used by https://www.npmjs.com/package/ignore-styles - * to accomplish the same thing. - */ -export async function load(url, context, nextLoad) { - if (extensionsRegex.test(url)) { - return { - format: "json", - source: "{}", - }; - } - - // Defer to the next hook in the chain. - return nextLoad(url, context); -} diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcReferenceUpdatesInSummary.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcReferenceUpdatesInSummary.spec.ts index 67e4202dff14..cb3f9afe3d35 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcReferenceUpdatesInSummary.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcReferenceUpdatesInSummary.spec.ts @@ -7,11 +7,11 @@ import { strict as assert } from "assert"; import { IContainer } from "@fluidframework/container-definitions"; import { ContainerRuntime, IContainerRuntimeOptions } from "@fluidframework/container-runtime"; import { IFluidHandle } from "@fluidframework/core-interfaces"; -import { SharedMatrix } from "@fluidframework/matrix"; +import type { SharedMatrix } from "@fluidframework/matrix"; import { Marker, ReferenceType, reservedMarkerIdKey } from "@fluidframework/merge-tree"; import { requestFluidObject } from "@fluidframework/runtime-utils"; import { ISummaryTree, SummaryType } from "@fluidframework/protocol-definitions"; -import { SharedString } from "@fluidframework/sequence"; +import type { SharedString } from "@fluidframework/sequence"; import { TelemetryNullLogger } from "@fluidframework/telemetry-utils"; import { ITestObjectProvider, waitForContainerConnection } from "@fluidframework/test-utils"; import { describeFullCompat } from "@fluid-internal/test-version-utils"; @@ -68,6 +68,7 @@ describeFullCompat("GC reference updates in local summary", (getTestObjectProvid } let provider: ITestObjectProvider; + const { SharedMatrix, SharedString } = apis.dds; const factory = new apis.dataRuntime.DataObjectFactory( "TestDataObject", TestDataObject, diff --git a/packages/test/test-version-utils/src/compatConfig.ts b/packages/test/test-version-utils/src/compatConfig.ts index 3b7f26d6c7cd..18860f06174a 100644 --- a/packages/test/test-version-utils/src/compatConfig.ts +++ b/packages/test/test-version-utils/src/compatConfig.ts @@ -262,8 +262,7 @@ export const configList = new Lazy(() => { * }); * ``` * - * If the linked github issue is ever fixed, the module load logic in `./testApi.js` can be simplified considerably - * and this can be once again used as a global setup fixture. + * If the linked github issue is ever fixed, this can be once again used as a global setup fixture. */ export async function mochaGlobalSetup() { const versions = new Set(configList.value.map((value) => value.compatVersion)); @@ -279,7 +278,7 @@ export async function mochaGlobalSetup() { let error: unknown | undefined; for (const p of installP) { try { - const pkg = await p; + await p; } catch (e) { error = e; } diff --git a/packages/test/test-version-utils/src/compatUtils.ts b/packages/test/test-version-utils/src/compatUtils.ts index 133e7f05fe83..2550c4b68480 100644 --- a/packages/test/test-version-utils/src/compatUtils.ts +++ b/packages/test/test-version-utils/src/compatUtils.ts @@ -97,7 +97,7 @@ function createGetDataStoreFactoryFunction(api: ReturnType, driverConfig?: { type?: TestDriverTypes; config?: FluidTestDriverConfig; @@ -141,12 +141,13 @@ export async function getVersionedTestObjectProvider( runtimeVersion?: number | string, dataRuntimeVersion?: number | string, ): Promise { - const apis: CompatApis = { - loader: getLoaderApi(baseVersion, loaderVersion), - containerRuntime: getContainerRuntimeApi(baseVersion, runtimeVersion), - dataRuntime: getDataRuntimeApi(baseVersion, dataRuntimeVersion), - driver: getDriverApi(baseVersion, driverConfig?.version), - }; - - return getVersionedTestObjectProviderFromApis(apis, driverConfig); + return getVersionedTestObjectProviderFromApis( + { + loader: getLoaderApi(baseVersion, loaderVersion), + containerRuntime: getContainerRuntimeApi(baseVersion, runtimeVersion), + dataRuntime: getDataRuntimeApi(baseVersion, dataRuntimeVersion), + driver: getDriverApi(baseVersion, driverConfig?.version), + }, + driverConfig, + ); } diff --git a/packages/test/test-version-utils/src/describeCompat.ts b/packages/test/test-version-utils/src/describeCompat.ts index d844b3313e36..343e29b8d5aa 100644 --- a/packages/test/test-version-utils/src/describeCompat.ts +++ b/packages/test/test-version-utils/src/describeCompat.ts @@ -20,6 +20,7 @@ import { getDriverApi, } from "./testApi.js"; +// See doc comment on mochaGlobalSetup. await mochaGlobalSetup(); /* @@ -39,9 +40,11 @@ function createCompatSuite( describe(config.name, function () { let provider: TestObjectProvider; let resetAfterEach: boolean; + const dataRuntimeApi = getDataRuntimeApi(baseVersion, config.dataRuntime); const apis: CompatApis = { containerRuntime: getContainerRuntimeApi(baseVersion, config.containerRuntime), - dataRuntime: getDataRuntimeApi(baseVersion, config.dataRuntime), + dataRuntime: dataRuntimeApi, + dds: dataRuntimeApi.dds, driver: getDriverApi(baseVersion, config.driver), loader: getLoaderApi(baseVersion, config.loader), }; diff --git a/packages/test/test-version-utils/src/testApi.ts b/packages/test/test-version-utils/src/testApi.ts index 4e2261ffda73..1dc0a2969394 100644 --- a/packages/test/test-version-utils/src/testApi.ts +++ b/packages/test/test-version-utils/src/testApi.ts @@ -80,6 +80,8 @@ export const ensurePackageInstalled = async ( return pkg; }; +// We'd like to support synchronous functions to import packages once their install has been completed. +// Since dynamic import is async, we thus cache the modules based on their package version. const loaderCache = new Map(); const containerRuntimeCache = new Map(); const dataRuntimeCache = new Map(); @@ -341,6 +343,7 @@ export function getDriverApi(baseVersion: string, requested?: number | string): export interface CompatApis { containerRuntime: ReturnType; dataRuntime: ReturnType; + dds: ReturnType["dds"]; driver: ReturnType; loader: ReturnType; } From c14cc8b3fe9c7e058141187cf42779c638906415 Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Fri, 16 Jun 2023 10:03:59 -0700 Subject: [PATCH 12/15] add same backlog item note to test-version-utils eslint --- packages/test/test-version-utils/.eslintrc.cjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/test/test-version-utils/.eslintrc.cjs b/packages/test/test-version-utils/.eslintrc.cjs index 2218f5eaf158..06a2d8c663d3 100644 --- a/packages/test/test-version-utils/.eslintrc.cjs +++ b/packages/test/test-version-utils/.eslintrc.cjs @@ -11,6 +11,8 @@ module.exports = { // ESLint's resolver doesn't resolve relative imports of ESNext modules correctly, since // it resolves the path relative to the .ts file (and assumes a file with a .js extension // should exist there) + // AB#4614 tracks moving to eslint-import-resolver-typescript (which handles such imports + // out of the box) and removing this exception. "import/no-unresolved": ["error", { ignore: ["^\\.(.*)\\.js$"] }], }, parserOptions: { From f9e29e0fcb914c8c18625265e85ad5db2e96e5c3 Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Fri, 16 Jun 2023 10:05:52 -0700 Subject: [PATCH 13/15] clarify comment --- packages/test/test-version-utils/src/testApi.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/test/test-version-utils/src/testApi.ts b/packages/test/test-version-utils/src/testApi.ts index 1dc0a2969394..45a0fb753ce4 100644 --- a/packages/test/test-version-utils/src/testApi.ts +++ b/packages/test/test-version-utils/src/testApi.ts @@ -80,7 +80,7 @@ export const ensurePackageInstalled = async ( return pkg; }; -// We'd like to support synchronous functions to import packages once their install has been completed. +// This module supports synchronous functions to import packages once their install has been completed. // Since dynamic import is async, we thus cache the modules based on their package version. const loaderCache = new Map(); const containerRuntimeCache = new Map(); From 0a7d2dbbbc089c3fe4f90ee9c74eb6c767edd34b Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Fri, 16 Jun 2023 14:34:09 -0700 Subject: [PATCH 14/15] Make SharedMatrix/SharedString reference more clear --- .../src/test/gc/gcReferenceUpdatesInSummary.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/test/test-end-to-end-tests/src/test/gc/gcReferenceUpdatesInSummary.spec.ts b/packages/test/test-end-to-end-tests/src/test/gc/gcReferenceUpdatesInSummary.spec.ts index cb3f9afe3d35..c0f1533f58d9 100644 --- a/packages/test/test-end-to-end-tests/src/test/gc/gcReferenceUpdatesInSummary.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/gc/gcReferenceUpdatesInSummary.spec.ts @@ -25,6 +25,8 @@ import { UndoRedoStackManager } from "@fluidframework/undo-redo"; * the "unreferenced" property. */ describeFullCompat("GC reference updates in local summary", (getTestObjectProvider, apis) => { + const { SharedMatrix, SharedString } = apis.dds; + class TestDataObject extends apis.dataRuntime.DataObject { public get _root() { return this.root; @@ -68,7 +70,6 @@ describeFullCompat("GC reference updates in local summary", (getTestObjectProvid } let provider: ITestObjectProvider; - const { SharedMatrix, SharedString } = apis.dds; const factory = new apis.dataRuntime.DataObjectFactory( "TestDataObject", TestDataObject, From cbabb42092c65aeda8c60499f2b9d1fd95ff6c62 Mon Sep 17 00:00:00 2001 From: Abram Sanderson Date: Fri, 16 Jun 2023 14:45:54 -0700 Subject: [PATCH 15/15] PR feedback --- .../test/test-version-utils/src/testApi.ts | 29 +++++-------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/packages/test/test-version-utils/src/testApi.ts b/packages/test/test-version-utils/src/testApi.ts index 45a0fb753ce4..59e04a9c5db2 100644 --- a/packages/test/test-version-utils/src/testApi.ts +++ b/packages/test/test-version-utils/src/testApi.ts @@ -118,13 +118,10 @@ const DataRuntimeApi = { }, }; -async function loadLoader( - baseVersion: string, - requested?: number | string, -): Promise { +async function loadLoader(baseVersion: string, requested?: number | string): Promise { const requestedStr = getRequestedRange(baseVersion, requested); if (semver.satisfies(pkgVersion, requestedStr)) { - return LoaderApi; + return; } const { version, modulePath } = checkInstalled(requestedStr); @@ -135,16 +132,15 @@ async function loadLoader( }; loaderCache.set(version, loader); } - return loaderCache.get(version) ?? throwNotFound("Loader", version); } async function loadContainerRuntime( baseVersion: string, requested?: number | string, -): Promise { +): Promise { const requestedStr = getRequestedRange(baseVersion, requested); if (semver.satisfies(pkgVersion, requestedStr)) { - return ContainerRuntimeApi; + return; } const { version, modulePath } = checkInstalled(requestedStr); @@ -159,16 +155,12 @@ async function loadContainerRuntime( }; containerRuntimeCache.set(version, containerRuntime); } - return containerRuntimeCache.get(version) ?? throwNotFound("ContainerRuntime", version); } -async function loadDataRuntime( - baseVersion: string, - requested?: number | string, -): Promise { +async function loadDataRuntime(baseVersion: string, requested?: number | string): Promise { const requestedStr = getRequestedRange(baseVersion, requested); if (semver.satisfies(pkgVersion, requestedStr)) { - return DataRuntimeApi; + return; } const { version, modulePath } = checkInstalled(requestedStr); if (!dataRuntimeCache.has(version)) { @@ -225,16 +217,12 @@ async function loadDataRuntime( }; dataRuntimeCache.set(version, dataRuntime); } - return dataRuntimeCache.get(version) ?? throwNotFound("DataRuntime", version); } -async function loadDriver( - baseVersion: string, - requested?: number | string, -): Promise { +async function loadDriver(baseVersion: string, requested?: number | string): Promise { const requestedStr = getRequestedRange(baseVersion, requested); if (semver.satisfies(pkgVersion, requestedStr)) { - return DriverApi; + return; } const { version, modulePath } = checkInstalled(requestedStr); @@ -284,7 +272,6 @@ async function loadDriver( RouterliciousDriverApi, }); } - return driverCache.get(version) ?? throwNotFound("Driver", version); } function throwNotFound(layer: string, version: string): never {