Skip to content

Commit

Permalink
fix multiple imports of same module
Browse files Browse the repository at this point in the history
  • Loading branch information
YousefED committed Oct 11, 2023
1 parent c45fefe commit b4539e7
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 29 deletions.
33 changes: 20 additions & 13 deletions packages/editor/src/app/documentRenderers/richtext/FrameHost.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,40 +68,47 @@ export function FrameHost(props: {
processYjsMessage: async (message: ArrayBuffer) => {
provider.onMessage(message, "penpal");
},
registerTypeCellModuleCompiler: async (moduleName: string) => {
if (moduleManagers.has(moduleName)) {
console.warn("already has moduleManager for", moduleName);
return;
}
resolveModuleName: async (moduleName: string) => {
if (!moduleName.startsWith("!")) {
throw new Error("invalid module name");
}
const identifierStr = moduleName.substring(1);

const identifier = parseIdentifier(moduleName.substring(1));
const identifierStr = identifier.toString();
return identifierStr;
},
registerTypeCellModuleCompiler: async (identifierStr: string) => {
const identifier = parseIdentifier(identifierStr);
if (moduleManagers.has(identifierStr)) {
console.warn("already has moduleManager for", identifierStr);
return identifierStr;
}

const provider = new DocumentResourceModelProvider(
identifier,
props.sessionStore,
);

const forwarder = new ModelForwarder(
"modules/" + moduleName,
"modules/" + identifierStr,
provider,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
connectionMethods.current!,
);
moduleManagers.set(moduleName, { provider, forwarder });

moduleManagers.set(identifierStr, { provider, forwarder });
await forwarder.initialize();
return identifier.toString();
return identifierStr;
},
unregisterTypeCellModuleCompiler: async (moduleName: string) => {
const moduleManager = moduleManagers.get(moduleName);
unregisterTypeCellModuleCompiler: async (identifierStr: string) => {
const moduleManager = moduleManagers.get(identifierStr);
if (!moduleManager) {
console.warn("no moduleManager for", moduleName);
console.warn("no moduleManager for", identifierStr);
return;
}
moduleManager.provider.dispose();
moduleManager.forwarder.dispose();
moduleManagers.delete(moduleName);
moduleManagers.delete(identifierStr);
},
};

Expand Down
46 changes: 32 additions & 14 deletions packages/frame/src/Frame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ const slashMenuItems = [...originalItems];

export const Frame: React.FC<Props> = observer((props) => {
const modelReceivers = useMemo(() => new Map<string, ModelReceiver>(), []);
const subCompilers = useMemo(
() => new Map<string, SourceModelCompiler>(),
[],
);
const connectionMethods = useRef<AsyncMethodReturns<HostBridgeMethods>>();
const editorStore = useRef(new EditorStore());

Expand Down Expand Up @@ -224,31 +228,45 @@ export const Frame: React.FC<Props> = observer((props) => {
const newCompiler = new SourceModelCompiler(monaco);
const resolver = new Resolver(async (moduleName) => {
// How to resolve typecell modules (i.e.: `import * as nb from "!dALYTUW8TXxsw"`)
const subcompiler = new SourceModelCompiler(monaco);

const modelReceiver = new ModelReceiver();
// TODO: what if we have multiple usage of the same module?
modelReceivers.set("modules/" + moduleName, modelReceiver);

modelReceiver.onDidCreateModel((model) => {
subcompiler.registerModel(model);
});

const fullIdentifier =
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
await connectionMethods.current!.registerTypeCellModuleCompiler(
moduleName,
);
await connectionMethods.current!.resolveModuleName(moduleName);

// register an alias for the module so that types resolve
// (e.g.: from "!dALYTUW8TXxsw" to "!typecell:typecell.org/dALYTUW8TXxsw")
if ("!" + fullIdentifier !== moduleName) {
// register an alias for the module so that types resolve
// (e.g.: from "!dALYTUW8TXxsw" to "!typecell:typecell.org/dALYTUW8TXxsw")

monaco.languages.typescript.typescriptDefaults.addExtraLib(
`export * from "!${fullIdentifier}";`,
`file:///node_modules/@types/${moduleName}/index.d.ts`,
);
}

let modelReceiver = modelReceivers.get("modules/" + fullIdentifier);

if (modelReceiver) {
const subCompiler = subCompilers.get("modules/" + fullIdentifier);
if (!subCompiler) {
throw new Error("subCompiler not found");
}
return subCompiler;
}
modelReceiver = new ModelReceiver();

modelReceivers.set("modules/" + fullIdentifier, modelReceiver);

const subcompiler = new SourceModelCompiler(monaco);
modelReceiver.onDidCreateModel((model) => {
subcompiler.registerModel(model);
});

subCompilers.set("modules/" + fullIdentifier, subcompiler);

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
await connectionMethods.current!.registerTypeCellModuleCompiler(
fullIdentifier,
);
// TODO: dispose modelReceiver
return subcompiler;
}, editorStore.current);
Expand Down
5 changes: 3 additions & 2 deletions packages/shared/src/frameInterop/HostBridgeMethods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ export type HostBridgeMethods = {
* send the compiled javascript back to the iframe. It also keeps watching the TypeCell module for changes
* and sends changes across the bridge.
*/
registerTypeCellModuleCompiler: (moduleName: string) => Promise<string>;
unregisterTypeCellModuleCompiler: (moduleName: string) => Promise<void>;
resolveModuleName: (moduleName: string) => Promise<string>;
registerTypeCellModuleCompiler: (identifierStr: string) => Promise<string>;
unregisterTypeCellModuleCompiler: (identifierStr: string) => Promise<void>;

/**
* Function for y-penpal
Expand Down

0 comments on commit b4539e7

Please sign in to comment.