@lvce-editor/extension-host-worker 8.20.0 → 8.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/extension-api/index.js +938 -33
- package/dist/extension-api/parts/Activation/Activation.js +4 -2
- package/dist/extension-api/parts/CommandRegistry/CommandRegistry.js +3 -1
- package/dist/extension-api/parts/CompletionProviderRegistry/CompletionProviderRegistry.js +29 -2
- package/dist/extension-api/parts/DiagnosticProviderRegistry/DiagnosticProviderRegistry.js +4 -1
- package/dist/extension-api/parts/ExecuteCommand/ExecuteCommand.js +2 -2
- package/dist/extension-api/parts/ExtensionApiCommandMap/ExtensionApiCommandMap.js +17 -1
- package/dist/extension-api/parts/FormattingProviderRegistry/FormattingProviderRegistry.js +4 -1
- package/dist/extension-api/parts/HoverProviderRegistry/HoverProviderRegistry.js +4 -1
- package/dist/extension-api/parts/NotifyStatusBarChange/NotifyStatusBarChange.js +2 -2
- package/dist/extension-api/parts/OutputChannel/OutputChannel.js +71 -0
- package/dist/extension-api/parts/OutputChannelHandle/OutputChannelHandle.js +0 -0
- package/dist/extension-api/parts/OutputChannelRegistrySnapshot/OutputChannelRegistrySnapshot.js +0 -0
- package/dist/extension-api/parts/QuickPick/QuickPick.js +2 -2
- package/dist/extension-api/parts/RegisteredOutputChannel/RegisteredOutputChannel.js +0 -0
- package/dist/extension-api/parts/StatusBarItemProviderRegistry/StatusBarItemProviderRegistry.js +3 -1
- package/dist/extension-api/parts/View/View.js +0 -0
- package/dist/extension-api/parts/ViewRegistry/ViewRegistry.js +148 -0
- package/dist/extensionHostWorkerMain.js +112 -41
- package/extension-api/dist/index.d.ts +6 -0
- package/extension-api/dist/index.js +2 -0
- package/extension-api/dist/parts/Activation/Activation.js +4 -2
- package/extension-api/dist/parts/CommandMap/CommandMap.d.ts +7 -0
- package/extension-api/dist/parts/CommandRegistry/CommandRegistry.js +3 -1
- package/extension-api/dist/parts/CommandRegistrySnapshot/CommandRegistrySnapshot.d.ts +3 -2
- package/extension-api/dist/parts/CompletionProviderRegistry/CompletionProviderRegistry.js +30 -2
- package/extension-api/dist/parts/CompletionProviderRegistrySnapshot/CompletionProviderRegistrySnapshot.d.ts +4 -2
- package/extension-api/dist/parts/DiagnosticProviderRegistry/DiagnosticProviderRegistry.js +4 -1
- package/extension-api/dist/parts/DiagnosticProviderRegistrySnapshot/DiagnosticProviderRegistrySnapshot.d.ts +4 -2
- package/extension-api/dist/parts/ExecuteCommand/ExecuteCommand.js +2 -2
- package/extension-api/dist/parts/ExtensionApiCommandMap/ExtensionApiCommandMap.d.ts +7 -0
- package/extension-api/dist/parts/ExtensionApiCommandMap/ExtensionApiCommandMap.js +9 -0
- package/extension-api/dist/parts/ExtensionApiWorkerCommandMap/ExtensionApiWorkerCommandMap.d.ts +7 -0
- package/extension-api/dist/parts/FormattingProviderRegistry/FormattingProviderRegistry.js +4 -1
- package/extension-api/dist/parts/FormattingProviderRegistrySnapshot/FormattingProviderRegistrySnapshot.d.ts +4 -2
- package/extension-api/dist/parts/HoverProviderRegistry/HoverProviderRegistry.js +4 -1
- package/extension-api/dist/parts/HoverProviderRegistrySnapshot/HoverProviderRegistrySnapshot.d.ts +4 -2
- package/extension-api/dist/parts/NotifyStatusBarChange/NotifyStatusBarChange.js +2 -2
- package/extension-api/dist/parts/OutputChannel/OutputChannel.d.ts +9 -0
- package/extension-api/dist/parts/OutputChannel/OutputChannel.js +64 -0
- package/extension-api/dist/parts/OutputChannelHandle/OutputChannelHandle.d.ts +6 -0
- package/extension-api/dist/parts/OutputChannelHandle/OutputChannelHandle.js +1 -0
- package/extension-api/dist/parts/OutputChannelRegistrySnapshot/OutputChannelRegistrySnapshot.d.ts +4 -0
- package/extension-api/dist/parts/OutputChannelRegistrySnapshot/OutputChannelRegistrySnapshot.js +1 -0
- package/extension-api/dist/parts/QuickPick/QuickPick.js +2 -2
- package/extension-api/dist/parts/RegisteredOutputChannel/RegisteredOutputChannel.d.ts +3 -0
- package/extension-api/dist/parts/RegisteredOutputChannel/RegisteredOutputChannel.js +1 -0
- package/extension-api/dist/parts/StatusBarItemProviderRegistry/StatusBarItemProviderRegistry.js +3 -1
- package/extension-api/dist/parts/StatusBarItemProviderRegistrySnapshot/StatusBarItemProviderRegistrySnapshot.d.ts +3 -2
- package/extension-api/dist/parts/View/View.d.ts +43 -0
- package/extension-api/dist/parts/View/View.js +1 -0
- package/extension-api/dist/parts/ViewRegistry/ViewRegistry.d.ts +10 -0
- package/extension-api/dist/parts/ViewRegistry/ViewRegistry.js +138 -0
- package/extension-api/package.json +4 -2
- package/extension-api/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/dist/extension-api/parts/Rpc/Rpc.js +0 -14
- package/extension-api/dist/parts/Rpc/Rpc.d.ts +0 -3
- package/extension-api/dist/parts/Rpc/Rpc.js +0 -10
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import { ExtensionManagementWorker } from "@lvce-editor/rpc-registry";
|
|
1
2
|
import { listen } from "../ExtensionApiWorkerListen/ExtensionApiWorkerListen.js";
|
|
2
|
-
import
|
|
3
|
+
import { activateOutputChannels } from "../OutputChannel/OutputChannel.js";
|
|
3
4
|
let rpcPromise;
|
|
4
5
|
const activate = async () => {
|
|
5
6
|
if (!rpcPromise) {
|
|
6
7
|
rpcPromise = listen();
|
|
7
8
|
}
|
|
8
9
|
const rpc = await rpcPromise;
|
|
9
|
-
|
|
10
|
+
ExtensionManagementWorker.set(rpc);
|
|
11
|
+
activateOutputChannels();
|
|
10
12
|
};
|
|
11
13
|
export {
|
|
12
14
|
activate
|
|
@@ -30,7 +30,9 @@ const registerCommand = (command) => {
|
|
|
30
30
|
};
|
|
31
31
|
const getCommandRegistrySnapshot = () => {
|
|
32
32
|
return {
|
|
33
|
-
commands: Object.values(commands)
|
|
33
|
+
commands: Object.values(commands).map((command) => ({
|
|
34
|
+
id: command.id
|
|
35
|
+
}))
|
|
34
36
|
};
|
|
35
37
|
};
|
|
36
38
|
const executeCommand = async (id, ...args) => {
|
|
@@ -9,16 +9,40 @@ const getType = (value) => {
|
|
|
9
9
|
}
|
|
10
10
|
return typeof value;
|
|
11
11
|
};
|
|
12
|
+
const sanitizeCompletionItem = (item) => {
|
|
13
|
+
const sanitizedItem = {};
|
|
14
|
+
for (const [key, value] of Object.entries(item)) {
|
|
15
|
+
if (typeof value !== "function") {
|
|
16
|
+
sanitizedItem[key] = value;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const { kind: itemKind, type } = item;
|
|
20
|
+
let kind = 0;
|
|
21
|
+
if (typeof itemKind === "number") {
|
|
22
|
+
kind = itemKind;
|
|
23
|
+
} else if (typeof type === "number") {
|
|
24
|
+
kind = type;
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
...sanitizedItem,
|
|
28
|
+
flags: typeof item.flags === "number" ? item.flags : 0,
|
|
29
|
+
kind,
|
|
30
|
+
label: typeof item.label === "string" ? item.label : "",
|
|
31
|
+
matches: Array.isArray(item.matches) ? item.matches : []
|
|
32
|
+
};
|
|
33
|
+
};
|
|
12
34
|
const validateCompletionResult = (completion) => {
|
|
13
35
|
if (!Array.isArray(completion)) {
|
|
14
36
|
throw new ExtensionApiError(`invalid completion result: completion must be of type array but is ${getType(completion)}`);
|
|
15
37
|
}
|
|
38
|
+
const completionItems = [];
|
|
16
39
|
for (const item of completion) {
|
|
17
40
|
if (!item || typeof item !== "object" || Array.isArray(item)) {
|
|
18
41
|
throw new ExtensionApiError(`invalid completion result: expected completion item to be of type object but was of type ${getType(item)}`);
|
|
19
42
|
}
|
|
43
|
+
completionItems.push(sanitizeCompletionItem(item));
|
|
20
44
|
}
|
|
21
|
-
return
|
|
45
|
+
return completionItems;
|
|
22
46
|
};
|
|
23
47
|
const registry = createProviderRegistry({
|
|
24
48
|
mapProvider(provider) {
|
|
@@ -63,7 +87,10 @@ const executeResolveCompletionItemProvider = async (textDocument, offset, name,
|
|
|
63
87
|
const getCompletionProviders = registry.getProviders;
|
|
64
88
|
const getCompletionProviderRegistrySnapshot = () => {
|
|
65
89
|
return {
|
|
66
|
-
providers: registry.getProviders()
|
|
90
|
+
providers: registry.getProviders().map((provider) => ({
|
|
91
|
+
id: provider.id,
|
|
92
|
+
languageId: provider.languageId
|
|
93
|
+
}))
|
|
67
94
|
};
|
|
68
95
|
};
|
|
69
96
|
const resetCompletionProviderRegistry = registry.reset;
|
|
@@ -52,7 +52,10 @@ const executeDiagnosticProvider = async (textDocument, ...args) => {
|
|
|
52
52
|
const getDiagnosticProviders = registry.getProviders;
|
|
53
53
|
const getDiagnosticProviderRegistrySnapshot = () => {
|
|
54
54
|
return {
|
|
55
|
-
providers: registry.getProviders()
|
|
55
|
+
providers: registry.getProviders().map((provider) => ({
|
|
56
|
+
id: provider.id,
|
|
57
|
+
languageId: provider.languageId
|
|
58
|
+
}))
|
|
56
59
|
};
|
|
57
60
|
};
|
|
58
61
|
const resetDiagnosticProviderRegistry = registry.reset;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ExtensionManagementWorker } from "@lvce-editor/rpc-registry";
|
|
2
2
|
const executeCommand = async (id, ...args) => {
|
|
3
|
-
return
|
|
3
|
+
return ExtensionManagementWorker.invoke("Extensions.executeCommand", id, ...args);
|
|
4
4
|
};
|
|
5
5
|
export {
|
|
6
6
|
executeCommand
|
|
@@ -4,19 +4,35 @@ import { executeDiagnosticProvider, getDiagnosticProviderRegistrySnapshot } from
|
|
|
4
4
|
import { executeFormattingProvider, getFormattingProviderRegistrySnapshot } from "../Formatting/Formatting.js";
|
|
5
5
|
import { getStatusBarItems } from "../GetStatusBarItems/GetStatusBarItems.js";
|
|
6
6
|
import { executeHoverProvider, getHoverProviderRegistrySnapshot } from "../Hover/Hover.js";
|
|
7
|
+
import { getOutputChannelRegistrySnapshot } from "../OutputChannel/OutputChannel.js";
|
|
8
|
+
import {
|
|
9
|
+
createViewInstance,
|
|
10
|
+
dispatchViewEvent,
|
|
11
|
+
disposeViewInstance,
|
|
12
|
+
executeViewProvider,
|
|
13
|
+
getViewRegistrySnapshot,
|
|
14
|
+
saveViewInstanceState
|
|
15
|
+
} from "../ViewRegistry/ViewRegistry.js";
|
|
7
16
|
const commandMap = {
|
|
17
|
+
"ExtensionApi.createViewInstance": createViewInstance,
|
|
18
|
+
"ExtensionApi.dispatchViewEvent": dispatchViewEvent,
|
|
19
|
+
"ExtensionApi.disposeViewInstance": disposeViewInstance,
|
|
8
20
|
"ExtensionApi.executeCommand": executeCommand,
|
|
9
21
|
"ExtensionApi.executeCompletionProvider": executeCompletionProvider,
|
|
10
22
|
"ExtensionApi.executeDiagnosticProvider": executeDiagnosticProvider,
|
|
11
23
|
"ExtensionApi.executeFormattingProvider": executeFormattingProvider,
|
|
12
24
|
"ExtensionApi.executeHoverProvider": executeHoverProvider,
|
|
13
25
|
"ExtensionApi.executeResolveCompletionItemProvider": executeResolveCompletionItemProvider,
|
|
26
|
+
"ExtensionApi.executeViewProvider": executeViewProvider,
|
|
14
27
|
"ExtensionApi.getCommandRegistrySnapshot": getCommandRegistrySnapshot,
|
|
15
28
|
"ExtensionApi.getCompletionProviderRegistrySnapshot": getCompletionProviderRegistrySnapshot,
|
|
16
29
|
"ExtensionApi.getDiagnosticProviderRegistrySnapshot": getDiagnosticProviderRegistrySnapshot,
|
|
17
30
|
"ExtensionApi.getFormattingProviderRegistrySnapshot": getFormattingProviderRegistrySnapshot,
|
|
18
31
|
"ExtensionApi.getHoverProviderRegistrySnapshot": getHoverProviderRegistrySnapshot,
|
|
19
|
-
"ExtensionApi.
|
|
32
|
+
"ExtensionApi.getOutputChannelRegistrySnapshot": getOutputChannelRegistrySnapshot,
|
|
33
|
+
"ExtensionApi.getStatusBarItems": getStatusBarItems,
|
|
34
|
+
"ExtensionApi.getViewRegistrySnapshot": getViewRegistrySnapshot,
|
|
35
|
+
"ExtensionApi.saveViewInstanceState": saveViewInstanceState
|
|
20
36
|
};
|
|
21
37
|
export {
|
|
22
38
|
commandMap
|
|
@@ -28,7 +28,10 @@ const executeFormattingProvider = async (textDocument, ...args) => {
|
|
|
28
28
|
const getFormattingProviders = registry.getProviders;
|
|
29
29
|
const getFormattingProviderRegistrySnapshot = () => {
|
|
30
30
|
return {
|
|
31
|
-
providers: registry.getProviders()
|
|
31
|
+
providers: registry.getProviders().map((provider) => ({
|
|
32
|
+
id: provider.id,
|
|
33
|
+
languageId: provider.languageId
|
|
34
|
+
}))
|
|
32
35
|
};
|
|
33
36
|
};
|
|
34
37
|
const resetFormattingProviderRegistry = registry.reset;
|
|
@@ -50,7 +50,10 @@ const executeHoverProvider = async (textDocument, offset, ...args) => {
|
|
|
50
50
|
const getHoverProviders = registry.getProviders;
|
|
51
51
|
const getHoverProviderRegistrySnapshot = () => {
|
|
52
52
|
return {
|
|
53
|
-
providers: registry.getProviders()
|
|
53
|
+
providers: registry.getProviders().map((provider) => ({
|
|
54
|
+
id: provider.id,
|
|
55
|
+
languageId: provider.languageId
|
|
56
|
+
}))
|
|
54
57
|
};
|
|
55
58
|
};
|
|
56
59
|
const resetHoverProviderRegistry = registry.reset;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ExtensionManagementWorker } from "@lvce-editor/rpc-registry";
|
|
2
2
|
const notifyStatusBarChange = async (id) => {
|
|
3
|
-
await
|
|
3
|
+
await ExtensionManagementWorker.invoke("StatusBar.handleChange", id);
|
|
4
4
|
};
|
|
5
5
|
export {
|
|
6
6
|
notifyStatusBarChange
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ExtensionManagementWorker } from "@lvce-editor/rpc-registry";
|
|
2
|
+
import { ExtensionApiError } from "../ExtensionApiError/ExtensionApiError.js";
|
|
3
|
+
const outputChannels = /* @__PURE__ */ Object.create(null);
|
|
4
|
+
let isActivated = false;
|
|
5
|
+
const RE_DASH_CASE = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
6
|
+
const assertOutputChannelId = (id) => {
|
|
7
|
+
if (typeof id !== "string" || id.length === 0) {
|
|
8
|
+
throw new ExtensionApiError("output channel id is required");
|
|
9
|
+
}
|
|
10
|
+
if (!RE_DASH_CASE.test(id)) {
|
|
11
|
+
throw new ExtensionApiError(`output channel id ${id} must be dash-case`);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const assertCanWrite = (id) => {
|
|
15
|
+
if (!isActivated) {
|
|
16
|
+
throw new ExtensionApiError(`output channel ${id} cannot be written before activate`);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
class ExtensionOutputChannel {
|
|
20
|
+
#id;
|
|
21
|
+
constructor(id) {
|
|
22
|
+
this.#id = id;
|
|
23
|
+
}
|
|
24
|
+
async append(text) {
|
|
25
|
+
assertCanWrite(this.#id);
|
|
26
|
+
await ExtensionManagementWorker.invoke("ExtensionApi.appendOutputChannel", this.#id, text);
|
|
27
|
+
}
|
|
28
|
+
async appendLine(text) {
|
|
29
|
+
assertCanWrite(this.#id);
|
|
30
|
+
await ExtensionManagementWorker.invoke("ExtensionApi.appendOutputChannel", this.#id, `${text}
|
|
31
|
+
`);
|
|
32
|
+
}
|
|
33
|
+
async clear() {
|
|
34
|
+
assertCanWrite(this.#id);
|
|
35
|
+
await ExtensionManagementWorker.invoke("ExtensionApi.clearOutputChannel", this.#id);
|
|
36
|
+
}
|
|
37
|
+
async replace(text) {
|
|
38
|
+
assertCanWrite(this.#id);
|
|
39
|
+
await ExtensionManagementWorker.invoke("ExtensionApi.replaceOutputChannel", this.#id, text);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const activateOutputChannels = () => {
|
|
43
|
+
isActivated = true;
|
|
44
|
+
};
|
|
45
|
+
const createOutputChannel = (id) => {
|
|
46
|
+
assertOutputChannelId(id);
|
|
47
|
+
if (id in outputChannels) {
|
|
48
|
+
throw new ExtensionApiError(`output channel ${id} is already created`);
|
|
49
|
+
}
|
|
50
|
+
outputChannels[id] = {
|
|
51
|
+
id
|
|
52
|
+
};
|
|
53
|
+
return new ExtensionOutputChannel(id);
|
|
54
|
+
};
|
|
55
|
+
const getOutputChannelRegistrySnapshot = () => {
|
|
56
|
+
return {
|
|
57
|
+
outputChannels: Object.values(outputChannels)
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
const resetOutputChannelRegistry = () => {
|
|
61
|
+
for (const id of Object.keys(outputChannels)) {
|
|
62
|
+
delete outputChannels[id];
|
|
63
|
+
}
|
|
64
|
+
isActivated = false;
|
|
65
|
+
};
|
|
66
|
+
export {
|
|
67
|
+
activateOutputChannels,
|
|
68
|
+
createOutputChannel,
|
|
69
|
+
getOutputChannelRegistrySnapshot,
|
|
70
|
+
resetOutputChannelRegistry
|
|
71
|
+
};
|
|
File without changes
|
package/dist/extension-api/parts/OutputChannelRegistrySnapshot/OutputChannelRegistrySnapshot.js
ADDED
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ExtensionManagementWorker } from "@lvce-editor/rpc-registry";
|
|
2
2
|
const showQuickPick = async (options) => {
|
|
3
|
-
return
|
|
3
|
+
return ExtensionManagementWorker.invoke("ExtensionHostQuickPick.showQuickPick", options);
|
|
4
4
|
};
|
|
5
5
|
export {
|
|
6
6
|
showQuickPick
|
|
File without changes
|
package/dist/extension-api/parts/StatusBarItemProviderRegistry/StatusBarItemProviderRegistry.js
CHANGED
|
@@ -38,7 +38,9 @@ const getStatusBarItems = () => {
|
|
|
38
38
|
};
|
|
39
39
|
const getStatusBarItemProviderRegistrySnapshot = () => {
|
|
40
40
|
return {
|
|
41
|
-
providers: registry.getProviders()
|
|
41
|
+
providers: registry.getProviders().map((provider) => ({
|
|
42
|
+
id: provider.id
|
|
43
|
+
}))
|
|
42
44
|
};
|
|
43
45
|
};
|
|
44
46
|
const resetStatusBarItemProviderRegistry = registry.reset;
|
|
File without changes
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { diffTree } from "@lvce-editor/virtual-dom-worker";
|
|
2
|
+
import { ExtensionApiError } from "../ExtensionApiError/ExtensionApiError.js";
|
|
3
|
+
const views = /* @__PURE__ */ Object.create(null);
|
|
4
|
+
const instances = /* @__PURE__ */ Object.create(null);
|
|
5
|
+
const renderedDoms = /* @__PURE__ */ Object.create(null);
|
|
6
|
+
const assertView = (view) => {
|
|
7
|
+
if (!view) {
|
|
8
|
+
throw new ExtensionApiError("view is not defined");
|
|
9
|
+
}
|
|
10
|
+
if (typeof view.id !== "string" || view.id.length === 0) {
|
|
11
|
+
throw new ExtensionApiError("view is missing id");
|
|
12
|
+
}
|
|
13
|
+
if (typeof view.create !== "function") {
|
|
14
|
+
throw new ExtensionApiError(`view ${view.id} is missing create function`);
|
|
15
|
+
}
|
|
16
|
+
if (view.id in views) {
|
|
17
|
+
throw new ExtensionApiError(`view ${view.id} is already registered`);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const toRegisteredView = (view) => {
|
|
21
|
+
const registeredView = {
|
|
22
|
+
icon: view.icon,
|
|
23
|
+
id: view.id,
|
|
24
|
+
title: view.title
|
|
25
|
+
};
|
|
26
|
+
if (view.kind) {
|
|
27
|
+
return {
|
|
28
|
+
...registeredView,
|
|
29
|
+
kind: view.kind
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return registeredView;
|
|
33
|
+
};
|
|
34
|
+
const registerView = (view) => {
|
|
35
|
+
assertView(view);
|
|
36
|
+
views[view.id] = view;
|
|
37
|
+
return {
|
|
38
|
+
dispose() {
|
|
39
|
+
delete views[view.id];
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
const executeViewProvider = (id) => {
|
|
44
|
+
const view = views[id];
|
|
45
|
+
if (!view) {
|
|
46
|
+
throw new ExtensionApiError(`view ${id} not found`);
|
|
47
|
+
}
|
|
48
|
+
return view.create();
|
|
49
|
+
};
|
|
50
|
+
const assertVirtualDomViewInstance = (id, instance) => {
|
|
51
|
+
if (!instance || typeof instance !== "object") {
|
|
52
|
+
throw new ExtensionApiError(`view ${id} did not return a view instance`);
|
|
53
|
+
}
|
|
54
|
+
if (typeof instance.render !== "function") {
|
|
55
|
+
throw new ExtensionApiError(`view ${id} instance is missing render function`);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const getVirtualDomInstance = (uid) => {
|
|
59
|
+
const instance = instances[uid];
|
|
60
|
+
if (!instance) {
|
|
61
|
+
throw new ExtensionApiError(`view instance ${uid} not found`);
|
|
62
|
+
}
|
|
63
|
+
return instance;
|
|
64
|
+
};
|
|
65
|
+
const renderDom = async (instance) => {
|
|
66
|
+
const dom = await instance.render();
|
|
67
|
+
if (!Array.isArray(dom)) {
|
|
68
|
+
throw new ExtensionApiError("view render result must be an array");
|
|
69
|
+
}
|
|
70
|
+
return dom;
|
|
71
|
+
};
|
|
72
|
+
const createViewInstance = async (viewId, uid, context) => {
|
|
73
|
+
const view = views[viewId];
|
|
74
|
+
if (!view) {
|
|
75
|
+
throw new ExtensionApiError(`view ${viewId} not found`);
|
|
76
|
+
}
|
|
77
|
+
if (view.kind !== "virtualDom") {
|
|
78
|
+
throw new ExtensionApiError(`view ${viewId} is not a virtual dom view`);
|
|
79
|
+
}
|
|
80
|
+
const instance = await view.create({
|
|
81
|
+
...context,
|
|
82
|
+
uid,
|
|
83
|
+
viewId
|
|
84
|
+
});
|
|
85
|
+
assertVirtualDomViewInstance(viewId, instance);
|
|
86
|
+
instances[uid] = instance;
|
|
87
|
+
const dom = await renderDom(instance);
|
|
88
|
+
renderedDoms[uid] = dom;
|
|
89
|
+
return {
|
|
90
|
+
dom,
|
|
91
|
+
type: "setDom"
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
const dispatchViewEvent = async (uid, event) => {
|
|
95
|
+
const instance = getVirtualDomInstance(uid);
|
|
96
|
+
if (typeof instance.handleEvent === "function") {
|
|
97
|
+
await instance.handleEvent(event);
|
|
98
|
+
}
|
|
99
|
+
const oldDom = renderedDoms[uid] || [];
|
|
100
|
+
const newDom = await renderDom(instance);
|
|
101
|
+
renderedDoms[uid] = newDom;
|
|
102
|
+
const patches = diffTree(oldDom, newDom);
|
|
103
|
+
return {
|
|
104
|
+
patches,
|
|
105
|
+
type: "setPatches"
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
const disposeViewInstance = async (uid) => {
|
|
109
|
+
const instance = instances[uid];
|
|
110
|
+
if (instance && typeof instance.dispose === "function") {
|
|
111
|
+
await instance.dispose();
|
|
112
|
+
}
|
|
113
|
+
delete instances[uid];
|
|
114
|
+
delete renderedDoms[uid];
|
|
115
|
+
};
|
|
116
|
+
const saveViewInstanceState = async (uid) => {
|
|
117
|
+
const instance = getVirtualDomInstance(uid);
|
|
118
|
+
if (typeof instance.saveState !== "function") {
|
|
119
|
+
return void 0;
|
|
120
|
+
}
|
|
121
|
+
return instance.saveState();
|
|
122
|
+
};
|
|
123
|
+
const getViewRegistrySnapshot = () => {
|
|
124
|
+
return {
|
|
125
|
+
views: Object.values(views).map(toRegisteredView)
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
const resetViewRegistry = () => {
|
|
129
|
+
for (const id of Object.keys(views)) {
|
|
130
|
+
delete views[id];
|
|
131
|
+
}
|
|
132
|
+
for (const uid of Object.keys(instances)) {
|
|
133
|
+
delete instances[Number(uid)];
|
|
134
|
+
}
|
|
135
|
+
for (const uid of Object.keys(renderedDoms)) {
|
|
136
|
+
delete renderedDoms[Number(uid)];
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
export {
|
|
140
|
+
createViewInstance,
|
|
141
|
+
dispatchViewEvent,
|
|
142
|
+
disposeViewInstance,
|
|
143
|
+
executeViewProvider,
|
|
144
|
+
getViewRegistrySnapshot,
|
|
145
|
+
registerView,
|
|
146
|
+
resetViewRegistry,
|
|
147
|
+
saveViewInstanceState
|
|
148
|
+
};
|