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
5 changes: 5 additions & 0 deletions .changeset/fix-component-cssid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@lynx-js/web-core": patch
---

Fix componentCSSID behavior for SSR and main thread by calculating element css_id from parent component correctly.
6 changes: 3 additions & 3 deletions packages/web-platform/web-core/binary/client/client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@ export class MainThreadWasmContext {
add_dataset(unique_id: number, key: any, value: any): void;
add_run_worklet_event(unique_id: number, event_type: string, event_name: string, event_handler_identifier?: any | null): void;
common_event_handler(event: any, bubble_unique_id_path: Uint32Array, event_name: string, is_bubble: boolean): void;
create_element_common(parent_component_unique_id: number, dom: HTMLElement, dom_ref: WeakRef<object>, css_id?: number | null, component_id?: string | null): number;
create_element_common(parent_component_unique_id: number, dom: HTMLElement, dom_ref: WeakRef<object>, component_css_id?: number | null, component_id?: string | null): number;
dispatch_event_by_path(bubble_unique_id_path: Uint32Array, event_name: string, is_capture: boolean, serialized_event: any): boolean;
dispatch_global_bind_event(bubble_unique_id_path: Uint32Array, event_name: string, serialized_event: any): void;
gc(): void;
get_component_id(unique_id: number): string | undefined;
get_config(unique_id: number): object;
get_css_id_by_unique_id(unique_id: number): number | undefined;
get_data_by_key(unique_id: number, key: string): any;
get_dataset(unique_id: number): object;
get_dom_by_unique_id(unique_id: number): WeakRef<object> | undefined;
Expand All @@ -49,6 +48,7 @@ export class MainThreadWasmContext {
set_dataset(unique_id: number, dom: HTMLElement, new_dataset: object): void;
set_page_element_unique_id(unique_id: number): void;
take_timing_flags(): string[];
update_component_css_id(unique_id: number, component_css_id: number): void;
update_component_id(unique_id: number, component_id?: string | null): void;
update_css_og_style(unique_id: number, entry_name?: string | null): void;
}
Expand Down Expand Up @@ -208,7 +208,6 @@ export interface InitOutput {
readonly mainthreadwasmcontext_gc: (a: number) => void;
readonly mainthreadwasmcontext_get_component_id: (a: number, b: number) => [number, number, number, number];
readonly mainthreadwasmcontext_get_config: (a: number, b: number) => [number, number, number];
readonly mainthreadwasmcontext_get_css_id_by_unique_id: (a: number, b: number) => number;
readonly mainthreadwasmcontext_get_data_by_key: (a: number, b: number, c: number, d: number) => [number, number, number];
readonly mainthreadwasmcontext_get_dataset: (a: number, b: number) => [number, number, number];
readonly mainthreadwasmcontext_get_dom_by_unique_id: (a: number, b: number) => any;
Expand All @@ -223,6 +222,7 @@ export interface InitOutput {
readonly mainthreadwasmcontext_set_dataset: (a: number, b: number, c: any, d: any) => [number, number];
readonly mainthreadwasmcontext_set_page_element_unique_id: (a: number, b: number) => void;
readonly mainthreadwasmcontext_take_timing_flags: (a: number) => [number, number];
readonly mainthreadwasmcontext_update_component_css_id: (a: number, b: number, c: number) => [number, number];
readonly mainthreadwasmcontext_update_component_id: (a: number, b: number, c: number, d: number) => [number, number];
readonly mainthreadwasmcontext_update_css_og_style: (a: number, b: number, c: number, d: number) => [number, number];
readonly rawstyleinfo_append_import: (a: number, b: number, c: number) => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export const mainthreadwasmcontext_dispatch_global_bind_event: (a: number, b: nu
export const mainthreadwasmcontext_gc: (a: number) => void;
export const mainthreadwasmcontext_get_component_id: (a: number, b: number) => [number, number, number, number];
export const mainthreadwasmcontext_get_config: (a: number, b: number) => [number, number, number];
export const mainthreadwasmcontext_get_css_id_by_unique_id: (a: number, b: number) => number;
export const mainthreadwasmcontext_get_data_by_key: (a: number, b: number, c: number, d: number) => [number, number, number];
export const mainthreadwasmcontext_get_dataset: (a: number, b: number) => [number, number, number];
export const mainthreadwasmcontext_get_dom_by_unique_id: (a: number, b: number) => any;
Expand All @@ -44,6 +43,7 @@ export const mainthreadwasmcontext_set_css_id: (a: number, b: number, c: number,
export const mainthreadwasmcontext_set_dataset: (a: number, b: number, c: any, d: any) => [number, number];
export const mainthreadwasmcontext_set_page_element_unique_id: (a: number, b: number) => void;
export const mainthreadwasmcontext_take_timing_flags: (a: number) => [number, number];
export const mainthreadwasmcontext_update_component_css_id: (a: number, b: number, c: number) => [number, number];
export const mainthreadwasmcontext_update_component_id: (a: number, b: number, c: number, d: number) => [number, number];
export const mainthreadwasmcontext_update_css_og_style: (a: number, b: number, c: number, d: number) => [number, number];
export const rawstyleinfo_append_import: (a: number, b: number, c: number) => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@ export class MainThreadWasmContext {
add_dataset(unique_id: number, key: any, value: any): void;
add_run_worklet_event(unique_id: number, event_type: string, event_name: string, event_handler_identifier?: any | null): void;
common_event_handler(event: any, bubble_unique_id_path: Uint32Array, event_name: string, is_bubble: boolean): void;
create_element_common(parent_component_unique_id: number, dom: HTMLElement, dom_ref: WeakRef<object>, css_id?: number | null, component_id?: string | null): number;
create_element_common(parent_component_unique_id: number, dom: HTMLElement, dom_ref: WeakRef<object>, component_css_id?: number | null, component_id?: string | null): number;
dispatch_event_by_path(bubble_unique_id_path: Uint32Array, event_name: string, is_capture: boolean, serialized_event: any): boolean;
dispatch_global_bind_event(bubble_unique_id_path: Uint32Array, event_name: string, serialized_event: any): void;
gc(): void;
get_component_id(unique_id: number): string | undefined;
get_config(unique_id: number): object;
get_css_id_by_unique_id(unique_id: number): number | undefined;
get_data_by_key(unique_id: number, key: string): any;
get_dataset(unique_id: number): object;
get_dom_by_unique_id(unique_id: number): WeakRef<object> | undefined;
Expand All @@ -49,6 +48,7 @@ export class MainThreadWasmContext {
set_dataset(unique_id: number, dom: HTMLElement, new_dataset: object): void;
set_page_element_unique_id(unique_id: number): void;
take_timing_flags(): string[];
update_component_css_id(unique_id: number, component_css_id: number): void;
update_component_id(unique_id: number, component_id?: string | null): void;
update_css_og_style(unique_id: number, entry_name?: string | null): void;
}
Expand Down Expand Up @@ -208,7 +208,6 @@ export interface InitOutput {
readonly mainthreadwasmcontext_gc: (a: number) => void;
readonly mainthreadwasmcontext_get_component_id: (a: number, b: number, c: number) => void;
readonly mainthreadwasmcontext_get_config: (a: number, b: number, c: number) => void;
readonly mainthreadwasmcontext_get_css_id_by_unique_id: (a: number, b: number) => number;
readonly mainthreadwasmcontext_get_data_by_key: (a: number, b: number, c: number, d: number, e: number) => void;
readonly mainthreadwasmcontext_get_dataset: (a: number, b: number, c: number) => void;
readonly mainthreadwasmcontext_get_dom_by_unique_id: (a: number, b: number) => number;
Expand All @@ -223,6 +222,7 @@ export interface InitOutput {
readonly mainthreadwasmcontext_set_dataset: (a: number, b: number, c: number, d: number, e: number) => void;
readonly mainthreadwasmcontext_set_page_element_unique_id: (a: number, b: number) => void;
readonly mainthreadwasmcontext_take_timing_flags: (a: number, b: number) => void;
readonly mainthreadwasmcontext_update_component_css_id: (a: number, b: number, c: number, d: number) => void;
readonly mainthreadwasmcontext_update_component_id: (a: number, b: number, c: number, d: number, e: number) => void;
readonly mainthreadwasmcontext_update_css_og_style: (a: number, b: number, c: number, d: number, e: number) => void;
readonly rawstyleinfo_append_import: (a: number, b: number, c: number) => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export const mainthreadwasmcontext_dispatch_global_bind_event: (a: number, b: nu
export const mainthreadwasmcontext_gc: (a: number) => void;
export const mainthreadwasmcontext_get_component_id: (a: number, b: number, c: number) => void;
export const mainthreadwasmcontext_get_config: (a: number, b: number, c: number) => void;
export const mainthreadwasmcontext_get_css_id_by_unique_id: (a: number, b: number) => number;
export const mainthreadwasmcontext_get_data_by_key: (a: number, b: number, c: number, d: number, e: number) => void;
export const mainthreadwasmcontext_get_dataset: (a: number, b: number, c: number) => void;
export const mainthreadwasmcontext_get_dom_by_unique_id: (a: number, b: number) => number;
Expand All @@ -44,6 +43,7 @@ export const mainthreadwasmcontext_set_css_id: (a: number, b: number, c: number,
export const mainthreadwasmcontext_set_dataset: (a: number, b: number, c: number, d: number, e: number) => void;
export const mainthreadwasmcontext_set_page_element_unique_id: (a: number, b: number) => void;
export const mainthreadwasmcontext_take_timing_flags: (a: number, b: number) => void;
export const mainthreadwasmcontext_update_component_css_id: (a: number, b: number, c: number, d: number) => void;
export const mainthreadwasmcontext_update_component_id: (a: number, b: number, c: number, d: number, e: number) => void;
export const mainthreadwasmcontext_update_css_og_style: (a: number, b: number, c: number, d: number, e: number) => void;
export const rawstyleinfo_append_import: (a: number, b: number, c: number) => void;
Expand Down
2 changes: 1 addition & 1 deletion packages/web-platform/web-core/binary/server/server.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class MainThreadServerContext {
add_class(element_id: number, class_name: string): void;
add_inline_style_raw_string_key(element_id: number, key: string, value?: string | null): void;
append_child(parent_id: number, child_id: number): void;
create_element(tag_name: string, parent_component_unique_id?: number | null, css_id_opt?: number | null, component_id?: string | null): number;
create_element(tag_name: string, parent_component_unique_id?: number | null, component_css_id_opt?: number | null, component_id?: string | null): number;
generate_html(element_id: number): string;
get_attribute(element_id: number, key: string): string | undefined;
get_attributes(element_id: number): object;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,17 @@ impl MainThreadWasmContext {
.component_id = component_id;
Ok(())
}

pub fn update_component_css_id(
&self,
unique_id: usize,
component_css_id: i32,
) -> Result<(), JsError> {
self
.get_element_data_by_unique_id(unique_id)
.ok_or_else(|| JsError::new(&format!("Element {unique_id} not found")))?
.borrow_mut()
.component_css_id = component_css_id;
Ok(())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl MainThreadWasmContext {
parent_component_unique_id: usize,
dom: web_sys::HtmlElement,
dom_ref: js_sys::WeakRef,
css_id: Option<i32>,
component_css_id: Option<i32>,
component_id: Option<String>,
) -> usize {
// unique id
Expand All @@ -89,12 +89,10 @@ impl MainThreadWasmContext {
let unique_id = self.unique_id_to_element_map.len();

let css_id = {
if let Some(css_id) = css_id {
css_id
} else if let Some(parent_component_data) =
if let Some(parent_component_data) =
self.get_element_data_by_unique_id(parent_component_unique_id)
{
parent_component_data.borrow().css_id
parent_component_data.borrow().component_css_id
} else {
0
}
Expand All @@ -106,7 +104,12 @@ impl MainThreadWasmContext {
if css_id != 0 {
let _ = dom.set_attribute(constants::CSS_ID_ATTRIBUTE, &css_id.to_string());
}
let element_data = LynxElementData::new(parent_component_unique_id, css_id, component_id);
let element_data = LynxElementData::new(
parent_component_unique_id,
css_id,
component_css_id.unwrap_or(0),
component_id,
);

let element_data = Box::new(element_data);
self
Expand Down Expand Up @@ -138,14 +141,6 @@ impl MainThreadWasmContext {
None
}

pub fn get_css_id_by_unique_id(&self, unique_id: usize) -> Option<i32> {
self
.unique_id_to_element_map
.get(unique_id)
.and_then(|opt| opt.as_ref())
.map(|element_data_cell| element_data_cell.borrow().css_id)
}

pub fn gc(&mut self) {
let mut ids_to_remove = Vec::new();
for (unique_id, weak_ref) in self.unique_id_to_dom_map.iter() {
Expand Down
11 changes: 10 additions & 1 deletion packages/web-platform/web-core/src/main_thread/element_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub struct EventHandler {
pub struct LynxElementData {
pub(crate) parent_component_unique_id: usize,
pub(crate) css_id: i32,
pub(crate) component_css_id: i32,
#[with(rkyv::with::Skip)]
pub(crate) component_id: Option<String>,
#[with(rkyv::with::Skip)]
Expand Down Expand Up @@ -54,11 +55,13 @@ impl LynxElementData {
pub(crate) fn new(
parent_component_unique_id: usize,
css_id: i32,
component_css_id: i32,
component_id: Option<String>,
) -> Self {
LynxElementData {
parent_component_unique_id,
css_id,
component_css_id,
component_id,
dataset: None,
component_config: None,
Expand Down Expand Up @@ -152,10 +155,16 @@ impl LynxElementData {
pub(crate) fn new_with_tag_name(
parent_component_unique_id: usize,
css_id: i32,
component_css_id: i32,
component_id: Option<String>,
tag_name: String,
) -> Self {
let mut data = Self::new(parent_component_unique_id, css_id, component_id);
let mut data = Self::new(
parent_component_unique_id,
css_id,
component_css_id,
component_id,
);
data.tag_name = tag_name;
data
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,21 +141,27 @@ impl MainThreadServerContext {
&mut self,
tag_name: String,
parent_component_unique_id: Option<usize>,
css_id_opt: Option<i32>,
component_css_id_opt: Option<i32>,
component_id: Option<String>,
) -> usize {
let id = self.elements.len();
let parent_id = parent_component_unique_id.unwrap_or(0);

let css_id = if let Some(css_id) = css_id_opt {
css_id
} else if let Some(Some(parent_component_data)) = self.elements.get(parent_id) {
parent_component_data.css_id
let css_id = if let Some(Some(parent_component_data)) = self.elements.get(parent_id) {
parent_component_data.component_css_id
} else {
0
};

let mut element = LynxElementData::new_with_tag_name(parent_id, css_id, component_id, tag_name);
let component_css_id = component_css_id_opt.unwrap_or(0);

let mut element = LynxElementData::new_with_tag_name(
parent_id,
css_id,
component_css_id,
component_id,
tag_name,
);
if css_id != 0 {
element.set_attribute(
crate::constants::CSS_ID_ATTRIBUTE.to_string(),
Expand Down Expand Up @@ -571,4 +577,25 @@ mod tests {
// Should not contain the style property since we ignored the empty value
assert!(!html.contains("background-color:"));
}

#[test]
fn test_component_css_id() {
let mut ctx = MainThreadServerContext::new("".to_string(), true, false, false, false);
// Create a component with component_css_id = 42
let comp_id = ctx.create_element(
"x-view".to_string(),
None,
Some(42),
Some("comp1".to_string()),
);

// Create a child element inside this component
// It should inherit css id 42 from the component's component_css_id
let child_id = ctx.create_element("view".to_string(), Some(comp_id), None, None);
ctx.append_child(comp_id, child_id);

let html = ctx.generate_html(comp_id);
// The child should have `l-css-id="42"`
assert!(html.contains("l-css-id=\"42\""), "Generated HTML: {}", html);
}
}
56 changes: 55 additions & 1 deletion packages/web-platform/web-core/tests/element-apis.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,26 @@ describe('Element APIs', () => {
expect(mtsGlobalThis.__GetAttributeByName(ret, 'name')).toBe('name');
});

test('client component_css_id properly cascades to child element', () => {
const root = mtsGlobalThis.__CreatePage('page', 0);
const comp = mtsGlobalThis.__CreateComponent(
0,
'comp1',
42,
'test_entry',
'test_name',
'path',
{},
{},
);
const compId = mtsGlobalThis.__GetElementUniqueID(comp);
const childView = mtsGlobalThis.__CreateElement('view', compId);
mtsGlobalThis.__AppendElement(comp, childView);
mtsGlobalThis.__AppendElement(root, comp);
mtsGlobalThis.__FlushElementTree();
expect(rootDom.querySelector(`[${cssIdAttribute}="42"]`)).not.toBeNull();
});

test('__CreateView', () => {
const ret = mtsGlobalThis.__CreateView(0);
expect(mtsGlobalThis.__GetTag(ret)).toBe('view');
Expand Down Expand Up @@ -1351,10 +1371,44 @@ describe('Element APIs', () => {
const cssID = mtsGlobalThis.__GetAttributeByName(ele, cssIdAttribute);
const name = mtsGlobalThis.__GetAttributeByName(ele, 'name');
expect(id).toBe('id2');
expect(cssID).toBe('8');
expect(cssID).toBeNull();
expect(name).toBe('name2');
});

test('__UpdateComponentInfo updates componentCSSID', () => {
const root = mtsGlobalThis.__CreatePage('page', 0);
const comp = mtsGlobalThis.__CreateComponent(
0,
'comp1',
42,
'test_entry',
'test_name',
'path',
{},
{},
);

mtsGlobalThis.__UpdateComponentInfo(comp, {
componentID: 'comp1_new',
cssID: 43,
entry: 'new_entry',
name: 'new_name',
});

const compId = mtsGlobalThis.__GetElementUniqueID(comp);
const childView = mtsGlobalThis.__CreateElement('view', compId);
mtsGlobalThis.__AppendElement(comp, childView);
mtsGlobalThis.__AppendElement(root, comp);
mtsGlobalThis.__FlushElementTree();

expect(rootDom.querySelector(`[${cssIdAttribute}="43"]`)).not.toBeNull();

// the component itself also gets the attributes updated
expect(comp.getAttribute('name')).toBe('new_name');
expect(comp.getAttribute('l-e-name')).toBe('new_entry');
expect(mtsGlobalThis.__GetComponentID(comp)).toBe('comp1_new');
});

test('__MarkTemplate_and_Get_Parts', () => {
/*
* <view template> <!-- grand parent template -->
Expand Down
Loading
Loading