Skip to content

fix(style-order): align editor diagnostics and checkpoint extraction work - #766

Draft
owjs3901 wants to merge 57 commits into
mainfrom
fix/style-order-everywhere
Draft

owjs3901 wants to merge 57 commits into
mainfrom
fix/style-order-everywhere

Conversation

@owjs3901

@owjs3901 owjs3901 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Refs #684, #685 (W38: JSX 외 styleOrder 및 리터럴 CSS 메타데이터). #756과 #757을 W39의 통합 merge 7391e11a로 포함하며 두 PR이 모두 병합된 뒤 병합해야 합니다. 선행 #750도 포함됩니다. 자동 병합하지 않습니다.

요약

css()와 styled()의 조건부 styleOrder를 JSX와 같은 순서 레이어와 클래스 선택으로 컴파일합니다. 전역 스타일의 정적인 순서는 실제 oN 레이어에 놓고, 의미 없는 순서 메타데이터는 위치가 있는 빌드 오류로 보고합니다. 객체 키와 리터럴 CSS의 style-order 모두 CSS 선언으로 새어나오지 않도록 검사합니다. 의존성과 스타일링 런타임을 추가하지 않습니다.

동작

  • 명시적 순서는 정확한 ECMAScript Number 정수 1~254 또는 부호·공백·선행 0 없는 정규 십진 문자열입니다. '01'은 오류이고 +'01'은 정확한 Number 1로 유효합니다. 공유 exact StringToNumber 판정을 유지합니다. #763과 허용 집합이 같아야 하며 나중에 병합되는 PR이 공유 파서를 조정해야 합니다.
  • 클래스 규칙은 유효한 순서로 한정되는 조건식과 &&의 암묵적 미선택 분기를 지원합니다. 조건과 getter는 원래 소스가 읽는 위치에서 한 번씩 평가하고, 선택하지 않은 분기는 읽지 않습니다. 같은 식을 소스에서 두 번 썼다면 두 읽기를 임의로 합치지 않습니다. 지원되지 않는 명시적 값·분기는 조용히 버리지 않고 오류입니다.
  • styled()의 비함수 순서 식은 컴포넌트 정의 시 캡처하고 렌더 시 다시 읽지 않습니다. 함수 보간은 원래 closure와 조기 반환을 유지하며 렌더별로 한 번 실행합니다. 상속·attrs·withComponent에서도 저장한 값과 closure를 재사용하고 ref/as/forwardedAs 및 대상별 prop 필터링을 유지합니다. 저장된 환경은 값 전달만 하며 스타일 객체 해석·CSS 생성·클래스 문자열 파싱을 하지 않습니다.
  • 이미 생성한 css() 결과는 primitive 문자열을 유지합니다. 빌드가 증명한 닫힌 결과 전체와 선언 provenance로만 후속 정적 합성을 수행하고, 원래 조건을 재실행하거나 임의의 외부 클래스 토큰을 분석하지 않습니다. 같은 속성·선택자·breakpoint·이름 레이어·숫자 순서에서 나중 선언이 이기며, 다른 순서의 선언은 서로 지우지 않습니다.
  • 전역 선택자 규칙은 CSS cascade에서 경쟁하므로 정적 전역 순서는 의미가 있습니다. globalCss, Emotion Global, styled-components createGlobalStyle 및 지원되는 globalStyle 경로는 실제 sheet에 등록된 oN 레이어를 사용합니다. 전역 규칙에는 런타임 클래스 선택이 없으므로 동적인 순서는 오류입니다.
  • keyframes는 이름으로 참조되는 애니메이션 정의여서 클래스 선언 우선순위를 프레임에 적용하는 개념이 없습니다. font-face descriptor 역시 선택자 cascade 선언이 아니며 styleOrder는 유효한 descriptor가 아닙니다. 네이티브 StyleX 선언도 Devup 순서 메타데이터를 받는 경로가 아니므로 이 문맥들은 명시적인 no-effect 오류를 보고합니다. 실제 선언 키와 selector/layer record·namespace·변수·일반 데이터 이름은 구분합니다.
  • 리터럴 CSS의 style-order는 객체의 styleOrder와 같은 메타데이터입니다. scope와 quote/comment/escape/function/attribute selector/custom-property token stream을 먼저 읽고 값을 판정합니다. bare CSS 숫자는 정확한 Number로, 인용된 문자열은 디코딩한 정규 문자열로 판정합니다. 정확한 보간은 primitive 타입을 유지하고 혼합 보간은 문자열 의미를 유지합니다. 순서가 scope 뒤에 쓰여도 해당 scope 전체에 적용하며 내부 명시적 순서는 외부 상속보다 우선합니다. comment·덮어쓴 순서·빈 규칙의 원래 보간 효과도 유지합니다.
  • 공유 sheet 정렬은 변경하지 않습니다. 선택자 그룹이 먼저, breakpoint가 다음이며 같은 그룹 안에서 반응형 규칙이 비반응형 규칙 뒤에 놓입니다. 그룹이 다르면 기존 pseudo-class 우선순위가 모든 너비에서 적용되어 일반 :active가 반응형 :hover 뒤에 놓일 수 있습니다. 기존 typography t 레이어도 유지합니다.
  • style-order-range 편집기 규칙은 실제 어휘적 API import와 별칭을 따라 객체 및 리터럴 문맥을 검사합니다. shadow·일반 props/vars/attrs/config 데이터·선택자/레이어 record 키·StyleX namespace 이름을 선언 메타데이터로 오인하지 않습니다. 사용자 함수 실행이나 외부 모듈 로딩을 추가하지 않고 기존 범위의 빌드 증명 위임을 유지합니다.

새로 생기는 오류

모든 빌드 오류는 실제 입력의 파일:줄:열과 문제가 된 키 또는 값을 포함합니다. 원래 expression·보간·import 참조의 위치를 사용하며 생성된 offset이나 line 1로 바꾸지 않습니다.

  • 명시적 0/255/음수/소수/비유한 Number, 비정규 문자열 '01'·부호·공백·단위·지수/소수 표기 문자열, null/boolean/undefined 또는 유효한 순서로 증명되지 않는 동적 값·분기.
  • 전역 규칙에서 런타임 조건으로 순서를 고르는 객체 키 또는 리터럴 선언.
  • keyframes 최상위·프레임·중첩 문맥, fontFaces/font-face descriptor, 네이티브 StyleX 선언에서 효과 없는 순서 키. 리터럴 형태도 같은 위치 기반 오류이며 CSS 선언이나 CSS 변수로 바꾸지 않습니다.
  • literal CSS의 잘못된 순서 token 또는 primitive 타입을 보존한 잘못된 보간. quote·comment·URL·selector·custom property에 들어 있는 단순 텍스트는 순서 선언이 아닙니다.

실제 오류 출력과 각 원본 evidence 경로의 변경 전/후 출력은 아래 검증에 최종 재빌드 결과로 기록합니다.

남는 한계

임의의 외부 className 합성은 기존 CSS cascade를 따릅니다. 빌드가 증명한 결과와 무관한 문자열을 클래스 토큰 일치만으로 정적 합성하지 않습니다. 전역·프레임 API에는 동적 CSS 변수를 붙일 요소나 런타임 클래스 선택이 없으므로 기존 빌드 시 확정 요구를 유지합니다. 편집기는 외부 모듈의 값을 실행하지 않으며 빌드가 최종 권위입니다.

순서가 없는 vanilla-extract fontFace/globalFontFace 대조 fixture의 기존 WASM trap은 #761의 별도 소유입니다. 이 PR에서는 고치거나 그 브랜치를 병합하지 않습니다. 순서 메타데이터 거부 자체는 이 PR 범위에 남습니다.

검증

  • 현재 head: b2c71a14100e094362aaf343bdefe3d0d230b8df; Linux CI 37503689539: failure, coverage 후속 작업이 남은 Draft. 앞서 overflow한 테스트를 포함한 Rust 3,568개가 모두 통과했으나 tarpaulin은 **98.31% (16,253/16,532)**로 100% 기준에 실패했습니다. 실제 미커버 279줄/37파일을 CI-wide format에서 원본 위치로 매핑해 후속 회귀로 채워야 합니다. publish build·package entry/tarball·lint와 나머지 세 job은 통과했습니다: benchmark success, vinext 각 29개, Next 각 130개 E2E. publish의 Bun/Codecov 및 후속 E2E는 미실행/skipped이며 성공으로 주장하지 않습니다. 외부 Codecov/runner outage가 아니며 Linux 100% 전 ready/병합 상태로 바꾸지 않습니다.
  • 미커버 279개 전체를 같은 Rust 1.99 wide-format 설정으로 재구성한 소스와 매핑했습니다: 255개는 정확한 원본 span, 24개는 UNKNOWN으로 명시하여 위치를 추측하지 않았습니다. 전체 wide/normal 소스와 해시·원래 CI range·주변 코드가 보존되어 있으며 coverage 후속 작업으로 인계합니다. 이 매핑은 coverage 수정이나 Linux 100% 달성으로 간주하지 않습니다. 작업트리는 위 head로 clean이며 PR은 Draft를 유지합니다.
  • 앞선 37495427755, head 8fc666cf는 publish tarpaulin 중 stack overflow로 실패하여 coverage/Bun/Codecov 결과가 없었습니다. build·package entry/tarball·lint와 benchmark/vinext29+29/Next130+130 E2E는 통과했고 외부 outage는 아니었습니다. 단계별 재현에서 extraction/Oxc가 끝난 뒤 Boa Script::parse가 테스트 어댑터의 불필요한 외부 함수 wrapper 때문에 더 깊게 재귀하는 것을 확인했습니다. 같은 입력은 실제 WASM과 깊이 4/8/16/24에서 추출·생성 JS 실행 모두 통과했고 앞선 네 입력의 출력 bytes는 동일합니다. 테스트 전체 파일에만 추가되던 wrapper를 제거하여 재귀 프레임을 줄였으며 production 코드·원래 assertions·stack size·workflow/env는 바꾸지 않았습니다. 수정 후 기본 stack의 전체 workspace 3,568개와 실제 instrumented target, 정상 hook의 full tarpaulin/Bun 6,448개가 통과했습니다. 이 Windows 증거를 새 Linux 커버리지의 대체로 사용하지 않습니다.
  • Rust 1.99 workspace/all-targets clippy -D warnings, fmt, FORCE_PASS를 설정하지 않은 strict workspace 3,568개 테스트가 모두 통과했습니다. 정상 CI-unset pre-commit hook도 lint/tarpaulin/Bun을 통과했으며 hook 우회나 stash 없이 검사한 전체 파일을 커밋했습니다. Windows Rust tarpaulin은 **96.13% (23,010/23,936)**이고, 확정 규칙에 따라 Linux CI의 100%가 권위입니다. 정상 lint에는 선행 base의 경고 두 개만 남습니다.
  • 실제 WASM 및 root build 통과. 공유 판정표 82개 × 객체/리터럴 분리 = 164개가 실제 WASM에서 통과했습니다. 한 경로의 오류가 다른 경로의 판정을 가리지 않습니다. 추가 lexical/scope 프로브 10개, 원본 API별 프로브 분류 및 생성 코드 실행 검증을 통과했습니다.
  • 전체 Bun 6,448 pass / 0 fail, 89개 snapshot 및 aggregate 함수/줄 커버리지 100% 출력을 확인했습니다. Windows 개별 Vite plugin row는 99.63%이며 미커버 위치 303은 기존 // Vite ids are POSIX absolute paths 주석의 source-map 경계입니다. Vite 소스나 coverage 제외 설정을 바꾸지 않았으며 aggregate 수치·파일별 관찰·Linux 결과를 구분합니다.
  • native tsc: 편집기/React project, 긍정·부정 소비자 26개 및 실제 build dist entrypoint 소비자 검증 통과. 타입으로 TemplateStringsArray 내용을 읽거나 임의 JavaScript 정적 계산·범위를 증명할 수는 없으므로 그 부분은 빌드와 lint가 권위입니다.
  • Rust snapshot 132개를 각 old/new 속성·값·선택자·level·숫자/이름 layer·decoded code·원래 읽기 횟수/위치와 양쪽 SHA256으로 개별 검토했습니다. 132개 승인 bytes에서 assertion_line만 제거하여 반영했고 모든 최종 해시가 일치하며 .snap.new는 없습니다. Bun DOM 11개 변경도 전체 HTML과 class token multiset/다른 attribute·text·CSS rule 및 파일 역변환 해시를 각각 확인한 단순 class 순서 변경입니다. 내부 base bucket 테스트는 무효한 public styleOrder={0} 대신 정상 추출 결과를 내부 순서 0에 놓아 기존 (true, true) 판정을 그대로 검사하며 sheet production/sort 코드는 변경하지 않았습니다.
  • 두 기존 getter 결함은 fix(extractor): preserve JavaScript semantics across values and element calls #756/fix(extractor): locate diagnostics and enforce deterministic evaluation #757 base에서 이미 존재했으며 #766이 소유한 capture 경로에서 수정했습니다: 조건부 순서와 typography의 원래 읽기를 각 분기에서 한 번 유지하고, Emotion spread의 className/style getter를 복사 이후 원본에서 다시 읽지 않습니다. 각각 getter-counting 및 source-order 회귀가 실패 후 통과했습니다.
  • #763과 직접 겹치는 선언: packages/react/src/types/props/selector/index.ts, src/utils/css.ts, global-css.ts, keyframes.ts. create-global-style.ts도 읽고 기존 선언을 재사용했으며 관련 primitive-rest 서명은 이미 동일하므로 수정하지 않았습니다. fix(types): align remaining StyleX, shorthand and lint contracts #763 d69f5193의 적용 가능한 선언을 그대로 재사용하고, global root collision·no-effect never·object alias·template fallback 방지만 필요한 범위로 보강했습니다. 나중 병합되는 PR은 이 파일들과 strict parser를 함께 조정해야 합니다.
  • Patch changepack: WASM, React, ESLint, components. 의존성·workflow·공유 sheet 정렬 변경 없음. LSP는 Rust daemon timeout 및 설치가 거절된 TS server로 clean을 주장하지 않습니다.

실제 프로브 출력

원본 evidence의 여섯 경로를 분리하여 실제 변경 전/후 출력 전체를 기록합니다. 합친 원본 fixture는 이제 무효한 keyframes 순서를 명시적으로 거부하므로 격리 fixture가 다른 경로의 정상 출력을 함께 증명합니다.

order-css

입력과 변경 전/후 전체 WASM 출력
import { css } from '@devup-ui/react'
export const plain = css({ color: 'blue', styleOrder: active ? 1 : 2 })

변경 전:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
export const plain = "a";

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */.a{color:blue}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */.a{color:blue}

변경 후:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
export const plain = ((__devupValue0) => `${__devupValue0 ? "a" : ""} ${__devupValue0 ? "" : "b"}`)(active);

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.a{color:blue}}@layer o2{.b{color:blue}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.a{color:blue}}@layer o2{.b{color:blue}}

order-styled

입력과 변경 전/후 전체 WASM 출력
import { styled } from '@devup-ui/react'
export const Card = styled('div', { color: 'green', styleOrder: active ? 1 : 2 })

변경 전:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
import { forwardRef as __devupForwardRef } from "react";
export const Card = __devupForwardRef((__devupRefProps, __devupRef) => (({ style, className, as: DevupAs = "div", forwardedAs, ...rest }) => <DevupAs {...(({ "theme": __devupOmit0, ...__devupDom }) => __devupDom)(rest)} as={forwardedAs} className={["a", className].filter(Boolean).join(" ")} style={style} />)({
	...__devupRefProps,
	ref: __devupRef
}));

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */.a{color:green}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */.a{color:green}

변경 후:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
import { forwardRef as __devupForwardRef } from "react";
export const Card = ((__devupValue0) => ((__devupEnvironment0Component) => (__devupEnvironment0Component["__devupEnvironment0"] = (__devupEnvironment0Continue) => __devupEnvironment0Continue(__devupValue0), __devupEnvironment0Component))(__devupForwardRef((__devupRefProps, __devupRef) => ((__devupStyleProps) => (({ style, className, as: DevupAs = "div", forwardedAs, ...rest }) => <DevupAs {...(({ "theme": __devupOmit0, ...__devupDom }) => __devupDom)(rest)} as={forwardedAs} className={[`${__devupValue0 ? "" : "a"} ${__devupValue0 ? "b" : ""}`, className].filter(Boolean).join(" ")} style={style} />)(__devupStyleProps))({
	...__devupRefProps,
	ref: __devupRef
}))))(active);

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.b{color:green}}@layer o2{.a{color:green}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.b{color:green}}@layer o2{.a{color:green}}

order-jsx

입력과 변경 전/후 전체 WASM 출력
import { Box } from '@devup-ui/react'
export const App = <Box color="red" styleOrder={active ? 1 : 2} />

변경 전:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
export const App = <div className={active ? "a" : "b"} />;

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.a{color:red}}@layer o2{.b{color:red}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.a{color:red}}@layer o2{.b{color:red}}

변경 후:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
export const App = ((__devupValue0) => <div className={__devupValue0 ? "a" : "b"} />)(active);

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.a{color:red}}@layer o2{.b{color:red}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.a{color:red}}@layer o2{.b{color:red}}

order-runtime

입력과 변경 전/후 전체 WASM 출력
import { Box } from '@devup-ui/react'
import { jsx } from 'react/jsx-runtime'
export const Runtime = jsx(Box, { color: 'pink', styleOrder: active ? 1 : 2 })

변경 전:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
import { jsx } from "react/jsx-runtime";
export const Runtime = jsx("div", { className: active ? "a" : "b" });

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.a{color:pink}}@layer o2{.b{color:pink}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.a{color:pink}}@layer o2{.b{color:pink}}

변경 후:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
import { jsx } from "react/jsx-runtime";
export const Runtime = jsx("div", ((__devupValue0) => ({ className: __devupValue0 ? "a" : "b" }))(active));

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.a{color:pink}}@layer o2{.b{color:pink}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.a{color:pink}}@layer o2{.b{color:pink}}

order-global

입력과 변경 전/후 전체 WASM 출력
import { globalCss } from '@devup-ui/react'
globalCss({ body: { color: 'gray', styleOrder: 2 }, styleOrder: 2 })

변경 전:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
;

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer b;@layer b{body{color:gray;style-order:8px}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer b;@layer b{body{color:gray;style-order:8px}}

변경 후:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
;

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2;@layer o2{body{color:gray}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2;@layer o2{body{color:gray}}

order-keyframes

입력과 변경 전/후 전체 WASM 출력
import { keyframes } from '@devup-ui/react'
export const fade = keyframes({ from: { opacity: 0, styleOrder: 2 }, to: { opacity: 1 } })

변경 전:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
export const fade = "a";

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@keyframes a{from{opacity:0}to{opacity:1}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@keyframes a{from{opacity:0}to{opacity:1}}

변경 후:

=== ERROR ===
C:/Users/devfive3901/AppData/Local/Temp/opencode/workers/w38-style-order/order-keyframes.tsx:2:53: `keyframes()` cannot use `styleOrder` at build time: styleOrder is reserved cascade metadata and has no effect in this API

order-semantics-base

입력과 변경 전/후 전체 WASM 출력
import { Box, css, styled, globalCss, keyframes } from '@devup-ui/react'
import { jsx } from 'react/jsx-runtime'
const plain = css({ color: 'blue', styleOrder: active ? 1 : 2 })
const Card = styled('div', { color: 'green', styleOrder: active ? 1 : 2 })
globalCss({ body: { color: 'gray', styleOrder: 2 }, styleOrder: 2 })
const fade = keyframes({ from: { opacity: 0, styleOrder: 2 }, to: { opacity: 1 } })
export const App = <Box color="red" styleOrder={active ? 1 : 2} className={plain} animationName={fade}><Card /></Box>
export const Runtime = jsx(Box, { color: 'pink', styleOrder: active ? 1 : 2 })

변경 전:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
import { forwardRef as __devupForwardRef } from "react";
import { jsx } from "react/jsx-runtime";
const plain = "a";
const Card = __devupForwardRef((__devupRefProps, __devupRef) => (({ style, className, as: DevupAs = "div", forwardedAs, ...rest }) => <DevupAs {...(({ "theme": __devupOmit0, ...__devupDom }) => __devupDom)(rest)} as={forwardedAs} className={["b", className].filter(Boolean).join(" ")} style={style} />)({
	...__devupRefProps,
	ref: __devupRef
}));
;
const fade = "c";
export const App = <div className={active ? "a d e" : "a f g"}><Card /></div>;
export const Runtime = jsx("div", { className: active ? "h" : "i" });

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer b,o1,o2;@layer b{body{color:gray;style-order:8px}}@keyframes c{from{opacity:0}to{opacity:1}}@layer o1{.e{animation-name:c}.h{color:pink}.d{color:red}}@layer o2{.g{animation-name:c}.i{color:pink}.f{color:red}}.a{color:blue}.b{color:green}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer b,o1,o2;@layer b{body{color:gray;style-order:8px}}@keyframes c{from{opacity:0}to{opacity:1}}@layer o1{.e{animation-name:c}.h{color:pink}.d{color:red}}@layer o2{.g{animation-name:c}.i{color:pink}.f{color:red}}.a{color:blue}.b{color:green}

변경 후:

=== ERROR ===
C:/Users/devfive3901/AppData/Local/Temp/opencode/workers/w38-style-order/order-semantics-base.tsx:6:46: `keyframes()` cannot use `styleOrder` at build time: styleOrder is reserved cascade metadata and has no effect in this API

order-literal-css

입력과 변경 전/후 전체 WASM 출력
import { css } from '@devup-ui/react'
export const plain = css`style-order: 2; color: blue; &:hover { style-order: 3; color: green; }`

변경 전 (객체 lane 체크포인트, 리터럴 처리 전):

=== CODE ===
import "@devup-ui/react/devup-ui.css";
export const plain = "a b c d";

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */.d{color:blue}.b{style-order:8px}.c:hover{color:green}.a:hover{style-order:12px}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */.d{color:blue}.b{style-order:8px}.c:hover{color:green}.a:hover{style-order:12px}

변경 후:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
export const plain = "a b";

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2,o3;@layer o2{.b{color:blue}}@layer o3{.a:hover{color:green}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2,o3;@layer o2{.b{color:blue}}@layer o3{.a:hover{color:green}}

order-literal-styled

입력과 변경 전/후 전체 WASM 출력
import { styled } from '@devup-ui/react'
export const Card = styled.div`style-order: 2; color: green;`

변경 전 (객체 lane 체크포인트, 리터럴 처리 전):

=== CODE ===
import "@devup-ui/react/devup-ui.css";
import { forwardRef as __devupForwardRef } from "react";
export const Card = __devupForwardRef((__devupRefProps, __devupRef) => ((__devupStyleProps) => (({ style, className, as: DevupAs = "div", forwardedAs, ...rest }) => <DevupAs {...(({ "theme": __devupOmit0, ...__devupDom }) => __devupDom)(rest)} as={forwardedAs} className={["a b", className].filter(Boolean).join(" ")} style={style} />)(__devupStyleProps))({
	...__devupRefProps,
	ref: __devupRef
}));

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */.b{color:green}.a{style-order:8px}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */.b{color:green}.a{style-order:8px}

변경 후:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
import { forwardRef as __devupForwardRef } from "react";
export const Card = __devupForwardRef((__devupRefProps, __devupRef) => ((__devupStyleProps) => (({ style, className, as: DevupAs = "div", forwardedAs, ...rest }) => <DevupAs {...(({ "theme": __devupOmit0, ...__devupDom }) => __devupDom)(rest)} as={forwardedAs} className={["a", className].filter(Boolean).join(" ")} style={style} />)(__devupStyleProps))({
	...__devupRefProps,
	ref: __devupRef
}));

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2;@layer o2{.a{color:green}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2;@layer o2{.a{color:green}}

order-literal-global

입력과 변경 전/후 전체 WASM 출력
import { globalCss } from '@devup-ui/react'
globalCss`body { style-order: 2; color: gray; &:hover { style-order: 3; color: blue; } }`

변경 전 (객체 lane 체크포인트, 리터럴 처리 전):

=== CODE ===
import "@devup-ui/react/devup-ui.css";
;

=== CSS (this file) ===

=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */body{style-order:2;color:gray;&:hover{style-order:3;color:blue}}

변경 후:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
;

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2,o3;@layer o2{body{color:gray}}@layer o3{body:hover{color:blue}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2,o3;@layer o2{body{color:gray}}@layer o3{body:hover{color:blue}}

order-literal-emotion

입력과 변경 전/후 전체 WASM 출력
import { css } from '@emotion/react'
export const plain = css`style-order: 2; color: blue;`

변경 전 (객체 lane 체크포인트, 리터럴 처리 전):

=== CODE ===
import "@devup-ui/react/devup-ui.css";
export const plain = "a b";

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */.b{color:blue}.a{style-order:8px}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */.b{color:blue}.a{style-order:8px}

변경 후:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
export const plain = "a";

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2;@layer o2{.a{color:blue}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2;@layer o2{.a{color:blue}}

order-literal-sc

입력과 변경 전/후 전체 WASM 출력
import styled from 'styled-components'
export const Card = styled.div`style-order: 2; color: green;`

변경 전 (객체 lane 체크포인트, 리터럴 처리 전):

=== CODE ===
import "@devup-ui/react/devup-ui.css";
import { forwardRef as __devupForwardRef } from "react";
export const Card = __devupForwardRef((__devupRefProps, __devupRef) => ((__devupStyleProps) => (({ style, className, as: DevupAs = "div", forwardedAs, ...rest }) => <DevupAs {...(({ "theme": __devupOmit0, ...__devupDom }) => __devupDom)(rest)} as={forwardedAs} className={["a b", className].filter(Boolean).join(" ")} style={style} />)(__devupStyleProps))({
	...__devupRefProps,
	ref: __devupRef
}));

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */.b{color:green}.a{style-order:8px}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */.b{color:green}.a{style-order:8px}

변경 후:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
import { forwardRef as __devupForwardRef } from "react";
export const Card = __devupForwardRef((__devupRefProps, __devupRef) => ((__devupStyleProps) => (({ style, className, as: DevupAs = "div", forwardedAs, ...rest }) => <DevupAs {...(({ "theme": __devupOmit0, ...__devupDom }) => __devupDom)(rest)} as={forwardedAs} className={["a", className].filter(Boolean).join(" ")} style={style} />)(__devupStyleProps))({
	...__devupRefProps,
	ref: __devupRef
}));

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2;@layer o2{.a{color:green}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2;@layer o2{.a{color:green}}

order-literal-sc-global

입력과 변경 전/후 전체 WASM 출력
import { createGlobalStyle } from 'styled-components'
export const Global = createGlobalStyle`body { style-order: 2; color: gray; }`

변경 전 (객체 lane 체크포인트, 리터럴 처리 전):

=== CODE ===
import "@devup-ui/react/devup-ui.css";
export const Global = () => null;

=== CSS (this file) ===

=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */body{style-order:2;color:gray}

변경 후:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
export const Global = () => null;

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2;@layer o2{body{color:gray}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o2;@layer o2{body{color:gray}}

order-literal-dynamic

입력과 변경 전/후 전체 WASM 출력
import { css } from '@devup-ui/react'
const events = []
function choose() { events.push('order'); return true }
export const plain = css`style-order: ${choose() ? 1 : 2}; color: blue;`

변경 전 (객체 lane 체크포인트, 리터럴 처리 전):

=== ERROR ===
C:/Users/devfive3901/AppData/Local/Temp/opencode/workers/w38-style-order/order-literal-dynamic.tsx:4:22: `css()` cannot use `choose()?1:2` at build time: its values must be literals, theme tokens or constants, or be computed from them

변경 후:

=== CODE ===
import "@devup-ui/react/devup-ui.css";
const events = [];
function choose() {
	events.push("order");
	return true;
}
export const plain = ((__devupValue0) => `${__devupValue0 ? "a" : ""} ${__devupValue0 ? "" : "b"}`)(choose());

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.a{color:blue}}@layer o2{.b{color:blue}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@layer o1,o2;@layer o1{.a{color:blue}}@layer o2{.b{color:blue}}

order-literal-keyframes

입력과 변경 전/후 전체 WASM 출력
import { keyframes } from '@devup-ui/react'
export const fade = keyframes`from { style-order: 2; opacity: 0; } to { opacity: 1; }`

변경 전 (객체 lane 체크포인트, 리터럴 처리 전):

=== CODE ===
import "@devup-ui/react/devup-ui.css";
export const fade = "a";

=== CSS (this file) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@keyframes a{from{opacity:0;style-order:8px}to{opacity:1}}
=== CSS (whole sheet) ===
/*! devup-ui v1.0.82, | Apache License 2.0 | https://devup-ui.com */@keyframes a{from{opacity:0;style-order:8px}to{opacity:1}}

변경 후:

=== ERROR ===
C:/Users/devfive3901/AppData/Local/Temp/opencode/workers/w38-style-order/order-literal-keyframes.tsx:2:38: `keyframes()` cannot use `styleOrder` at build time: styleOrder is reserved cascade metadata and has no effect in this API

owjs3901 and others added 30 commits October 1, 2026 21:16
…rations

css(a, b) composing classes whose styles the build knows, bound to css() in the file or exported by another module, merges their atoms per property, selector, breakpoint and layer, conditions included, instead of joining classes whose winner the stylesheet order picked. vanilla-extract style([...]) passes each composed style as its own argument, keeping a style composed again later.

Refs #688

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #688

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #688

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #688

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…asurable

Refs #688

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…JSX spreads win

Refs #688

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…led order and JSX element className

Refs #688

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #689

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…uate shouldForwardProp at build time

Refs #689

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…ring

Refs #689

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #691

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #690

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
… and conditional styles

Refs #690

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…h Emotion

Refs #690

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #690

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…ed parameters

Refs #690

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #690

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…ead through namespaces

Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…akes from the visitor

Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…eclared after their use

Refs #695, #686

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…nding

Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
owjs3901 and others added 23 commits October 5, 2026 00:48
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #685, #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #685, #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #685, #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #685, #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #685, #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #685, #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #685, #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #685, #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…graphs

Refs #685, #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #685, #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #685, #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #685, #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #685, #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Resolve both module-declaration and regenerated snapshot conflicts; adapt the #756 source-evaluation test to #757 evaluate_located. Synchronize bun.lock workspace versions.

Split shadowed require from global resolver diagnostics, preserve entry-ingress fallback, and adapt empty JSX styleOrder to located parse rejection. Both #756 and #757 must merge first.

Refs #694, #695

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #684, #685

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Changepacks

@devup-ui/wasm@1.0.83 → 1.0.84 - bindings/devup-ui-wasm/package.json

Patch

  • A project module re-exporting Devup UI (export { Box, css } from '@devup-ui/react', export * from '@devup-ui/react', export { styled as s }, export * as Devup, a default export of an import, chains of barrels and the compat entry) now works: a file importing Box or css from it compiles exactly as if it imported from the package, following the barrel through the resolver (relative paths, tsconfig paths, package exports), and hasDevupUI sees such a file. Members read from a namespace or default import of the package (Devup['css'], const { css } = Devup, Devup.css as a value) compile where the build can follow them, Devup.x for a name the package compiles being read like the named import. New build errors, located at the use: what a barrel re-exports but the build cannot read (an unresolvable export * or module, a namespace of modules re-exporting the package) is an error where its name is used instead of a runtime crash, and a namespace member read by a key the build cannot know (Devup[key]), written, or destructured in a form it cannot follow (a rest, a computed key, a default value, a nested pattern, an exported declaration, or members mixed with ones that stay at runtime) is an error that names the members to read. A namespace passed on whole (Object.keys(Devup), spyOn(Devup, 'css'), export default Devup) is left as it is
  • css(a, b) composing classes whose styles the build knows (a const bound to css() in the file, or a css() result another module exports with a rule object every value of which is known) merges their styles: a later part's declaration replaces an earlier one's for the same property, selector, breakpoint and layer, also under conditions (css(base, cond && danger)) and for ||/?? parts, where the classes used to be joined and the stylesheet order picked the winner. vanilla-extract style([a, b]) passes each composed style as its own argument, so the later one wins, and a style composed again later (style([a, b, a])) is kept. Classes the build does not know (strings, props, CSS Modules) are kept as they are
  • styled(Base) extending a styled component the file binds to a const renders Base's tag directly with Base's styles composed under its own, so the extension's declarations replace Base's for the same property, selector, breakpoint and layer instead of losing to them by stylesheet order; Base's attrs apply before the extension's. attrs merge as styled-components merges them: className is joined with the caller's, style is merged and other props replace earlier ones. On an element, a className or style spread after the explicit prop now wins, as React merges props in the order they are written
  • Emotion's now compiles at build time with no runtime: the element becomes what its child function ({ css, cx, theme }) => ... renders, each css and cx call becomes the classes it composes (later styles replace earlier ones; css reads strings as CSS text and its tagged templates split around mixins; cx keeps unknown classes, reads { name: condition } objects as conditional classes and composes nested css and cx calls), and theme.a.b in their values becomes var(--a-b). Numbers in css rules are px lengths, as Emotion reads them, and top-level constants are inlined. New build errors, each at file:line:col: a without exactly one child function taking { css, cx, theme } that gives what it renders at once (attributes, other children, rest or default parameters, async or generator functions, several statements); reading the theme other than as theme.a.b in a css value; using css or cx other than by calling them; a cx object with a spread, getter or method; parts css and cx cannot compose (runtime calls, spreads, a condition choosing between styles and classes). @devup-ui/react/compat exports ClassNames with the ClassNamesContent and ClassNamesArg types, and the @emotion/react declarations include them
  • Emotion and styled-components component selectors now compile at build time: a styled component the file defines that another style selects (${Child} { ... } in CSS text, [Child] or [&:hover ${Child}] as a rule key) gets a short marker class, which only such components get, and the selector reads it as .marker; a component extending it, or an element inlining it for its css prop, keeps the marker. Selectors written without & now nest under the component as stylis nests them (ul { ... } is & ul, a selector list nests each selector, :hover applies to the component itself) instead of becoming global rules, and rule-object keys starting with ., #, [, *, >, + or ~ are read as nested selectors instead of properties
  • Emotion's css prop compiles at build time while @emotion/react is aliased: on tags and Devup UI components always, and on every element once the file imports @emotion/react or @emotion/styled or names @emotion/react in a @jsxImportSource pragma; jsx, jsxs and jsxDEV from @emotion/react/jsx-runtime (or jsx-dev-runtime) and jsx from @emotion/react compile it too, so libraries built with Emotion's JSX runtime do as well. The prop becomes the element's className, with CSS variables in its style for values only the runtime gives: arrays and conditions compose with a later part replacing what an earlier one sets, css() classes the file knows compose by their styles, strings and templates are CSS text, css`` mixins split the text around them, a function of the theme reads theme.a.b as var(--a-b), unitless numbers are px as in Emotion (constants included), and a className holding known css() classes overrides the prop as Emotion's registered classes do. A styled component the file defines renders its tag in the element's place when the prop overrides its styles and it renders a tag with no attrs or props read and the element has no spread, as or forwardedAs. Emotion's JSX runtime imports become react/jsx-runtime, the pragma names react, and jsx comes from @devup-ui/react/compat (React's createElement); @devup-ui/react/compat/css-prop types the prop on React.Attributes. New build errors, each with file:line:column and the code: a css prop part the build cannot read (a call, an element), a style object declared inside a function or with let, a binding only running the module gives or code changes, a theme function that does more than return rules or reads the theme other than as theme.a.b in a value, an interpolation CSS text cannot place or a mixin inside a nested rule, and a css prop overriding a styled component's styles where its tag cannot be rendered in place. Composing css() with a part that reads a known binding (such as a keyframes name) now reads its value
  • A project whose tsconfig.json (or jsconfig.json) builds JSX with Emotion (compilerOptions.jsxImportSource of @emotion/react, through extends and project references too) now compiles the css prop on every element of every file, and its .tsx and .jsx files are built with React's JSX runtime through a /** @jsxImportSource react */ pragma, which a file's own JSX pragma overrides, so the bundler no longer imports Emotion's runtime. The plugins read the setting into a new @emotion/react/jsx-runtime alias (importAliases can turn it off with false, and it is left out when @emotion/react is not aliased); @devup-ui/react/compat/emotion-jsx-runtime declares Emotion's JSX runtimes as React's so the project type-checks without Emotion installed. plugin-utils exports readJsxImportSource, and mergeImportAliases takes the JSX import source
  • hasDevupUI takes the import aliases and is true for a file extraction changes: one importing a redirected package (@emotion/styled, ...), naming @emotion/react in a @jsxImportSource pragma, or in a project whose tsconfig jsxImportSource is @emotion/react, so the Bun plugin no longer skips files whose only Devup UI is Emotion's css prop or an aliased import. Aliases of Devup UI now compile like the original: export const B = Box, const c = css; export { c as cc }, export const D = Devup and export const C = Devup.css in a barrel (the barrel module exports them as re-exports of the package, and what imports them follows them), export { Box } after an import, export default Box, const D = Devup namespace aliases, and const inner = css declared inside a function. A css() or keyframes() const that a function reads before its declaration compiles. New build error: a css()/keyframes() const read before its declaration runs (outside a function) is located and says to move the declaration above its first read
  • Preserve JavaScript semantics for exact imported enum and Math values including negative zero, lexical constants, binding-aware CommonJS require, React createElement calls, type-only imports, and source-ordered props evaluation with native spread snapshots and CSS-variable fallbacks without a styling runtime. Migrate UI-kit style defaults by pure reordering and test reset CSS through compiled output. Report located build errors for runtime styleOrder values, unknowable whole-object style overrides, opaque selector literals, genuinely unmovable lazy logical suspension, Devup UI namespaces passed whole to runtime code, and immediate style reads in the temporal dead zone of lexical bindings; deferred initialized reads keep folding and pre-assignment var reads remain dynamic.
  • Report extraction, module-resolution and stylesheet execution failures at their original source locations with the cause and repair. Reject recoverable syntax errors, nondeterministic build-time reads, synthetic descriptor/function-source and legacy accessor reflection, and unsafe stylesheet execution fallbacks instead of silently changing CSS. Preserve module resolver and serialization exceptions, evaluate transitive helper side effects, and prevent placeholder-name collisions from losing styles. Match import package names only at exact or slash-delimited boundaries so sibling data packages remain external. Retain helper CSS loads in evaluation order with deduplicated portable relative specifiers and query suffixes, without CSS content dependencies. Report missing CSS or incompatible path roots as located errors, and reject host-recorded unknown CSS export observations even when caught; unused bindings, object passing and typeof follow default TypeScript/JavaScript import semantics.
  • Resolve compiled styling APIs and components by their lexical binding so shadowed local names, including minified library identifiers, remain ordinary JavaScript and JSX. No new build errors; existing diagnostics now apply only to the compiled binding they describe.
  • Styled components the build generates are wrapped in React's forwardRef, so a ref passed to them reaches the element they render on React 18 as well as React 19; the file imports forwardRef from react when it defines one
  • Styled components no longer pass every prop to the tag they render: $ props, theme and the props their style functions or attrs read are kept away from a tag unless it takes them as attributes, and shouldForwardProp (Emotion options or styled-components withConfig) is evaluated at build time. A shouldForwardProp the build cannot evaluate is a build error naming the file, line and code, with the forms it accepts. An element using a styled component the file defines drops props the component neither reads nor passes on; spread props are passed as written
  • Styled components render what their as prop names, defaulting to the tag or component they were defined with, and pass forwardedAs on as as, as styled-components and Emotion do; as used to reach the rendered tag as an attribute. Component.withComponent(target) on a styled component the file binds to a const builds a component rendering the same styles and attrs as target (a tag name or a component JSX can name), where it used to call a method the generated function does not have and throw

@devup-ui/bun-plugin@1.0.22 → 1.0.23 - packages/bun-plugin/package.json

Patch

  • A project whose tsconfig.json (or jsconfig.json) builds JSX with Emotion (compilerOptions.jsxImportSource of @emotion/react, through extends and project references too) now compiles the css prop on every element of every file, and its .tsx and .jsx files are built with React's JSX runtime through a /** @jsxImportSource react */ pragma, which a file's own JSX pragma overrides, so the bundler no longer imports Emotion's runtime. The plugins read the setting into a new @emotion/react/jsx-runtime alias (importAliases can turn it off with false, and it is left out when @emotion/react is not aliased); @devup-ui/react/compat/emotion-jsx-runtime declares Emotion's JSX runtimes as React's so the project type-checks without Emotion installed. plugin-utils exports readJsxImportSource, and mergeImportAliases takes the JSX import source
  • hasDevupUI takes the import aliases and is true for a file extraction changes: one importing a redirected package (@emotion/styled, ...), naming @emotion/react in a @jsxImportSource pragma, or in a project whose tsconfig jsxImportSource is @emotion/react, so the Bun plugin no longer skips files whose only Devup UI is Emotion's css prop or an aliased import. Aliases of Devup UI now compile like the original: export const B = Box, const c = css; export { c as cc }, export const D = Devup and export const C = Devup.css in a barrel (the barrel module exports them as re-exports of the package, and what imports them follows them), export { Box } after an import, export default Box, const D = Devup namespace aliases, and const inner = css declared inside a function. A css() or keyframes() const that a function reads before its declaration compiles. New build error: a css()/keyframes() const read before its declaration runs (outside a function) is located and says to move the declaration above its first read

@devup-ui/components@0.1.60 → 0.1.61 - packages/components/package.json

Patch

  • Preserve JavaScript semantics for exact imported enum and Math values including negative zero, lexical constants, binding-aware CommonJS require, React createElement calls, type-only imports, and source-ordered props evaluation with native spread snapshots and CSS-variable fallbacks without a styling runtime. Migrate UI-kit style defaults by pure reordering and test reset CSS through compiled output. Report located build errors for runtime styleOrder values, unknowable whole-object style overrides, opaque selector literals, genuinely unmovable lazy logical suspension, Devup UI namespaces passed whole to runtime code, and immediate style reads in the temporal dead zone of lexical bindings; deferred initialized reads keep folding and pre-assignment var reads remain dynamic.

@devup-ui/eslint-plugin@1.0.22 → 1.0.23 - packages/eslint-plugin/package.json

Patch

  • Align style-order-range editor diagnostics with exact integer Number orders from 1 to 254 and canonical decimal strings, support finite class-order choices and lexical API aliases, and flag conditional global orders or no-effect keyframe, font-face and StyleX declaration metadata. Unknown imported static proof remains deferred to the build; no styling runtime is added.

@devup-ui/next-plugin@1.0.90 → 1.0.91 - packages/next-plugin/package.json

Patch

  • A project whose tsconfig.json (or jsconfig.json) builds JSX with Emotion (compilerOptions.jsxImportSource of @emotion/react, through extends and project references too) now compiles the css prop on every element of every file, and its .tsx and .jsx files are built with React's JSX runtime through a /** @jsxImportSource react */ pragma, which a file's own JSX pragma overrides, so the bundler no longer imports Emotion's runtime. The plugins read the setting into a new @emotion/react/jsx-runtime alias (importAliases can turn it off with false, and it is left out when @emotion/react is not aliased); @devup-ui/react/compat/emotion-jsx-runtime declares Emotion's JSX runtimes as React's so the project type-checks without Emotion installed. plugin-utils exports readJsxImportSource, and mergeImportAliases takes the JSX import source

@devup-ui/plugin-utils@1.0.17 → 1.0.18 - packages/plugin-utils/package.json

Patch

  • A project whose tsconfig.json (or jsconfig.json) builds JSX with Emotion (compilerOptions.jsxImportSource of @emotion/react, through extends and project references too) now compiles the css prop on every element of every file, and its .tsx and .jsx files are built with React's JSX runtime through a /** @jsxImportSource react */ pragma, which a file's own JSX pragma overrides, so the bundler no longer imports Emotion's runtime. The plugins read the setting into a new @emotion/react/jsx-runtime alias (importAliases can turn it off with false, and it is left out when @emotion/react is not aliased); @devup-ui/react/compat/emotion-jsx-runtime declares Emotion's JSX runtimes as React's so the project type-checks without Emotion installed. plugin-utils exports readJsxImportSource, and mergeImportAliases takes the JSX import source

@devup-ui/react@1.0.44 → 1.0.45 - packages/react/package.json

Patch

  • Emotion's now compiles at build time with no runtime: the element becomes what its child function ({ css, cx, theme }) => ... renders, each css and cx call becomes the classes it composes (later styles replace earlier ones; css reads strings as CSS text and its tagged templates split around mixins; cx keeps unknown classes, reads { name: condition } objects as conditional classes and composes nested css and cx calls), and theme.a.b in their values becomes var(--a-b). Numbers in css rules are px lengths, as Emotion reads them, and top-level constants are inlined. New build errors, each at file:line:col: a without exactly one child function taking { css, cx, theme } that gives what it renders at once (attributes, other children, rest or default parameters, async or generator functions, several statements); reading the theme other than as theme.a.b in a css value; using css or cx other than by calling them; a cx object with a spread, getter or method; parts css and cx cannot compose (runtime calls, spreads, a condition choosing between styles and classes). @devup-ui/react/compat exports ClassNames with the ClassNamesContent and ClassNamesArg types, and the @emotion/react declarations include them
  • Emotion's css prop compiles at build time while @emotion/react is aliased: on tags and Devup UI components always, and on every element once the file imports @emotion/react or @emotion/styled or names @emotion/react in a @jsxImportSource pragma; jsx, jsxs and jsxDEV from @emotion/react/jsx-runtime (or jsx-dev-runtime) and jsx from @emotion/react compile it too, so libraries built with Emotion's JSX runtime do as well. The prop becomes the element's className, with CSS variables in its style for values only the runtime gives: arrays and conditions compose with a later part replacing what an earlier one sets, css() classes the file knows compose by their styles, strings and templates are CSS text, css`` mixins split the text around them, a function of the theme reads theme.a.b as var(--a-b), unitless numbers are px as in Emotion (constants included), and a className holding known css() classes overrides the prop as Emotion's registered classes do. A styled component the file defines renders its tag in the element's place when the prop overrides its styles and it renders a tag with no attrs or props read and the element has no spread, as or forwardedAs. Emotion's JSX runtime imports become react/jsx-runtime, the pragma names react, and jsx comes from @devup-ui/react/compat (React's createElement); @devup-ui/react/compat/css-prop types the prop on React.Attributes. New build errors, each with file:line:column and the code: a css prop part the build cannot read (a call, an element), a style object declared inside a function or with let, a binding only running the module gives or code changes, a theme function that does more than return rules or reads the theme other than as theme.a.b in a value, an interpolation CSS text cannot place or a mixin inside a nested rule, and a css prop overriding a styled component's styles where its tag cannot be rendered in place. Composing css() with a part that reads a known binding (such as a keyframes name) now reads its value
  • A project whose tsconfig.json (or jsconfig.json) builds JSX with Emotion (compilerOptions.jsxImportSource of @emotion/react, through extends and project references too) now compiles the css prop on every element of every file, and its .tsx and .jsx files are built with React's JSX runtime through a /** @jsxImportSource react */ pragma, which a file's own JSX pragma overrides, so the bundler no longer imports Emotion's runtime. The plugins read the setting into a new @emotion/react/jsx-runtime alias (importAliases can turn it off with false, and it is left out when @emotion/react is not aliased); @devup-ui/react/compat/emotion-jsx-runtime declares Emotion's JSX runtimes as React's so the project type-checks without Emotion installed. plugin-utils exports readJsxImportSource, and mergeImportAliases takes the JSX import source

@devup-ui/reset-css@1.0.31 → 1.0.32 - packages/reset-css/package.json

Patch

  • Preserve JavaScript semantics for exact imported enum and Math values including negative zero, lexical constants, binding-aware CommonJS require, React createElement calls, type-only imports, and source-ordered props evaluation with native spread snapshots and CSS-variable fallbacks without a styling runtime. Migrate UI-kit style defaults by pure reordering and test reset CSS through compiled output. Report located build errors for runtime styleOrder values, unknowable whole-object style overrides, opaque selector literals, genuinely unmovable lazy logical suspension, Devup UI namespaces passed whole to runtime code, and immediate style reads in the temporal dead zone of lexical bindings; deferred initialized reads keep folding and pre-assignment var reads remain dynamic.

@devup-ui/rsbuild-plugin@1.0.67 → 1.0.68 - packages/rsbuild-plugin/package.json

Patch

  • A project whose tsconfig.json (or jsconfig.json) builds JSX with Emotion (compilerOptions.jsxImportSource of @emotion/react, through extends and project references too) now compiles the css prop on every element of every file, and its .tsx and .jsx files are built with React's JSX runtime through a /** @jsxImportSource react */ pragma, which a file's own JSX pragma overrides, so the bundler no longer imports Emotion's runtime. The plugins read the setting into a new @emotion/react/jsx-runtime alias (importAliases can turn it off with false, and it is left out when @emotion/react is not aliased); @devup-ui/react/compat/emotion-jsx-runtime declares Emotion's JSX runtimes as React's so the project type-checks without Emotion installed. plugin-utils exports readJsxImportSource, and mergeImportAliases takes the JSX import source

@devup-ui/vite-plugin@1.0.73 → 1.0.74 - packages/vite-plugin/package.json

Patch

  • A project whose tsconfig.json (or jsconfig.json) builds JSX with Emotion (compilerOptions.jsxImportSource of @emotion/react, through extends and project references too) now compiles the css prop on every element of every file, and its .tsx and .jsx files are built with React's JSX runtime through a /** @jsxImportSource react */ pragma, which a file's own JSX pragma overrides, so the bundler no longer imports Emotion's runtime. The plugins read the setting into a new @emotion/react/jsx-runtime alias (importAliases can turn it off with false, and it is left out when @emotion/react is not aliased); @devup-ui/react/compat/emotion-jsx-runtime declares Emotion's JSX runtimes as React's so the project type-checks without Emotion installed. plugin-utils exports readJsxImportSource, and mergeImportAliases takes the JSX import source

@devup-ui/webpack-plugin@1.0.71 → 1.0.72 - packages/webpack-plugin/package.json

Patch

  • A project whose tsconfig.json (or jsconfig.json) builds JSX with Emotion (compilerOptions.jsxImportSource of @emotion/react, through extends and project references too) now compiles the css prop on every element of every file, and its .tsx and .jsx files are built with React's JSX runtime through a /** @jsxImportSource react */ pragma, which a file's own JSX pragma overrides, so the bundler no longer imports Emotion's runtime. The plugins read the setting into a new @emotion/react/jsx-runtime alias (importAliases can turn it off with false, and it is left out when @emotion/react is not aliased); @devup-ui/react/compat/emotion-jsx-runtime declares Emotion's JSX runtimes as React's so the project type-checks without Emotion installed. plugin-utils exports readJsxImportSource, and mergeImportAliases takes the JSX import source

@codecov

codecov Bot commented Oct 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
bindings/devup-ui-wasm/src/lib.rs 100.00% <ø> (ø)
bindings/devup-ui-wasm/src/resolver_state.rs 100.00% <100.00%> (ø)
libs/css/src/lib.rs 100.00% <100.00%> (ø)
libs/css/src/theme_tokens.rs 100.00% <ø> (ø)
libs/extractor/src/barrel.rs 100.00% <100.00%> (ø)
libs/extractor/src/barrel/aliases.rs 100.00% <100.00%> (ø)
libs/extractor/src/barrel/gate.rs 100.00% <100.00%> (ø)
libs/extractor/src/barrel/namespace_aliases.rs 100.00% <100.00%> (ø)
libs/extractor/src/build_time_values.rs 100.00% <100.00%> (ø)
libs/extractor/src/build_time_values/exact_math.rs 100.00% <100.00%> (ø)
... and 50 more

... and 50 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

owjs3901 and others added 4 commits October 7, 2026 01:16
Refs #684, #685

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #684, #685

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Carry a typed definitive/evaluation disposition from strict metadata parsing
through nested diagnostics and styled extraction to the lib.rs Boa retry gate.
Validate all authored alternatives, preserve first-error ties, and avoid
synthetic capture diagnostics for rejected metadata. Keep exact computation
of pure controller/value leaves without erasing false-AND absence.

The bounded build_time_values.rs extension is required: an unrelated computed
width previously retried false && 2 as explicit false. Recognize literal and
constant computed keys before metadata folding. Regressions also preserve
invalid unselected literals and exact once-only lazy source guards.

Explicit props bags are ordinary pass-through data. In the newly changed
prop_modify_utils.rs and its shared order_forward helper, filter only copied
styling-origin forwarded inputs and preserve raw source/class/style reads.
Known Devup factory runtime-only order metadata has no CSS effect and never
reaches the DOM; other unknown styling keys retain their existing behavior.
The protected order-data fixture remains byte-identical to b2c71a1.

Remove the ignored callback wrapper and never-called closures; move their
otherwise unused purity helper unchanged into test ownership. Remove CSS
dispatch unreachable after unconditional argument clearing and the immutable
empty class tail. Composition keys cannot return None by finite-tree induction.
Remove this PR's orphan extractor/ordered_arguments.rs: absent at 7391e11,
added by 8fc666c, and never owned by the Rust module graph. Split the infallible
TemplateLiteral CssText constructor instead of retaining impossible formatter
or None failure paths. No coverage exclusion or threshold change.

Add 190 Rust contracts over the b2 baseline, strengthen only two obsolete
forwarded-spread shape checks, and individually review/accept 15 generated
code snapshots for the named metadata leak fix. No style-record/CSS delta;
48 original WASM fixtures remain byte-identical. Local default workspace
3758/0, Rust 1.99 clippy/fmt, WASM/root builds, Bun 6448/0 at aggregate 100%,
lint and generated-code timing pass. Linux coverage remains the authority;
the remaining B/C coverage batches follow this exact-tree checkpoint.

Refs #684 #685

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Move the serial attribute after the final rstest case. Attributes preceding
a case apply only to that case; the previous placement left three fallback
evaluations outside the shared debug/class-state lock.

Preserve all fixtures, trace/class assertions, production code, snapshots,
coverage thresholds and default test concurrency. Every generated case now
uses exactly one existing default serial lock.

Refs #684, #685

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant