@lvce-editor/preview-sandbox-worker 1.0.0 → 1.2.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.
@@ -96,12 +96,6 @@ const array = value => {
96
96
  throw new AssertionError('expected value to be of type array');
97
97
  }
98
98
  };
99
- const string = value => {
100
- const type = getType(value);
101
- if (type !== String$1) {
102
- throw new AssertionError('expected value to be of type string');
103
- }
104
- };
105
99
 
106
100
  const isMessagePort = value => {
107
101
  return value && value instanceof MessagePort;
@@ -514,7 +508,7 @@ const IpcParentWithMessagePort$1 = {
514
508
 
515
509
  const Two$1 = '2.0';
516
510
  const callbacks$1 = Object.create(null);
517
- const get$3 = id => {
511
+ const get$2 = id => {
518
512
  return callbacks$1[id];
519
513
  };
520
514
  const remove$1 = id => {
@@ -663,7 +657,7 @@ const warn = (...args) => {
663
657
  console.warn(...args);
664
658
  };
665
659
  const resolve = (id, response) => {
666
- const fn = get$3(id);
660
+ const fn = get$2(id);
667
661
  if (!fn) {
668
662
  console.log(response);
669
663
  warn(`callback ${id} may already be disposed`);
@@ -713,7 +707,7 @@ const getErrorProperty = (error, prettyError) => {
713
707
  }
714
708
  };
715
709
  };
716
- const create$1$1 = (id, error) => {
710
+ const create$1 = (id, error) => {
717
711
  return {
718
712
  jsonrpc: Two$1,
719
713
  id,
@@ -724,9 +718,9 @@ const getErrorResponse = (id, error, preparePrettyError, logError) => {
724
718
  const prettyError = preparePrettyError(error);
725
719
  logError(error, prettyError);
726
720
  const errorProperty = getErrorProperty(error, prettyError);
727
- return create$1$1(id, errorProperty);
721
+ return create$1(id, errorProperty);
728
722
  };
729
- const create$4 = (message, result) => {
723
+ const create$3 = (message, result) => {
730
724
  return {
731
725
  jsonrpc: Two$1,
732
726
  id: message.id,
@@ -735,7 +729,7 @@ const create$4 = (message, result) => {
735
729
  };
736
730
  const getSuccessResponse = (message, result) => {
737
731
  const resultProperty = result ?? null;
738
- return create$4(message, resultProperty);
732
+ return create$3(message, resultProperty);
739
733
  };
740
734
  const getErrorResponseSimple = (id, error) => {
741
735
  return {
@@ -963,53 +957,6 @@ const listen$1 = async (module, options) => {
963
957
  const ipc = module.wrap(rawIpc);
964
958
  return ipc;
965
959
  };
966
-
967
- /* eslint-disable @typescript-eslint/no-misused-promises */
968
-
969
- const createSharedLazyRpc = factory => {
970
- let rpcPromise;
971
- const getOrCreate = () => {
972
- if (!rpcPromise) {
973
- rpcPromise = factory();
974
- }
975
- return rpcPromise;
976
- };
977
- return {
978
- async dispose() {
979
- const rpc = await getOrCreate();
980
- await rpc.dispose();
981
- },
982
- async invoke(method, ...params) {
983
- const rpc = await getOrCreate();
984
- return rpc.invoke(method, ...params);
985
- },
986
- async invokeAndTransfer(method, ...params) {
987
- const rpc = await getOrCreate();
988
- return rpc.invokeAndTransfer(method, ...params);
989
- },
990
- async send(method, ...params) {
991
- const rpc = await getOrCreate();
992
- rpc.send(method, ...params);
993
- }
994
- };
995
- };
996
- const create$j = async ({
997
- commandMap,
998
- isMessagePortOpen,
999
- send
1000
- }) => {
1001
- return createSharedLazyRpc(() => {
1002
- return create$3({
1003
- commandMap,
1004
- isMessagePortOpen,
1005
- send
1006
- });
1007
- });
1008
- };
1009
- const LazyTransferMessagePortRpcParent = {
1010
- __proto__: null,
1011
- create: create$j
1012
- };
1013
960
  const create$5 = async ({
1014
961
  commandMap,
1015
962
  isMessagePortOpen = true,
@@ -1027,23 +974,11 @@ const create$5 = async ({
1027
974
  messagePort.start();
1028
975
  return rpc;
1029
976
  };
1030
- const create$3 = async ({
1031
- commandMap,
1032
- isMessagePortOpen,
1033
- send
1034
- }) => {
1035
- const {
1036
- port1,
1037
- port2
1038
- } = new MessageChannel();
1039
- await send(port1);
1040
- return create$5({
1041
- commandMap,
1042
- isMessagePortOpen,
1043
- messagePort: port2
1044
- });
977
+ const PlainMessagePortRpc = {
978
+ __proto__: null,
979
+ create: create$5
1045
980
  };
1046
- const create$2$1 = async ({
981
+ const create$2 = async ({
1047
982
  commandMap
1048
983
  }) => {
1049
984
  // TODO create a commandMap per rpc instance
@@ -1055,7 +990,7 @@ const create$2$1 = async ({
1055
990
  };
1056
991
  const WebWorkerRpcClient = {
1057
992
  __proto__: null,
1058
- create: create$2$1
993
+ create: create$2
1059
994
  };
1060
995
  const createMockRpc = ({
1061
996
  commandMap
@@ -1085,7 +1020,7 @@ const Span$1 = 8;
1085
1020
  const Table$1 = 9;
1086
1021
  const TBody$1 = 10;
1087
1022
  const Td$1 = 11;
1088
- const Text$2 = 12;
1023
+ const Text = 12;
1089
1024
  const Th$1 = 13;
1090
1025
  const THead$1 = 14;
1091
1026
  const Tr$1 = 15;
@@ -1132,17 +1067,13 @@ const Html = 73;
1132
1067
  const Canvas$1 = 77;
1133
1068
  const Reference = 100;
1134
1069
 
1135
- const EditorWorker = 99;
1136
1070
  const RendererWorker = 1;
1137
1071
 
1138
- const SetDom2 = 'Viewlet.setDom2';
1139
- const SetPatches = 'Viewlet.setPatches';
1140
-
1141
1072
  const rpcs = Object.create(null);
1142
- const set$5 = (id, rpc) => {
1073
+ const set$3 = (id, rpc) => {
1143
1074
  rpcs[id] = rpc;
1144
1075
  };
1145
- const get$2 = id => {
1076
+ const get$1 = id => {
1146
1077
  return rpcs[id];
1147
1078
  };
1148
1079
  const remove = id => {
@@ -1150,21 +1081,21 @@ const remove = id => {
1150
1081
  };
1151
1082
 
1152
1083
  /* eslint-disable @typescript-eslint/explicit-function-return-type */
1153
- const create$2 = rpcId => {
1084
+ const create = rpcId => {
1154
1085
  return {
1155
1086
  async dispose() {
1156
- const rpc = get$2(rpcId);
1087
+ const rpc = get$1(rpcId);
1157
1088
  await rpc.dispose();
1158
1089
  },
1159
1090
  // @ts-ignore
1160
1091
  invoke(method, ...params) {
1161
- const rpc = get$2(rpcId);
1092
+ const rpc = get$1(rpcId);
1162
1093
  // @ts-ignore
1163
1094
  return rpc.invoke(method, ...params);
1164
1095
  },
1165
1096
  // @ts-ignore
1166
1097
  invokeAndTransfer(method, ...params) {
1167
- const rpc = get$2(rpcId);
1098
+ const rpc = get$1(rpcId);
1168
1099
  // @ts-ignore
1169
1100
  return rpc.invokeAndTransfer(method, ...params);
1170
1101
  },
@@ -1172,7 +1103,7 @@ const create$2 = rpcId => {
1172
1103
  const mockRpc = createMockRpc({
1173
1104
  commandMap
1174
1105
  });
1175
- set$5(rpcId, mockRpc);
1106
+ set$3(rpcId, mockRpc);
1176
1107
  // @ts-ignore
1177
1108
  mockRpc[Symbol.dispose] = () => {
1178
1109
  remove(rpcId);
@@ -1181,205 +1112,20 @@ const create$2 = rpcId => {
1181
1112
  return mockRpc;
1182
1113
  },
1183
1114
  set(rpc) {
1184
- set$5(rpcId, rpc);
1115
+ set$3(rpcId, rpc);
1185
1116
  }
1186
1117
  };
1187
1118
  };
1188
1119
 
1189
- const {
1190
- invoke: invoke$1,
1191
- set: set$4
1192
- } = create$2(EditorWorker);
1193
-
1194
1120
  const {
1195
1121
  invoke,
1196
- invokeAndTransfer,
1197
- set: set$3
1198
- } = create$2(RendererWorker);
1199
- const sendMessagePortToEditorWorker = async (port, rpcId) => {
1200
- const command = 'HandleMessagePort.handleMessagePort';
1201
- await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToEditorWorker', port, command, rpcId);
1202
- };
1203
- const readFile = async uri => {
1204
- return invoke('FileSystem.readFile', uri);
1205
- };
1122
+ set: set$2
1123
+ } = create(RendererWorker);
1206
1124
 
1207
- const toCommandId = key => {
1208
- const dotIndex = key.indexOf('.');
1209
- return key.slice(dotIndex + 1);
1210
- };
1211
- const create$1 = () => {
1212
- const states = Object.create(null);
1213
- const commandMapRef = {};
1214
- return {
1215
- clear() {
1216
- for (const key of Object.keys(states)) {
1217
- delete states[key];
1218
- }
1219
- },
1220
- diff(uid, modules, numbers) {
1221
- const {
1222
- newState,
1223
- oldState
1224
- } = states[uid];
1225
- const diffResult = [];
1226
- for (let i = 0; i < modules.length; i++) {
1227
- const fn = modules[i];
1228
- if (!fn(oldState, newState)) {
1229
- diffResult.push(numbers[i]);
1230
- }
1231
- }
1232
- return diffResult;
1233
- },
1234
- dispose(uid) {
1235
- delete states[uid];
1236
- },
1237
- get(uid) {
1238
- return states[uid];
1239
- },
1240
- getCommandIds() {
1241
- const keys = Object.keys(commandMapRef);
1242
- const ids = keys.map(toCommandId);
1243
- return ids;
1244
- },
1245
- getKeys() {
1246
- return Object.keys(states).map(key => {
1247
- return Number.parseInt(key);
1248
- });
1249
- },
1250
- registerCommands(commandMap) {
1251
- Object.assign(commandMapRef, commandMap);
1252
- },
1253
- set(uid, oldState, newState) {
1254
- states[uid] = {
1255
- newState,
1256
- oldState
1257
- };
1258
- },
1259
- wrapCommand(fn) {
1260
- const wrapped = async (uid, ...args) => {
1261
- const {
1262
- newState,
1263
- oldState
1264
- } = states[uid];
1265
- const newerState = await fn(newState, ...args);
1266
- if (oldState === newerState || newState === newerState) {
1267
- return;
1268
- }
1269
- const latestOld = states[uid];
1270
- const latestNew = {
1271
- ...latestOld.newState,
1272
- ...newerState
1273
- };
1274
- states[uid] = {
1275
- newState: latestNew,
1276
- oldState: latestOld.oldState
1277
- };
1278
- };
1279
- return wrapped;
1280
- },
1281
- wrapGetter(fn) {
1282
- const wrapped = (uid, ...args) => {
1283
- const {
1284
- newState
1285
- } = states[uid];
1286
- return fn(newState, ...args);
1287
- };
1288
- return wrapped;
1289
- }
1290
- };
1291
- };
1292
1125
  const terminate = () => {
1293
1126
  globalThis.close();
1294
1127
  };
1295
1128
 
1296
- const createSandboxRpc = async () => {
1297
- const sandboxRpc = await LazyTransferMessagePortRpcParent.create({
1298
- commandMap: {},
1299
- send: async port => await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToPreviewSandBoxWorker', port, 'SandBox.handleMessagePort')
1300
- });
1301
- return sandboxRpc;
1302
- };
1303
-
1304
- const {
1305
- get: get$1,
1306
- getCommandIds,
1307
- getKeys: getKeys$1,
1308
- registerCommands,
1309
- set: set$2,
1310
- wrapCommand,
1311
- wrapGetter
1312
- } = create$1();
1313
-
1314
- const create = async (uid, uri, x, y, width, height, platform, assetDir) => {
1315
- const sandboxRpc = await createSandboxRpc();
1316
- const state = {
1317
- assetDir,
1318
- content: '',
1319
- css: [],
1320
- errorCount: 0,
1321
- errorMessage: '',
1322
- height,
1323
- initial: true,
1324
- parsedDom: [],
1325
- parsedNodesChildNodeCount: 0,
1326
- platform,
1327
- sandboxRpc,
1328
- scripts: [],
1329
- uid,
1330
- uri,
1331
- useSandboxWorker: false,
1332
- warningCount: 0,
1333
- width,
1334
- x,
1335
- y
1336
- };
1337
- set$2(uid, state, state);
1338
- };
1339
-
1340
- const iEqual = (oldState, newState) => {
1341
- if (oldState.css.length !== newState.css.length) {
1342
- return false;
1343
- }
1344
- for (let i = 0; i < oldState.css.length; i++) {
1345
- if (oldState.css[i] !== newState.css[i]) {
1346
- return false;
1347
- }
1348
- }
1349
- return true;
1350
- };
1351
-
1352
- const isEqual = (oldState, newState) => {
1353
- return oldState.warningCount === newState.warningCount && oldState.initial === newState.initial && oldState.content === newState.content && oldState.parsedDom === newState.parsedDom && oldState.parsedNodesChildNodeCount === newState.parsedNodesChildNodeCount && oldState.css === newState.css && oldState.scripts === newState.scripts;
1354
- };
1355
-
1356
- const RenderItems = 4;
1357
- const RenderCss = 10;
1358
- const RenderIncremental = 11;
1359
-
1360
- const modules = [isEqual, iEqual];
1361
- const numbers = [RenderIncremental, RenderCss];
1362
-
1363
- const diff = (oldState, newState) => {
1364
- const diffResult = [];
1365
- for (let i = 0; i < modules.length; i++) {
1366
- const fn = modules[i];
1367
- if (!fn(oldState, newState)) {
1368
- diffResult.push(numbers[i]);
1369
- }
1370
- }
1371
- return diffResult;
1372
- };
1373
-
1374
- const diff2 = uid => {
1375
- const {
1376
- newState,
1377
- oldState
1378
- } = get$1(uid);
1379
- const result = diff(oldState, newState);
1380
- return result;
1381
- };
1382
-
1383
1129
  /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
1384
1130
  const callBacks = Object.create(null);
1385
1131
  let id = 0;
@@ -1405,6 +1151,7 @@ const executeCallback = (id, ...args) => {
1405
1151
  }
1406
1152
  };
1407
1153
  const getOffscreenCanvas = async (width, height) => {
1154
+ // TODO ask preview worker
1408
1155
  const {
1409
1156
  id,
1410
1157
  promise
@@ -1417,61 +1164,6 @@ const getOffscreenCanvas = async (width, height) => {
1417
1164
  };
1418
1165
  };
1419
1166
 
1420
- const dispatchEvent = (element, event) => {
1421
- element.dispatchEvent(event);
1422
-
1423
- // Also invoke direct on* handler if set (e.g. element.onclick = function(){})
1424
- const handlerName = `on${event.type}`;
1425
- const handler = element[handlerName];
1426
- if (typeof handler === 'function') {
1427
- handler.call(element, event);
1428
- } else if (handler === null || handler === undefined) {
1429
- if (!element.getAttribute) {
1430
- return;
1431
- }
1432
- // Check if there's an inline HTML attribute that wasn't converted to a property
1433
- const attrValue = element.getAttribute(handlerName);
1434
- if (attrValue && typeof attrValue === 'string' && element.ownerDocument && element.ownerDocument.defaultView) {
1435
- const window = element.ownerDocument.defaultView;
1436
- // Handle inline event handlers like onclick="someFunction(2)"
1437
- // Evaluate in the context of the window so functions are in scope
1438
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
1439
- const fn = new Function('event', `with(this) { ${attrValue} }`);
1440
- fn.call(window, event);
1441
- }
1442
- }
1443
- };
1444
-
1445
- const dispatchClickEvent = (element, window) => {
1446
- const clickEvent = new window.MouseEvent('click', {
1447
- bubbles: true
1448
- });
1449
- dispatchEvent(element, clickEvent);
1450
- };
1451
-
1452
- const getParsedNodesChildNodeCount = parsedDom => {
1453
- array(parsedDom);
1454
- const rootCountFromParse = parsedDom.rootChildCount;
1455
- if (typeof rootCountFromParse === 'number') {
1456
- return rootCountFromParse;
1457
- }
1458
- let rootChildCount = 0;
1459
- let i = 0;
1460
- while (i < parsedDom.length) {
1461
- rootChildCount++;
1462
-
1463
- // skip the entire subtree of the current node
1464
- let toSkip = parsedDom[i].childCount;
1465
- i++;
1466
- while (toSkip > 0 && i < parsedDom.length) {
1467
- toSkip -= 1;
1468
- toSkip += parsedDom[i].childCount;
1469
- i++;
1470
- }
1471
- }
1472
- return rootChildCount;
1473
- };
1474
-
1475
1167
  /* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
1476
1168
 
1477
1169
  const states$1 = new Map();
@@ -1486,298 +1178,10 @@ const text = data => {
1486
1178
  return {
1487
1179
  childCount: 0,
1488
1180
  text: data,
1489
- type: Text$2
1181
+ type: Text
1490
1182
  };
1491
1183
  };
1492
1184
 
1493
- const SetText = 1;
1494
- const Replace = 2;
1495
- const SetAttribute = 3;
1496
- const RemoveAttribute = 4;
1497
- const Add = 6;
1498
- const NavigateChild = 7;
1499
- const NavigateParent = 8;
1500
- const RemoveChild = 9;
1501
- const NavigateSibling = 10;
1502
- const SetReferenceNodeUid = 11;
1503
-
1504
- const isKey = key => {
1505
- return key !== 'type' && key !== 'childCount';
1506
- };
1507
-
1508
- const getKeys = node => {
1509
- const keys = Object.keys(node).filter(isKey);
1510
- return keys;
1511
- };
1512
-
1513
- const arrayToTree = nodes => {
1514
- const result = [];
1515
- let i = 0;
1516
- while (i < nodes.length) {
1517
- const node = nodes[i];
1518
- const {
1519
- children,
1520
- nodesConsumed
1521
- } = getChildrenWithCount(nodes, i + 1, node.childCount || 0);
1522
- result.push({
1523
- node,
1524
- children
1525
- });
1526
- i += 1 + nodesConsumed;
1527
- }
1528
- return result;
1529
- };
1530
- const getChildrenWithCount = (nodes, startIndex, childCount) => {
1531
- if (childCount === 0) {
1532
- return {
1533
- children: [],
1534
- nodesConsumed: 0
1535
- };
1536
- }
1537
- const children = [];
1538
- let i = startIndex;
1539
- let remaining = childCount;
1540
- let totalConsumed = 0;
1541
- while (remaining > 0 && i < nodes.length) {
1542
- const node = nodes[i];
1543
- const nodeChildCount = node.childCount || 0;
1544
- const {
1545
- children: nodeChildren,
1546
- nodesConsumed
1547
- } = getChildrenWithCount(nodes, i + 1, nodeChildCount);
1548
- children.push({
1549
- node,
1550
- children: nodeChildren
1551
- });
1552
- const nodeSize = 1 + nodesConsumed;
1553
- i += nodeSize;
1554
- totalConsumed += nodeSize;
1555
- remaining--;
1556
- }
1557
- return {
1558
- children,
1559
- nodesConsumed: totalConsumed
1560
- };
1561
- };
1562
-
1563
- const compareNodes = (oldNode, newNode) => {
1564
- const patches = [];
1565
- // Check if node type changed - return null to signal incompatible nodes
1566
- // (caller should handle this with a Replace operation)
1567
- if (oldNode.type !== newNode.type) {
1568
- return null;
1569
- }
1570
- // Handle reference nodes - special handling for uid changes
1571
- if (oldNode.type === Reference) {
1572
- if (oldNode.uid !== newNode.uid) {
1573
- patches.push({
1574
- type: SetReferenceNodeUid,
1575
- uid: newNode.uid
1576
- });
1577
- }
1578
- return patches;
1579
- }
1580
- // Handle text nodes
1581
- if (oldNode.type === Text$2 && newNode.type === Text$2) {
1582
- if (oldNode.text !== newNode.text) {
1583
- patches.push({
1584
- type: SetText,
1585
- value: newNode.text
1586
- });
1587
- }
1588
- return patches;
1589
- }
1590
- // Compare attributes
1591
- const oldKeys = getKeys(oldNode);
1592
- const newKeys = getKeys(newNode);
1593
- // Check for attribute changes
1594
- for (const key of newKeys) {
1595
- if (oldNode[key] !== newNode[key]) {
1596
- patches.push({
1597
- type: SetAttribute,
1598
- key,
1599
- value: newNode[key]
1600
- });
1601
- }
1602
- }
1603
- // Check for removed attributes
1604
- for (const key of oldKeys) {
1605
- if (!(key in newNode)) {
1606
- patches.push({
1607
- type: RemoveAttribute,
1608
- key
1609
- });
1610
- }
1611
- }
1612
- return patches;
1613
- };
1614
-
1615
- const treeToArray = node => {
1616
- const result = [node.node];
1617
- for (const child of node.children) {
1618
- result.push(...treeToArray(child));
1619
- }
1620
- return result;
1621
- };
1622
-
1623
- const diffChildren = (oldChildren, newChildren, patches) => {
1624
- const maxLength = Math.max(oldChildren.length, newChildren.length);
1625
- // Track where we are: -1 means at parent, >= 0 means at child index
1626
- let currentChildIndex = -1;
1627
- // Collect indices of children to remove (we'll add these patches at the end in reverse order)
1628
- const indicesToRemove = [];
1629
- for (let i = 0; i < maxLength; i++) {
1630
- const oldNode = oldChildren[i];
1631
- const newNode = newChildren[i];
1632
- if (!oldNode && !newNode) {
1633
- continue;
1634
- }
1635
- if (!oldNode) {
1636
- // Add new node - we should be at the parent
1637
- if (currentChildIndex >= 0) {
1638
- // Navigate back to parent
1639
- patches.push({
1640
- type: NavigateParent
1641
- });
1642
- currentChildIndex = -1;
1643
- }
1644
- // Flatten the entire subtree so renderInternal can handle it
1645
- const flatNodes = treeToArray(newNode);
1646
- patches.push({
1647
- type: Add,
1648
- nodes: flatNodes
1649
- });
1650
- } else if (newNode) {
1651
- // Compare nodes to see if we need any patches
1652
- const nodePatches = compareNodes(oldNode.node, newNode.node);
1653
- // If nodePatches is null, the node types are incompatible - need to replace
1654
- if (nodePatches === null) {
1655
- // Navigate to this child
1656
- if (currentChildIndex === -1) {
1657
- patches.push({
1658
- type: NavigateChild,
1659
- index: i
1660
- });
1661
- currentChildIndex = i;
1662
- } else if (currentChildIndex !== i) {
1663
- patches.push({
1664
- type: NavigateSibling,
1665
- index: i
1666
- });
1667
- currentChildIndex = i;
1668
- }
1669
- // Replace the entire subtree
1670
- const flatNodes = treeToArray(newNode);
1671
- patches.push({
1672
- type: Replace,
1673
- nodes: flatNodes
1674
- });
1675
- // After replace, we're at the new element (same position)
1676
- continue;
1677
- }
1678
- // Check if we need to recurse into children
1679
- const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
1680
- // Only navigate to this element if we need to do something
1681
- if (nodePatches.length > 0 || hasChildrenToCompare) {
1682
- // Navigate to this child if not already there
1683
- if (currentChildIndex === -1) {
1684
- patches.push({
1685
- type: NavigateChild,
1686
- index: i
1687
- });
1688
- currentChildIndex = i;
1689
- } else if (currentChildIndex !== i) {
1690
- patches.push({
1691
- type: NavigateSibling,
1692
- index: i
1693
- });
1694
- currentChildIndex = i;
1695
- }
1696
- // Apply node patches (these apply to the current element, not children)
1697
- if (nodePatches.length > 0) {
1698
- patches.push(...nodePatches);
1699
- }
1700
- // Compare children recursively
1701
- if (hasChildrenToCompare) {
1702
- diffChildren(oldNode.children, newNode.children, patches);
1703
- }
1704
- }
1705
- } else {
1706
- // Remove old node - collect the index for later removal
1707
- indicesToRemove.push(i);
1708
- }
1709
- }
1710
- // Navigate back to parent if we ended at a child
1711
- if (currentChildIndex >= 0) {
1712
- patches.push({
1713
- type: NavigateParent
1714
- });
1715
- currentChildIndex = -1;
1716
- }
1717
- // Add remove patches in reverse order (highest index first)
1718
- // This ensures indices remain valid as we remove
1719
- for (let j = indicesToRemove.length - 1; j >= 0; j--) {
1720
- patches.push({
1721
- type: RemoveChild,
1722
- index: indicesToRemove[j]
1723
- });
1724
- }
1725
- };
1726
- const diffTrees = (oldTree, newTree, patches, path) => {
1727
- // At the root level (path.length === 0), we're already AT the element
1728
- // So we compare the root node directly, then compare its children
1729
- if (path.length === 0 && oldTree.length === 1 && newTree.length === 1) {
1730
- const oldNode = oldTree[0];
1731
- const newNode = newTree[0];
1732
- // Compare root nodes
1733
- const nodePatches = compareNodes(oldNode.node, newNode.node);
1734
- // If nodePatches is null, the root node types are incompatible - need to replace
1735
- if (nodePatches === null) {
1736
- const flatNodes = treeToArray(newNode);
1737
- patches.push({
1738
- type: Replace,
1739
- nodes: flatNodes
1740
- });
1741
- return;
1742
- }
1743
- if (nodePatches.length > 0) {
1744
- patches.push(...nodePatches);
1745
- }
1746
- // Compare children
1747
- if (oldNode.children.length > 0 || newNode.children.length > 0) {
1748
- diffChildren(oldNode.children, newNode.children, patches);
1749
- }
1750
- } else {
1751
- // Non-root level or multiple root elements - use the regular comparison
1752
- diffChildren(oldTree, newTree, patches);
1753
- }
1754
- };
1755
-
1756
- const removeTrailingNavigationPatches = patches => {
1757
- // Find the last non-navigation patch
1758
- let lastNonNavigationIndex = -1;
1759
- for (let i = patches.length - 1; i >= 0; i--) {
1760
- const patch = patches[i];
1761
- if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling) {
1762
- lastNonNavigationIndex = i;
1763
- break;
1764
- }
1765
- }
1766
- // Return patches up to and including the last non-navigation patch
1767
- return lastNonNavigationIndex === -1 ? [] : patches.slice(0, lastNonNavigationIndex + 1);
1768
- };
1769
-
1770
- const diffTree = (oldNodes, newNodes) => {
1771
- // Step 1: Convert flat arrays to tree structures
1772
- const oldTree = arrayToTree(oldNodes);
1773
- const newTree = arrayToTree(newNodes);
1774
- // Step 3: Compare the trees
1775
- const patches = [];
1776
- diffTrees(oldTree, newTree, patches, []);
1777
- // Remove trailing navigation patches since they serve no purpose
1778
- return removeTrailingNavigationPatches(patches);
1779
- };
1780
-
1781
1185
  const Div = 'div';
1782
1186
  const H1 = 'h1';
1783
1187
  const H2 = 'h2';
@@ -1985,7 +1389,7 @@ const isDefaultAllowedAttribute = (attributeName, defaultAllowedAttributes) => {
1985
1389
  const TAGS_TO_SKIP = new Set(['script', 'meta', 'title']);
1986
1390
 
1987
1391
  // Tags to skip but process children
1988
- const TAGS_TO_SKIP_TAG_ONLY$1 = new Set(['html', 'body', 'head']);
1392
+ const TAGS_TO_SKIP_TAG_ONLY = new Set(['html', 'body', 'head']);
1989
1393
 
1990
1394
  // Tags where we extract content as CSS
1991
1395
  const CSS_TAGS = new Set(['style']);
@@ -2026,7 +1430,7 @@ const serializeNode = (node, dom, css, context) => {
2026
1430
  }
2027
1431
 
2028
1432
  // For html/body tags, serialize children only
2029
- if (TAGS_TO_SKIP_TAG_ONLY$1.has(tagName)) {
1433
+ if (TAGS_TO_SKIP_TAG_ONLY.has(tagName)) {
2030
1434
  let childCount = 0;
2031
1435
  const {
2032
1436
  childNodes
@@ -2136,680 +1540,260 @@ const serialize = (document, elementMap) => {
2136
1540
  };
2137
1541
  };
2138
1542
 
2139
- const handleClickSandbox = async (state, hdId) => {
2140
- const {
2141
- sandboxRpc,
2142
- uid
2143
- } = state;
2144
- await sandboxRpc.invoke('SandBox.handleClick', uid, hdId);
2145
- const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
2146
- const parsedDom = serialized.dom;
1543
+ const getSerializedDom = uid => {
1544
+ const item = get(uid);
1545
+ if (!item) {
1546
+ throw new Error(`No HappyDom instance found for uid ${uid}`);
1547
+ }
2147
1548
  const {
2148
- css
2149
- } = serialized;
2150
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
2151
- return {
2152
- ...state,
2153
- css,
2154
- parsedDom,
2155
- parsedNodesChildNodeCount
2156
- };
1549
+ document,
1550
+ elementMap
1551
+ } = item;
1552
+ const serialized = serialize(document, elementMap);
1553
+ return serialized;
1554
+ };
1555
+
1556
+ const dispatchEvent = (element, event) => {
1557
+ element.dispatchEvent(event);
1558
+
1559
+ // Also invoke direct on* handler if set (e.g. element.onclick = function(){})
1560
+ const handlerName = `on${event.type}`;
1561
+ const handler = element[handlerName];
1562
+ if (typeof handler === 'function') {
1563
+ handler.call(element, event);
1564
+ } else if (handler === null || handler === undefined) {
1565
+ if (!element.getAttribute) {
1566
+ return;
1567
+ }
1568
+ // Check if there's an inline HTML attribute that wasn't converted to a property
1569
+ const attrValue = element.getAttribute(handlerName);
1570
+ if (attrValue && typeof attrValue === 'string' && element.ownerDocument && element.ownerDocument.defaultView) {
1571
+ const window = element.ownerDocument.defaultView;
1572
+ // Handle inline event handlers like onclick="someFunction(2)"
1573
+ // Evaluate in the context of the window so functions are in scope
1574
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
1575
+ const fn = new Function('event', `with(this) { ${attrValue} }`);
1576
+ fn.call(window, event);
1577
+ }
1578
+ }
2157
1579
  };
2158
- const handleClickLocal = (state, hdId) => {
2159
- const happyDomInstance = get(state.uid);
1580
+
1581
+ const dispatchClickEvent = (element, window) => {
1582
+ const clickEvent = new window.MouseEvent('click', {
1583
+ bubbles: true
1584
+ });
1585
+ dispatchEvent(element, clickEvent);
1586
+ };
1587
+
1588
+ const handleClickLocal = (uid, hdId) => {
1589
+ const happyDomInstance = get(uid);
2160
1590
  if (!happyDomInstance) {
2161
- return state;
1591
+ return;
2162
1592
  }
2163
1593
  const element = happyDomInstance.elementMap.get(hdId);
2164
1594
  if (!element) {
2165
- return state;
1595
+ return;
2166
1596
  }
2167
1597
  dispatchClickEvent(element, happyDomInstance.window);
2168
1598
  const elementMap = new Map();
2169
- const serialized = serialize(happyDomInstance.document, elementMap);
2170
- set$1(state.uid, {
1599
+ set$1(uid, {
2171
1600
  document: happyDomInstance.document,
2172
1601
  elementMap,
2173
1602
  window: happyDomInstance.window
2174
1603
  });
2175
- const parsedDom = serialized.dom;
2176
- const {
2177
- css
2178
- } = serialized;
2179
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
2180
- return {
2181
- ...state,
2182
- css,
2183
- parsedDom,
2184
- parsedNodesChildNodeCount
2185
- };
2186
1604
  };
2187
- const handleClick = (state, hdId) => {
2188
- if (!hdId) {
2189
- return state;
2190
- }
2191
- if (state.useSandboxWorker) {
2192
- return handleClickSandbox(state, hdId);
2193
- }
2194
- return handleClickLocal(state, hdId);
1605
+ const handleClick = (uid, hdId) => {
1606
+ return handleClickLocal(uid, hdId);
2195
1607
  };
2196
1608
 
2197
- const None = 0;
2198
- const OpeningAngleBracket = 1;
2199
- const ClosingAngleBracket = 2;
2200
- const TagNameStart = 3;
2201
- const TagNameEnd = 4;
2202
- const Content = 5;
2203
- const ClosingTagSlash = 6;
2204
- const WhitespaceInsideOpeningTag = 7;
2205
- const AttributeName = 8;
2206
- const AttributeEqualSign = 9;
2207
- const AttributeQuoteStart = 10;
2208
- const AttributeValue = 11;
2209
- const AttributeQuoteEnd = 12;
2210
- const WhitespaceAfterClosingTagSlash = 13;
2211
- const WhitespaceAfterOpeningTagOpenAngleBracket = 14;
2212
- const ExclamationMark = 15;
2213
- const Doctype = 16;
2214
- const StartCommentDashes = 17;
2215
- const Comment = 18;
2216
- const EndCommentTag = 19;
2217
- const Text = 20;
2218
- const CommentStart = 21;
2219
-
2220
- const isSelfClosingTag = tag => {
2221
- switch (tag.toLowerCase()) {
2222
- case 'area':
2223
- case 'base':
2224
- case 'col':
2225
- case Br:
2226
- case Hr:
2227
- case Img:
2228
- case Input:
2229
- case 'embed':
2230
- case 'link':
2231
- case 'meta':
2232
- case 'param':
2233
- case 'source':
2234
- case 'track':
2235
- case 'wbr':
2236
- return true;
2237
- default:
2238
- return false;
1609
+ const dispatchInputEvent = (element, window) => {
1610
+ const inputEvent = new window.Event('input', {
1611
+ bubbles: true
1612
+ });
1613
+ dispatchEvent(element, inputEvent);
1614
+ };
1615
+
1616
+ const handleInputLocal = (uid, hdId, value) => {
1617
+ const happyDomInstance = get(uid);
1618
+ if (!happyDomInstance) {
1619
+ return;
2239
1620
  }
1621
+ const element = happyDomInstance.elementMap.get(hdId);
1622
+ if (!element) {
1623
+ return;
1624
+ }
1625
+ element.value = value;
1626
+ dispatchInputEvent(element, happyDomInstance.window);
1627
+ const elementMap = new Map();
1628
+ set$1(uid, {
1629
+ document: happyDomInstance.document,
1630
+ elementMap,
1631
+ window: happyDomInstance.window
1632
+ });
1633
+ };
1634
+ const handleInput = (uid, hdId, value) => {
1635
+ return handleInputLocal(uid, hdId, value);
2240
1636
  };
2241
1637
 
2242
- const parseText = text => {
2243
- return text.replaceAll('&gt;', '>').replaceAll('&lt;', '<').replaceAll('&amp;', '&');
1638
+ const dispatchKeydownEvent = (element, window, key, code) => {
1639
+ const keydownEvent = new window.KeyboardEvent('keydown', {
1640
+ bubbles: true,
1641
+ code,
1642
+ key
1643
+ });
1644
+ dispatchEvent(element, keydownEvent);
2244
1645
  };
2245
1646
 
2246
- class UnexpectedTokenError extends Error {
2247
- constructor() {
2248
- super('Unexpected token');
2249
- this.name = 'UnexpectedTokenError';
1647
+ const handleKeydownLocal = (uid, hdId, key, code) => {
1648
+ const happyDomInstance = get(uid);
1649
+ if (!happyDomInstance) {
1650
+ return;
2250
1651
  }
2251
- }
1652
+ const element = hdId ? happyDomInstance.elementMap.get(hdId) : happyDomInstance.document;
1653
+ if (!element) {
1654
+ return;
1655
+ }
1656
+ dispatchKeydownEvent(element, happyDomInstance.window, key, code);
1657
+ const elementMap = new Map();
1658
+ set$1(uid, {
1659
+ document: happyDomInstance.document,
1660
+ elementMap,
1661
+ window: happyDomInstance.window
1662
+ });
1663
+ };
1664
+ const handleKeydown = (uid, hdId, key, code) => {
1665
+ return handleKeydownLocal(uid, hdId, key, code);
1666
+ };
2252
1667
 
2253
- const State = {
2254
- AfterAttributeEqualSign: 8,
2255
- AfterAttributeName: 7,
2256
- AfterAttributeValueClosingQuote: 11,
2257
- AfterAttributeValueInsideDoubleQuote: 10,
2258
- AfterClosingTagName: 5,
2259
- AfterClosingTagSlash: 4,
2260
- AfterExclamationMark: 16,
2261
- AfterOpeningAngleBracket: 2,
2262
- InsideAttributeAfterDoubleQuote: 9,
2263
- InsideComment: 17,
2264
- InsideOpeningTag: 3,
2265
- InsideOpeningTagAfterWhitespace: 6,
2266
- InsideRawTextElement: 18,
2267
- TopLevelContent: 1
1668
+ const dispatchKeyupEvent = (element, window, key, code) => {
1669
+ const keyupEvent = new window.KeyboardEvent('keyup', {
1670
+ bubbles: true,
1671
+ code,
1672
+ key
1673
+ });
1674
+ dispatchEvent(element, keyupEvent);
2268
1675
  };
2269
1676
 
2270
- // Raw-text elements whose content should not be parsed as HTML
2271
- const RAW_TEXT_ELEMENTS = new Set(['script', 'style']);
2272
- const RE_ANGLE_BRACKET_OPEN = /^</;
2273
- const RE_ANGLE_BRACKET_OPEN_TAG = /^<(?![\s%])/;
2274
- const RE_ANGLE_BRACKET_CLOSE = /^>/;
2275
- const RE_SLASH = /^\//;
2276
- const RE_TAGNAME = /^[a-zA-Z\d$]+/;
2277
- const RE_CONTENT = /^[^<>]+/;
2278
- const RE_WHITESPACE = /^\s+/;
2279
- const RE_ATTRIBUTE_NAME = /^[a-zA-Z\d-]+/;
2280
- const RE_EQUAL_SIGN = /^=/;
2281
- const RE_DOUBLE_QUOTE = /^"/;
2282
- const RE_ATTRIBUTE_VALUE_INSIDE_DOUBLE_QUOTE = /^[^"\n]+/;
2283
- const RE_TEXT = /^[^<>]+/;
2284
- const RE_EXCLAMATION_MARK = /^!/;
2285
- const RE_DASH_DASH = /^--/;
2286
- const RE_DOCTYPE = /^doctype/i;
2287
- const RE_BLOCK_COMMENT_CONTENT = /^[a-zA-Z\s]+/;
2288
- const RE_COMMENT_END = /^-->/;
2289
- const RE_TAG_TEXT = /^[^\s>]+/;
2290
- const RE_ANY_TEXT = /^[^\n]+/;
2291
- const RE_ATTRIBUTE_TEXT = /^[^\n<>/\s]+/;
2292
- const RE_BLOCK_COMMENT_START = /^<!--/;
2293
- const RE_SELF_CLOSING = /^\/>/;
2294
- const tokenizeHtml = text => {
2295
- string(text);
2296
- let state = State.TopLevelContent;
2297
- let index = 0;
2298
- let next;
2299
- const tokens = [];
2300
- let token = None;
2301
- let rawTextTagName = ''; // Track which raw-text element we're inside
2302
- while (index < text.length) {
2303
- const part = text.slice(index);
2304
- switch (state) {
2305
- case State.AfterAttributeEqualSign:
2306
- if (next = part.match(RE_DOUBLE_QUOTE)) {
2307
- token = AttributeQuoteStart;
2308
- state = State.InsideAttributeAfterDoubleQuote;
2309
- } else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
2310
- token = ClosingAngleBracket;
2311
- state = State.TopLevelContent;
2312
- } else if (next = part.match(RE_ATTRIBUTE_TEXT)) {
2313
- token = AttributeValue;
2314
- state = State.InsideOpeningTag;
2315
- } else {
2316
- throw new UnexpectedTokenError();
2317
- }
2318
- break;
2319
- case State.AfterAttributeName:
2320
- if (next = part.match(RE_EQUAL_SIGN)) {
2321
- token = AttributeEqualSign;
2322
- state = State.AfterAttributeEqualSign;
2323
- } else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
2324
- token = ClosingAngleBracket;
2325
- state = State.TopLevelContent;
2326
- } else if (next = part.match(RE_WHITESPACE)) {
2327
- token = WhitespaceInsideOpeningTag;
2328
- state = State.InsideOpeningTagAfterWhitespace;
2329
- } else if (next = part.match(RE_ANGLE_BRACKET_OPEN)) {
2330
- token = OpeningAngleBracket;
2331
- state = State.AfterOpeningAngleBracket;
2332
- } else {
2333
- text.slice(index); // ?
2334
- throw new UnexpectedTokenError();
2335
- }
2336
- break;
2337
- case State.AfterAttributeValueClosingQuote:
2338
- if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
2339
- token = ClosingAngleBracket;
2340
- state = State.TopLevelContent;
2341
- } else if (next = part.match(RE_WHITESPACE)) {
2342
- token = WhitespaceInsideOpeningTag;
2343
- state = State.InsideOpeningTagAfterWhitespace;
2344
- } else if (next = part.match(RE_SELF_CLOSING)) {
2345
- token = ClosingAngleBracket;
2346
- state = State.TopLevelContent;
2347
- } else {
2348
- throw new UnexpectedTokenError();
2349
- }
2350
- break;
2351
- case State.AfterAttributeValueInsideDoubleQuote:
2352
- if (next = part.match(RE_DOUBLE_QUOTE)) {
2353
- token = AttributeQuoteEnd;
2354
- state = State.AfterAttributeValueClosingQuote;
2355
- } else {
2356
- throw new UnexpectedTokenError();
2357
- }
2358
- break;
2359
- case State.AfterClosingTagName:
2360
- if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
2361
- token = ClosingAngleBracket;
2362
- state = State.TopLevelContent;
2363
- } else if (next = part.match(RE_WHITESPACE)) {
2364
- token = Content;
2365
- state = State.TopLevelContent;
2366
- } else {
2367
- throw new UnexpectedTokenError();
2368
- }
2369
- break;
2370
- case State.AfterClosingTagSlash:
2371
- if (next = part.match(RE_TAGNAME)) {
2372
- token = TagNameEnd;
2373
- state = State.AfterClosingTagName;
2374
- } else if (next = part.match(RE_WHITESPACE)) {
2375
- token = WhitespaceAfterClosingTagSlash;
2376
- state = State.TopLevelContent;
2377
- } else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
2378
- token = ClosingAngleBracket;
2379
- state = State.TopLevelContent;
2380
- } else {
2381
- throw new UnexpectedTokenError();
2382
- }
2383
- break;
2384
- case State.AfterExclamationMark:
2385
- if (next = part.match(RE_DASH_DASH)) {
2386
- token = StartCommentDashes;
2387
- state = State.InsideComment;
2388
- } else if (next = part.match(RE_DOCTYPE)) {
2389
- token = Doctype;
2390
- state = State.InsideOpeningTag;
2391
- } else {
2392
- text.slice(index); // ?
2393
- throw new UnexpectedTokenError();
2394
- }
2395
- break;
2396
- case State.AfterOpeningAngleBracket:
2397
- if (next = part.match(RE_TAGNAME)) {
2398
- token = TagNameStart;
2399
- state = State.InsideOpeningTag;
2400
- // Track raw-text elements so we can switch to raw content mode after >
2401
- if (RAW_TEXT_ELEMENTS.has(next[0].toLowerCase())) {
2402
- rawTextTagName = next[0].toLowerCase();
2403
- }
2404
- } else if (next = part.match(RE_SLASH)) {
2405
- token = ClosingTagSlash;
2406
- state = State.AfterClosingTagSlash;
2407
- } else if (next = part.match(RE_WHITESPACE)) {
2408
- token = WhitespaceAfterOpeningTagOpenAngleBracket;
2409
- state = State.TopLevelContent;
2410
- } else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
2411
- token = ClosingAngleBracket;
2412
- state = State.TopLevelContent;
2413
- } else if (next = part.match(RE_EXCLAMATION_MARK)) {
2414
- token = ExclamationMark;
2415
- state = State.AfterExclamationMark;
2416
- } else if (next = part.match(RE_ANY_TEXT)) {
2417
- token = Text;
2418
- state = State.TopLevelContent;
2419
- } else {
2420
- text.slice(index); // ?
2421
- throw new UnexpectedTokenError();
2422
- }
2423
- break;
2424
- case State.InsideAttributeAfterDoubleQuote:
2425
- if (next = text.slice(index).match(RE_ATTRIBUTE_VALUE_INSIDE_DOUBLE_QUOTE)) {
2426
- token = AttributeValue;
2427
- state = State.AfterAttributeValueInsideDoubleQuote;
2428
- } else if (next = part.match(RE_DOUBLE_QUOTE)) {
2429
- token = AttributeQuoteEnd;
2430
- state = State.AfterAttributeValueClosingQuote;
2431
- } else {
2432
- throw new UnexpectedTokenError();
2433
- }
2434
- break;
2435
- case State.InsideComment:
2436
- if (next = part.match(RE_BLOCK_COMMENT_CONTENT)) {
2437
- token = Comment;
2438
- state = State.InsideComment;
2439
- } else if (next = part.match(RE_COMMENT_END)) {
2440
- token = EndCommentTag;
2441
- state = State.TopLevelContent;
2442
- } else {
2443
- text.slice(index); // ?
2444
- throw new UnexpectedTokenError();
2445
- }
2446
- break;
2447
- case State.InsideOpeningTag:
2448
- if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
2449
- token = ClosingAngleBracket;
2450
- state = State.TopLevelContent;
2451
- } else if (next = part.match(RE_WHITESPACE)) {
2452
- token = WhitespaceInsideOpeningTag;
2453
- state = State.InsideOpeningTagAfterWhitespace;
2454
- } else if (next = part.match(RE_TAG_TEXT)) {
2455
- token = Text;
2456
- state = State.TopLevelContent;
2457
- } else {
2458
- throw new UnexpectedTokenError();
2459
- }
2460
- break;
2461
- case State.InsideOpeningTagAfterWhitespace:
2462
- if (next = part.match(RE_ATTRIBUTE_NAME)) {
2463
- token = AttributeName;
2464
- state = State.AfterAttributeName;
2465
- } else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
2466
- token = ClosingAngleBracket;
2467
- state = State.TopLevelContent;
2468
- } else if (next = part.match(RE_SELF_CLOSING)) {
2469
- token = ClosingAngleBracket;
2470
- state = State.TopLevelContent;
2471
- } else if (next = part.match(RE_TEXT)) {
2472
- token = AttributeName;
2473
- state = State.AfterAttributeName;
2474
- } else {
2475
- text.slice(index).match(RE_TEXT); // ?
2476
- text.slice(index); // ?
2477
- throw new UnexpectedTokenError();
2478
- }
2479
- break;
2480
- case State.InsideRawTextElement:
2481
- {
2482
- // Match everything up to the closing tag for the current raw-text element
2483
- const closingTagPattern = new RegExp(`^([\\s\\S]*?)(<\\/${rawTextTagName}>)`, 'i');
2484
- const rawMatch = part.match(closingTagPattern);
2485
- if (rawMatch) {
2486
- // Emit content before the closing tag (if any)
2487
- if (rawMatch[1].length > 0) {
2488
- tokens.push({
2489
- text: rawMatch[1],
2490
- type: Content
2491
- });
2492
- index += rawMatch[1].length;
2493
- }
2494
- // Now emit the closing tag tokens: <, /, tagname, >
2495
- // < token
2496
- tokens.push({
2497
- text: '<',
2498
- type: OpeningAngleBracket
2499
- });
2500
- index += 1;
2501
- // / token
2502
- tokens.push({
2503
- text: '/',
2504
- type: ClosingTagSlash
2505
- });
2506
- index += 1;
2507
- // tagname token
2508
- tokens.push({
2509
- text: rawTextTagName,
2510
- type: TagNameEnd
2511
- });
2512
- index += rawTextTagName.length;
2513
- // > token
2514
- tokens.push({
2515
- text: '>',
2516
- type: ClosingAngleBracket
2517
- });
2518
- index += 1;
2519
- rawTextTagName = '';
2520
- state = State.TopLevelContent;
2521
- continue;
2522
- }
2523
- // No closing tag found — consume everything as content
2524
- next = [part];
2525
- token = Content;
2526
- rawTextTagName = '';
2527
- state = State.TopLevelContent;
2528
- break;
2529
- }
2530
- case State.TopLevelContent:
2531
- if (next = part.match(RE_ANGLE_BRACKET_OPEN_TAG)) {
2532
- token = OpeningAngleBracket;
2533
- state = State.AfterOpeningAngleBracket;
2534
- } else if (next = part.match(RE_CONTENT)) {
2535
- token = Content;
2536
- state = State.TopLevelContent;
2537
- } else if (next = part.match(RE_BLOCK_COMMENT_START)) {
2538
- token = CommentStart;
2539
- state = State.InsideComment;
2540
- } else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
2541
- token = Content;
2542
- state = State.TopLevelContent;
2543
- } else if (next = part.match(RE_ANGLE_BRACKET_OPEN)) {
2544
- token = Text;
2545
- state = State.TopLevelContent;
2546
- } else {
2547
- throw new UnexpectedTokenError();
2548
- }
2549
- break;
2550
- default:
2551
- throw new UnexpectedTokenError();
2552
- }
2553
- const tokenText = next[0];
2554
- // After closing angle bracket of a raw-text element opening tag,
2555
- // switch to raw text content mode instead of top-level content
2556
- if (rawTextTagName && token === ClosingAngleBracket && state === State.TopLevelContent) {
2557
- state = State.InsideRawTextElement;
2558
- }
2559
- tokens.push({
2560
- text: tokenText,
2561
- type: token
2562
- });
2563
- index += tokenText.length;
1677
+ const handleKeyupLocal = (uid, hdId, key, code) => {
1678
+ const happyDomInstance = get(uid);
1679
+ if (!happyDomInstance) {
1680
+ return;
2564
1681
  }
2565
- return tokens;
1682
+ const element = hdId ? happyDomInstance.elementMap.get(hdId) : happyDomInstance.document;
1683
+ if (!element) {
1684
+ return;
1685
+ }
1686
+ dispatchKeyupEvent(element, happyDomInstance.window, key, code);
1687
+ const elementMap = new Map();
1688
+ set$1(uid, {
1689
+ document: happyDomInstance.document,
1690
+ elementMap,
1691
+ window: happyDomInstance.window
1692
+ });
1693
+ };
1694
+ const handleKeyup = (uid, hdId, key, code) => {
1695
+ return handleKeyupLocal(uid, hdId, key, code);
2566
1696
  };
2567
1697
 
2568
- // Tags that should be completely skipped (both tag and content)
2569
- const TAGS_TO_SKIP_COMPLETELY = new Set(['meta', 'title']);
2570
-
2571
- // Tags that should have their opening/closing tags skipped but content processed
2572
- const TAGS_TO_SKIP_TAG_ONLY = new Set(['html', 'head']);
2573
-
2574
- // Tags where we capture content as CSS
2575
- const TAGS_TO_CAPTURE_AS_CSS = new Set(['style']);
1698
+ const handleMessagePort = async port => {
1699
+ await PlainMessagePortRpc.create({
1700
+ commandMap: {},
1701
+ messagePort: port
1702
+ });
1703
+ };
2576
1704
 
2577
- // Tags where we capture content as JavaScript
2578
- const TAGS_TO_CAPTURE_AS_JS = new Set(['script']);
2579
- const parseHtml = (html, allowedAttributes = [], defaultAllowedAttributes = []) => {
2580
- string(html);
2581
- array(allowedAttributes);
2582
- array(defaultAllowedAttributes);
1705
+ const dispatchMousedownEvent = (element, window, clientX = 0, clientY = 0) => {
1706
+ const mousedownEvent = new window.MouseEvent('mousedown', {
1707
+ bubbles: true,
1708
+ clientX,
1709
+ clientY
1710
+ });
1711
+ dispatchEvent(element, mousedownEvent);
1712
+ };
2583
1713
 
2584
- // Combine default allowed attributes with any additional ones provided
2585
- const allAllowedAttributes = new Set([...defaultAllowedAttributes, ...allowedAttributes]);
2586
- const useBuiltInDefaults = allowedAttributes.length === 0;
2587
- const tokens = tokenizeHtml(html);
2588
- const dom = [];
2589
- const css = [];
2590
- const scripts = [];
2591
- const root = {
2592
- childCount: 0,
2593
- type: 0
2594
- };
2595
- let current = root;
2596
- const stack = [root];
2597
- const tagStack = []; // Track tag names to match closing tags
2598
- let attributeName = '';
2599
- let lastTagWasSelfClosing = false;
2600
- let skipDepth = 0; // Track how many levels deep we are in skipped content
2601
- let captureCss = false; // Track if we're inside a style tag
2602
- let cssContent = ''; // Accumulate CSS content
2603
- let captureJs = false; // Track if we're inside a script tag
2604
- let jsContent = ''; // Accumulate JavaScript content
2605
-
2606
- for (const token of tokens) {
2607
- switch (token.type) {
2608
- case AttributeName:
2609
- if (skipDepth === 0 && !captureCss && !captureJs) {
2610
- attributeName = token.text;
2611
- }
2612
- break;
2613
- case AttributeValue:
2614
- if (skipDepth === 0 && !captureCss && !captureJs && (allAllowedAttributes.has(attributeName) || useBuiltInDefaults && isDefaultAllowedAttribute(attributeName, defaultAllowedAttributes))) {
2615
- let finalAttributeName = attributeName;
2616
- if (attributeName === 'class') finalAttributeName = 'className';else if (attributeName === 'type') finalAttributeName = 'inputType';
2617
- current[finalAttributeName] = token.text;
2618
- }
2619
- attributeName = '';
2620
- break;
2621
- case ClosingAngleBracket:
2622
- if (skipDepth === 0 && !captureCss && !captureJs) {
2623
- // Handle boolean attributes (attributes without values)
2624
- if (attributeName && (allAllowedAttributes.has(attributeName) || useBuiltInDefaults && isDefaultAllowedAttribute(attributeName, defaultAllowedAttributes))) {
2625
- let finalAttributeName = attributeName;
2626
- if (attributeName === 'class') finalAttributeName = 'className';else if (attributeName === 'type') finalAttributeName = 'inputType';
2627
- current[finalAttributeName] = attributeName;
2628
- }
2629
- attributeName = '';
2630
- // Return to parent if the current tag is self-closing
2631
- if (lastTagWasSelfClosing) {
2632
- current = stack.at(-1) || root;
2633
- lastTagWasSelfClosing = false;
2634
- }
2635
- }
2636
- break;
2637
- case Content:
2638
- if (captureCss) {
2639
- cssContent += token.text;
2640
- } else if (captureJs) {
2641
- jsContent += token.text;
2642
- } else if (skipDepth === 0) {
2643
- current.childCount++;
2644
- dom.push(text(parseText(token.text)));
2645
- }
2646
- break;
2647
- case Doctype:
2648
- // Ignore DOCTYPE - it's parsed but not rendered since we're in a div
2649
- break;
2650
- case TagNameEnd:
2651
- const tagNameToClose = tagStack.pop()?.toLowerCase() || '';
2652
- if (TAGS_TO_CAPTURE_AS_CSS.has(tagNameToClose)) {
2653
- // Finished capturing CSS
2654
- if (cssContent.trim()) {
2655
- css.push(cssContent);
2656
- }
2657
- cssContent = '';
2658
- captureCss = false;
2659
- } else if (TAGS_TO_CAPTURE_AS_JS.has(tagNameToClose)) {
2660
- // Finished capturing JavaScript
2661
- if (jsContent.trim()) {
2662
- scripts.push(jsContent);
2663
- }
2664
- jsContent = '';
2665
- captureJs = false;
2666
- } else if (TAGS_TO_SKIP_COMPLETELY.has(tagNameToClose)) {
2667
- // We were skipping this content, so decrement skipDepth
2668
- skipDepth--;
2669
- } else if (TAGS_TO_SKIP_TAG_ONLY.has(tagNameToClose)) ; else {
2670
- // Normal tag - pop from stack
2671
- if (stack.length > 1) {
2672
- stack.pop();
2673
- }
2674
- current = stack.at(-1) || root;
2675
- }
2676
- break;
2677
- case TagNameStart:
2678
- const tagNameLower = token.text.toLowerCase();
2679
- lastTagWasSelfClosing = isSelfClosingTag(token.text);
2680
-
2681
- // Check if this tag captures CSS content
2682
- if (TAGS_TO_CAPTURE_AS_CSS.has(tagNameLower)) {
2683
- captureCss = true;
2684
- cssContent = '';
2685
- tagStack.push(token.text);
2686
- }
2687
- // Check if this tag captures JavaScript content
2688
- else if (TAGS_TO_CAPTURE_AS_JS.has(tagNameLower)) {
2689
- captureJs = true;
2690
- jsContent = '';
2691
- tagStack.push(token.text);
2692
- }
2693
- // Check if this tag should be completely skipped (meta, title)
2694
- else if (TAGS_TO_SKIP_COMPLETELY.has(tagNameLower)) {
2695
- if (!lastTagWasSelfClosing) {
2696
- // For non-self-closing tags like title, mark as skipped
2697
- skipDepth++;
2698
- tagStack.push(token.text);
2699
- }
2700
- // For self-closing tags like meta, we just skip them without tracking
2701
- }
2702
- // Check if this tag should have its opening/closing tags skipped (html, head)
2703
- else if (TAGS_TO_SKIP_TAG_ONLY.has(tagNameLower)) {
2704
- if (!lastTagWasSelfClosing) {
2705
- // Track the tag name for matching the closing tag
2706
- tagStack.push(token.text);
2707
- }
2708
- }
2709
- // Normal tag processing
2710
- else if (skipDepth === 0) {
2711
- current.childCount++;
2712
- const newNode = {
2713
- childCount: 0,
2714
- type: getVirtualDomTag(token.text)
2715
- };
2716
- dom.push(newNode);
2717
- current = newNode;
2718
- if (!lastTagWasSelfClosing) {
2719
- stack.push(current);
2720
- tagStack.push(token.text);
2721
- }
2722
- }
2723
- break;
2724
- case WhitespaceInsideOpeningTag:
2725
- if (skipDepth === 0 && !captureCss && !captureJs &&
2726
- // Handle boolean attributes (attributes without values)
2727
- attributeName && (allAllowedAttributes.has(attributeName) || useBuiltInDefaults && isDefaultAllowedAttribute(attributeName, defaultAllowedAttributes))) {
2728
- let finalAttributeName = attributeName;
2729
- if (attributeName === 'class') finalAttributeName = 'className';else if (attributeName === 'type') finalAttributeName = 'inputType';
2730
- current[finalAttributeName] = attributeName;
2731
- }
2732
- attributeName = '';
2733
- break;
2734
- }
1714
+ const handleMousedownLocal = (uid, hdId, clientX, clientY, x, y) => {
1715
+ const happyDomInstance = get(uid);
1716
+ if (!happyDomInstance) {
1717
+ return;
2735
1718
  }
2736
- try {
2737
- Object.defineProperty(dom, 'rootChildCount', {
2738
- configurable: true,
2739
- enumerable: false,
2740
- value: root.childCount
2741
- });
2742
- } catch {
2743
- dom.rootChildCount = root.childCount;
1719
+ const element = happyDomInstance.elementMap.get(hdId);
1720
+ if (!element) {
1721
+ return;
2744
1722
  }
2745
- return {
2746
- css,
2747
- dom,
2748
- scripts
2749
- };
1723
+ const adjustedClientX = clientX - x;
1724
+ const adjustedClientY = clientY - y;
1725
+ dispatchMousedownEvent(element, happyDomInstance.window, adjustedClientX, adjustedClientY);
1726
+ const elementMap = new Map();
1727
+ set$1(uid, {
1728
+ document: happyDomInstance.document,
1729
+ elementMap,
1730
+ window: happyDomInstance.window
1731
+ });
1732
+ };
1733
+ const handleMousedown = (uid, hdId, clientX, clientY, x, y) => {
1734
+ return handleMousedownLocal(uid, hdId, clientX, clientY, x, y);
2750
1735
  };
2751
1736
 
2752
- const handleEditorChanged = async () => {
2753
- // Get all preview instance keys
2754
- const previewKeys = getKeys$1();
2755
-
2756
- // Get all editor keys from the editor worker
2757
- const editorKeys = await invoke$1('Editor.getKeys');
2758
-
2759
- // For each preview instance
2760
- for (const previewUid of previewKeys) {
2761
- const {
2762
- newState: state
2763
- } = get$1(previewUid);
1737
+ const dispatchMousemoveEvent = (element, window, clientX = 0, clientY = 0) => {
1738
+ const mousemoveEvent = new window.MouseEvent('mousemove', {
1739
+ bubbles: true,
1740
+ clientX,
1741
+ clientY
1742
+ });
1743
+ dispatchEvent(element, mousemoveEvent);
1744
+ };
2764
1745
 
2765
- // Skip if no URI is set
2766
- if (!state.uri) {
2767
- continue;
2768
- }
1746
+ const handleMousemoveLocal = (uid, hdId, clientX, clientY, x, y) => {
1747
+ const happyDomInstance = get(uid);
1748
+ if (!happyDomInstance) {
1749
+ return;
1750
+ }
1751
+ const element = happyDomInstance.elementMap.get(hdId);
1752
+ if (!element) {
1753
+ return;
1754
+ }
1755
+ const adjustedClientX = clientX - x;
1756
+ const adjustedClientY = clientY - y;
1757
+ dispatchMousemoveEvent(element, happyDomInstance.window, adjustedClientX, adjustedClientY);
1758
+ const elementMap = new Map();
1759
+ set$1(uid, {
1760
+ document: happyDomInstance.document,
1761
+ elementMap,
1762
+ window: happyDomInstance.window
1763
+ });
1764
+ };
1765
+ const handleMousemove = (uid, hdId, clientX, clientY, x, y) => {
1766
+ return handleMousemoveLocal(uid, hdId, clientX, clientY, x, y);
1767
+ };
2769
1768
 
2770
- // Find the editor that matches our preview's URI
2771
- let matchingEditorUid = null;
2772
- for (const editorKey of editorKeys) {
2773
- const editorUid = Number.parseFloat(editorKey);
2774
- const editorUri = await invoke$1('Editor.getUri', editorUid);
2775
- if (editorUri === state.uri) {
2776
- matchingEditorUid = editorUid;
2777
- break;
2778
- }
2779
- }
1769
+ const dispatchMouseupEvent = (element, window, clientX = 0, clientY = 0) => {
1770
+ const mouseupEvent = new window.MouseEvent('mouseup', {
1771
+ bubbles: true,
1772
+ clientX,
1773
+ clientY
1774
+ });
1775
+ dispatchEvent(element, mouseupEvent);
1776
+ };
2780
1777
 
2781
- // If we found a matching editor, get its text and update the preview
2782
- if (matchingEditorUid !== null) {
2783
- try {
2784
- const content = await invoke$1('Editor.getText', matchingEditorUid);
2785
- const parseResult = parseHtml(content, []);
2786
- const updatedState = {
2787
- ...state,
2788
- content,
2789
- css: parseResult.css,
2790
- errorMessage: '',
2791
- parsedDom: parseResult.dom,
2792
- scripts: parseResult.scripts
2793
- };
2794
- set$2(previewUid, state, updatedState);
2795
- } catch (error) {
2796
- // If getting text fails, update with error message
2797
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
2798
- const updatedState = {
2799
- ...state,
2800
- content: '',
2801
- css: [],
2802
- errorMessage,
2803
- parsedDom: [],
2804
- scripts: []
2805
- };
2806
- set$2(previewUid, state, updatedState);
2807
- }
2808
- }
1778
+ const handleMouseupLocal = (uid, hdId) => {
1779
+ const happyDomInstance = get(uid);
1780
+ if (!happyDomInstance) {
1781
+ return;
2809
1782
  }
2810
-
2811
- // Rerender all previews after updates are complete
2812
- await invoke('Preview.rerender');
1783
+ const element = happyDomInstance.elementMap.get(hdId);
1784
+ if (!element) {
1785
+ return;
1786
+ }
1787
+ dispatchMouseupEvent(element, happyDomInstance.window);
1788
+ const elementMap = new Map();
1789
+ set$1(uid, {
1790
+ document: happyDomInstance.document,
1791
+ elementMap,
1792
+ window: happyDomInstance.window
1793
+ });
1794
+ };
1795
+ const handleMouseup = (uid, hdId) => {
1796
+ return handleMouseupLocal(uid, hdId);
2813
1797
  };
2814
1798
 
2815
1799
  function getDefaultExportFromCjs (x) {
@@ -90551,6 +89535,29 @@ const executeScripts = (window, document, scripts, width = 0, height = 0) => {
90551
89535
  }
90552
89536
  };
90553
89537
 
89538
+ const getParsedNodesChildNodeCount = parsedDom => {
89539
+ array(parsedDom);
89540
+ const rootCountFromParse = parsedDom.rootChildCount;
89541
+ if (typeof rootCountFromParse === 'number') {
89542
+ return rootCountFromParse;
89543
+ }
89544
+ let rootChildCount = 0;
89545
+ let i = 0;
89546
+ while (i < parsedDom.length) {
89547
+ rootChildCount++;
89548
+
89549
+ // skip the entire subtree of the current node
89550
+ let toSkip = parsedDom[i].childCount;
89551
+ i++;
89552
+ while (toSkip > 0 && i < parsedDom.length) {
89553
+ toSkip -= 1;
89554
+ toSkip += parsedDom[i].childCount;
89555
+ i++;
89556
+ }
89557
+ }
89558
+ return rootChildCount;
89559
+ };
89560
+
90554
89561
  /* eslint-disable @typescript-eslint/no-floating-promises */
90555
89562
  const observers = new Map();
90556
89563
  const handleMutations = async uid => {
@@ -90565,22 +89572,17 @@ const handleMutations = async uid => {
90565
89572
  elementMap,
90566
89573
  window: happyDomInstance.window
90567
89574
  });
90568
- const {
90569
- newState: state,
90570
- oldState
90571
- } = get$1(uid);
90572
89575
  const parsedDom = serialized.dom;
90573
- const {
90574
- css
90575
- } = serialized;
90576
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
90577
- const updatedState = {
90578
- ...state,
90579
- css,
90580
- parsedDom,
90581
- parsedNodesChildNodeCount
90582
- };
90583
- set$2(uid, oldState, updatedState);
89576
+ // @ts-ignore
89577
+ getParsedNodesChildNodeCount(parsedDom);
89578
+
89579
+ // const updatedState = {
89580
+ // css,
89581
+ // parsedDom,
89582
+ // parsedNodesChildNodeCount,
89583
+ // }
89584
+
89585
+ // TODO notify
90584
89586
  try {
90585
89587
  await invoke('Preview.rerender', uid);
90586
89588
  } catch {
@@ -90692,754 +89694,44 @@ const patchCanvasElements = async (document, uid) => {
90692
89694
  });
90693
89695
  };
90694
89696
 
90695
- /* eslint-disable prefer-destructuring */
90696
-
90697
- const updateContent = async (state, uri) => {
89697
+ const updateContent = async (uid, width, height, content, scripts) => {
90698
89698
  try {
90699
- // Read the file content using RendererWorker RPC
90700
- const content = await readFile(uri);
90701
-
90702
- // Parse the content into virtual DOM and CSS
90703
- const parseResult = parseHtml(content);
90704
- let parsedDom = parseResult.dom;
90705
- let {
90706
- css
90707
- } = parseResult;
90708
89699
  const {
90709
- scripts
90710
- } = parseResult;
90711
-
90712
- // If scripts are present and not using sandbox worker, execute them via happy-dom and re-serialize the DOM
90713
- if (scripts.length > 0 && !state.useSandboxWorker) {
90714
- try {
90715
- const {
90716
- document: happyDomDocument,
90717
- window: happyDomWindow
90718
- } = createWindow(content);
90719
- await patchCanvasElements(happyDomDocument, state.uid);
90720
- executeScripts(happyDomWindow, happyDomDocument, scripts, state.width, state.height);
90721
- const elementMap = new Map();
90722
- const serialized = serialize(happyDomDocument, elementMap);
90723
- parsedDom = serialized.dom;
90724
- css = serialized.css;
90725
- set$1(state.uid, {
90726
- document: happyDomDocument,
90727
- elementMap,
90728
- window: happyDomWindow
90729
- });
90730
- observe(state.uid, happyDomDocument, happyDomWindow);
90731
- } catch (error) {
90732
- console.error(error);
90733
- // If script execution fails, fall back to static HTML parsing
90734
- }
90735
- }
90736
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
89700
+ document: happyDomDocument,
89701
+ window: happyDomWindow
89702
+ } = createWindow(content);
89703
+ await patchCanvasElements(happyDomDocument, uid);
89704
+ executeScripts(happyDomWindow, happyDomDocument, scripts, width, height);
89705
+ const elementMap = new Map();
89706
+ set$1(uid, {
89707
+ document: happyDomDocument,
89708
+ elementMap,
89709
+ window: happyDomWindow
89710
+ });
89711
+ observe(uid, happyDomDocument, happyDomWindow);
90737
89712
  return {
90738
- content,
90739
- css,
90740
- errorMessage: '',
90741
- parsedDom,
90742
- parsedNodesChildNodeCount,
90743
- scripts
89713
+ errorMessage: ''
90744
89714
  };
90745
89715
  } catch (error) {
90746
89716
  // If file reading or parsing fails, return empty content and parsedDom with error message
90747
89717
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
90748
89718
  return {
90749
- content: '',
90750
- css: [],
90751
- errorMessage,
90752
- parsedDom: [],
90753
- parsedNodesChildNodeCount: 0,
90754
- scripts: []
89719
+ errorMessage
90755
89720
  };
90756
89721
  }
90757
89722
  };
90758
89723
 
90759
- const handleFileEdited = async state => {
90760
- const {
90761
- content,
90762
- css,
90763
- errorMessage,
90764
- parsedDom,
90765
- parsedNodesChildNodeCount,
90766
- scripts
90767
- } = await updateContent(state, state.uri);
90768
- return {
90769
- ...state,
90770
- content,
90771
- css,
90772
- errorMessage,
90773
- parsedDom,
90774
- parsedNodesChildNodeCount,
90775
- scripts
90776
- };
90777
- };
90778
-
90779
- const dispatchInputEvent = (element, window) => {
90780
- const inputEvent = new window.Event('input', {
90781
- bubbles: true
90782
- });
90783
- dispatchEvent(element, inputEvent);
90784
- };
90785
-
90786
- const handleInputSandbox = async (state, hdId, value) => {
90787
- const {
90788
- sandboxRpc,
90789
- uid
90790
- } = state;
90791
- await sandboxRpc.invoke('SandBox.handleInput', uid, hdId, value);
90792
- const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
90793
- const parsedDom = serialized.dom;
90794
- const {
90795
- css
90796
- } = serialized;
90797
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
90798
- return {
90799
- ...state,
90800
- css,
90801
- parsedDom,
90802
- parsedNodesChildNodeCount
90803
- };
90804
- };
90805
- const handleInputLocal = (state, hdId, value) => {
90806
- const happyDomInstance = get(state.uid);
90807
- if (!happyDomInstance) {
90808
- return state;
90809
- }
90810
- const element = happyDomInstance.elementMap.get(hdId);
90811
- if (!element) {
90812
- return state;
90813
- }
90814
- element.value = value;
90815
- dispatchInputEvent(element, happyDomInstance.window);
90816
- const elementMap = new Map();
90817
- const serialized = serialize(happyDomInstance.document, elementMap);
90818
- set$1(state.uid, {
90819
- document: happyDomInstance.document,
90820
- elementMap,
90821
- window: happyDomInstance.window
90822
- });
90823
- const parsedDom = serialized.dom;
90824
- const {
90825
- css
90826
- } = serialized;
90827
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
90828
- return {
90829
- ...state,
90830
- css,
90831
- parsedDom,
90832
- parsedNodesChildNodeCount
90833
- };
90834
- };
90835
- const handleInput = (state, hdId, value) => {
90836
- if (!hdId) {
90837
- return state;
90838
- }
90839
- if (state.useSandboxWorker) {
90840
- return handleInputSandbox(state, hdId, value);
90841
- }
90842
- return handleInputLocal(state, hdId, value);
90843
- };
90844
-
90845
- const dispatchKeydownEvent = (element, window, key, code) => {
90846
- const keydownEvent = new window.KeyboardEvent('keydown', {
90847
- bubbles: true,
90848
- code,
90849
- key
90850
- });
90851
- dispatchEvent(element, keydownEvent);
90852
- };
90853
-
90854
- const handleKeydownSandbox = async (state, hdId, key, code) => {
90855
- const {
90856
- sandboxRpc,
90857
- uid
90858
- } = state;
90859
- await sandboxRpc.invoke('SandBox.handleKeyDown', uid, hdId, key, code);
90860
- const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
90861
- const parsedDom = serialized.dom;
90862
- const {
90863
- css
90864
- } = serialized;
90865
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
90866
- return {
90867
- ...state,
90868
- css,
90869
- parsedDom,
90870
- parsedNodesChildNodeCount
90871
- };
90872
- };
90873
- const handleKeydownLocal = (state, hdId, key, code) => {
90874
- const happyDomInstance = get(state.uid);
90875
- if (!happyDomInstance) {
90876
- return state;
90877
- }
90878
- const element = hdId ? happyDomInstance.elementMap.get(hdId) : happyDomInstance.document;
90879
- if (!element) {
90880
- return state;
90881
- }
90882
- dispatchKeydownEvent(element, happyDomInstance.window, key, code);
90883
- const elementMap = new Map();
90884
- const serialized = serialize(happyDomInstance.document, elementMap);
90885
- set$1(state.uid, {
90886
- document: happyDomInstance.document,
90887
- elementMap,
90888
- window: happyDomInstance.window
90889
- });
90890
- const parsedDom = serialized.dom;
90891
- const {
90892
- css
90893
- } = serialized;
90894
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
90895
- return {
90896
- ...state,
90897
- css,
90898
- parsedDom,
90899
- parsedNodesChildNodeCount
90900
- };
90901
- };
90902
- const handleKeydown = (state, hdId, key, code) => {
90903
- if (state.useSandboxWorker) {
90904
- return handleKeydownSandbox(state, hdId, key, code);
90905
- }
90906
- return handleKeydownLocal(state, hdId, key, code);
90907
- };
90908
-
90909
- const dispatchKeyupEvent = (element, window, key, code) => {
90910
- const keyupEvent = new window.KeyboardEvent('keyup', {
90911
- bubbles: true,
90912
- code,
90913
- key
90914
- });
90915
- dispatchEvent(element, keyupEvent);
90916
- };
90917
-
90918
- const handleKeyupSandbox = async (state, hdId, key, code) => {
90919
- const {
90920
- sandboxRpc,
90921
- uid
90922
- } = state;
90923
- await sandboxRpc.invoke('SandBox.handleKeyUp', uid, hdId, key, code);
90924
- const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
90925
- const parsedDom = serialized.dom;
90926
- const {
90927
- css
90928
- } = serialized;
90929
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
90930
- return {
90931
- ...state,
90932
- css,
90933
- parsedDom,
90934
- parsedNodesChildNodeCount
90935
- };
90936
- };
90937
- const handleKeyupLocal = (state, hdId, key, code) => {
90938
- const happyDomInstance = get(state.uid);
90939
- if (!happyDomInstance) {
90940
- return state;
90941
- }
90942
- const element = hdId ? happyDomInstance.elementMap.get(hdId) : happyDomInstance.document;
90943
- if (!element) {
90944
- return state;
90945
- }
90946
- dispatchKeyupEvent(element, happyDomInstance.window, key, code);
90947
- const elementMap = new Map();
90948
- const serialized = serialize(happyDomInstance.document, elementMap);
90949
- set$1(state.uid, {
90950
- document: happyDomInstance.document,
90951
- elementMap,
90952
- window: happyDomInstance.window
90953
- });
90954
- const parsedDom = serialized.dom;
90955
- const {
90956
- css
90957
- } = serialized;
90958
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
90959
- return {
90960
- ...state,
90961
- css,
90962
- parsedDom,
90963
- parsedNodesChildNodeCount
90964
- };
90965
- };
90966
- const handleKeyup = (state, hdId, key, code) => {
90967
- if (state.useSandboxWorker) {
90968
- return handleKeyupSandbox(state, hdId, key, code);
90969
- }
90970
- return handleKeyupLocal(state, hdId, key, code);
90971
- };
90972
-
90973
- const dispatchMousedownEvent = (element, window, clientX = 0, clientY = 0) => {
90974
- const mousedownEvent = new window.MouseEvent('mousedown', {
90975
- bubbles: true,
90976
- clientX,
90977
- clientY
90978
- });
90979
- dispatchEvent(element, mousedownEvent);
90980
- };
90981
-
90982
- const handleMousedownSandbox = async (state, hdId) => {
90983
- const {
90984
- sandboxRpc,
90985
- uid
90986
- } = state;
90987
- await sandboxRpc.invoke('SandBox.handleMousedown', uid, hdId);
90988
- const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
90989
- const parsedDom = serialized.dom;
90990
- const {
90991
- css
90992
- } = serialized;
90993
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
90994
- return {
90995
- ...state,
90996
- css,
90997
- parsedDom,
90998
- parsedNodesChildNodeCount
90999
- };
91000
- };
91001
- const handleMousedownLocal = (state, hdId, clientX, clientY) => {
91002
- const happyDomInstance = get(state.uid);
91003
- if (!happyDomInstance) {
91004
- return state;
91005
- }
91006
- const element = happyDomInstance.elementMap.get(hdId);
91007
- if (!element) {
91008
- return state;
91009
- }
91010
- const adjustedClientX = clientX - state.x;
91011
- const adjustedClientY = clientY - state.y;
91012
- dispatchMousedownEvent(element, happyDomInstance.window, adjustedClientX, adjustedClientY);
91013
- const elementMap = new Map();
91014
- const serialized = serialize(happyDomInstance.document, elementMap);
91015
- set$1(state.uid, {
91016
- document: happyDomInstance.document,
91017
- elementMap,
91018
- window: happyDomInstance.window
91019
- });
91020
- const parsedDom = serialized.dom;
91021
- const {
91022
- css
91023
- } = serialized;
91024
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
91025
- return {
91026
- ...state,
91027
- css,
91028
- parsedDom,
91029
- parsedNodesChildNodeCount
91030
- };
91031
- };
91032
- const handleMousedown = (state, hdId, clientX, clientY) => {
91033
- if (!hdId) {
91034
- return state;
91035
- }
91036
- if (state.useSandboxWorker) {
91037
- return handleMousedownSandbox(state, hdId);
91038
- }
91039
- return handleMousedownLocal(state, hdId, clientX, clientY);
91040
- };
91041
-
91042
- const dispatchMousemoveEvent = (element, window, clientX = 0, clientY = 0) => {
91043
- const mousemoveEvent = new window.MouseEvent('mousemove', {
91044
- bubbles: true,
91045
- clientX,
91046
- clientY
91047
- });
91048
- dispatchEvent(element, mousemoveEvent);
91049
- };
91050
-
91051
- const handleMousemoveSandbox = async (state, hdId) => {
91052
- const {
91053
- sandboxRpc,
91054
- uid
91055
- } = state;
91056
- await sandboxRpc.invoke('SandBox.handleMousemove', uid, hdId);
91057
- const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
91058
- const parsedDom = serialized.dom;
91059
- const {
91060
- css
91061
- } = serialized;
91062
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
91063
- return {
91064
- ...state,
91065
- css,
91066
- parsedDom,
91067
- parsedNodesChildNodeCount
91068
- };
91069
- };
91070
- const handleMousemoveLocal = (state, hdId, clientX, clientY) => {
91071
- const happyDomInstance = get(state.uid);
91072
- if (!happyDomInstance) {
91073
- return state;
91074
- }
91075
- const element = happyDomInstance.elementMap.get(hdId);
91076
- if (!element) {
91077
- return state;
91078
- }
91079
- const adjustedClientX = clientX - state.x;
91080
- const adjustedClientY = clientY - state.y;
91081
- dispatchMousemoveEvent(element, happyDomInstance.window, adjustedClientX, adjustedClientY);
91082
- const elementMap = new Map();
91083
- const serialized = serialize(happyDomInstance.document, elementMap);
91084
- set$1(state.uid, {
91085
- document: happyDomInstance.document,
91086
- elementMap,
91087
- window: happyDomInstance.window
91088
- });
91089
- const parsedDom = serialized.dom;
91090
- const {
91091
- css
91092
- } = serialized;
91093
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
91094
- return {
91095
- ...state,
91096
- css,
91097
- parsedDom,
91098
- parsedNodesChildNodeCount
91099
- };
91100
- };
91101
- const handleMousemove = (state, hdId, clientX, clientY) => {
91102
- if (!hdId) {
91103
- return state;
91104
- }
91105
- if (state.useSandboxWorker) {
91106
- return handleMousemoveSandbox(state, hdId);
91107
- }
91108
- return handleMousemoveLocal(state, hdId, clientX, clientY);
91109
- };
91110
-
91111
- const dispatchMouseupEvent = (element, window, clientX = 0, clientY = 0) => {
91112
- const mouseupEvent = new window.MouseEvent('mouseup', {
91113
- bubbles: true,
91114
- clientX,
91115
- clientY
91116
- });
91117
- dispatchEvent(element, mouseupEvent);
91118
- };
91119
-
91120
- const handleMouseupSandbox = async (state, hdId) => {
91121
- const {
91122
- sandboxRpc,
91123
- uid
91124
- } = state;
91125
- await sandboxRpc.invoke('SandBox.handleMouseup', uid, hdId);
91126
- const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', uid);
91127
- const parsedDom = serialized.dom;
91128
- const {
91129
- css
91130
- } = serialized;
91131
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
91132
- return {
91133
- ...state,
91134
- css,
91135
- parsedDom,
91136
- parsedNodesChildNodeCount
91137
- };
91138
- };
91139
- const handleMouseupLocal = (state, hdId) => {
91140
- const happyDomInstance = get(state.uid);
91141
- if (!happyDomInstance) {
91142
- return state;
91143
- }
91144
- const element = happyDomInstance.elementMap.get(hdId);
91145
- if (!element) {
91146
- return state;
91147
- }
91148
- dispatchMouseupEvent(element, happyDomInstance.window);
91149
- const elementMap = new Map();
91150
- const serialized = serialize(happyDomInstance.document, elementMap);
91151
- set$1(state.uid, {
91152
- document: happyDomInstance.document,
91153
- elementMap,
91154
- window: happyDomInstance.window
91155
- });
91156
- const parsedDom = serialized.dom;
91157
- const {
91158
- css
91159
- } = serialized;
91160
- const parsedNodesChildNodeCount = getParsedNodesChildNodeCount(parsedDom);
91161
- return {
91162
- ...state,
91163
- css,
91164
- parsedDom,
91165
- parsedNodesChildNodeCount
91166
- };
91167
- };
91168
- const handleMouseup = (state, hdId) => {
91169
- if (!hdId) {
91170
- return state;
91171
- }
91172
- if (state.useSandboxWorker) {
91173
- return handleMouseupSandbox(state, hdId);
91174
- }
91175
- return handleMouseupLocal(state, hdId);
91176
- };
91177
-
91178
- const loadContent = async state => {
89724
+ const loadContent = async (uid, width, height, content, scripts) => {
91179
89725
  // Try to register to receive editor change notifications from the editor worker.
91180
89726
  // Use dynamic access and ignore errors so this is safe in environments where
91181
89727
  // the EditorWorker / ListenerType are not available (e.g. unit tests).
91182
- const EditorChange = 1;
91183
- const rpcId = 9112;
91184
- try {
91185
- await invoke$1('Listener.register', EditorChange, rpcId);
91186
- } catch (error) {
91187
- console.error(error);
91188
- }
91189
89728
 
91190
89729
  // Read and parse file contents if we have a URI
91191
89730
  const {
91192
- content,
91193
- css,
91194
- errorMessage,
91195
- parsedDom,
91196
- parsedNodesChildNodeCount,
91197
- scripts
91198
- } = state.uri ? await updateContent(state, state.uri) : {
91199
- content: state.content,
91200
- css: state.css,
91201
- errorMessage: state.errorMessage,
91202
- parsedDom: state.parsedDom,
91203
- parsedNodesChildNodeCount: state.parsedNodesChildNodeCount,
91204
- scripts: state.scripts
91205
- };
91206
- const {
91207
- sandboxRpc
91208
- } = state;
91209
- let finalParsedDom = parsedDom;
91210
- let finalCss = css;
91211
- let finalParsedNodesChildNodeCount = parsedNodesChildNodeCount;
91212
- if (state.useSandboxWorker && scripts.length > 0) {
91213
- await sandboxRpc.invoke('SandBox.initialize', state.uid, content, scripts);
91214
- const serialized = await sandboxRpc.invoke('SandBox.getSerializedDom', state.uid);
91215
- finalParsedDom = serialized.dom;
91216
- finalCss = serialized.css;
91217
- finalParsedNodesChildNodeCount = finalParsedDom.length > 0 ? finalParsedDom[0].childCount || 0 : 0;
91218
- }
91219
- return {
91220
- ...state,
91221
- content,
91222
- css: finalCss,
91223
- errorCount: 0,
91224
- errorMessage,
91225
- initial: false,
91226
- parsedDom: finalParsedDom,
91227
- parsedNodesChildNodeCount: finalParsedNodesChildNodeCount,
91228
- sandboxRpc,
91229
- scripts,
91230
- warningCount: 1
91231
- };
91232
- };
91233
-
91234
- const BODY_SELECTOR_REGEX = /\bbody\b/g;
91235
- const HTML_SELECTOR_REGEX = /\bhtml\b/g;
91236
-
91237
- /**
91238
- * Wraps CSS in a CSS nesting block (.Preview { ... }) and replaces 'html' and 'body'
91239
- * selectors with '&' (the parent selector in CSS nesting).
91240
- * This approach uses CSS nesting to automatically scope all selectors to the preview div.
91241
- * Other selectors like 'button' or '*' are automatically scoped within the nesting.
91242
- *
91243
- * @param css The CSS string to process
91244
- * @returns The CSS string wrapped in .Preview nesting block with proper selector replacements
91245
- */
91246
- const replaceCssBodySelector = css => {
91247
- if (!css.trim()) {
91248
- return css;
91249
- }
91250
-
91251
- // Replace 'html' selector with '&' (CSS nesting parent selector)
91252
- let result = css.replaceAll(HTML_SELECTOR_REGEX, '&');
91253
-
91254
- // Replace 'body' selector with '&' (CSS nesting parent selector)
91255
- result = result.replaceAll(BODY_SELECTOR_REGEX, '&');
91256
-
91257
- // Wrap the entire CSS in .Preview nesting block
91258
- result = `.Preview {\n${result}\n}`;
91259
- return result;
91260
- };
91261
-
91262
- const renderCss = (oldState, newState) => {
91263
- const {
91264
- css,
91265
- uid
91266
- } = newState;
91267
-
91268
- // Combine all CSS strings into a single string
91269
- let cssString = css.join('\n');
91270
-
91271
- // Replace body selector with .Preview since we render the preview in a div element, not a body
91272
- cssString = replaceCssBodySelector(cssString);
91273
-
91274
- // Return command in format that can be handled by the viewlet
91275
- // The 'Viewlet.setCss' is a method that should be called on the viewlet
91276
- return ['Viewlet.setCss', uid, cssString];
91277
- };
91278
-
91279
- const HandleInput = 4;
91280
- const HandleClick = 11;
91281
- const HandleKeydown = 12;
91282
- const HandleKeyup = 13;
91283
- const HandleMousedown = 14;
91284
- const HandleMousemove = 15;
91285
- const HandleMouseup = 16;
91286
-
91287
- const getEmptyPreviewDom = () => {
91288
- return [{
91289
- childCount: 1,
91290
- className: 'Viewlet Preview',
91291
- type: Div$1
91292
- }, {
91293
- childCount: 1,
91294
- type: H1$1
91295
- }, {
91296
- text: 'No URI has been specified',
91297
- type: Text$2
91298
- }];
91299
- };
91300
-
91301
- const getPreviewDom = state => {
91302
- const {
91303
- parsedDom,
91304
- parsedNodesChildNodeCount,
91305
- uri
91306
- } = state;
91307
- if (!uri) {
91308
- return getEmptyPreviewDom();
91309
- }
91310
-
91311
- // If parsedDom is available, render it as children of the wrapper
91312
- if (parsedDom && parsedDom.length > 0) {
91313
- return [{
91314
- childCount: parsedNodesChildNodeCount,
91315
- className: 'Viewlet Preview',
91316
- onClick: HandleClick,
91317
- onInput: HandleInput,
91318
- onKeyDown: HandleKeydown,
91319
- onKeyUp: HandleKeyup,
91320
- onMouseDown: HandleMousedown,
91321
- onMouseMove: HandleMousemove,
91322
- onMouseUp: HandleMouseup,
91323
- tabIndex: 0,
91324
- type: Div$1
91325
- }, ...parsedDom];
91326
- }
91327
- return [{
91328
- childCount: 1,
91329
- className: 'Viewlet Preview',
91330
- onClick: HandleClick,
91331
- onInput: HandleInput,
91332
- onKeyDown: HandleKeydown,
91333
- onKeyUp: HandleKeyup,
91334
- onMouseDown: HandleMousedown,
91335
- onMouseMove: HandleMousemove,
91336
- onMouseUp: HandleMouseup,
91337
- tabIndex: 0,
91338
- type: Div$1
91339
- }, {
91340
- childCount: 1,
91341
- type: H1$1
91342
- }, {
91343
- text: 'Edit the file on the left to get started.',
91344
- type: Text$2
91345
- }];
91346
- };
91347
-
91348
- const renderItems = (oldState, newState) => {
91349
- const {
91350
- initial,
91351
- uid
91352
- } = newState;
91353
- if (initial) {
91354
- return [SetDom2, uid, []];
91355
- }
91356
- const dom = getPreviewDom(newState);
91357
- return [SetDom2, uid, dom];
91358
- };
91359
-
91360
- const renderIncremental = (oldState, newState) => {
91361
- const oldDom = renderItems(oldState, oldState)[2];
91362
- const newDom = renderItems(newState, newState)[2];
91363
- const patches = diffTree(oldDom, newDom);
91364
- return [SetPatches, newState.uid, patches];
91365
- };
91366
-
91367
- const getRenderer = diffType => {
91368
- switch (diffType) {
91369
- case RenderCss:
91370
- return renderCss;
91371
- case RenderIncremental:
91372
- return renderIncremental;
91373
- case RenderItems:
91374
- return renderItems;
91375
- default:
91376
- throw new Error('unknown renderer');
91377
- }
91378
- };
91379
-
91380
- const applyRender = (oldState, newState, diffResult) => {
91381
- const commands = [];
91382
- for (const item of diffResult) {
91383
- const fn = getRenderer(item);
91384
- const result = fn(oldState, newState);
91385
- if (result.length > 0) {
91386
- commands.push(result);
91387
- }
91388
- }
91389
- return commands;
91390
- };
91391
-
91392
- const render2 = (uid, diffResult) => {
91393
- const {
91394
- newState,
91395
- oldState
91396
- } = get$1(uid);
91397
- set$2(uid, newState, newState);
91398
- const commands = applyRender(oldState, newState, diffResult);
91399
- return commands;
91400
- };
91401
-
91402
- const renderEventListeners = () => {
91403
- return [{
91404
- capture: true,
91405
- name: HandleClick,
91406
- params: ['handleClick', 'event.target.dataset.id']
91407
- }, {
91408
- capture: true,
91409
- name: HandleInput,
91410
- params: ['handleInput', 'event.target.dataset.id', 'event.target.value']
91411
- }, {
91412
- capture: true,
91413
- name: HandleKeydown,
91414
- params: ['handleKeyDown', 'event.target.dataset.id', 'event.key', 'event.code']
91415
- }, {
91416
- capture: true,
91417
- name: HandleKeyup,
91418
- params: ['handleKeyUp', 'event.target.dataset.id', 'event.key', 'event.code']
91419
- }, {
91420
- capture: true,
91421
- name: HandleMousedown,
91422
- params: ['handleMousedown', 'event.target.dataset.id', 'event.clientX', 'event.clientY']
91423
- }, {
91424
- capture: true,
91425
- name: HandleMousemove,
91426
- params: ['handleMousemove', 'event.target.dataset.id', 'event.clientX', 'event.clientY']
91427
- }, {
91428
- capture: true,
91429
- name: HandleMouseup,
91430
- params: ['handleMouseup', 'event.target.dataset.id']
91431
- }];
91432
- };
91433
-
91434
- const rerender = state => {
91435
- // Create a new copy of parsedDom array to trigger diff
91436
- const parsedDom = [...state.parsedDom];
91437
-
91438
- // Return a new state object with the copied parsedDom
91439
- // This will cause DiffItems.isEqual to return false since parsedDom reference changed
89731
+ errorMessage
89732
+ } = await updateContent(uid, width, height, content, scripts);
91440
89733
  return {
91441
- ...state,
91442
- parsedDom
89734
+ errorMessage
91443
89735
  };
91444
89736
  };
91445
89737
 
@@ -91450,68 +89742,27 @@ const resize = (state, dimensions) => {
91450
89742
  };
91451
89743
  };
91452
89744
 
91453
- const saveState = state => {
91454
- return {
91455
- x: 0
91456
- };
91457
- };
91458
-
91459
- const setUri = async (state, uri) => {
91460
- const {
91461
- content,
91462
- css,
91463
- errorMessage,
91464
- parsedDom,
91465
- parsedNodesChildNodeCount,
91466
- scripts
91467
- } = await updateContent(state, uri);
91468
- return {
91469
- ...state,
91470
- content,
91471
- css,
91472
- errorMessage,
91473
- parsedDom,
91474
- parsedNodesChildNodeCount,
91475
- scripts,
91476
- uri
91477
- };
91478
- };
91479
-
91480
89745
  const commandMap = {
91481
- handleEditorChanged: handleEditorChanged,
91482
- 'Preview.create': create,
91483
- 'Preview.diff2': diff2,
91484
- 'Preview.executeCallback': executeCallback,
91485
- 'Preview.getCommandIds': getCommandIds,
91486
- 'Preview.handleClick': wrapCommand(handleClick),
91487
- 'Preview.handleFileEdited': wrapCommand(handleFileEdited),
91488
- 'Preview.handleInput': wrapCommand(handleInput),
91489
- 'Preview.handleKeyDown': wrapCommand(handleKeydown),
91490
- 'Preview.handleKeyUp': wrapCommand(handleKeyup),
91491
- 'Preview.handleMousedown': wrapCommand(handleMousedown),
91492
- 'Preview.handleMousemove': wrapCommand(handleMousemove),
91493
- 'Preview.handleMouseup': wrapCommand(handleMouseup),
91494
- 'Preview.loadContent': wrapCommand(loadContent),
91495
- 'Preview.render2': render2,
91496
- 'Preview.renderEventListeners': renderEventListeners,
91497
- 'Preview.rerender': wrapCommand(rerender),
91498
- 'Preview.resize': wrapCommand(resize),
91499
- 'Preview.saveState': wrapGetter(saveState),
91500
- 'Preview.setUri': wrapCommand(setUri),
91501
- 'Preview.terminate': terminate
89746
+ 'SandBox.executeCallback': executeCallback,
89747
+ 'SandBox.getSerializedDom': getSerializedDom,
89748
+ 'SandBox.handleClick': handleClick,
89749
+ 'SandBox.handleInput': handleInput,
89750
+ 'SandBox.handleKeyDown': handleKeydown,
89751
+ 'SandBox.handleKeyUp': handleKeyup,
89752
+ 'SandBox.handleMessagePort': handleMessagePort,
89753
+ 'SandBox.handleMousedown': handleMousedown,
89754
+ 'SandBox.handleMousemove': handleMousemove,
89755
+ 'SandBox.handleMouseup': handleMouseup,
89756
+ 'SandBox.loadContent': loadContent,
89757
+ 'SandBox.resize': resize,
89758
+ 'SandBox.terminate': terminate
91502
89759
  };
91503
89760
 
91504
89761
  const listen = async () => {
91505
- registerCommands(commandMap);
91506
89762
  const rpc = await WebWorkerRpcClient.create({
91507
89763
  commandMap: commandMap
91508
89764
  });
91509
- set$3(rpc);
91510
- const editorRpc = await LazyTransferMessagePortRpcParent.create({
91511
- commandMap: {},
91512
- send: port => sendMessagePortToEditorWorker(port, 9112)
91513
- });
91514
- set$4(editorRpc);
89765
+ set$2(rpc);
91515
89766
  };
91516
89767
 
91517
89768
  const main = async () => {