• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mobxjs / mobx / 12284363416

11 Dec 2024 08:28PM UTC coverage: 90.44% (-1.1%) from 91.534%
12284363416

push

github

web-flow
React 19 support (#3985)

* deprecate `IObserver` options and its properties in JSDoc

* Preparing for React 19 - some tests fail

* RTL hooks error

* skipping legacy context tests

* skipping propTypes and defaultProps forwarding tests

* skipping class propTypes test

* render time check

* changed some assertions

* added extra render

* added todo

* added warning for legacy context types in function components

* added changeset

---------

Co-authored-by: Michel Weststrate <mweststrate@gmail.com>

1811 of 2267 branches covered (79.89%)

2 of 6 new or added lines in 2 files covered. (33.33%)

37 existing lines in 5 files now uncovered.

3349 of 3703 relevant lines covered (90.44%)

6504.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

18.06
/packages/mobx-react/src/propTypes.ts
1
import { isObservableArray, isObservableObject, isObservableMap, untracked } from "mobx"
13✔
2

3
// Copied from React.PropTypes
4
function createChainableTypeChecker(validator: React.Validator<any>): React.Requireable<any> {
5
    function checkType(
6
        isRequired: boolean,
7
        props: any,
8
        propName: string,
9
        componentName: string,
10
        location: string,
11
        propFullName: string,
12
        ...rest: any[]
13
    ) {
UNCOV
14
        return untracked(() => {
×
UNCOV
15
            componentName = componentName || "<<anonymous>>"
×
UNCOV
16
            propFullName = propFullName || propName
×
UNCOV
17
            if (props[propName] == null) {
×
18
                if (isRequired) {
×
19
                    const actual = props[propName] === null ? "null" : "undefined"
×
20
                    return new Error(
×
21
                        "The " +
22
                            location +
23
                            " `" +
24
                            propFullName +
25
                            "` is marked as required " +
26
                            "in `" +
27
                            componentName +
28
                            "`, but its value is `" +
29
                            actual +
30
                            "`."
31
                    )
32
                }
33
                return null
×
34
            } else {
35
                // @ts-ignore rest arg is necessary for some React internals - fails tests otherwise
UNCOV
36
                return validator(props, propName, componentName, location, propFullName, ...rest)
×
37
            }
38
        })
39
    }
40

41
    const chainedCheckType: any = checkType.bind(null, false)
65✔
42
    // Add isRequired to satisfy Requirable
43
    chainedCheckType.isRequired = checkType.bind(null, true)
65✔
44
    return chainedCheckType
65✔
45
}
46

47
// Copied from React.PropTypes
48
function isSymbol(propType: any, propValue: any): boolean {
49
    // Native Symbol.
50
    if (propType === "symbol") {
×
51
        return true
×
52
    }
53

54
    // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'
55
    if (propValue["@@toStringTag"] === "Symbol") {
×
56
        return true
×
57
    }
58

59
    // Fallback for non-spec compliant Symbols which are polyfilled.
60
    if (typeof Symbol === "function" && propValue instanceof Symbol) {
×
61
        return true
×
62
    }
63

64
    return false
×
65
}
66

67
// Copied from React.PropTypes
68
function getPropType(propValue: any): string {
UNCOV
69
    const propType = typeof propValue
×
UNCOV
70
    if (Array.isArray(propValue)) {
×
UNCOV
71
        return "array"
×
72
    }
73
    if (propValue instanceof RegExp) {
×
74
        // Old webkits (at least until Android 4.0) return 'function' rather than
75
        // 'object' for typeof a RegExp. We'll normalize this here so that /bla/
76
        // passes PropTypes.object.
77
        return "object"
×
78
    }
79
    if (isSymbol(propType, propValue)) {
×
80
        return "symbol"
×
81
    }
82
    return propType
×
83
}
84

85
// This handles more types than `getPropType`. Only used for error messages.
86
// Copied from React.PropTypes
87
function getPreciseType(propValue: any): string {
UNCOV
88
    const propType = getPropType(propValue)
×
UNCOV
89
    if (propType === "object") {
×
90
        if (propValue instanceof Date) {
×
91
            return "date"
×
92
        } else if (propValue instanceof RegExp) {
×
93
            return "regexp"
×
94
        }
95
    }
UNCOV
96
    return propType
×
97
}
98

99
function createObservableTypeCheckerCreator(
100
    allowNativeType: any,
101
    mobxType: any
102
): React.Requireable<any> {
103
    return createChainableTypeChecker((props, propName, componentName, location, propFullName) => {
65✔
UNCOV
104
        return untracked(() => {
×
UNCOV
105
            if (allowNativeType) {
×
UNCOV
106
                if (getPropType(props[propName]) === mobxType.toLowerCase()) return null
×
107
            }
108
            let mobxChecker
UNCOV
109
            switch (mobxType) {
×
110
                case "Array":
UNCOV
111
                    mobxChecker = isObservableArray
×
UNCOV
112
                    break
×
113
                case "Object":
114
                    mobxChecker = isObservableObject
×
115
                    break
×
116
                case "Map":
117
                    mobxChecker = isObservableMap
×
118
                    break
×
119
                default:
120
                    throw new Error(`Unexpected mobxType: ${mobxType}`)
×
121
            }
UNCOV
122
            const propValue = props[propName]
×
UNCOV
123
            if (!mobxChecker(propValue)) {
×
UNCOV
124
                const preciseType = getPreciseType(propValue)
×
UNCOV
125
                const nativeTypeExpectationMessage = allowNativeType
×
126
                    ? " or javascript `" + mobxType.toLowerCase() + "`"
127
                    : ""
UNCOV
128
                return new Error(
×
129
                    "Invalid prop `" +
130
                        propFullName +
131
                        "` of type `" +
132
                        preciseType +
133
                        "` supplied to" +
134
                        " `" +
135
                        componentName +
136
                        "`, expected `mobx.Observable" +
137
                        mobxType +
138
                        "`" +
139
                        nativeTypeExpectationMessage +
140
                        "."
141
                )
142
            }
UNCOV
143
            return null
×
144
        })
145
    })
146
}
147

148
function createObservableArrayOfTypeChecker(
149
    allowNativeType: boolean,
150
    typeChecker: React.Validator<any>
151
) {
152
    return createChainableTypeChecker(
×
153
        (props, propName, componentName, location, propFullName, ...rest) => {
154
            return untracked(() => {
×
155
                if (typeof typeChecker !== "function") {
×
156
                    return new Error(
×
157
                        "Property `" +
158
                            propFullName +
159
                            "` of component `" +
160
                            componentName +
161
                            "` has " +
162
                            "invalid PropType notation."
163
                    )
164
                } else {
165
                    let error = createObservableTypeCheckerCreator(allowNativeType, "Array")(
×
166
                        props,
167
                        propName,
168
                        componentName,
169
                        location,
170
                        propFullName
171
                    )
172

173
                    if (error instanceof Error) return error
×
174
                    const propValue = props[propName]
×
175
                    for (let i = 0; i < propValue.length; i++) {
×
176
                        error = (typeChecker as React.Validator<any>)(
×
177
                            propValue,
178
                            i as any,
179
                            componentName,
180
                            location,
181
                            propFullName + "[" + i + "]",
182
                            ...rest
183
                        )
184
                        if (error instanceof Error) return error
×
185
                    }
186

187
                    return null
×
188
                }
189
            })
190
        }
191
    )
192
}
193

194
const observableArray = createObservableTypeCheckerCreator(false, "Array")
13✔
195
const observableArrayOf = createObservableArrayOfTypeChecker.bind(null, false)
13✔
196
const observableMap = createObservableTypeCheckerCreator(false, "Map")
13✔
197
const observableObject = createObservableTypeCheckerCreator(false, "Object")
13✔
198
const arrayOrObservableArray = createObservableTypeCheckerCreator(true, "Array")
13✔
199
const arrayOrObservableArrayOf = createObservableArrayOfTypeChecker.bind(null, true)
13✔
200
const objectOrObservableObject = createObservableTypeCheckerCreator(true, "Object")
13✔
201

202
export const PropTypes = {
13✔
203
    observableArray,
204
    observableArrayOf,
205
    observableMap,
206
    observableObject,
207
    arrayOrObservableArray,
208
    arrayOrObservableArrayOf,
209
    objectOrObservableObject
210
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc