@@ -270,6 +270,9 @@ export interface ComponentRenderContext {
270270
271271export const isReservedPrefix = ( key : string ) => key === '_' || key === '$'
272272
273+ const hasSetupBinding = ( state : Data , key : string ) =>
274+ state !== EMPTY_OBJ && ! state . __isScriptSetup && hasOwn ( state , key )
275+
273276export const PublicInstanceProxyHandlers : ProxyHandler < any > = {
274277 get ( { _ : instance } : ComponentRenderContext , key : string ) {
275278 const { ctx, setupState, data, props, accessCache, type, appContext } =
@@ -280,19 +283,6 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
280283 return true
281284 }
282285
283- // prioritize <script setup> bindings during dev.
284- // this allows even properties that start with _ or $ to be used - so that
285- // it aligns with the production behavior where the render fn is inlined and
286- // indeed has access to all declared variables.
287- if (
288- __DEV__ &&
289- setupState !== EMPTY_OBJ &&
290- setupState . __isScriptSetup &&
291- hasOwn ( setupState , key )
292- ) {
293- return setupState [ key ]
294- }
295-
296286 // data / props / ctx
297287 // This getter gets called for every property access on the render context
298288 // during render and is a major hotspot. The most expensive part of this
@@ -314,7 +304,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
314304 return props ! [ key ]
315305 // default: just fallthrough
316306 }
317- } else if ( setupState !== EMPTY_OBJ && hasOwn ( setupState , key ) ) {
307+ } else if ( hasSetupBinding ( setupState , key ) ) {
318308 accessCache ! [ key ] = AccessTypes . SETUP
319309 return setupState [ key ]
320310 } else if ( data !== EMPTY_OBJ && hasOwn ( data , key ) ) {
@@ -403,26 +393,28 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
403393 value : any
404394 ) : boolean {
405395 const { data, setupState, ctx } = instance
406- if ( setupState !== EMPTY_OBJ && hasOwn ( setupState , key ) ) {
396+ if ( hasSetupBinding ( setupState , key ) ) {
407397 setupState [ key ] = value
408398 return true
399+ } else if (
400+ __DEV__ &&
401+ setupState . __isScriptSetup &&
402+ hasOwn ( setupState , key )
403+ ) {
404+ warn ( `Cannot mutate <script setup> binding "${ key } " from Options API.` )
405+ return false
409406 } else if ( data !== EMPTY_OBJ && hasOwn ( data , key ) ) {
410407 data [ key ] = value
411408 return true
412409 } else if ( hasOwn ( instance . props , key ) ) {
413- __DEV__ &&
414- warn (
415- `Attempting to mutate prop "${ key } ". Props are readonly.` ,
416- instance
417- )
410+ __DEV__ && warn ( `Attempting to mutate prop "${ key } ". Props are readonly.` )
418411 return false
419412 }
420413 if ( key [ 0 ] === '$' && key . slice ( 1 ) in instance ) {
421414 __DEV__ &&
422415 warn (
423416 `Attempting to mutate public property "${ key } ". ` +
424- `Properties starting with $ are reserved and readonly.` ,
425- instance
417+ `Properties starting with $ are reserved and readonly.`
426418 )
427419 return false
428420 } else {
@@ -449,7 +441,7 @@ export const PublicInstanceProxyHandlers: ProxyHandler<any> = {
449441 return (
450442 ! ! accessCache ! [ key ] ||
451443 ( data !== EMPTY_OBJ && hasOwn ( data , key ) ) ||
452- ( setupState !== EMPTY_OBJ && hasOwn ( setupState , key ) ) ||
444+ hasSetupBinding ( setupState , key ) ||
453445 ( ( normalizedProps = propsOptions [ 0 ] ) && hasOwn ( normalizedProps , key ) ) ||
454446 hasOwn ( ctx , key ) ||
455447 hasOwn ( publicPropertiesMap , key ) ||
0 commit comments