Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions examples/server-side-rendering/backend/app.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'module-alias/register';
import { join } from 'node:path';
import zlib from 'node:zlib';
import express from 'express';
import compression from 'compression';
import { json } from 'body-parser';
Expand All @@ -21,12 +22,19 @@ app.use('/service-worker.js.map', express.static(join(__dirname, '../frontend/st
createRestApi(app);

app.get('*', (req, res) => {
const encoding = req.headers['accept-encoding'] || '';
const { url } = req;
console.log('url', url);
const stream = bootstrap({ props: { url, api } });

console.log('url', url);
res.statusCode = 200;
stream.pipe(res);

if (encoding.includes('gzip')) {
res.setHeader('Content-Encoding', 'gzip');
stream.pipe(zlib.createGzip()).pipe(res);
} else {
stream.pipe(res);
}
});

const server = app.listen(PORT, () => {
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ const Metadata = component<MetadataProps>(({ marker }) => {
<meta name='theme-color' content='#fdd835' />
<meta name='description' content={description} />
<link rel='manifest' href='/static/assets/manifest.webmanifest' />
<link rel='preload' href='/static/assets/fonts/Roboto-Regular.ttf' _as='font' crossorigin='anonymous' />
<link
rel='preload'
href='/static/assets/fonts/Roboto-Regular.woff2'
_as='font'
type='font/woff2'
crossorigin='anonymous'
/>
<base href='/' />
<title>{title}</title>
</Metatags>
Expand Down
2 changes: 1 addition & 1 deletion examples/server-side-rendering/frontend/components/ui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const GlobalStyle = createGlobalStyle`
font-family: 'Roboto';
font-weight: 400;
font-display: swap;
src: url('/static/assets/fonts/Roboto-Regular.ttf');
src: url('/static/assets/fonts/Roboto-Regular.woff2');
}

*, *::before, *::after {
Expand Down
13 changes: 4 additions & 9 deletions packages/core/src/fiber/fiber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,19 +186,14 @@ class Hook<T = unknown> {
}

drop() {
const { atoms } = this;
const { atoms, values, owner } = this;

if (this.values.length > 0) {
const $hook = this as Hook<HookValue<UseEffectValue>>;

this.owner.mask & EFFECT_HOST_MASK && dropEffects($hook);
if (values.length > 0 && owner.mask & EFFECT_HOST_MASK) {
dropEffects(this as Hook<HookValue<UseEffectValue>>);
}

if (atoms) {
for (const [_, cleanup] of atoms) {
cleanup();
}

for (const [_, cleanup] of atoms) cleanup();
this.atoms = null;
}
}
Expand Down
11 changes: 7 additions & 4 deletions packages/core/src/unmount/unmount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { EFFECT_HOST_MASK, ATOM_HOST_MASK } from '../constants';
import { removeScope, $$scope } from '../scope';
import { detectIsUndefined } from '../utils';
import { type Callback } from '../shared';
import { platform } from '../platform';
import { type Fiber } from '../fiber';
import { walk } from '../walk';

Expand All @@ -19,14 +20,16 @@ function onWalk(fiber: Fiber, skip: Callback) {
hook?.drop();
}

function unmountRoot(rootId: number, onCompleted: () => void) {
function unmountRoot(rootId: number) {
if (detectIsUndefined(rootId)) return;
const $scope = $$scope(rootId);

unmountFiber($scope.getRoot());
$scope.off();
if (platform.detectIsDynamic()) {
unmountFiber($scope.getRoot());
$scope.off();
}

removeScope(rootId);
onCompleted();
}

export { unmountFiber, unmountRoot };
3 changes: 3 additions & 0 deletions packages/core/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ const mapRecord = <T extends object>(record: T) => keys(record).map(x => record[

const createError = (x: unknown) => (x instanceof Error ? x : new Error(String(x)));

const stringify = JSON.stringify as (x: unknown) => string;

export {
detectIsFunction,
detectIsUndefined,
Expand Down Expand Up @@ -99,4 +101,5 @@ export {
createIndexKey,
mapRecord,
createError,
stringify,
};
73 changes: 40 additions & 33 deletions packages/core/src/workloop/workloop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,47 +388,54 @@ function supportConditional(inst: Instance) {
}

function commit($scope: Scope) {
const isStream = $scope.getIsStream();

if (process.env.NODE_ENV !== 'production') {
process.env.NODE_ENV === 'development' && $scope.setIsHot(false);
}

const wip = $scope.getWorkInProgress();
const deletions = $scope.getDeletions();
const candidates = $scope.getCandidates();
const isUpdate = $scope.getIsUpdate();
const awaiter = $scope.getAwaiter();
const unmounts: Array<Fiber> = [];
const inst = wip.inst as Component;

// !
for (const fiber of deletions) {
const canAsync = fiber.mask & ATOM_HOST_MASK && !(fiber.mask & EFFECT_HOST_MASK);

canAsync ? unmounts.push(fiber) : unmountFiber(fiber);
fiber.tag = DELETE_EFFECT_TAG;
platform.commit(fiber);
}
if (isStream) {
platform.finishCommit();
cleanup($scope);
} else {
const wip = $scope.getWorkInProgress();
const deletions = $scope.getDeletions();
const candidates = $scope.getCandidates();
const isUpdate = $scope.getIsUpdate();
const awaiter = $scope.getAwaiter();
const unmounts: Array<Fiber> = [];
const inst = wip.inst as Component;

// !
for (const fiber of deletions) {
const canAsync = fiber.mask & ATOM_HOST_MASK && !(fiber.mask & EFFECT_HOST_MASK);

canAsync ? unmounts.push(fiber) : unmountFiber(fiber);
fiber.tag = DELETE_EFFECT_TAG;
platform.commit(fiber);
}

isUpdate && sync(wip);
$scope.runInsertionEffects();
isUpdate && sync(wip);
$scope.runInsertionEffects();

for (const fiber of candidates) {
const item = fiber.inst as CanHaveChildren;
for (const fiber of candidates) {
const item = fiber.inst as CanHaveChildren;

fiber.tag !== SKIP_EFFECT_TAG && platform.commit(fiber);
fiber.alt = null;
item.children && (item.children = null);
}
fiber.tag !== SKIP_EFFECT_TAG && platform.commit(fiber);
fiber.alt = null;
item.children && (item.children = null);
}

wip.alt = null;
wip.hook?.setIsWip(false);
inst.children = null;
platform.finishCommit(); // !
$scope.runLayoutEffects();
$scope.runAsyncEffects();
awaiter.resolve();
unmounts.length > 0 && setTimeout(onUnmount(unmounts));
cleanup($scope);
wip.alt = null;
wip.hook?.setIsWip(false);
inst.children = null;
platform.finishCommit(); // !
$scope.runLayoutEffects();
$scope.runAsyncEffects();
awaiter.resolve();
unmounts.length > 0 && setTimeout(onUnmount(unmounts));
cleanup($scope);
}
}

const onUnmount = (fibers: Array<Fiber>) => () => fibers.forEach(unmountFiber);
Expand Down
3 changes: 2 additions & 1 deletion packages/data/src/use-query/use-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ import {
useId,
$$scope,
throwThis,
stringify,
__useSSR as useSSR,
__useInSuspense as useInSuspense,
__useInBoundary as useInBoundary,
} from '@dark-engine/core';

import { type InMemoryCache, checkCache } from '../cache';
import { illegal, stringify } from '../utils';
import { ROOT_ID } from '../constants';
import { useCache } from '../client';
import { illegal } from '../utils';

export type UseQueryOptions<T, V extends Variables> = {
variables?: V;
Expand Down
4 changes: 1 addition & 3 deletions packages/data/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,4 @@ import { LIB } from '../constants';

const illegal = (x: string) => $illegal(x, LIB);

const stringify = (x: unknown) => JSON.stringify(x);

export { illegal, stringify };
export { illegal };
7 changes: 3 additions & 4 deletions packages/platform-browser/src/create-root/create-root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ function createRoot(container: TagNativeElement) {
function unmount(container: TagNativeElement) {
const rootId = roots.get(container);

unmountRoot(rootId, () => {
roots.delete(container);
removeContent(container);
});
unmountRoot(rootId);
roots.delete(container);
removeContent(container);
}

export { createRoot, unmount };
2 changes: 1 addition & 1 deletion packages/platform-native/src/render/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ function render(options: RenderOptions): NSElement {
if (detectIsFunction(onCompleted)) {
const nativeView = getRootNativeView();

isSubRoot && unmountRoot(rootId, () => {});
isSubRoot && unmountRoot(rootId);
onCompleted(nativeView);
}

Expand Down
34 changes: 4 additions & 30 deletions packages/platform-server/src/dom/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,17 @@ import {
ROOT,
REF_ATTR,
ATTR_BLACK_LIST,
CREATE_EFFECT_TAG,
detectIsFunction,
detectIsUndefined,
NodeType,
detectIsTagVirtualNode,
getFiberWithElement,
dummyFn,
detectIsPlainVirtualNode,
detectIsTextVirtualNode,
createReplacer,
detectIsTextBased,
} from '@dark-engine/core';
import {
type AttributeValue,
VALUE_ATTR,
TEXTAREA_TAG,
PREVENT,
detectIsVoidElement,
} from '@dark-engine/platform-browser';
import { type AttributeValue, VALUE_ATTR, TEXTAREA_TAG, PREVENT } from '@dark-engine/platform-browser';

import { NativeElement, TagNativeElement, TextNativeElement, CommentNativeElement } from '../native-element';

Expand Down Expand Up @@ -82,28 +75,9 @@ const specialCasesMap: Record<
},
};

function commitCreation(fiber: Fiber<NativeElement>) {
const parent = getFiberWithElement<NativeElement, TagNativeElement>(fiber.parent);
const parentElement = parent.el;
const vNode = parent.inst as TagVirtualNode;

!detectIsVoidElement(vNode.name) && appendNativeElement(fiber.el, parentElement);
detectIsTagVirtualNode(fiber.inst) && addAttributes(fiber.el, fiber.inst as TagVirtualNode);
}
const commit = dummyFn;

function commit(fiber: Fiber<NativeElement>) {
switch (fiber.tag) {
case CREATE_EFFECT_TAG:
fiber.el && commitCreation(fiber);
break;
default:
break;
}
}

const finishCommit = () => {
chunkIds = {};
};
const finishCommit = () => (chunkIds = {});

function createChunk(fiber: Fiber<NativeElement>) {
let chunk = '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
CLASS_NAME_ATTR,
EXCLUDE_ATTR_MARK,
TEXTAREA_TAG,
VALUE_ATTR,
DANGER_HTML_ATTR,
detectIsVoidElement,
} from '@dark-engine/platform-browser';
Expand Down Expand Up @@ -56,9 +55,7 @@ class TagNativeElement extends NativeElement {

override render(isOpening?: boolean) {
const content =
this.name === TEXTAREA_TAG
? (this.attrs[VALUE_ATTR] as string) || ''
: (this.attrs[DANGER_HTML_ATTR] as string) || '';
this.name === TEXTAREA_TAG ? this.children[0]?.render() || '' : (this.attrs[DANGER_HTML_ATTR] as string) || '';
const isVoid = detectIsVoidElement(this.name);
const attrs = getAttributes(this.attrs);
const chunk = isOpening
Expand Down
4 changes: 2 additions & 2 deletions packages/platform-server/src/render/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,15 @@ function renderToReadableStream(element: DarkElement, options?: RenderToStreamOp

stream.push(withState());
stream.push(null);
unmountRoot(rootId, dummyFn);
unmountRoot(rootId);
};

const onError = (err: string) => {
const rootId = getRootId();

stream.emit('error', new Error(err));
stream.push(null);
unmountRoot(rootId, dummyFn);
unmountRoot(rootId);
};

scheduleRender({ element, onStart, onCompleted, onError });
Expand Down
Loading