Skip to content
This repository was archived by the owner on Oct 15, 2020. It is now read-only.

Commit a5288c0

Browse files
tcarechakrabot
authored andcommitted
deps: update ChakraCore to chakra-core/ChakraCore@9fe64abd2e
[1.8>1.9] [MERGE #4431 @tcare] Ensure WithScopeObject is unwrapped for scoped __proto__ stores Merge pull request #4431 from tcare:withproto Fixes OS: 14291082 Setting __proto__ inside an eval inside a with takes us down a weird path. Usually we would have unwrapped the WithScopeObject automatically by using SetProperty or similar, but __proto__ is special cased (along with some other things like HostDispatch) and will directly fetch the setter function and call it, bypassing the WithScopeObject:: methods (although still keeping the @@unscopables check.) Fix is to unwrap the object after the @@unscopables object check has finished when getting the __proto__ setter. I tried several other paths but they end up going through the WithScopeObject shims. Reviewed-By: chakrabot <[email protected]>
1 parent 1727576 commit a5288c0

File tree

5 files changed

+205
-167
lines changed

5 files changed

+205
-167
lines changed

Diff for: deps/chakrashim/core/lib/Runtime/Language/JavascriptOperators.cpp

+122-130
Original file line numberDiff line numberDiff line change
@@ -2486,132 +2486,164 @@ namespace Js
24862486
return SetProperty_Internal<false>(instance, instance, true, propertyId, newValue, info, requestContext, propertyOperationFlags);
24872487
}
24882488

2489-
template <bool unscopables>
2490-
BOOL JavascriptOperators::SetProperty_Internal(Var receiver, RecyclableObject* object, const bool isRoot, PropertyId propertyId, Var newValue, PropertyValueInfo * info, ScriptContext* requestContext, PropertyOperationFlags propertyOperationFlags)
2491-
{
2492-
if (receiver)
2489+
// Returns true if a result was written.
2490+
bool JavascriptOperators::SetAccessorOrNonWritableProperty(
2491+
Var receiver,
2492+
RecyclableObject* object,
2493+
PropertyId propertyId,
2494+
Var newValue,
2495+
PropertyValueInfo * info,
2496+
ScriptContext* requestContext,
2497+
PropertyOperationFlags propertyOperationFlags,
2498+
bool isRoot,
2499+
bool allowUndecInConsoleScope,
2500+
BOOL *result)
2501+
{
2502+
*result = FALSE;
2503+
Var setterValueOrProxy = nullptr;
2504+
DescriptorFlags flags = None;
2505+
if ((isRoot && JavascriptOperators::CheckPrototypesForAccessorOrNonWritableRootProperty(object, propertyId, &setterValueOrProxy, &flags, info, requestContext)) ||
2506+
(!isRoot && JavascriptOperators::CheckPrototypesForAccessorOrNonWritableProperty(object, propertyId, &setterValueOrProxy, &flags, info, requestContext)))
24932507
{
2494-
Assert(!TaggedNumber::Is(receiver));
2495-
Var setterValueOrProxy = nullptr;
2496-
DescriptorFlags flags = None;
2497-
if ((isRoot && JavascriptOperators::CheckPrototypesForAccessorOrNonWritableRootProperty(object, propertyId, &setterValueOrProxy, &flags, info, requestContext)) ||
2498-
(!isRoot && JavascriptOperators::CheckPrototypesForAccessorOrNonWritableProperty(object, propertyId, &setterValueOrProxy, &flags, info, requestContext)))
2508+
if ((flags & Accessor) == Accessor)
24992509
{
2500-
if ((flags & Accessor) == Accessor)
2510+
if (JavascriptError::ThrowIfStrictModeUndefinedSetter(propertyOperationFlags, setterValueOrProxy, requestContext) ||
2511+
JavascriptError::ThrowIfNotExtensibleUndefinedSetter(propertyOperationFlags, setterValueOrProxy, requestContext))
2512+
{
2513+
*result = TRUE;
2514+
return true;
2515+
}
2516+
if (setterValueOrProxy)
25012517
{
2502-
if (JavascriptError::ThrowIfStrictModeUndefinedSetter(propertyOperationFlags, setterValueOrProxy, requestContext) ||
2503-
JavascriptError::ThrowIfNotExtensibleUndefinedSetter(propertyOperationFlags, setterValueOrProxy, requestContext))
2518+
RecyclableObject* func = RecyclableObject::FromVar(setterValueOrProxy);
2519+
Assert(!info || info->GetFlags() == InlineCacheSetterFlag || info->GetPropertyIndex() == Constants::NoSlot);
2520+
2521+
if (WithScopeObject::Is(receiver))
25042522
{
2505-
return TRUE;
2523+
receiver = (RecyclableObject::FromVar(receiver))->GetThisObjectOrUnWrap();
25062524
}
2507-
if (setterValueOrProxy)
2525+
else
25082526
{
2509-
RecyclableObject* func = RecyclableObject::FromVar(setterValueOrProxy);
2510-
Assert(!info || info->GetFlags() == InlineCacheSetterFlag || info->GetPropertyIndex() == Constants::NoSlot);
2511-
2512-
if (WithScopeObject::Is(receiver))
2513-
{
2514-
receiver = (RecyclableObject::FromVar(receiver))->GetThisObjectOrUnWrap();
2515-
}
2516-
else
2517-
{
2518-
CacheOperators::CachePropertyWrite(RecyclableObject::FromVar(receiver), isRoot, object->GetType(), propertyId, info, requestContext);
2519-
}
2527+
CacheOperators::CachePropertyWrite(RecyclableObject::FromVar(receiver), isRoot, object->GetType(), propertyId, info, requestContext);
2528+
}
25202529
#ifdef ENABLE_MUTATION_BREAKPOINT
2521-
if (MutationBreakpoint::IsFeatureEnabled(requestContext))
2522-
{
2523-
MutationBreakpoint::HandleSetProperty(requestContext, object, propertyId, newValue);
2524-
}
2525-
#endif
2526-
JavascriptOperators::CallSetter(func, receiver, newValue, requestContext);
2530+
if (MutationBreakpoint::IsFeatureEnabled(requestContext))
2531+
{
2532+
MutationBreakpoint::HandleSetProperty(requestContext, object, propertyId, newValue);
25272533
}
2528-
return TRUE;
2534+
#endif
2535+
JavascriptOperators::CallSetter(func, receiver, newValue, requestContext);
25292536
}
2530-
else if ((flags & Proxy) == Proxy)
2531-
{
2532-
Assert(JavascriptProxy::Is(setterValueOrProxy));
2533-
JavascriptProxy* proxy = JavascriptProxy::FromVar(setterValueOrProxy);
2534-
// We can't cache the property at this time. both target and handler can be changed outside of the proxy, so the inline cache needs to be
2535-
// invalidate when target, handler, or handler prototype has changed. We don't have a way to achieve this yet.
2536-
PropertyValueInfo::SetNoCache(info, proxy);
2537-
PropertyValueInfo::DisablePrototypeCache(info, proxy); // We can't cache prototype property either
2537+
*result = TRUE;
2538+
return true;
2539+
}
2540+
else if ((flags & Proxy) == Proxy)
2541+
{
2542+
Assert(JavascriptProxy::Is(setterValueOrProxy));
2543+
JavascriptProxy* proxy = JavascriptProxy::FromVar(setterValueOrProxy);
2544+
// We can't cache the property at this time. both target and handler can be changed outside of the proxy, so the inline cache needs to be
2545+
// invalidate when target, handler, or handler prototype has changed. We don't have a way to achieve this yet.
2546+
PropertyValueInfo::SetNoCache(info, proxy);
2547+
PropertyValueInfo::DisablePrototypeCache(info, proxy); // We can't cache prototype property either
25382548

2539-
return proxy->SetPropertyTrap(receiver, JavascriptProxy::SetPropertyTrapKind::SetPropertyKind, propertyId, newValue, requestContext);
2540-
}
2541-
else
2549+
*result = proxy->SetPropertyTrap(receiver, JavascriptProxy::SetPropertyTrapKind::SetPropertyKind, propertyId, newValue, requestContext);
2550+
return true;
2551+
}
2552+
else
2553+
{
2554+
Assert((flags & Data) == Data && (flags & Writable) == None);
2555+
if (!allowUndecInConsoleScope)
25422556
{
2543-
Assert((flags & Data) == Data && (flags & Writable) == None);
25442557
if (flags & Const)
25452558
{
25462559
JavascriptError::ThrowTypeError(requestContext, ERRAssignmentToConst);
25472560
}
25482561

25492562
JavascriptError::ThrowCantAssign(propertyOperationFlags, requestContext, propertyId);
25502563
JavascriptError::ThrowCantAssignIfStrictMode(propertyOperationFlags, requestContext);
2551-
return FALSE;
2564+
2565+
*result = FALSE;
2566+
return true;
25522567
}
25532568
}
2554-
else if (!JavascriptOperators::IsObject(receiver))
2555-
{
2556-
JavascriptError::ThrowCantAssignIfStrictMode(propertyOperationFlags, requestContext);
2557-
return FALSE;
2558-
}
2569+
}
2570+
return false;
2571+
}
2572+
2573+
template <bool unscopables>
2574+
BOOL JavascriptOperators::SetProperty_Internal(Var receiver, RecyclableObject* object, const bool isRoot, PropertyId propertyId, Var newValue, PropertyValueInfo * info, ScriptContext* requestContext, PropertyOperationFlags propertyOperationFlags)
2575+
{
2576+
if (receiver == nullptr)
2577+
{
2578+
return FALSE;
2579+
}
2580+
2581+
Assert(!TaggedNumber::Is(receiver));
2582+
BOOL setAccessorResult = FALSE;
2583+
if (SetAccessorOrNonWritableProperty(receiver, object, propertyId, newValue, info, requestContext, propertyOperationFlags, isRoot, false, &setAccessorResult))
2584+
{
2585+
return setAccessorResult;
2586+
}
2587+
else if (!JavascriptOperators::IsObject(receiver))
2588+
{
2589+
JavascriptError::ThrowCantAssignIfStrictMode(propertyOperationFlags, requestContext);
2590+
return FALSE;
2591+
}
25592592

25602593
#ifdef ENABLE_MUTATION_BREAKPOINT
2561-
// Break on mutation if needed
2562-
bool doNotUpdateCacheForMbp = MutationBreakpoint::IsFeatureEnabled(requestContext) ?
2563-
MutationBreakpoint::HandleSetProperty(requestContext, object, propertyId, newValue) : false;
2594+
// Break on mutation if needed
2595+
bool doNotUpdateCacheForMbp = MutationBreakpoint::IsFeatureEnabled(requestContext) ?
2596+
MutationBreakpoint::HandleSetProperty(requestContext, object, propertyId, newValue) : false;
25642597
#endif
25652598

2566-
// Get the original type before setting the property
2567-
Type *typeWithoutProperty = object->GetType();
2568-
BOOL didSetProperty = false;
2569-
if (isRoot)
2570-
{
2571-
AssertMsg(JavascriptOperators::GetTypeId(receiver) == TypeIds_GlobalObject
2572-
|| JavascriptOperators::GetTypeId(receiver) == TypeIds_ModuleRoot,
2573-
"Root must be a global object!");
2599+
// Get the original type before setting the property
2600+
Type *typeWithoutProperty = object->GetType();
2601+
BOOL didSetProperty = false;
2602+
if (isRoot)
2603+
{
2604+
AssertMsg(JavascriptOperators::GetTypeId(receiver) == TypeIds_GlobalObject
2605+
|| JavascriptOperators::GetTypeId(receiver) == TypeIds_ModuleRoot,
2606+
"Root must be a global object!");
25742607

2575-
RootObjectBase* rootObject = static_cast<RootObjectBase*>(receiver);
2576-
didSetProperty = rootObject->SetRootProperty(propertyId, newValue, propertyOperationFlags, info);
2577-
}
2578-
else
2608+
RootObjectBase* rootObject = static_cast<RootObjectBase*>(receiver);
2609+
didSetProperty = rootObject->SetRootProperty(propertyId, newValue, propertyOperationFlags, info);
2610+
}
2611+
else
2612+
{
2613+
RecyclableObject* instanceObject = RecyclableObject::FromVar(receiver);
2614+
while (!JavascriptOperators::IsNull(instanceObject))
25792615
{
2580-
RecyclableObject* instanceObject = RecyclableObject::FromVar(receiver);
2581-
while (!JavascriptOperators::IsNull(instanceObject))
2616+
if (unscopables && JavascriptOperators::IsPropertyUnscopable(instanceObject, propertyId))
25822617
{
2583-
if (unscopables && JavascriptOperators::IsPropertyUnscopable(instanceObject, propertyId))
2618+
break;
2619+
}
2620+
else
2621+
{
2622+
didSetProperty = instanceObject->SetProperty(propertyId, newValue, propertyOperationFlags, info);
2623+
if (didSetProperty || !unscopables)
25842624
{
25852625
break;
25862626
}
2587-
else
2588-
{
2589-
didSetProperty = instanceObject->SetProperty(propertyId, newValue, propertyOperationFlags, info);
2590-
if (didSetProperty || !unscopables)
2591-
{
2592-
break;
2593-
}
2594-
}
2595-
instanceObject = JavascriptOperators::GetPrototypeNoTrap(instanceObject);
25962627
}
2628+
instanceObject = JavascriptOperators::GetPrototypeNoTrap(instanceObject);
25972629
}
2630+
}
25982631

2599-
if (didSetProperty)
2600-
{
2601-
bool updateCache = true;
2632+
if (didSetProperty)
2633+
{
2634+
bool updateCache = true;
26022635
#ifdef ENABLE_MUTATION_BREAKPOINT
2603-
updateCache = updateCache && !doNotUpdateCacheForMbp;
2636+
updateCache = updateCache && !doNotUpdateCacheForMbp;
26042637
#endif
26052638

2606-
if (updateCache)
2639+
if (updateCache)
2640+
{
2641+
if (!JavascriptProxy::Is(receiver))
26072642
{
2608-
if (!JavascriptProxy::Is(receiver))
2609-
{
2610-
CacheOperators::CachePropertyWrite(RecyclableObject::FromVar(receiver), isRoot, typeWithoutProperty, propertyId, info, requestContext);
2611-
}
2643+
CacheOperators::CachePropertyWrite(RecyclableObject::FromVar(receiver), isRoot, typeWithoutProperty, propertyId, info, requestContext);
26122644
}
2613-
return TRUE;
26142645
}
2646+
return TRUE;
26152647
}
26162648

26172649
return FALSE;
@@ -2939,50 +2971,10 @@ namespace Js
29392971
// is true, this must be a normal property.
29402972
// TODO: merge OP_HasProperty and GetSetter in one pass if there is perf problem. In fastDOM we have quite
29412973
// a lot of setters so separating the two might be actually faster.
2942-
Var setterValueOrProxy = nullptr;
2943-
DescriptorFlags flags = None;
2944-
if (JavascriptOperators::CheckPrototypesForAccessorOrNonWritableProperty(object, propertyId, &setterValueOrProxy, &flags, &info, scriptContext))
2974+
BOOL setAccessorResult = FALSE;
2975+
if (SetAccessorOrNonWritableProperty(object, object, propertyId, newValue, &info, scriptContext, propertyOperationFlags, false, allowUndecInConsoleScope, &setAccessorResult))
29452976
{
2946-
if ((flags & Accessor) == Accessor)
2947-
{
2948-
if (setterValueOrProxy)
2949-
{
2950-
JavascriptFunction* func = (JavascriptFunction*)setterValueOrProxy;
2951-
Assert(info.GetFlags() == InlineCacheSetterFlag || info.GetPropertyIndex() == Constants::NoSlot);
2952-
CacheOperators::CachePropertyWrite(object, false, type, propertyId, &info, scriptContext);
2953-
JavascriptOperators::CallSetter(func, object, newValue, scriptContext);
2954-
}
2955-
2956-
Assert(!isLexicalThisSlotSymbol);
2957-
return;
2958-
}
2959-
else if ((flags & Proxy) == Proxy)
2960-
{
2961-
Assert(JavascriptProxy::Is(setterValueOrProxy));
2962-
JavascriptProxy* proxy = JavascriptProxy::FromVar(setterValueOrProxy);
2963-
auto fn = [&](RecyclableObject* target) -> BOOL {
2964-
return JavascriptOperators::SetProperty(object, target, propertyId, newValue, scriptContext, propertyOperationFlags);
2965-
};
2966-
// We can't cache the property at this time. both target and handler can be changed outside of the proxy, so the inline cache needs to be
2967-
// invalidate when target, handler, or handler prototype has changed. We don't have a way to achieve this yet.
2968-
PropertyValueInfo::SetNoCache(&info, proxy);
2969-
PropertyValueInfo::DisablePrototypeCache(&info, proxy); // We can't cache prototype property either
2970-
proxy->SetPropertyTrap(object, JavascriptProxy::SetPropertyTrapKind::SetPropertyKind, propertyId, newValue, scriptContext);
2971-
}
2972-
else
2973-
{
2974-
Assert((flags & Data) == Data && (flags & Writable) == None);
2975-
if (!allowUndecInConsoleScope)
2976-
{
2977-
if (flags & Const)
2978-
{
2979-
JavascriptError::ThrowTypeError(scriptContext, ERRAssignmentToConst);
2980-
}
2981-
2982-
Assert(!isLexicalThisSlotSymbol);
2983-
return;
2984-
}
2985-
}
2977+
return;
29862978
}
29872979
else if (!JavascriptOperators::IsObject(object))
29882980
{

Diff for: deps/chakrashim/core/lib/Runtime/Language/JavascriptOperators.h

+12
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,18 @@ namespace Js
674674
static BOOL PropertyReferenceWalk_Impl(Var instance, RecyclableObject** propertyObject, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext);
675675
static Var TypeofFld_Internal(Var instance, const bool isRoot, PropertyId propertyId, ScriptContext* scriptContext);
676676

677+
static bool SetAccessorOrNonWritableProperty(
678+
Var receiver,
679+
RecyclableObject* object,
680+
PropertyId propertyId,
681+
Var newValue,
682+
PropertyValueInfo * info,
683+
ScriptContext* requestContext,
684+
PropertyOperationFlags propertyOperationFlags,
685+
bool isRoot,
686+
bool allowUndecInConsoleScope,
687+
BOOL *result);
688+
677689
template <bool unscopables>
678690
static BOOL SetProperty_Internal(Var instance, RecyclableObject* object, const bool isRoot, PropertyId propertyId, Var newValue, PropertyValueInfo * info, ScriptContext* requestContext, PropertyOperationFlags flags);
679691

Diff for: deps/chakrashim/core/lib/Runtime/Library/RuntimeLibraryPch.h

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include "Library/JavascriptWeakMap.h"
5353
#include "Library/JavascriptWeakSet.h"
5454

55+
#include "Types/WithScopeObject.h"
5556
#include "Types/PropertyIndexRanges.h"
5657
#include "Types/DictionaryPropertyDescriptor.h"
5758
#include "Types/DictionaryTypeHandler.h"

0 commit comments

Comments
 (0)