Repository navigation
[전수조사/D] 흡수 라이브러리 기능: css prop, 컴포넌트 선택자, @emotion/css, VE·StyleX API #690
Copy link
Copy link
Open
Labels
bugSomething isn't workingSomething isn't workingenhancementNew feature or requestNew feature or request
Description
원 라이브러리에서 흔히 쓰는 기능 중 지원되지 않거나 조용히 빠지는 것들입니다.
전체 계획과 결정 사항은 추적 이슈(#682)에 있습니다. 조사 기준 커밋: 77daad74 (현재 main d0b84255).
결정에 따른 작업
- (필수) Emotion css prop: import/pragma/tsconfig
jsxImportSource/컴파일된@emotion/react/jsx-runtime(include라이브러리 포함; 감지 비용 측정 결과 MUI 1,312파일 약 2.9 ms). DOM 요소는 항상, 사용자 컴포넌트는 Emotion 신호가 있을 때만 컴파일. 사용자 컴포넌트의 동적 값은style도 전달해야 함(문서화) - (필수) 컴포넌트 선택자: 선택자로 참조된 컴포넌트에만 짧은 marker class
- (필수)
@emotion/css: css/keyframes/injectGlobal/cx/merge.cx는 이슈 A의 정적 합성 사용 - (필수) alias된 Emotion 파일의 배열 값은 fallback 의미(EMO-15)
발견 항목
심각도: P0 = 흔한 사용에서 조용히 틀리거나 크래시, P1 = 흔한 패턴이 명시적 에러로 막히거나 드물게 조용히 틀림, P2 = 드문 경우·도구/문서 불일치, P3 = 있으면 좋음.
필수 (7)
- EMO-01 (P0, WRONG) Emotion css prop is never compiled in any source or compiled-JSX form (KNOWN-1)
- 근거: css-prop-no-import.tsx emits
<div css={{ color: 'red' }} />and no CSS; css-prop-jsx-runtime.ts retainsimport { jsx } from '@emotion/react/jsx-runtime'and{ css: { color:'red' } }; css-prop-css-result.tsx emitsconst style="a"but retains<div css={style}> - 수정 방향: recognize JSX css attributes independent of imports, Emotion jsx/jsxs factory calls and jsx-runtime subpaths; lower accepted values through the normal style extractor, remove css, and merge into className/style with Emotion precedence
- 근거: css-prop-no-import.tsx emits
- EMO-03 (P0, WRONG) Nested composition silently drops serialized styles
- 근거: react-css-nested-compose.tsx turns
css({ '&:hover,&:focus': hotpink })intoexport const hover = ""; only the unrelated base.a{color:hotpink}remains, with no hover/focus rule or error - 수정 방향: resolve known css-result bindings as nested rule fragments, preserving selector context; otherwise emit an explicit build error instead of empty output
- 근거: react-css-nested-compose.tsx turns
- SX-03 (P0, WRONG)
attrsreturns the wrong inline-style representation- 근거: Dynamic width produces
{ class: "b", style: { "--a": ... } }. - 수정 방향: Serialize dynamic variable declarations for
attrswhile retaining object form for React-orientedprops.
- 근거: Dynamic width produces
- VE-04 (P0, WRONG) companion CSS generators silently bypass Devup
- 근거:
recipe(...),defineProperties(...), andcreateSprinkles(...)remain verbatim while both per-file and whole-sheet Devup CSS contain no recipe/sprinkle rules. Only exact@vanilla-extract/cssis aliased (packages/plugin-utils/src/types.ts:96-103); ordinarynode_modulesare skipped (packages/plugin-utils/src/shared.ts:46-60,packages/vite-plugin/src/plugin.ts:525-554… - 수정 방향: Either integrate/alias companion packages and generate their CSS, or detect these imports and issue a build error telling users to disable the Devup alias/use the vanilla-extract plugin.
- 근거:
- EMO-12 (P1, ERR-gap) Emotion component selectors fail in both template and object forms
- 근거: styled-selector-template.tsx errors
Cannot place Child; styled-selector-object.tsx errors on[Child] - 수정 방향: assign a stable marker only to selector-referenced styled components and resolve bindings/computed keys to that marker; emit the marker in parent selector rules
- 근거: styled-selector-template.tsx errors
- EMO-15 (P1, WRONG) CSS fallback arrays are silently reinterpreted as responsive values
- 근거: object-fallback-values.tsx turns
background:['red','linear-gradient(...)']into.a{background:red}plus@media(min-width:480px){.b{background:linear-gradient(...)}}; Emotion emits two same-rule declarations as browser fallbacks - 수정 방향: in Emotion-aliased rule objects, distinguish property-value arrays (fallback declarations) from top-level style arrays; do not route property arrays through Devup responsive semantics
- 근거: object-fallback-values.tsx turns
- EMO-16 (P1, MISMATCH) @emotion/css and create-instance are entirely outside alias handling despite DECIDED support (KNOWN-12)
- 근거: every emotion-css-*.tsx probe retains imports/calls and emits no extracted CSS; DEFAULT_IMPORT_ALIASES at packages/plugin-utils/src/types.ts:98-103 lacks @emotion/css and its subpath
- 수정 방향: add explicit @emotion/css mappings for extractable APIs and a deliberate policy/error for stateful low-level APIs; generate matching ambient declarations
권장 (12)
- EMO-04 (P1, ERR-gap) Global supports only a direct object, rejecting documented static css-result and array forms
- 근거: react-global-css-result.tsx errors that
"a"is not usable; react-global-array.tsx rejects a static array; react-global-theme-function.tsx rejects a function - 수정 방향: feed Global through the same composition flattener as css; support exact theme paths as CSS variables and retain explicit errors for genuinely runtime-only functions
- 근거: react-global-css-result.tsx errors that
- EMO-13 (P1, ERR-gap) Function object styles are rejected although they are a primary Emotion styled form (KNOWN-7)
- 근거: styled-function-object.tsx errors on
props => ({ color: ... }); styled-theme-object.tsx errors on({theme}) => ..., while the equivalent template interpolation works via CSS variables - 수정 방향: lower property-level exact branches to classes/variables using the same machinery as template functions; explicitly reject object shapes that are unknowable at build time
- 근거: styled-function-object.tsx errors on
- SX-04 (P1, ERR-gap) dynamic contextual values are rejected
- 근거: A dynamic namespace with
color:{default:'red', ':hover':size, '@media (min-width:600px)':size}errors that the object cannot be used at build time. - 수정 방향: Recursively decompose contextual objects in dynamic namespaces and bind each dynamic leaf to the generated runtime variable assignment.
- 근거: A dynamic namespace with
- SX-05 (P1, WRONG) all
types.*wrappers lose typed custom-property semantics- 근거: Every helper (
length,lengthPercentage,color,angle,integer,number,percentage,time,url,image,resolution,transformFunction,transformList) emits only:root{--a:<value>}. Code treats anytypes.*as a transparent first-argument wrapper (libs/extractor/src/stylex.rs:234-246,585-597). - 수정 방향: Carry the helper kind into variable metadata, emit one typed
@property, and validate/cast helper-specific values (especially integer).
- 근거: Every helper (
- SX-06 (P1, WRONG) explicit global variable names are not preserved
- 근거: Output is
{ "--global": "var(--a)" }plus:root{--a:black}, and use viacolors['--global']is separately rejected as non-static. - 수정 방향: Detect dashed custom-property keys before identifier allocation; keep
--globalin both returned reference and emitted root declaration, and resolve computed literal access.
- 근거: Output is
- SX-07 (P1, WRONG)
positionTryoutput is semantically wrong and cannot be consumed- 근거: Declaration probe emits
@position-try --a{position-anchor:var(--anchor);...}forpositionAnchor:'--anchor'; the documented consumptionpositionTryFallbacks:fallbackerrors thatfallbackis not static. - 수정 방향: Preserve dashed identifiers for anchor properties and register
positionTrybindings as resolvable static identifiers increate.
- 근거: Declaration probe emits
- SX-08 (P1, ERR-gap)
viewTransitionClassimplements the wrong input shape- 근거:
{old:{animationDuration:'2s'}, new:{animationDuration:'1s'}}produces two build errors saying nested objects are not static values. The extractor reads one flat declaration object (libs/extractor/src/extractor/extract_style_from_stylex.rs:42-71). - 수정 방향: Parse the four documented groups, emit pseudo-element rules, and reject only unsupported nested media queries.
- 근거:
- SX-09 (P1, ERR-gap) contextual-selector APIs are absent
- 근거: Dedicated probes for
ancestor,descendant,siblingBefore,siblingAfter, andanySiblingall error that the computed key “must be known.” The recognized API enum omitswhen(libs/extractor/src/stylex.rs:15-41). - 수정 방향: Implement marker values plus computed-key evaluation for each contextual selector and preserve StyleX's specificity ordering.
- 근거: Dedicated probes for
- SX-10 (P1, WRONG) marker APIs escape to runtime
- 근거: Transformed code still contains
stylex.defaultMarker()/stylex.defineMarker()and runtime.flat(...).join(...); no marker CSS/value is generated. - 수정 방향: Recognize both APIs, generate deterministic marker references, and consume them from
propsandwhen.*without runtime StyleX calls.
- 근거: Transformed code still contains
- SX-12 (P1, ERR-gap) media-query constants cannot form contextual keys
- 근거:
[constants.query]wherequeryis'@media (min-width: 600px)'errors that the key must be known, though direct constant values work. - 수정 방향: Resolve computed keys through the same local/imported constant evaluator already used for declaration values.
- 근거:
- VE-02 (P1, ERR-gap)
globalKeyframesis declared but not callable- 근거:
globalKeyframes('fade-global', {...})→JS execution error: TypeError: not a callable function.register_vanilla_extract_apisregisters no such function (libs/extractor/src/vanilla_extract.rs:604-665), whilepackages/react/src/compat/vanilla-extract.d.ts:25-38declares it. - 수정 방향: Register and serialize
globalKeyframes(name, frames)in the Boa API; align the ambient declaration and add a stylesheet probe test.
- 근거:
- VE-05 (P1, ERR-gap)
css-utilscannot be evaluated in stylesheet mode- 근거: Importing
calcfrom@vanilla-extract/css-utilsgivesCannot load '@vanilla-extract/css-utils' without a module resolver; the default alias table contains only@vanilla-extract/css. - 수정 방향: Statically evaluate this pure utility surface, or resolve the package through the stylesheet module resolver and guarantee deterministic output.
- 근거: Importing
선택 (3)
- EMO-07 (P2, WRONG) Emotion label is discarded in objects and emitted as an invalid CSS declaration in templates
- 근거: react-label-object.tsx yields
.a{color:red}with no readable suffix; react-label-template.tsx yields.a{label:template-name} - 수정 방향: parse and remove label from rule generation; append a sanitized label only in a compatibility/debug naming mode, or document deterministic minified names and consistently discard it without invalid CSS
- 근거: react-label-object.tsx yields
- SX-11 (P2, ERR-gap)
stylex.envconfiguration substitution is absent- 근거:
stylex.env.tokens.colors.primaryincreateerrors that it is not a literal, theme token, or constant;envis not a recognized API. - 수정 방향: Add an explicit Devup StyleX environment option and static member substitution, or document this experimental API as unsupported with a targeted diagnostic.
- 근거:
- VE-03 (P3, MISMATCH)
styledebugId is accepted but ignored- 근거:
style({color:'red'}, 'root debug')under--debugyields classcolor-0-red--255; sibling APIs produce--token_debug-0-0,area_debug-0-1, andutilities_debug-0-2. - 수정 방향: Carry style debug IDs into Devup debug class naming, or document that style debug IDs are intentionally not preserved.
- 근거:
제외 (3)
- EMO-17 (P2, ERR-gap) Computed styled tag access remains a runtime read of an erased binding (KNOWN-13)
- 근거: styled-bracket.tsx errors that styled is read at runtime
- 수정 방향: accept static computed string members in styled-factory recognition; retain the explicit error for dynamic computed keys
- SX-13 (P2, MISMATCH) alternate StyleX resolution policy is unavailable
- 근거: Shorthand/longhand output gives the longhand fixed later stylesheet order in both application orders; no Devup plugin option maps StyleX
styleResolution. - 수정 방향: Either expose and implement the option or document that Devup targets only the default policy and reject incompatible configuration expectations.
- 근거: Shorthand/longhand output gives the longhand fixed later stylesheet order in both application orders; no Devup plugin option maps StyleX
- SX-14 (P3, MISMATCH) Devup exposes a non-StyleX
include()extension- 근거:
...stylex.include(base.root)compiles successfully and is exported in Devup's compatibility surface, but the official API index has no JavaScriptinclude; officialincludeis a PostCSS path/glob option. - 수정 방향: Document and namespace the extension, or remove it from claims of StyleX API parity.
- 근거:
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingenhancementNew feature or requestNew feature or request
Activity
refactor(extractor): filter style props before building attrs text
refactor(extractor): keep attrs style prop filter on one line
test(plugins): expect the @emotion/css default alias
test(extractor): cover css props on styled components with responsive…
test(extractor): cover ClassNames child functions taking rest or nest…
fix(extractor): compile Emotion cx as class names and merge as class …
test(extractor): cover parenthesized function-local style objects
fix(extractor): compile Emotion CSS namespace imports
chore: document Emotion CSS namespace compilation in changepack
test(extractor): cover Emotion namespace error and loader branches
test(extractor): cover composition and styled branches reported by Linux
fix(extractor): preserve exact StyleX dynamic defaults and calls
fix(extractor): enforce exact StyleX helper and namespace contracts
38 remaining items
test(extractor): cover native execution alias, escape and diagnostic …
test(extractor): cover native import and source slice edges
test(extractor): cover native rewrite and API selection edges
test(extractor): cover native selection closure, demand and escape edges
test(extractor): cover mixed detection, selector escapes and styleshe…
test(extractor): cover authored stylesheet import, alias and safety e…
test(extractor): cover native capture emission errors and prototypes
test(extractor): cover retained native state failures and terminal ma…
test(extractor): cover native demand runtime compile and finalize edges
test(extractor): cover star export fallbacks and stylesheet execution…
test(extractor): cover the last four Linux coverage gaps
fix(extractor): keep generated rendering helpers hygienic
chore: merge main into fix/emotion-css
Merge main 76b1a15 into fix/emotion-fallback-arrays
Merge main 76b1a15 into fix/nested-css-results