let div_id = ctx.create_element("div".to_string(), None, None, None);
@@ -555,7 +561,7 @@ mod tests {
#[test]
fn test_set_style_empty_value() {
- let mut ctx = MainThreadServerContext::new("".to_string(), true, false, false);
+ let mut ctx = MainThreadServerContext::new("".to_string(), true, false, false, false);
let div_id = ctx.create_element("div".to_string(), None, None, None);
// This should not panic
diff --git a/packages/web-platform/web-core/src/style_transformer/inline_style.rs b/packages/web-platform/web-core/src/style_transformer/inline_style.rs
index a598a79fbf..fd98cfdd9b 100644
--- a/packages/web-platform/web-core/src/style_transformer/inline_style.rs
+++ b/packages/web-platform/web-core/src/style_transformer/inline_style.rs
@@ -30,6 +30,7 @@ pub(crate) fn transform_inline_style_string(source: &str, config: &TransformerCo
TransformerConfig {
transform_vw: config.transform_vw,
transform_vh: config.transform_vh,
+ transform_rem: config.transform_rem,
},
);
transformer.parse(source);
@@ -49,6 +50,7 @@ pub(crate) fn transform_inline_style_key_value_vec(
TransformerConfig {
transform_vw: config.transform_vw,
transform_vh: config.transform_vh,
+ transform_rem: config.transform_rem,
},
);
diff --git a/packages/web-platform/web-core/src/style_transformer/token_transformer.rs b/packages/web-platform/web-core/src/style_transformer/token_transformer.rs
index b23ab5f1e9..6dc38d8f27 100644
--- a/packages/web-platform/web-core/src/style_transformer/token_transformer.rs
+++ b/packages/web-platform/web-core/src/style_transformer/token_transformer.rs
@@ -11,6 +11,7 @@ use std::borrow::Cow;
pub struct TransformerConfig {
pub transform_vw: bool,
pub transform_vh: bool,
+ pub transform_rem: bool,
}
/**
@@ -40,6 +41,12 @@ pub(crate) fn transform_one_token<'a>(
token_type,
Cow::Owned(format!("calc({value} * var(--ppx-unit))")),
);
+ } else if config.transform_rem && suffix.eq_ignore_ascii_case("rem") {
+ let value = &token_value[..len - 3];
+ return (
+ token_type,
+ Cow::Owned(format!("calc({value} * var(--rem-unit))")),
+ );
}
}
if len > 2 {
@@ -142,6 +149,25 @@ mod tests {
assert_eq!(tv, "100vh");
}
+ #[test]
+ fn test_transform_rem() {
+ let (_, tv) = transform_one_token(
+ DIMENSION_TOKEN,
+ "2rem",
+ &TransformerConfig {
+ transform_rem: true,
+ ..Default::default()
+ },
+ );
+ assert_eq!(tv, "calc(2 * var(--rem-unit))");
+ }
+
+ #[test]
+ fn test_transform_rem_disabled() {
+ let (_, tv) = transform_one_token(DIMENSION_TOKEN, "2rem", &TransformerConfig::default());
+ assert_eq!(tv, "2rem");
+ }
+
#[test]
fn test_transform_vw_case_insensitive() {
let (_, tv) = transform_one_token(
diff --git a/packages/web-platform/web-core/src/template/template_sections/style_info/decoded_style_data.rs b/packages/web-platform/web-core/src/template/template_sections/style_info/decoded_style_data.rs
index cbaa320d70..d28eef506f 100644
--- a/packages/web-platform/web-core/src/template/template_sections/style_info/decoded_style_data.rs
+++ b/packages/web-platform/web-core/src/template/template_sections/style_info/decoded_style_data.rs
@@ -48,6 +48,7 @@ pub fn decode_style_info(
config_enable_css_selector: bool,
transform_vw: bool,
transform_vh: bool,
+ transform_rem: bool,
) -> Result
{
let buf = buffer.to_vec();
let data = unsafe { rkyv::from_bytes_unchecked::(&buf) }
@@ -59,6 +60,7 @@ pub fn decode_style_info(
config_enable_css_selector,
transform_vw,
transform_vh,
+ transform_rem,
)?
.into();
@@ -76,6 +78,7 @@ pub fn encode_legacy_json_generated_raw_style_info(
entry_name: Option,
transform_vw: bool,
transform_vh: bool,
+ transform_rem: bool,
) -> Result {
let decode_data: DecodedStyleData = StyleInfoDecoder::new(
raw_style_info,
@@ -83,6 +86,7 @@ pub fn encode_legacy_json_generated_raw_style_info(
config_enable_css_selector,
transform_vw,
transform_vh,
+ transform_rem,
)?
.into();
let serialized = rkyv::to_bytes::<_, 1024>(&decode_data).map_err(|e| {
diff --git a/packages/web-platform/web-core/src/template/template_sections/style_info/raw_style_info.rs b/packages/web-platform/web-core/src/template/template_sections/style_info/raw_style_info.rs
index 4dc4d92c95..4c766271fd 100644
--- a/packages/web-platform/web-core/src/template/template_sections/style_info/raw_style_info.rs
+++ b/packages/web-platform/web-core/src/template/template_sections/style_info/raw_style_info.rs
@@ -141,7 +141,7 @@ impl RawStyleInfo {
*/
#[cfg(feature = "encode")]
pub fn encode(&mut self) -> Result {
- let decoded_style_info = StyleInfoDecoder::new(self.clone(), None, true, false, false)?;
+ let decoded_style_info = StyleInfoDecoder::new(self.clone(), None, true, false, false, false)?;
self.style_content_str_size_hint = decoded_style_info.style_content.len();
let serialized = rkyv::to_bytes::<_, 1024>(self)
.map_err(|e| JsError::new(&format!("Failed to encode RawStyleInfo: {e:?}")))?;
diff --git a/packages/web-platform/web-core/src/template/template_sections/style_info/style_info_decoder.rs b/packages/web-platform/web-core/src/template/template_sections/style_info/style_info_decoder.rs
index eceeee5e42..418e829364 100644
--- a/packages/web-platform/web-core/src/template/template_sections/style_info/style_info_decoder.rs
+++ b/packages/web-platform/web-core/src/template/template_sections/style_info/style_info_decoder.rs
@@ -28,6 +28,7 @@ pub struct StyleInfoDecoder {
config_enable_css_selector: bool,
transform_vw: bool,
transform_vh: bool,
+ transform_rem: bool,
entry_name: Option,
css_og_current_processing_css_ids: Option>,
css_og_current_processing_class_selector_names: Option>,
@@ -40,6 +41,7 @@ impl StyleInfoDecoder {
config_enable_css_selector: bool,
transform_vw: bool,
transform_vh: bool,
+ transform_rem: bool,
) -> Result {
let flattened_style_info: FlattenedStyleInfo = raw_style_info.into();
let mut decoded_style_info = StyleInfoDecoder {
@@ -55,6 +57,7 @@ impl StyleInfoDecoder {
config_enable_css_selector,
transform_vw,
transform_vh,
+ transform_rem,
is_processing_font_face: false,
css_og_current_processing_css_ids: None,
css_og_current_processing_class_selector_names: None,
@@ -288,6 +291,7 @@ impl StyleInfoDecoder {
crate::style_transformer::token_transformer::TransformerConfig {
transform_vw: self.transform_vw,
transform_vh: self.transform_vh,
+ transform_rem: self.transform_rem,
},
);
@@ -383,6 +387,7 @@ mod test {
config_enable_css_selector,
false,
false,
+ false,
)
.unwrap()
}
@@ -911,7 +916,7 @@ mod tests_roundtrip {
let decoded_raw = unsafe { rkyv::from_bytes_unchecked::(&buf) }
.expect("RawStyleInfo decode should succeed");
- let decoder = StyleInfoDecoder::new(decoded_raw, None, true, false, false)
+ let decoder = StyleInfoDecoder::new(decoded_raw, None, true, false, false, false)
.expect("StyleInfoDecoder should succeed");
let decoded_string = decoder.style_content;
@@ -962,7 +967,7 @@ mod tests_roundtrip {
let decoded_raw = unsafe { rkyv::from_bytes_unchecked::(&buf) }
.expect("RawStyleInfo decode should succeed");
- let decoder = StyleInfoDecoder::new(decoded_raw, None, true, false, false)
+ let decoder = StyleInfoDecoder::new(decoded_raw, None, true, false, false, false)
.expect("StyleInfoDecoder should succeed");
let decoded_string = decoder.style_content;
diff --git a/packages/web-platform/web-core/tests/__snapshots__/encode.spec.ts.snap b/packages/web-platform/web-core/tests/__snapshots__/encode.spec.ts.snap
index 82f9a8cbf4..c55388634d 100644
--- a/packages/web-platform/web-core/tests/__snapshots__/encode.spec.ts.snap
+++ b/packages/web-platform/web-core/tests/__snapshots__/encode.spec.ts.snap
@@ -21,3 +21,5 @@ exports[`encodeCSS > scoped css 1`] = `".foo:where([l-css-id="1"]):not([l-e-name
exports[`encodeCSS > scoped css, 2 css id 1`] = `".foo:where([l-css-id="1"]):not([l-e-name]),.foo:where([l-css-id="2"]):not([l-e-name]){background:red;}"`;
exports[`encodeCSS > scoped css, import non existing 1`] = `".foo:where([l-css-id="1"]):not([l-e-name]),.foo:where([l-css-id="20"]):not([l-e-name]),.foo:where([l-css-id="2"]):not([l-e-name]){background:red;}"`;
+
+exports[`encodeCSS > should encode KeyframesRule with CSS variables 1`] = `"@keyframes my-animation-with-vars{from{--my-var:0;opacity:{{--my-var}};}to{--my-var:1;opacity:{{--my-var}};}}"`;
diff --git a/packages/web-platform/web-core/tests/deploy.spec.ts b/packages/web-platform/web-core/tests/deploy.spec.ts
new file mode 100644
index 0000000000..8e07ebf844
--- /dev/null
+++ b/packages/web-platform/web-core/tests/deploy.spec.ts
@@ -0,0 +1,60 @@
+import { describe, it, expect, vi, beforeEach } from 'vitest';
+import { executeTemplate } from '../ts/server/deploy.js';
+import * as decodeModule from '../ts/server/decode.js';
+import type { DecodedTemplate } from '../ts/server/decode.js';
+import * as createElementAPIModule from '../ts/server/elementAPIs/createElementAPI.js';
+import type { MainThreadServerContext } from '../ts/server/wasm.js';
+import type { ElementPAPIs } from '../ts/types/index.js';
+
+vi.mock('../ts/server/decode.js', () => ({
+ decodeTemplate: vi.fn(),
+}));
+
+vi.mock('../ts/server/elementAPIs/createElementAPI.js', () => ({
+ createElementAPI: vi.fn(),
+}));
+
+vi.mock('vm', () => ({
+ createContext: vi.fn(),
+ runInContext: vi.fn(),
+}));
+
+describe('executeTemplate', () => {
+ beforeEach(() => {
+ vi.clearAllMocks();
+ });
+
+ it('should pass viewAttributes correctly when called with 7 arguments (legacy call)', () => {
+ const mockDecodeTemplate = vi.mocked(decodeModule.decodeTemplate);
+ const mockCreateElementAPI = vi.mocked(
+ createElementAPIModule.createElementAPI,
+ );
+
+ mockDecodeTemplate.mockReturnValue({
+ config: { enableCSSSelector: 'true' },
+ lepusCode: {},
+ styleInfo: new Uint8Array(),
+ } as DecodedTemplate);
+
+ mockCreateElementAPI.mockReturnValue({
+ globalThisAPIs: {} as ElementPAPIs,
+ wasmContext: {} as MainThreadServerContext,
+ });
+
+ const dummyBuffer = Buffer.from('test');
+
+ executeTemplate(
+ dummyBuffer,
+ {},
+ {},
+ () => {},
+ true, // transformVW
+ true, // transformVH
+ 'my-view-attr="123"', // viewAttributes
+ );
+
+ expect(mockCreateElementAPI).toHaveBeenCalled();
+ // 3rd arg is viewAttributes
+ expect(mockCreateElementAPI.mock.calls[0][2]).toBe('my-view-attr="123"');
+ });
+});
diff --git a/packages/web-platform/web-core/tests/encode.spec.ts b/packages/web-platform/web-core/tests/encode.spec.ts
index 9c6761ba27..6737ec6d61 100644
--- a/packages/web-platform/web-core/tests/encode.spec.ts
+++ b/packages/web-platform/web-core/tests/encode.spec.ts
@@ -124,6 +124,31 @@ describe('encodeCSS', () => {
expect(buffer.length).toBeGreaterThan(0);
});
+ test('should encode KeyframesRule with CSS variables', () => {
+ const css = `
+ @keyframes my-animation-with-vars {
+ from {
+ --my-var: 0;
+ opacity: var(--my-var);
+ }
+ to {
+ --my-var: 1;
+ opacity: var(--my-var);
+ }
+ }
+ `;
+ const cssMap = {
+ '1': CSS.parse(css).root,
+ };
+ const buffer = encodeCSS(cssMap);
+ expect(buffer).toBeInstanceOf(Uint8Array);
+ expect(buffer.length).toBeGreaterThan(0);
+ const decodedString = get_style_content(
+ decode_style_info(buffer, undefined, true),
+ );
+ expect(decodedString.trim()).toMatchSnapshot();
+ });
+
test('should handle complex selectors', () => {
const css = `
div > .foo + #bar[attr="val"]::before:hover {
diff --git a/packages/web-platform/web-core/tests/template-manager.spec.ts b/packages/web-platform/web-core/tests/template-manager.spec.ts
index b8402996ed..a45f35314b 100644
--- a/packages/web-platform/web-core/tests/template-manager.spec.ts
+++ b/packages/web-platform/web-core/tests/template-manager.spec.ts
@@ -87,6 +87,7 @@ describe('Template Manager', () => {
Promise.resolve(mockLynxViewInstance),
false,
false,
+ false,
);
// Verify data using getCustomSection
@@ -125,6 +126,7 @@ describe('Template Manager', () => {
Promise.resolve(mockLynxViewInstance),
false,
false,
+ false,
),
)
.rejects.toThrow('Unsupported version: 2');
@@ -169,6 +171,7 @@ describe('Template Manager', () => {
Promise.resolve(mockLynxViewInstance),
false,
false,
+ false,
);
// Verify data using getCustomSection
@@ -225,6 +228,7 @@ describe('Template Manager', () => {
Promise.resolve(mockLynxViewInstance),
false,
false,
+ false,
),
).rejects.toThrow('Stream failed');
@@ -258,6 +262,7 @@ describe('Template Manager', () => {
Promise.resolve(mockLynxViewInstance),
false,
false,
+ false,
overrideConfig as any,
);
@@ -333,6 +338,7 @@ describe('Template Manager', () => {
Promise.resolve(mockLynxViewInstance),
false,
false,
+ false,
);
// Verify config
@@ -384,6 +390,7 @@ describe('Template Manager', () => {
Promise.resolve(mockLynxViewInstance),
false,
false,
+ false,
);
// Verify config has appType = lazy and isLazy = true
@@ -432,12 +439,14 @@ describe('Template Manager', () => {
Promise.resolve(instance1 as unknown as LynxViewInstance),
false,
false,
+ false,
),
templateManager.fetchBundle(
'http://example.com/template_concurrent',
Promise.resolve(instance2 as unknown as LynxViewInstance),
false,
false,
+ false,
),
]);
diff --git a/packages/web-platform/web-core/ts/client/decodeWorker/cssLoader.ts b/packages/web-platform/web-core/ts/client/decodeWorker/cssLoader.ts
index a88dafe470..9c71809cae 100644
--- a/packages/web-platform/web-core/ts/client/decodeWorker/cssLoader.ts
+++ b/packages/web-platform/web-core/ts/client/decodeWorker/cssLoader.ts
@@ -20,6 +20,7 @@ export function loadStyleFromJSON(
configEnableCSSSelector: boolean,
transformVW: boolean,
transformVH: boolean,
+ transformREM: boolean,
entryName?: string,
): Uint8Array {
const rawStyleInfo = new wasmInstance.RawStyleInfo();
@@ -105,6 +106,7 @@ export function loadStyleFromJSON(
entryName,
transformVW,
transformVH,
+ transformREM,
);
}
diff --git a/packages/web-platform/web-core/ts/client/decodeWorker/decode.worker.ts b/packages/web-platform/web-core/ts/client/decodeWorker/decode.worker.ts
index 7fc4914cab..600e3fb5c9 100644
--- a/packages/web-platform/web-core/ts/client/decodeWorker/decode.worker.ts
+++ b/packages/web-platform/web-core/ts/client/decodeWorker/decode.worker.ts
@@ -106,7 +106,14 @@ self.onmessage = async (
wasmInstance.initSync({ module: wasmModule });
wasmModuleLoadedResolve();
} else if (data.type === 'load') {
- const { url, fetchUrl, overrideConfig, transformVW, transformVH } = data;
+ const {
+ url,
+ fetchUrl,
+ overrideConfig,
+ transformVW,
+ transformVH,
+ transformREM,
+ } = data;
try {
const response = await fetch(fetchUrl, {
headers: {
@@ -117,7 +124,14 @@ self.onmessage = async (
throw new Error(`Failed to fetch template: ${response.statusText}`);
}
const reader = response.body.getReader();
- await handleStream(url, reader, transformVW, transformVH, overrideConfig);
+ await handleStream(
+ url,
+ reader,
+ transformVW,
+ transformVH,
+ transformREM,
+ overrideConfig,
+ );
postMessage({ type: 'done', url } as MainMessage);
} catch (error) {
postMessage(
@@ -131,6 +145,7 @@ async function handleStream(
reader: ReadableStreamDefaultReader,
transformVW: boolean,
transformVH: boolean,
+ transformREM: boolean,
overrideConfig?: Partial,
) {
const streamReader = new StreamReader(reader);
@@ -148,7 +163,14 @@ async function handleStream(
const decoder = new TextDecoder();
const jsonStr = decoder.decode(headerBytes) + decoder.decode(rest);
const json = JSON.parse(jsonStr);
- await handleJSON(json, url, transformVW, transformVH, overrideConfig);
+ await handleJSON(
+ json,
+ url,
+ transformVW,
+ transformVH,
+ transformREM,
+ overrideConfig,
+ );
return;
}
@@ -227,6 +249,7 @@ async function handleStream(
config['enableCSSSelector'] === 'true',
transformVW,
transformVH,
+ transformREM,
);
postMessage(
{
@@ -313,6 +336,7 @@ async function handleJSON(
url: string,
transformVW: boolean,
transformVH: boolean,
+ transformREM: boolean,
overrideConfig?: Partial,
) {
// Configurations
@@ -350,6 +374,7 @@ async function handleJSON(
config['enableCSSSelector'] === 'true',
transformVW,
transformVH,
+ transformREM,
config['isLazy'] === 'true' ? url : undefined,
);
postMessage(
diff --git a/packages/web-platform/web-core/ts/client/decodeWorker/types.ts b/packages/web-platform/web-core/ts/client/decodeWorker/types.ts
index a442481d99..3cdef345a6 100644
--- a/packages/web-platform/web-core/ts/client/decodeWorker/types.ts
+++ b/packages/web-platform/web-core/ts/client/decodeWorker/types.ts
@@ -15,6 +15,7 @@ export interface LoadTemplateMessage extends DecodeWorkerMessage {
fetchUrl: string;
transformVW: boolean;
transformVH: boolean;
+ transformREM: boolean;
overrideConfig?: Record;
}
diff --git a/packages/web-platform/web-core/ts/client/mainthread/LynxView.ts b/packages/web-platform/web-core/ts/client/mainthread/LynxView.ts
index d871057e08..d58c376f21 100644
--- a/packages/web-platform/web-core/ts/client/mainthread/LynxView.ts
+++ b/packages/web-platform/web-core/ts/client/mainthread/LynxView.ts
@@ -75,6 +75,7 @@ export class LynxViewElement extends HTMLElement {
'browser-config',
'transform-vw',
'transform-vh',
+ 'transform-rem',
];
/**
* @private
@@ -163,6 +164,24 @@ export class LynxViewElement extends HTMLElement {
}
}
+ #transformREM: boolean = false;
+ /**
+ * @public
+ * @property transformREM
+ * Enable evaluating rem unit to the current CSS var(--rem-unit)
+ */
+ get transformREM(): boolean {
+ return this.#transformREM;
+ }
+ set transformREM(val: boolean) {
+ this.#transformREM = val;
+ if (val) {
+ this.setAttribute('transform-rem', '');
+ } else {
+ this.removeAttribute('transform-rem');
+ }
+ }
+
constructor() {
super();
if (!this.onNativeModulesCall) {
@@ -373,6 +392,9 @@ export class LynxViewElement extends HTMLElement {
case 'transform-vh':
this.transformVH = newValue !== 'false' && newValue !== null;
break;
+ case 'transform-rem':
+ this.transformREM = newValue !== 'false' && newValue !== null;
+ break;
}
}
}
@@ -459,6 +481,7 @@ export class LynxViewElement extends HTMLElement {
this.#initI18nResources,
this.transformVW,
this.transformVH,
+ this.transformREM,
this.browserConfig,
);
});
@@ -467,6 +490,7 @@ export class LynxViewElement extends HTMLElement {
lynxViewInstance,
this.transformVW,
this.transformVH,
+ this.transformREM,
undefined, // overrideConfig
);
@@ -493,6 +517,7 @@ export class LynxViewElement extends HTMLElement {
this.#upgradeProperty('browserConfig');
this.#upgradeProperty('transformVW');
this.#upgradeProperty('transformVH');
+ this.#upgradeProperty('transformREM');
if (this.url) {
this.#url = this.url;
}
diff --git a/packages/web-platform/web-core/ts/client/mainthread/LynxViewInstance.ts b/packages/web-platform/web-core/ts/client/mainthread/LynxViewInstance.ts
index fe18f9b244..ab3a7eabaa 100644
--- a/packages/web-platform/web-core/ts/client/mainthread/LynxViewInstance.ts
+++ b/packages/web-platform/web-core/ts/client/mainthread/LynxViewInstance.ts
@@ -86,6 +86,7 @@ export class LynxViewInstance implements AsyncDisposable {
initI18nResources?: InitI18nResources,
private readonly transformVW: boolean = false,
private readonly transformVH: boolean = false,
+ private readonly transformREM: boolean = false,
browserConfig?: Record,
) {
this.systemInfo = createSystemInfo(browserConfig);
@@ -132,6 +133,7 @@ export class LynxViewInstance implements AsyncDisposable {
defaultOverflowVisible,
this.transformVW,
this.transformVH,
+ this.transformREM,
),
createMainThreadGlobalAPIs(
this,
@@ -233,6 +235,7 @@ export class LynxViewInstance implements AsyncDisposable {
Promise.resolve(this),
this.transformVW,
this.transformVH,
+ this.transformREM,
{
enableCSSSelector: this.#pageConfig!['enableCSSSelector'],
},
diff --git a/packages/web-platform/web-core/ts/client/mainthread/TemplateManager.ts b/packages/web-platform/web-core/ts/client/mainthread/TemplateManager.ts
index 0bb03322d1..2ac62db93b 100644
--- a/packages/web-platform/web-core/ts/client/mainthread/TemplateManager.ts
+++ b/packages/web-platform/web-core/ts/client/mainthread/TemplateManager.ts
@@ -49,6 +49,7 @@ export class TemplateManager {
lynxViewInstancePromise: Promise,
transformVW: boolean,
transformVH: boolean,
+ transformREM: boolean,
overrideConfig?: Record,
): Promise {
if (this.#bundles.has(url) && !overrideConfig) {
@@ -80,6 +81,7 @@ export class TemplateManager {
lynxViewInstancePromise,
transformVW,
transformVH,
+ transformREM,
overrideConfig,
);
this.#loadingPromises.set(url, promise);
@@ -92,6 +94,7 @@ export class TemplateManager {
lynxViewInstancePromise: Promise,
transformVW: boolean,
transformVH: boolean,
+ transformREM: boolean,
overrideConfig?: Partial,
): Promise {
const currentTime = performance.now() + performance.timeOrigin;
@@ -112,6 +115,7 @@ export class TemplateManager {
fetchUrl: (new URL(url, location.href)).toString(),
transformVW,
transformVH,
+ transformREM,
overrideConfig,
};
this.#worker!.postMessage(msg);
diff --git a/packages/web-platform/web-core/ts/client/mainthread/elementAPIs/createElementAPI.ts b/packages/web-platform/web-core/ts/client/mainthread/elementAPIs/createElementAPI.ts
index a3c7d7ebc8..27ab251815 100644
--- a/packages/web-platform/web-core/ts/client/mainthread/elementAPIs/createElementAPI.ts
+++ b/packages/web-platform/web-core/ts/client/mainthread/elementAPIs/createElementAPI.ts
@@ -66,6 +66,7 @@ export function createElementAPI(
config_default_overflow_visible: boolean,
transform_vw: boolean,
transform_vh: boolean,
+ transform_rem: boolean,
): ElementPAPIs {
const wasmContext = new MainThreadWasmContext(
rootDom,
@@ -294,6 +295,7 @@ export function createElementAPI(
value,
transform_vw,
transform_vh,
+ transform_rem,
)
) {
element.setAttribute('style', value);
@@ -312,6 +314,7 @@ export function createElementAPI(
vec,
transform_vw,
transform_vh,
+ transform_rem,
);
}
}
diff --git a/packages/web-platform/web-core/ts/encode/encodeCSS.ts b/packages/web-platform/web-core/ts/encode/encodeCSS.ts
index 78d4b009b1..fb75c70d57 100644
--- a/packages/web-platform/web-core/ts/encode/encodeCSS.ts
+++ b/packages/web-platform/web-core/ts/encode/encodeCSS.ts
@@ -59,6 +59,12 @@ export function encodeCSS(
keyFrameChildrenRule.set_prelude(prelude);
+ for (
+ const [key, value] of Object.entries(keyframesStyle.variables ?? {})
+ ) {
+ keyFrameChildrenRule.push_declaration(key, value);
+ }
+
for (const decl of keyframesStyle.style) {
keyFrameChildrenRule.push_declaration(decl.name, decl.value);
}
diff --git a/packages/web-platform/web-core/ts/server/decode.ts b/packages/web-platform/web-core/ts/server/decode.ts
index f929b72cc9..df64244064 100644
--- a/packages/web-platform/web-core/ts/server/decode.ts
+++ b/packages/web-platform/web-core/ts/server/decode.ts
@@ -18,6 +18,7 @@ export function decodeTemplate(
buffer: Uint8Array,
transformVW: boolean,
transformVH: boolean,
+ transformREM: boolean,
): DecodedTemplate {
if (buffer.length < 8) {
throw new Error('Buffer too short for Magic Header');
@@ -89,6 +90,7 @@ export function decodeTemplate(
config['enableCSSSelector'] === 'true',
transformVW,
transformVH,
+ transformREM,
);
styleInfo = buffer;
break;
diff --git a/packages/web-platform/web-core/ts/server/deploy.ts b/packages/web-platform/web-core/ts/server/deploy.ts
index 9c5e28bf78..8cf6c27f0e 100644
--- a/packages/web-platform/web-core/ts/server/deploy.ts
+++ b/packages/web-platform/web-core/ts/server/deploy.ts
@@ -15,8 +15,14 @@ export function executeTemplate(
transformVW: boolean,
transformVH: boolean,
viewAttributes?: string,
+ transformREM?: boolean,
): string | undefined {
- const result = decodeTemplate(templateBuffer, transformVW, transformVH);
+ const result = decodeTemplate(
+ templateBuffer,
+ transformVW,
+ transformVH,
+ !!transformREM,
+ );
const config = result.config;
const binding: SSRBinding = { ssrResult: '' };
@@ -30,6 +36,7 @@ export function executeTemplate(
defaultDisplayLinear: config['defaultDisplayLinear'] !== 'false', // Default to true if not present or 'true'
transformVW: transformVW,
transformVH: transformVH,
+ transformREM: !!transformREM,
},
);
diff --git a/packages/web-platform/web-core/ts/server/elementAPIs/createElementAPI.ts b/packages/web-platform/web-core/ts/server/elementAPIs/createElementAPI.ts
index a6f120d7df..7caee0ac37 100644
--- a/packages/web-platform/web-core/ts/server/elementAPIs/createElementAPI.ts
+++ b/packages/web-platform/web-core/ts/server/elementAPIs/createElementAPI.ts
@@ -98,6 +98,7 @@ export function createElementAPI(
defaultDisplayLinear: boolean;
transformVW: boolean;
transformVH: boolean;
+ transformREM: boolean;
},
): { globalThisAPIs: ElementPAPIs; wasmContext: MainThreadServerContext } {
const wasmContext = new MainThreadServerContext(
@@ -105,6 +106,7 @@ export function createElementAPI(
config.enableCSSSelector,
config.transformVW,
config.transformVH,
+ config.transformREM,
);
if (styleInfo) {
const resource = new StyleSheetResource(styleInfo, undefined);