Skip to content

Commit 2110331

Browse files
authored
Merge pull request #8144 from QwikDev/v2-qrls-memoizing
feat: memoize qrl symbols in qwikloader
2 parents 200c81e + 94df210 commit 2110331

File tree

3 files changed

+10
-4
lines changed

3 files changed

+10
-4
lines changed

packages/qwik/src/core/shared/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { ISsrNode, StreamWriter, SymbolToChunkResolver } from '../ssr/ssr-t
33
import type { Scheduler } from './scheduler';
44
import type { SerializationContext } from './serdes/index';
55
import type { VNode } from '../client/vnode-impl';
6+
import type { ValueOrPromise } from './utils/types';
67

78
export interface DeserializeContainer {
89
$getObjectById$: (id: number | string) => unknown;
@@ -57,7 +58,7 @@ export interface Container {
5758
export type HostElement = VNode | ISsrNode;
5859

5960
export interface QElement extends Element {
60-
qDispatchEvent?: (event: Event, scope: QwikLoaderEventScope) => boolean;
61+
qDispatchEvent?: (event: Event, scope: QwikLoaderEventScope) => ValueOrPromise<unknown>;
6162
vNode?: VNode;
6263
}
6364

packages/qwik/src/qwikloader.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const doc = document as Document & { __q_context__?: [Element, Event, URL] | 0 }
2323
const win = window as unknown as qWindow;
2424
const events = new Set<string>();
2525
const roots = new Set<EventTarget & ParentNode>([doc]);
26+
const symbols: Record<string, unknown> = {};
2627

2728
let hasInitialized: number;
2829

@@ -142,6 +143,8 @@ const dispatch = async (
142143
importError = 'sync';
143144
error = new Error('sym:' + symbol);
144145
}
146+
} else if (symbol in symbols) {
147+
handler = symbols[symbol];
145148
} else {
146149
emitEvent<QwikSymbolEvent>('qsymbol', eventData);
147150
const uri = url.href.split('#')[0];
@@ -152,6 +155,8 @@ const dispatch = async (
152155
if (!handler) {
153156
importError = 'no-symbol';
154157
error = new Error(`${symbol} not in ${uri}`);
158+
} else {
159+
symbols[symbol] = handler;
155160
}
156161
} catch (err) {
157162
importError ||= 'async';

packages/qwik/src/qwikloader.unit.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ test('qwikloader script', () => {
2323
const compressed = compress(Buffer.from(qwikLoader), { mode: 1, quality: 11 });
2424
expect([compressed.length, qwikLoader.length]).toMatchInlineSnapshot(`
2525
[
26-
1488,
27-
3275,
26+
1515,
27+
3308,
2828
]
2929
`);
3030

3131
expect(qwikLoader).toMatchInlineSnapshot(
32-
`"const t=document,e=window,n=new Set,o=new Set([t]);let r;const s=(t,e)=>Array.from(t.querySelectorAll(e)),a=t=>{const e=[];return o.forEach(n=>e.push(...s(n,t))),e},i=t=>{m(t),s(t,"[q\\\\:shadowroot]").forEach(t=>{const e=t.shadowRoot;e&&i(e)})},c=t=>t&&"function"==typeof t.then,l=(t,e,n=e.type)=>{a("[on"+t+"\\\\:"+n+"]").forEach(o=>{u(o,t,e,n)})},f=e=>{if(void 0===e._qwikjson_){let n=(e===t.documentElement?t.body:e).lastElementChild;for(;n;){if("SCRIPT"===n.tagName&&"qwik/json"===n.getAttribute("type")){e._qwikjson_=JSON.parse(n.textContent.replace(/\\\\x3C(\\/?script)/gi,"<$1"));break}n=n.previousElementSibling}}},p=(t,e)=>new CustomEvent(t,{detail:e}),u=async(e,n,o,r=o.type)=>{const s="on"+n+":"+r;e.hasAttribute("preventdefault:"+r)&&o.preventDefault(),e.hasAttribute("stoppropagation:"+r)&&o.stopPropagation();const a=e._qc_,i=a&&a.li.filter(t=>t[0]===s);if(i&&i.length>0){for(const t of i){const n=t[1].getFn([e,o],()=>e.isConnected)(o,e),r=o.cancelBubble;c(n)&&await n,r&&o.stopPropagation()}return}const l=e.getAttribute(s),p=e.qDispatchEvent;if(p)return p(o,n);if(l){const n=e.closest("[q\\\\:container]:not([q\\\\:container=html]):not([q\\\\:container=text])"),r=n.getAttribute("q:base"),s=n.getAttribute("q:version")||"unknown",a=n.getAttribute("q:manifest-hash")||"dev",i=new URL(r,t.baseURI);for(const p of l.split("\\n")){const l=new URL(p,i),u=l.href,q=l.hash.replace(/^#?([^?[|]*).*$/,"$1")||"default",h=performance.now();let _,d,y;const g=p.startsWith("#"),m={qBase:r,qManifest:a,qVersion:s,href:u,symbol:q,element:e,reqTime:h};if(g){const e=n.getAttribute("q:instance");_=(t["qFuncs_"+e]||[])[Number.parseInt(q)],_||(d="sync",y=Error("sym:"+q))}else{b("qsymbol",m);const t=l.href.split("#")[0];try{const e=import(t);f(n),_=(await e)[q],_||(d="no-symbol",y=Error(\`\${q} not in \${t}\`))}catch(t){d||(d="async"),y=t}}if(!_){b("qerror",{importError:d,error:y,...m}),console.error(y);break}const w=t.__q_context__;if(e.isConnected)try{t.__q_context__=[e,o,l];const n=_(o,e);c(n)&&await n}catch(t){b("qerror",{error:t,...m})}finally{t.__q_context__=w}}}},b=(e,n)=>{t.dispatchEvent(p(e,n))},q=t=>t.replace(/([A-Z-])/g,t=>"-"+t.toLowerCase()),h=async t=>{let e=q(t.type),n=t.target;for(l("-document",t,e);n&&n.getAttribute;){const o=u(n,"",t,e);let r=t.cancelBubble;c(o)&&await o,r||(r=r||t.cancelBubble||n.hasAttribute("stoppropagation:"+t.type)),n=t.bubbles&&!0!==r?n.parentElement:null}},_=t=>{l("-window",t,q(t.type))},d=()=>{const s=t.readyState;if(!r&&("interactive"==s||"complete"==s)&&(o.forEach(i),r=1,b("qinit"),(e.requestIdleCallback??e.setTimeout).bind(e)(()=>b("qidle")),n.has("qvisible"))){const t=a("[on\\\\:qvisible]"),e=new IntersectionObserver(t=>{for(const n of t)n.isIntersecting&&(e.unobserve(n.target),u(n.target,"",p("qvisible",n)))});t.forEach(t=>e.observe(t))}},y=(t,e,n,o=!1)=>{t.addEventListener(e,n,{capture:o,passive:!1})},g=t=>t.replace(/-./g,t=>t[1].toUpperCase()),m=(...t)=>{for(const r of t)if("string"==typeof r){if(!n.has(r)){n.add(r);const t=g(r);o.forEach(e=>y(e,t,h,!0)),y(e,t,_,!0)}}else o.has(r)||(n.forEach(t=>{const e=g(t);y(r,e,h,!0)}),o.add(r))};if(!("__q_context__"in t)){t.__q_context__=0;const r=e.qwikevents;r&&(Array.isArray(r)?m(...r):m("click","input")),e.qwikevents={events:n,roots:o,push:m},y(t,"readystatechange",d),d()}"`
32+
`"const t=document,e=window,n=new Set,o=new Set([t]),r={};let s;const i=(t,e)=>Array.from(t.querySelectorAll(e)),a=t=>{const e=[];return o.forEach(n=>e.push(...i(n,t))),e},c=t=>{w(t),i(t,"[q\\\\:shadowroot]").forEach(t=>{const e=t.shadowRoot;e&&c(e)})},l=t=>t&&"function"==typeof t.then,f=(t,e,n=e.type)=>{a("[on"+t+"\\\\:"+n+"]").forEach(o=>{b(o,t,e,n)})},p=e=>{if(void 0===e._qwikjson_){let n=(e===t.documentElement?t.body:e).lastElementChild;for(;n;){if("SCRIPT"===n.tagName&&"qwik/json"===n.getAttribute("type")){e._qwikjson_=JSON.parse(n.textContent.replace(/\\\\x3C(\\/?script)/gi,"<$1"));break}n=n.previousElementSibling}}},u=(t,e)=>new CustomEvent(t,{detail:e}),b=async(e,n,o,s=o.type)=>{const i="on"+n+":"+s;e.hasAttribute("preventdefault:"+s)&&o.preventDefault(),e.hasAttribute("stoppropagation:"+s)&&o.stopPropagation();const a=e._qc_,c=a&&a.li.filter(t=>t[0]===i);if(c&&c.length>0){for(const t of c){const n=t[1].getFn([e,o],()=>e.isConnected)(o,e),r=o.cancelBubble;l(n)&&await n,r&&o.stopPropagation()}return}const f=e.getAttribute(i),u=e.qDispatchEvent;if(u)return u(o,n);if(f){const n=e.closest("[q\\\\:container]:not([q\\\\:container=html]):not([q\\\\:container=text])"),s=n.getAttribute("q:base"),i=n.getAttribute("q:version")||"unknown",a=n.getAttribute("q:manifest-hash")||"dev",c=new URL(s,t.baseURI);for(const u of f.split("\\n")){const f=new URL(u,c),b=f.href,h=f.hash.replace(/^#?([^?[|]*).*$/,"$1")||"default",_=performance.now();let d,y,g;const m=u.startsWith("#"),w={qBase:s,qManifest:a,qVersion:i,href:b,symbol:h,element:e,reqTime:_};if(m){const e=n.getAttribute("q:instance");d=(t["qFuncs_"+e]||[])[Number.parseInt(h)],d||(y="sync",g=Error("sym:"+h))}else if(h in r)d=r[h];else{q("qsymbol",w);const t=f.href.split("#")[0];try{const e=import(t);p(n),d=(await e)[h],d?r[h]=d:(y="no-symbol",g=Error(\`\${h} not in \${t}\`))}catch(t){y||(y="async"),g=t}}if(!d){q("qerror",{importError:y,error:g,...w}),console.error(g);break}const v=t.__q_context__;if(e.isConnected)try{t.__q_context__=[e,o,f];const n=d(o,e);l(n)&&await n}catch(t){q("qerror",{error:t,...w})}finally{t.__q_context__=v}}}},q=(e,n)=>{t.dispatchEvent(u(e,n))},h=t=>t.replace(/([A-Z-])/g,t=>"-"+t.toLowerCase()),_=async t=>{let e=h(t.type),n=t.target;for(f("-document",t,e);n&&n.getAttribute;){const o=b(n,"",t,e);let r=t.cancelBubble;l(o)&&await o,r||(r=r||t.cancelBubble||n.hasAttribute("stoppropagation:"+t.type)),n=t.bubbles&&!0!==r?n.parentElement:null}},d=t=>{f("-window",t,h(t.type))},y=()=>{const r=t.readyState;if(!s&&("interactive"==r||"complete"==r)&&(o.forEach(c),s=1,q("qinit"),(e.requestIdleCallback??e.setTimeout).bind(e)(()=>q("qidle")),n.has("qvisible"))){const t=a("[on\\\\:qvisible]"),e=new IntersectionObserver(t=>{for(const n of t)n.isIntersecting&&(e.unobserve(n.target),b(n.target,"",u("qvisible",n)))});t.forEach(t=>e.observe(t))}},g=(t,e,n,o=!1)=>{t.addEventListener(e,n,{capture:o,passive:!1})},m=t=>t.replace(/-./g,t=>t[1].toUpperCase()),w=(...t)=>{for(const r of t)if("string"==typeof r){if(!n.has(r)){n.add(r);const t=m(r);o.forEach(e=>g(e,t,_,!0)),g(e,t,d,!0)}}else o.has(r)||(n.forEach(t=>{const e=m(t);g(r,e,_,!0)}),o.add(r))};if(!("__q_context__"in t)){t.__q_context__=0;const r=e.qwikevents;r&&(Array.isArray(r)?w(...r):w("click","input")),e.qwikevents={events:n,roots:o,push:w},g(t,"readystatechange",y),y()}"`
3333
);
3434
});
3535

0 commit comments

Comments
 (0)