Skip to content

Commit

Permalink
Merge pull request #1 from QwikDev/build/v2
Browse files Browse the repository at this point in the history
Build/v2
  • Loading branch information
JerryWu1234 authored Jun 16, 2024
2 parents 078621b + eefc38b commit e1ff2f1
Show file tree
Hide file tree
Showing 19 changed files with 487 additions and 132 deletions.
3 changes: 2 additions & 1 deletion packages/docs/check-qwik-build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
import fs from 'fs';
import path from 'path';
import { spawnSync } from 'child_process';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(new URL(import.meta.url).pathname);
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const qwikPkgDir = path.join(__dirname, '..', 'qwik', 'dist');

if (!fs.existsSync(path.join(qwikPkgDir, 'core.d.ts'))) {
Expand Down
32 changes: 0 additions & 32 deletions packages/docs/src/routes/docs/(qwikcity)/server$/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ created_at: '2023-03-29T02:35:29Z'

> `server$` can accept any number of arguments and return any value that can be serialized by Qwik, that includes primitives, objects, arrays, bigint, JSX nodes and even Promises, just to name a few.
<<<<<<< HEAD
Your new function will have the following signature:
`([AbortSignal, ] ...): Promise<T>`
=======
>>>>>>> origin/main

`AbortSignal` is optional, and allows you to cancel a long running request by terminating the connection.
Your new function will have the following signature:
Expand Down Expand Up @@ -184,19 +179,6 @@ Terminating the generator on the client side (e.g., by calling `.return()` on th
import { component$, useSignal } from '@builder.io/qwik';
import { server$ } from '@builder.io/qwik-city';

<<<<<<< HEAD
const stream = server$(async function* () {
// Creation of an array with 10 undefined values
const iterationRange = Array(10).fill().entries();

for (const [index] of iterationRange) {
// Yield returns the index during each iteration
yield index;

// Waiting for 1 second before the next iteration
// This simulates a delay in the execution
await new Promise((resolve) => setTimeout(resolve, 1000));
=======
export const streamFromServer = server$(
// Async Generator Function
async function* () {
Expand All @@ -211,7 +193,6 @@ export const streamFromServer = server$(
// This simulates a delay in the execution
await new Promise((resolve) => setTimeout(resolve, 1000));
}
>>>>>>> origin/main
}
);

Expand All @@ -222,15 +203,6 @@ export default component$(() => {
return (
<div>
<button
<<<<<<< HEAD
onClick$={async () => {
// call the async stream function and wait for the response
const response = await stream();
// use a for-await-of loop to asynchronously iterate over the response
for await (const index of response) {
// add each index from the response to the message value
message.value += ` ${index}`;
=======
onClick$={
async () => {
// call the async stream function and wait for the response
Expand All @@ -241,7 +213,6 @@ export default component$(() => {
message.value += ` ${value}`;
}
// do anything else
>>>>>>> origin/main
}
}
>
Expand Down Expand Up @@ -278,9 +249,6 @@ When using `server$`, it's important to understand how [middleware functions](/d
To ensure that a middleware function runs for both types of requests, it should be defined in the `plugin.ts` file. This ensures that the middleware is executed consistently for all incoming requests, regardless of whether they are normal page requests or `server$` requests.

By [defining middleware in the `plugin.ts`](/docs/advanced/plugints) file, developers can maintain a centralized location for shared middleware logic, ensuring consistency and reducing potential errors or oversights.
<<<<<<< HEAD
=======



>>>>>>> origin/main
3 changes: 3 additions & 0 deletions packages/docs/vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ export default defineConfig(async () => {
// Suppress errors like these:
// FILE Module level directives cause errors when bundled, "use client" in FILE was ignored.
return;
} else if (level == 'warn' && log.code === 'SOURCEMAP_ERROR') {
// https://github.com/vitejs/vite/issues/15012
return;
}
defaultHandler(level, log);
},
Expand Down
4 changes: 2 additions & 2 deletions packages/qwik/src/core/container/resume.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import { createProxy, setObjectFlags } from '../state/store';
import { qDev, qSerialize } from '../util/qdev';
import { pauseContainer } from './pause';
import { isPrimitive } from '../render/dom/render-dom';
import { getWrappingContainer } from '../use/use-core';
import { getContext } from '../state/context';
import { EMPTY_ARRAY } from '../util/flyweight';
import { _getQContainerElement } from '../v2/client/dom-container';

export const resumeIfNeeded = (containerEl: Element): void => {
const isResumed = directGetAttribute(containerEl, QContainerAttr);
Expand Down Expand Up @@ -63,7 +63,7 @@ export const _deserializeData = (data: string, element?: unknown) => {
let doc = {} as Document;
let containerState = {} as any;
if (isNode(element) && isQwikElement(element)) {
const containerEl = getWrappingContainer(element);
const containerEl = _getQContainerElement(element);
if (containerEl) {
containerState = _getContainerState(containerEl);
doc = containerEl.ownerDocument;
Expand Down
12 changes: 3 additions & 9 deletions packages/qwik/src/core/render/dom/notify-render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { assertDefined, assertTrue } from '../../error/assert';
import { getPlatform, isServerPlatform } from '../../platform/platform';
import type { SubscriberSignal, Subscriptions } from '../../state/common';
import { HOST_FLAG_DIRTY, getContext, type QContext } from '../../state/context';
import { getWrappingContainer } from '../../use/use-core';
import { useLexicalScope } from '../../use/use-lexical-scope.public';
import {
TaskFlags,
Expand Down Expand Up @@ -136,14 +135,9 @@ const scheduleFrame = (containerState: ContainerState): Promise<void> => {
*/
export const _hW = () => {
const [task] = useLexicalScope<[SubscriberEffect]>();
if (vnode_isVNode(task.$el$)) {
const containerElement = getWrappingContainer(task.$el$ as fixMeAny) as HTMLElement;
const container = getDomContainer(containerElement);
const type = task.$flags$ & TaskFlags.VISIBLE_TASK ? ChoreType.VISIBLE : ChoreType.TASK;
container.$scheduler$(type, task as Task);
} else {
notifyTask(task, _getContainerState(getWrappingContainer(task.$el$)!));
}
const container = getDomContainer(task.$el$ as Element);
const type = task.$flags$ & TaskFlags.VISIBLE_TASK ? ChoreType.VISIBLE : ChoreType.TASK;
container.$scheduler$(type, task as Task);
};

const renderMarked = async (containerState: ContainerState): Promise<void> => {
Expand Down
16 changes: 2 additions & 14 deletions packages/qwik/src/core/use/use-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,8 @@ import { isArray } from '../util/types';
import { setLocale } from './use-locale';
import type { Subscriber } from '../state/common';
import type { Signal } from '../state/signal';
import type { Container2, fixMeAny } from '../v2/shared/types';
import {
vnode_getDomParent,
vnode_getNode,
vnode_isElementVNode,
vnode_isVNode,
} from '../v2/client/vnode';
import type { Container2 } from '../v2/shared/types';
import { vnode_getNode, vnode_isElementVNode, vnode_isVNode } from '../v2/client/vnode';
import { _getQContainerElement } from '../v2/client/dom-container';
import type { ContainerElement } from '../v2/client/types';

Expand Down Expand Up @@ -219,13 +214,6 @@ export const newInvokeContext = (
return ctx;
};

export const getWrappingContainer = (el: QwikElement): Element | null => {
if (vnode_isVNode(el)) {
el = vnode_getDomParent(el) as fixMeAny;
}
return el.closest(QContainerSelector);
};

/**
* Don't track listeners for this callback
*
Expand Down
6 changes: 3 additions & 3 deletions packages/qwik/src/core/use/use-lexical-scope.public.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { assertDefined } from '../error/assert';
import { inflateQrl, parseQRL } from '../qrl/qrl';
import { getWrappingContainer, getInvokeContext } from './use-core';
import { getInvokeContext } from './use-core';
import { assertQrl, type QRLInternal } from '../qrl/qrl-class';
import { getContext } from '../state/context';
import { resumeIfNeeded } from '../container/resume';
import { _getContainerState } from '../container/container';
import { getDomContainer } from '../v2/client/dom-container';
import { _getQContainerElement, getDomContainer } from '../v2/client/dom-container';

// <docs markdown="../readme.md#useLexicalScope">
// !!DO NOT EDIT THIS COMMENT DIRECTLY!!!
Expand All @@ -27,7 +27,7 @@ export const useLexicalScope = <VARS extends any[]>(): VARS => {
if (!qrl) {
const el = context.$element$;
assertDefined(el, 'invoke: element must be defined inside useLexicalScope()', context);
const containerElement = getWrappingContainer(el) as HTMLElement;
const containerElement = _getQContainerElement(el) as HTMLElement;
assertDefined(containerElement, `invoke: cant find parent q:container of`, el);
if (containerElement.getAttribute('q:runtime') == '2') {
const container = getDomContainer(containerElement);
Expand Down
6 changes: 3 additions & 3 deletions packages/qwik/src/core/v2/client/dom-render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import type { JSXNode } from '@builder.io/qwik';
import type { RenderOptions, RenderResult } from '../../render/dom/render.public';
import type { FunctionComponent, JSXOutput } from '../../render/jsx/types/jsx-node';
import { isDocument, isElement } from '../../util/element';
import { QContainerAttr } from '../../util/markers';
import { ChoreType } from '../shared/scheduler';
import type { HostElement, fixMeAny } from '../shared/types';
import { QContainerValue, type HostElement, type fixMeAny } from '../shared/types';
import { DomContainer, getDomContainer } from './dom-container';
import { cleanup } from './vnode-diff';
import { QContainerAttr } from '../../util/markers';

/**
* Render JSX.
Expand Down Expand Up @@ -37,7 +37,7 @@ export const render2 = async (
}
parent = child as Element;
}
(parent as Element).setAttribute(QContainerAttr, 'resumed');
(parent as Element).setAttribute(QContainerAttr, QContainerValue.RESUMED);

const container = getDomContainer(parent as HTMLElement) as DomContainer;
container.$serverData$ = opts.serverData!;
Expand Down
82 changes: 46 additions & 36 deletions packages/qwik/src/core/v2/client/vnode-diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {
} from '../../util/markers';
import { isPromise } from '../../util/promises';
import { type ValueOrPromise } from '../../util/types';
import { executeComponent2 } from '../shared/component-execution';
import {
convertEventNameFromJsxPropToHtmlAttr,
getEventNameFromJsxProp,
Expand All @@ -39,7 +38,7 @@ import {
} from '../shared/event-names';
import { ChoreType } from '../shared/scheduler';
import { hasClassAttr } from '../shared/scoped-styles';
import type { QElement2, QwikLoaderEventScope, fixMeAny } from '../shared/types';
import type { HostElement, QElement2, QwikLoaderEventScope, fixMeAny } from '../shared/types';
import { DEBUG_TYPE, QContainerValue, VirtualType } from '../shared/types';
import type { DomContainer } from './dom-container';
import {
Expand Down Expand Up @@ -88,6 +87,7 @@ import {
type VNodeJournal,
} from './vnode';
import { getNewElementNamespaceData } from './vnode-namespace';
import { executeComponent2 } from '../shared/component-execution';

export type ComponentQueue = Array<VNode>;

Expand Down Expand Up @@ -382,12 +382,28 @@ export const vnode_diff = (
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

function descendContentToProject(children: JSXChildren) {
function descendContentToProject(children: JSXChildren, host: VirtualVNode | null) {
if (!Array.isArray(children)) {
children = [children];
}
if (children.length) {
const createProjectionJSXNode = (slotName: string) => {
return new JSXNodeImpl(Projection, EMPTY_OBJ, null, [], 0, slotName);
};

const projections: Array<string | JSXNode> = [];
if (host) {
// we need to create empty projections for all the slots to remove unused slots content
for (let i = vnode_getPropStartIndex(host); i < host.length; i = i + 2) {
const prop = host[i] as string;
if (!prop.startsWith('q:')) {
const slotName = prop;
projections.push(slotName);
projections.push(createProjectionJSXNode(slotName));
}
}
}

/// STEP 1: Bucketize the children based on the projection name.
for (let i = 0; i < children.length; i++) {
const child = children[i];
Expand All @@ -397,14 +413,12 @@ export const vnode_diff = (
if (idx >= 0) {
jsxBucket = projections[idx + 1] as any;
} else {
projections.splice(
~idx,
0,
slotName,
(jsxBucket = new JSXNodeImpl(Projection, EMPTY_OBJ, null, [], 0, slotName))
);
projections.splice(~idx, 0, slotName, (jsxBucket = createProjectionJSXNode(slotName)));
}
const removeProjection = child === false;
if (!removeProjection) {
(jsxBucket.children as JSXChildren[]).push(child);
}
(jsxBucket.children as JSXChildren[]).push(child);
}
/// STEP 2: remove the names
for (let i = projections.length - 2; i >= 0; i = i - 2) {
Expand Down Expand Up @@ -904,7 +918,7 @@ export const vnode_diff = (

function expectComponent(component: Function) {
const componentMeta = (component as any)[SERIALIZABLE_STATE] as [QRLInternal<OnRenderFn<any>>];
let host = (vNewNode || vCurrent) as VirtualVNode;
let host = (vNewNode || vCurrent) as VirtualVNode | null;
if (componentMeta) {
const jsxProps = jsxValue.props;
// QComponent
Expand Down Expand Up @@ -944,45 +958,41 @@ export const vnode_diff = (
}
}

const vNodeProps = vnode_getProp<any>(host, ELEMENT_PROPS, container.$getObjectById$);
shouldRender = shouldRender || propsDiffer(jsxProps, vNodeProps);
if (shouldRender) {
container.$scheduler$(ChoreType.COMPONENT, host, componentQRL, jsxProps);
if (host) {
const vNodeProps = vnode_getProp<any>(host, ELEMENT_PROPS, container.$getObjectById$);
shouldRender = shouldRender || propsDiffer(jsxProps, vNodeProps);
if (shouldRender) {
container.$scheduler$(ChoreType.COMPONENT, host, componentQRL, jsxProps);
}
}
jsxValue.children != null && descendContentToProject(jsxValue.children);
jsxValue.children != null && descendContentToProject(jsxValue.children, host);
} else {
// Inline Component
if (!host) {
// We did not find the component, create it.
vnode_insertBefore(
journal,
vParent as VirtualVNode,
(vNewNode = vnode_newVirtual()),
vCurrent && getInsertBefore()
);
host = vNewNode;
}
isDev &&
vnode_setProp(
(vNewNode || vCurrent) as VirtualVNode,
DEBUG_TYPE,
VirtualType.InlineComponent
);
let component$Host: VNode = host;
vnode_insertBefore(
journal,
vParent as VirtualVNode,
(vNewNode = vnode_newVirtual()),
vCurrent && getInsertBefore()
);
isDev && vnode_setProp(vNewNode, DEBUG_TYPE, VirtualType.InlineComponent);
vnode_setProp(vNewNode, ELEMENT_PROPS, jsxValue.propsC);

host = vNewNode;
let component$Host: VNode | null = host;
// Find the closest component host which has `OnRender` prop.
while (
component$Host &&
(vnode_isVirtualVNode(component$Host)
? vnode_getProp(component$Host, OnRenderProp, null) === null
: true)
) {
component$Host = vnode_getParent(component$Host)!;
component$Host = vnode_getParent(component$Host);
}
const jsxOutput = executeComponent2(
container,
host,
(component$Host || container.rootVNode) as fixMeAny,
component as OnRenderFn<any>,
(component$Host || container.rootVNode) as HostElement,
component as OnRenderFn<unknown>,
jsxValue.propsC
);
asyncQueue.push(jsxOutput, host);
Expand Down
Loading

0 comments on commit e1ff2f1

Please sign in to comment.