Skip to content

Commit

Permalink
fix(qwik): don't bundle qwik internals in server
Browse files Browse the repository at this point in the history
Since /server is a separate entry point, all qwik code should come from imports and not be copied into the library.
Otherwise, we'd have multiple copies of singletons.
  • Loading branch information
wmertens committed Nov 22, 2024
1 parent 6746042 commit 521c98d
Show file tree
Hide file tree
Showing 29 changed files with 213 additions and 215 deletions.
3 changes: 1 addition & 2 deletions packages/qwik/src/core/client/dom-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ import {
} from './types';
import {
VNodeJournalOpCode,
mapArray_get,
mapArray_set,
vnode_applyJournal,
vnode_getDOMChildNodes,
vnode_getDomParent,
Expand All @@ -69,6 +67,7 @@ import {
vnode_setProp,
type VNodeJournal,
} from './vnode';
import { mapArray_get, mapArray_set } from './mapArray';
import { vnode_diff } from './vnode-diff';

/** @public */
Expand Down
70 changes: 70 additions & 0 deletions packages/qwik/src/core/client/mapArray.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { assertTrue } from '../shared/error/assert';

export const mapApp_findIndx = <T>(
elementVNode: (T | null)[],
key: string,
start: number
): number => {
assertTrue(start % 2 === 0, 'Expecting even number.');
let bottom = (start as number) >> 1;
let top = (elementVNode.length - 2) >> 1;
while (bottom <= top) {
const mid = bottom + ((top - bottom) >> 1);
const midKey = elementVNode[mid << 1] as string;
if (midKey === key) {
return mid << 1;
}
if (midKey < key) {
bottom = mid + 1;
} else {
top = mid - 1;
}
}
return (bottom << 1) ^ -1;
};

export const mapArray_set = <T>(
elementVNode: (T | null)[],
key: string,
value: T | null,
start: number
) => {
const indx = mapApp_findIndx(elementVNode, key, start);
if (indx >= 0) {
if (value == null) {
elementVNode.splice(indx, 2);
} else {
elementVNode[indx + 1] = value;
}
} else if (value != null) {
elementVNode.splice(indx ^ -1, 0, key as any, value);
}
};

export const mapApp_remove = <T>(
elementVNode: (T | null)[],
key: string,
start: number
): T | null => {
const indx = mapApp_findIndx(elementVNode, key, start);
let value: T | null = null;
if (indx >= 0) {
value = elementVNode[indx + 1];
elementVNode.splice(indx, 2);
return value;
}
return value;
};

export const mapArray_get = <T>(
elementVNode: (T | null)[],
key: string,
start: number
): T | null => {
const indx = mapApp_findIndx(elementVNode, key, start);
if (indx >= 0) {
return elementVNode[indx + 1] as T | null;
} else {
return null;
}
};
53 changes: 26 additions & 27 deletions packages/qwik/src/core/client/vnode-diff.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { isDev } from '@qwik.dev/core/build';
import { executeComponent } from '../shared/component-execution';
import { SERIALIZABLE_STATE, type OnRenderFn } from '../shared/component.public';
import { assertDefined, assertFalse, assertTrue } from '../shared/error/assert';
import type { QRLInternal } from '../shared/qrl/qrl-class';
import type { QRL } from '../shared/qrl/qrl.public';
import {
Fragment,
JSXNodeImpl,
Expand All @@ -14,9 +13,21 @@ import { Slot } from '../shared/jsx/slot.public';
import type { JSXNodeInternal, JSXOutput } from '../shared/jsx/types/jsx-node';
import type { JSXChildren } from '../shared/jsx/types/jsx-qwik-attributes';
import { SSRComment, SSRRaw, SkipRender } from '../shared/jsx/utils.public';
import { trackSignal, untrack } from '../use/use-core';
import { TaskFlags, cleanupTask, isTask } from '../use/use-task';
import type { QRLInternal } from '../shared/qrl/qrl-class';
import type { QRL } from '../shared/qrl/qrl.public';
import { ChoreType, type NodePropData } from '../shared/scheduler';
import type { HostElement, QElement, QwikLoaderEventScope, qWindow } from '../shared/types';
import { DEBUG_TYPE, QContainerValue, VirtualType } from '../shared/types';
import { escapeHTML } from '../shared/utils/character-escaping';
import {
convertEventNameFromJsxPropToHtmlAttr,
getEventNameFromJsxProp,
getEventNameScopeFromJsxProp,
isHtmlAttributeAnEventName,
isJsxPropertyAnEventName,
} from '../shared/utils/event-names';
import { EMPTY_OBJ } from '../shared/utils/flyweight';
import { throwErrorAndStop } from '../shared/utils/log';
import {
ELEMENT_KEY,
ELEMENT_PROPS,
Expand All @@ -31,19 +42,20 @@ import {
dangerouslySetInnerHTML,
} from '../shared/utils/markers';
import { isPromise } from '../shared/utils/promises';
import { isParentSlotProp, isSlotProp } from '../shared/utils/prop';
import { hasClassAttr } from '../shared/utils/scoped-styles';
import { serializeAttribute } from '../shared/utils/styles';
import { type ValueOrPromise } from '../shared/utils/types';
import { EffectData, EffectProperty, WrappedSignal, isSignal } from '../signal/signal';
import {
convertEventNameFromJsxPropToHtmlAttr,
getEventNameFromJsxProp,
getEventNameScopeFromJsxProp,
isHtmlAttributeAnEventName,
isJsxPropertyAnEventName,
} from '../shared/utils/event-names';
import { ChoreType, type NodePropData } from '../shared/scheduler';
import { hasClassAttr } from '../shared/utils/scoped-styles';
import type { HostElement, QElement, QwikLoaderEventScope, qWindow } from '../shared/types';
import { DEBUG_TYPE, QContainerValue, VirtualType } from '../shared/types';
clearSubscriberEffectDependencies,
clearVNodeEffectDependencies,
} from '../signal/signal-subscriber';
import type { Signal } from '../signal/signal.public';
import { trackSignal, untrack } from '../use/use-core';
import { TaskFlags, cleanupTask, isTask } from '../use/use-task';
import type { DomContainer } from './dom-container';
import { mapApp_findIndx, mapArray_set } from './mapArray';
import {
ElementVNodeProps,
VNodeFlags,
Expand All @@ -58,8 +70,6 @@ import {
type VirtualVNode,
} from './types';
import {
mapApp_findIndx,
mapArray_set,
vnode_ensureElementInflated,
vnode_getAttr,
vnode_getDomParentVNode,
Expand Down Expand Up @@ -91,17 +101,6 @@ import {
type VNodeJournal,
} from './vnode';
import { getNewElementNamespaceData } from './vnode-namespace';
import { WrappedSignal, EffectProperty, isSignal, EffectData } from '../signal/signal';
import type { Signal } from '../signal/signal.public';
import { executeComponent } from '../shared/component-execution';
import { isParentSlotProp, isSlotProp } from '../shared/utils/prop';
import { escapeHTML } from '../shared/utils/character-escaping';
import {
clearSubscriberEffectDependencies,
clearVNodeEffectDependencies,
} from '../signal/signal-subscriber';
import { throwErrorAndStop } from '../shared/utils/log';
import { serializeAttribute } from '../shared/utils/styles';

export type ComponentQueue = Array<VNode>;

Expand Down
72 changes: 1 addition & 71 deletions packages/qwik/src/core/client/vnode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ import {
vnode_getElementNamespaceFlags,
} from './vnode-namespace';
import { escapeHTML } from '../shared/utils/character-escaping';
import { mapArray_set, mapArray_get, mapApp_findIndx } from './mapArray';

//////////////////////////////////////////////////////////////////////////////////////////////////////

Expand Down Expand Up @@ -940,77 +941,6 @@ export const vnode_applyJournal = (journal: VNodeJournal) => {

//////////////////////////////////////////////////////////////////////////////////////////////////////

export const mapApp_findIndx = <T>(
elementVNode: (T | null)[],
key: string,
start: number
): number => {
assertTrue(start % 2 === 0, 'Expecting even number.');
let bottom = (start as number) >> 1;
let top = (elementVNode.length - 2) >> 1;
while (bottom <= top) {
const mid = bottom + ((top - bottom) >> 1);
const midKey = elementVNode[mid << 1] as string;
if (midKey === key) {
return mid << 1;
}
if (midKey < key) {
bottom = mid + 1;
} else {
top = mid - 1;
}
}
return (bottom << 1) ^ -1;
};

export const mapArray_set = <T>(
elementVNode: (T | null)[],
key: string,
value: T | null,
start: number
) => {
const indx = mapApp_findIndx(elementVNode, key, start);
if (indx >= 0) {
if (value == null) {
elementVNode.splice(indx, 2);
} else {
elementVNode[indx + 1] = value;
}
} else if (value != null) {
elementVNode.splice(indx ^ -1, 0, key as any, value);
}
};

export const mapApp_remove = <T>(
elementVNode: (T | null)[],
key: string,
start: number
): T | null => {
const indx = mapApp_findIndx(elementVNode, key, start);
let value: T | null = null;
if (indx >= 0) {
value = elementVNode[indx + 1];
elementVNode.splice(indx, 2);
return value;
}
return value;
};

export const mapArray_get = <T>(
elementVNode: (T | null)[],
key: string,
start: number
): T | null => {
const indx = mapApp_findIndx(elementVNode, key, start);
if (indx >= 0) {
return elementVNode[indx + 1] as T | null;
} else {
return null;
}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////

export const vnode_insertBefore = (
journal: VNodeJournal,
parent: ElementVNode | VirtualVNode,
Expand Down
3 changes: 2 additions & 1 deletion packages/qwik/src/core/shared/component-execution.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isDev } from '@qwik.dev/core/build';
import { isQwikComponent, type OnRenderFn } from './component.public';
import { assertDefined } from './error/assert';
import { isQrl, type QRLInternal } from './qrl/qrl-class';
import type { QRLInternal } from './qrl/qrl-class';
import { JSXNodeImpl, isJSXNode, type Props } from './jsx/jsx-runtime';
import type { JSXNodeInternal, JSXOutput } from './jsx/types/jsx-node';
import type { KnownEventNames } from './jsx/types/jsx-qwik-events';
Expand All @@ -23,6 +23,7 @@ import { logWarn } from './utils/log';
import { EffectProperty, isSignal } from '../signal/signal';
import { vnode_isVNode } from '../client/vnode';
import { clearVNodeEffectDependencies } from '../signal/signal-subscriber';
import { isQrl } from './qrl/qrl-utils';

/**
* Use `executeComponent` to execute a component.
Expand Down
2 changes: 1 addition & 1 deletion packages/qwik/src/core/shared/component.public.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {
import type { FunctionComponent } from './jsx/types/jsx-node';
import { _CONST_PROPS, _VAR_PROPS, _jsxSorted, _jsxSplit } from '../internal';
import type { QwikIntrinsicElements } from './jsx/types/jsx-qwik-elements';
import { assertQrl } from './qrl/qrl-class';
import { assertQrl } from './qrl/qrl-utils';
import { assertNumber } from './error/assert';
import { qTest } from './utils/qdev';

Expand Down
2 changes: 1 addition & 1 deletion packages/qwik/src/core/shared/platform/platform.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isServer } from '@qwik.dev/core/build';
import { qError, QError_qrlMissingChunk, QError_qrlMissingContainer } from '../error/error';
import { getSymbolHash } from '../qrl/qrl-class';
import { getSymbolHash } from '../qrl/qrl-utils';
import { qDynamicPlatform } from '../utils/qdev';
import type { CorePlatform } from './types';

Expand Down
39 changes: 1 addition & 38 deletions packages/qwik/src/core/shared/qrl/qrl-class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,16 @@ import { getQFuncs, QInstanceAttr } from '../utils/markers';
import { isPromise, maybeThen } from '../utils/promises';
import { qDev, qSerialize, qTest, seal } from '../utils/qdev';
import { isArray, isFunction, type ValueOrPromise } from '../utils/types';
import { isSignal } from '../../signal/signal';
import type { QRLDev } from './qrl';
import type { QRL, QrlArgs, QrlReturn } from './qrl.public';
import type { Signal } from '../../signal/signal.public';

export const isQrl = <T = unknown>(value: unknown): value is QRLInternal<T> => {
return typeof value === 'function' && typeof (value as any).getSymbol === 'function';
};

// Make sure this value is same as value in `platform.ts`
export const SYNC_QRL = '<sync>';
import { getSymbolHash, SYNC_QRL } from './qrl-utils';

interface SyncQRLSymbol {
$symbol$: typeof SYNC_QRL;
}

export type SyncQRLInternal = QRLInternal & SyncQRLSymbol;

/** Sync QRL is a function which is serialized into `<script q:func="qwik/json">` tag. */
export const isSyncQrl = (value: any): value is SyncQRLInternal => {
return isQrl(value) && value.$symbol$ == SYNC_QRL;
};

export type QRLInternalMethods<TYPE> = {
readonly $chunk$: string | null;
readonly $symbol$: string;
Expand Down Expand Up @@ -239,30 +226,6 @@ export const createQRL = <TYPE>(
return qrl;
};

export const getSymbolHash = (symbolName: string) => {
const index = symbolName.lastIndexOf('_');
if (index > -1) {
return symbolName.slice(index + 1);
}
return symbolName;
};

export function assertQrl<T>(qrl: QRL<T>): asserts qrl is QRLInternal<T> {
if (qDev) {
if (!isQrl(qrl)) {
throw new Error('Not a QRL');
}
}
}

export function assertSignal<T>(obj: unknown): asserts obj is Signal<T> {
if (qDev) {
if (!isSignal(obj) && !isSignal(obj)) {
throw new Error('Not a Signal');
}
}
}

const EMITTED = /*#__PURE__*/ new Set();

export const emitUsedSymbol = (symbol: string, element: Element | undefined, reqTime: number) => {
Expand Down
32 changes: 32 additions & 0 deletions packages/qwik/src/core/shared/qrl/qrl-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/** QRL related utilities that you can import without importing all of Qwik. */

import { isDev } from '@qwik.dev/core/build';
import type { QRLInternal, SyncQRLInternal } from './qrl-class';
import type { QRL } from './qrl.public';

export const SYNC_QRL = '<sync>';

/** Sync QRL is a function which is serialized into `<script q:func="qwik/json">` tag. */
export const isSyncQrl = (value: any): value is SyncQRLInternal => {
return isQrl(value) && value.$symbol$ == SYNC_QRL;
};

export const isQrl = <T = unknown>(value: unknown): value is QRLInternal<T> => {
return typeof value === 'function' && typeof (value as any).getSymbol === 'function';
};

export function assertQrl<T>(qrl: QRL<T>): asserts qrl is QRLInternal<T> {
if (isDev) {
if (!isQrl(qrl)) {
throw new Error('Not a QRL');
}
}
}

export const getSymbolHash = (symbolName: string) => {
const index = symbolName.lastIndexOf('_');
if (index > -1) {
return symbolName.slice(index + 1);
}
return symbolName;
};
Loading

0 comments on commit 521c98d

Please sign in to comment.