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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"test.e2e.firefox": "playwright test starters --browser=firefox --config starters/playwright.config.ts",
"test.e2e.webkit": "playwright test starters --browser=webkit --config starters/playwright.config.ts",
"serve": "yarn node -r esbuild-register --inspect starters/dev-server.ts 3300",
"serve.debug": "yarn node --inspect-brk -r esbuild-register --inspect starters/dev-server.ts 3300",
"docs.fetch.hackMD": "yarn node --trace-warnings -r esbuild-register scripts/docs_sync/fetch_hackmd.ts",
"docs.sync": "yarn node scripts/docs_sync",
"lint": "yarn lint.eslint && yarn lint.prettier && yarn lint.rust",
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/components/repl/repl-options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ const StoreOption = (props: StoreOptionProps) => {

const MODE_OPTIONS = ['development', 'production'];

const ENTRY_STRATEGY_OPTIONS = ['component', 'hook', 'single', 'smart'];
const ENTRY_STRATEGY_OPTIONS = ['component', 'hook', 'single', 'smart', 'inline'];

interface StoreOptionProps {
label: string;
Expand Down
7 changes: 6 additions & 1 deletion packages/qwik/src/core/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export interface Context<STATE extends object> {

// @public (undocumented)
export interface CorePlatform {
chunkForSymbol: (symbolName: string) => string | undefined;
chunkForSymbol: (symbolName: string) => [string, string] | undefined;
importSymbol: (element: Element, url: string | URL, symbol: string) => ValueOrPromise<any>;
isServer: boolean;
// (undocumented)
Expand Down Expand Up @@ -290,6 +290,9 @@ export function immutable<T extends {}>(input: T): Readonly<T>;
// @alpha
export function implicit$FirstArg<FIRST, REST extends any[], RET>(fn: (first: QRL<FIRST>, ...rest: REST) => RET): (first: FIRST, ...rest: REST) => RET;

// @alpha (undocumented)
export function inlinedQrl<T>(symbol: T, symbolName: string, lexicalScopeCapture?: any[]): QRL<T>;

// @public (undocumented)
export interface InvokeContext {
// (undocumented)
Expand Down Expand Up @@ -529,6 +532,8 @@ export interface SnapshotResult {
// (undocumented)
listeners: SnapshotListener[];
// (undocumented)
objs: any[];
// (undocumented)
state: SnapshotState;
}

Expand Down
49 changes: 41 additions & 8 deletions packages/qwik/src/core/import/qrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { tryGetInvokeContext } from '../use/use-core';

let runtimeSymbolId = 0;
const RUNTIME_QRL = '/runtimeQRL';
const INLINED_QRL = '/inlinedQRL';

// https://regexr.com/68v72
const EXTRACT_IMPORT_PATH = /\(\s*(['"])([^\1]+)\1\s*\)/;
Expand Down Expand Up @@ -109,11 +110,7 @@ export function qrl<T = any>(
}

// Unwrap subscribers
if (Array.isArray(lexicalScopeCapture)) {
for (let i = 0; i < lexicalScopeCapture.length; i++) {
lexicalScopeCapture[i] = unwrapSubscriber(lexicalScopeCapture[i]);
}
}
unwrapLexicalScope(lexicalScopeCapture);
const qrl = new QRLInternal<T>(chunk, symbol, null, symbolFn, null, lexicalScopeCapture);
const ctx = tryGetInvokeContext();
if (ctx && ctx.element) {
Expand All @@ -133,6 +130,34 @@ export function runtimeQrl<T>(symbol: T, lexicalScopeCapture: any[] = EMPTY_ARRA
);
}

/**
* @alpha
*/
export function inlinedQrl<T>(
symbol: T,
symbolName: string,
lexicalScopeCapture: any[] = EMPTY_ARRAY
): QRL<T> {
// Unwrap subscribers
return new QRLInternal<T>(
INLINED_QRL,
symbolName,
symbol,
null,
null,
unwrapLexicalScope(lexicalScopeCapture)
);
}

function unwrapLexicalScope(lexicalScope: any[] | null) {
if (Array.isArray(lexicalScope)) {
for (let i = 0; i < lexicalScope.length; i++) {
lexicalScope[i] = unwrapSubscriber(lexicalScope[i]);
}
}
return lexicalScope;
}

export interface QRLSerializeOptions {
platform?: CorePlatform;
element?: Element;
Expand All @@ -141,12 +166,20 @@ export interface QRLSerializeOptions {

export function stringifyQRL(qrl: QRL, opts: QRLSerializeOptions = {}) {
const qrl_ = toInternalQRL(qrl);
const symbol = qrl_.symbol;
let symbol = qrl_.symbol;
let chunk = qrl_.chunk;
const refSymbol = qrl_.refSymbol ?? symbol;
const platform = opts.platform;
const element = opts.element;
const chunk = platform ? platform.chunkForSymbol(refSymbol) ?? qrl_.chunk : qrl_.chunk;

if (platform) {
const result = platform.chunkForSymbol(refSymbol);
if (result) {
chunk = result[0];
if (!qrl_.refSymbol) {
symbol = result[1];
}
}
}
const parts: string[] = [chunk];
if (symbol && symbol !== 'default') {
parts.push('#', symbol);
Expand Down
2 changes: 1 addition & 1 deletion packages/qwik/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export type { SnapshotState, SnapshotResult } from './object/store.public';
// Internal Runtime
//////////////////////////////////////////////////////////////////////////////////////////
export { $, implicit$FirstArg } from './import/qrl.public';
export { qrl } from './import/qrl';
export { qrl, inlinedQrl } from './import/qrl';
export type { QRL, EventHandler } from './import/qrl.public';

export type { Props } from './props/props.public';
Expand Down
2 changes: 2 additions & 0 deletions packages/qwik/src/core/object/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ export interface SnapshotListener {
export interface SnapshotResult {
state: SnapshotState;
listeners: SnapshotListener[];
objs: any[];
}

export function snapshotState(containerEl: Element): SnapshotResult {
Expand Down Expand Up @@ -351,6 +352,7 @@ export function snapshotState(containerEl: Element): SnapshotResult {
objs: convertedObjs,
subs,
},
objs,
listeners,
};
}
Expand Down
2 changes: 1 addition & 1 deletion packages/qwik/src/core/platform/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ export interface CorePlatform {
/**
* Takes a qrl and serializes into a string
*/
chunkForSymbol: (symbolName: string) => string | undefined;
chunkForSymbol: (symbolName: string) => [string, string] | undefined;
}
1 change: 1 addition & 0 deletions packages/qwik/src/optimizer/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ fn optimize(
entry_strategy: optimizer_input.strategy,
explicity_extensions: optimizer_input.explicity_extensions,
dev: true,
scope: None,
})?;

result.write_to_fs(&current_dir.join(optimizer_input.dest).absolutize()?)?;
Expand Down
10 changes: 5 additions & 5 deletions packages/qwik/src/optimizer/core/src/code_move.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ pub fn transform_arrow_fn(
ast::BlockStmtOrExpr::BlockStmt(mut block) => {
let mut stmts = Vec::with_capacity(1 + block.stmts.len());
if !scoped_idents.is_empty() {
stmts.push(create_use_closure(qwik_ident, scoped_idents));
stmts.push(create_use_lexical_scope(qwik_ident, scoped_idents));
}
stmts.append(&mut block.stmts);
ast::ArrowExpr {
Expand All @@ -329,7 +329,7 @@ pub fn transform_arrow_fn(
ast::BlockStmtOrExpr::Expr(expr) => {
let mut stmts = Vec::with_capacity(2);
if !scoped_idents.is_empty() {
stmts.push(create_use_closure(qwik_ident, scoped_idents));
stmts.push(create_use_lexical_scope(qwik_ident, scoped_idents));
}
stmts.push(create_return_stmt(expr));
ast::ArrowExpr {
Expand All @@ -352,7 +352,7 @@ pub fn transform_fn(node: ast::FnExpr, qwik_ident: &Id, scoped_idents: &[Id]) ->
.map_or(0, |body| body.stmts.len()),
);
if !scoped_idents.is_empty() {
stmts.push(create_use_closure(qwik_ident, scoped_idents));
stmts.push(create_use_lexical_scope(qwik_ident, scoped_idents));
}
if let Some(mut body) = node.function.body {
stmts.append(&mut body.stmts);
Expand All @@ -376,7 +376,7 @@ const fn create_return_stmt(expr: Box<ast::Expr>) -> ast::Stmt {
})
}

fn create_use_closure(qwik_ident: &Id, scoped_idents: &[Id]) -> ast::Stmt {
fn create_use_lexical_scope(qwik_ident: &Id, scoped_idents: &[Id]) -> ast::Stmt {
ast::Stmt::Decl(ast::Decl::Var(ast::VarDecl {
span: DUMMY_SP,
declare: false,
Expand All @@ -386,7 +386,7 @@ fn create_use_closure(qwik_ident: &Id, scoped_idents: &[Id]) -> ast::Stmt {
span: DUMMY_SP,
init: Some(Box::new(ast::Expr::Call(create_internal_call(
qwik_ident,
&USE_CLOSURE,
&USE_LEXICAL_SCOPE,
vec![],
None,
)))),
Expand Down
17 changes: 17 additions & 0 deletions packages/qwik/src/optimizer/core/src/entry_strategy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ lazy_static! {
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum EntryStrategy {
Inline,
Single,
Hook,
Component,
Expand All @@ -33,6 +34,21 @@ pub trait EntryPolicy: Send + Sync {
) -> Option<JsWord>;
}

#[derive(Default, Clone)]
pub struct InlineStrategy;

impl EntryPolicy for InlineStrategy {
fn get_entry_for_sym(
&self,
_symbol: &str,
_path: &PathData,
_context: &[String],
_hook_data: &HookData,
) -> Option<JsWord> {
Some(ENTRY_HOOKS.clone())
}
}

#[derive(Default, Clone)]
pub struct SingleStrategy;

Expand Down Expand Up @@ -143,6 +159,7 @@ impl EntryPolicy for ManualStrategy {

pub fn parse_entry_strategy(strategy: EntryStrategy) -> Box<dyn EntryPolicy> {
match strategy {
EntryStrategy::Inline => Box::new(InlineStrategy::default()),
EntryStrategy::Single => Box::new(SingleStrategy::default()),
EntryStrategy::Hook => Box::new(PerHookStrategy::default()),
EntryStrategy::Component => Box::new(PerComponentStrategy::default()),
Expand Down
8 changes: 8 additions & 0 deletions packages/qwik/src/optimizer/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub struct TransformFsOptions {
pub transpile: bool,
pub explicity_extensions: bool,
pub dev: bool,
pub scope: Option<String>,
}

#[derive(Serialize, Debug, Deserialize)]
Expand All @@ -67,12 +68,14 @@ pub struct TransformModulesOptions {
pub entry_strategy: EntryStrategy,
pub explicity_extensions: bool,
pub dev: bool,
pub scope: Option<String>,
}

#[cfg(feature = "fs")]
pub fn transform_fs(config: TransformFsOptions) -> Result<TransformOutput, Error> {
let root_dir = Path::new(&config.root_dir);
let mut paths = vec![];
let is_inline = matches!(config.entry_strategy, EntryStrategy::Inline);
let entry_policy = &*parse_entry_strategy(config.entry_strategy);
find_files(root_dir, &mut paths)?;

Expand Down Expand Up @@ -100,8 +103,10 @@ pub fn transform_fs(config: TransformFsOptions) -> Result<TransformOutput, Error
source_maps: config.source_maps,
transpile: config.transpile,
print_ast: false,
scope: config.scope.as_ref(),
entry_policy,
dev: config.dev,
is_inline,
})
})
.reduce(|| Ok(TransformOutput::new()), |x, y| Ok(x?.append(&mut y?)))?;
Expand All @@ -112,6 +117,7 @@ pub fn transform_fs(config: TransformFsOptions) -> Result<TransformOutput, Error
}

pub fn transform_modules(config: TransformModulesOptions) -> Result<TransformOutput, Error> {
let is_inline = matches!(config.entry_strategy, EntryStrategy::Inline);
let entry_policy = &*parse_entry_strategy(config.entry_strategy);
#[cfg(feature = "parallel")]
let iterator = config.input.par_iter();
Expand All @@ -129,6 +135,8 @@ pub fn transform_modules(config: TransformModulesOptions) -> Result<TransformOut
print_ast: false,
entry_policy,
dev: config.dev,
scope: config.scope.as_ref(),
is_inline,
})
});

Expand Down
4 changes: 4 additions & 0 deletions packages/qwik/src/optimizer/core/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ pub struct TransformCodeOptions<'a> {
pub code: &'a str,
pub entry_policy: &'a dyn EntryPolicy,
pub dev: bool,
pub scope: Option<&'a String>,
pub is_inline: bool,
}

#[derive(Debug, Serialize, Deserialize, Default)]
Expand Down Expand Up @@ -208,7 +210,9 @@ pub fn transform_code(config: TransformCodeOptions) -> Result<TransformOutput, a
extension: extension.clone(),
comments: Some(&comments),
global_collect: collect,
scope: config.scope,
dev: config.dev,
is_inline: config.is_inline,
});

// Run main transform
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
source: packages/qwik/src/optimizer/core/src/test.rs
expression: output
---
==INPUT==


import { component$, useClientEffect$, useStore, useStyles$ } from '@builder.io/qwik';
import { thing } from 'dependency';
import mongodb from 'mongodb';

export const Child = component$(() => {

useStyles$('somestring');
const state = useStore({
count: 0
});

// Double count watch
useClientEffect$(() => {
state.count = thing.doStuff();
});

return (
<div onClick$={() => console.log(mongodb)}>
</div>
);
});


============================= test.tsx ==

import * as qwik from "@builder.io/qwik";
import { componentQrl } from "@builder.io/qwik";
import { useClientEffectQrl } from "@builder.io/qwik";
import { useStylesQrl } from "@builder.io/qwik";
import { useStore } from '@builder.io/qwik';
import { thing } from 'dependency';
import mongodb from 'mongodb';
export const Child = /*#__PURE__*/ componentQrl(qwik.inlinedQrl(()=>{
useStylesQrl(qwik.inlinedQrl('somestring', "Child_component_useStyles_qBZTuFM0160"));
const state = useStore({
count: 0
});
// Double count watch
useClientEffectQrl(qwik.inlinedQrl(()=>{
const [state] = qwik.useLexicalScope();
state.count = thing.doStuff();
}, "Child_component_useClientEffect_kYRT1iERt9g", [
state
]));
return <div onClickQrl={qwik.inlinedQrl(()=>{
return console.log(mongodb);
}, "Child_component_div_onClick_elliVSnAiOQ")}>

</div>;
}, "Child_component_9GyF01GDKqw"));

== DIAGNOSTICS ==

[]
Loading