35
35
#include " src/objects/js-array-inl.h"
36
36
#include " src/objects/megadom-handler.h"
37
37
#include " src/objects/module-inl.h"
38
+ #include " src/objects/property-descriptor.h"
38
39
#include " src/objects/prototype.h"
39
40
#include " src/objects/struct-inl.h"
40
41
#include " src/runtime/runtime-utils.h"
@@ -1726,6 +1727,69 @@ MaybeHandle<Object> StoreGlobalIC::Store(Handle<Name> name,
1726
1727
return StoreIC::Store (global, name, value);
1727
1728
}
1728
1729
1730
+ namespace {
1731
+ Maybe<bool > DefineOwnDataProperty (LookupIterator* it,
1732
+ LookupIterator::State original_state,
1733
+ Handle <Object> value,
1734
+ Maybe<ShouldThrow> should_throw,
1735
+ StoreOrigin store_origin) {
1736
+ // It should not be possible to call DefineOwnDataProperty in a
1737
+ // contextual store (indicated by IsJSGlobalObject()).
1738
+ DCHECK (!it->GetReceiver ()->IsJSGlobalObject (it->isolate ()));
1739
+
1740
+ // Handle special cases that can't be handled by
1741
+ // DefineOwnPropertyIgnoreAttributes first.
1742
+ switch (it->state ()) {
1743
+ case LookupIterator::JSPROXY: {
1744
+ PropertyDescriptor new_desc;
1745
+ new_desc.set_value (value);
1746
+ new_desc.set_writable (true );
1747
+ new_desc.set_enumerable (true );
1748
+ new_desc.set_configurable (true );
1749
+ DCHECK_EQ (original_state, LookupIterator::JSPROXY);
1750
+ // TODO(joyee): this will start the lookup again. Ideally we should
1751
+ // implement something that reuses the existing LookupIterator.
1752
+ return JSProxy::DefineOwnProperty (it->isolate (), it->GetHolder <JSProxy>(),
1753
+ it->GetName (), &new_desc, should_throw);
1754
+ }
1755
+ // When lazy feedback is disabled, the original state could be different
1756
+ // while the object is already prepared for TRANSITION.
1757
+ case LookupIterator::TRANSITION: {
1758
+ switch (original_state) {
1759
+ case LookupIterator::JSPROXY:
1760
+ case LookupIterator::TRANSITION:
1761
+ case LookupIterator::DATA:
1762
+ case LookupIterator::INTERCEPTOR:
1763
+ case LookupIterator::ACCESSOR:
1764
+ case LookupIterator::INTEGER_INDEXED_EXOTIC:
1765
+ UNREACHABLE ();
1766
+ case LookupIterator::ACCESS_CHECK: {
1767
+ DCHECK (!it->GetHolder <JSObject>()->IsAccessCheckNeeded ());
1768
+ V8_FALLTHROUGH;
1769
+ }
1770
+ case LookupIterator::NOT_FOUND:
1771
+ return Object::AddDataProperty (it, value, NONE,
1772
+ Nothing<ShouldThrow>(), store_origin);
1773
+ }
1774
+ }
1775
+ case LookupIterator::ACCESS_CHECK:
1776
+ case LookupIterator::NOT_FOUND:
1777
+ case LookupIterator::DATA:
1778
+ case LookupIterator::ACCESSOR:
1779
+ case LookupIterator::INTERCEPTOR:
1780
+ case LookupIterator::INTEGER_INDEXED_EXOTIC:
1781
+ break ;
1782
+ }
1783
+
1784
+ // We need to restart to handle interceptors properly.
1785
+ it->Restart ();
1786
+
1787
+ return JSObject::DefineOwnPropertyIgnoreAttributes (
1788
+ it, value, NONE, should_throw, JSObject::DONT_FORCE_FIELD,
1789
+ JSObject::EnforceDefineSemantics::kDefine );
1790
+ }
1791
+ } // namespace
1792
+
1729
1793
MaybeHandle<Object> StoreIC::Store (Handle <Object> object, Handle <Name> name,
1730
1794
Handle <Object> value,
1731
1795
StoreOrigin store_origin) {
@@ -1737,7 +1801,15 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
1737
1801
isolate (), object, key,
1738
1802
IsAnyStoreOwn () ? LookupIterator::OWN : LookupIterator::DEFAULT);
1739
1803
DCHECK_IMPLIES (IsStoreOwnIC (), it.IsFound () && it.HolderIsReceiver ());
1740
- MAYBE_RETURN_NULL (Object::SetProperty (&it, value, StoreOrigin::kNamed ));
1804
+ // TODO(joyee): IsStoreOwnIC() is used in [[DefineOwnProperty]]
1805
+ // operations during initialization of object literals and class
1806
+ // fields. Rename them or separate them out.
1807
+ if (IsStoreOwnIC ()) {
1808
+ MAYBE_RETURN_NULL (
1809
+ JSReceiver::CreateDataProperty (&it, value, Nothing<ShouldThrow>()));
1810
+ } else {
1811
+ MAYBE_RETURN_NULL (Object::SetProperty (&it, value, StoreOrigin::kNamed ));
1812
+ }
1741
1813
return value;
1742
1814
}
1743
1815
@@ -1785,6 +1857,23 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
1785
1857
use_ic = false ;
1786
1858
}
1787
1859
}
1860
+
1861
+ // For IsStoreOwnIC(), we can't simply do CreateDataProperty below
1862
+ // because we need to check the attributes before UpdateCaches updates
1863
+ // the state of the LookupIterator.
1864
+ LookupIterator::State original_state = it.state ();
1865
+ // We'll defer the check for JSProxy and objects with named interceptors,
1866
+ // because the defineProperty traps need to be called first if they are
1867
+ // present.
1868
+ if (IsStoreOwnIC () && !object->IsJSProxy () &&
1869
+ !Handle <JSObject>::cast (object)->HasNamedInterceptor ()) {
1870
+ Maybe<bool > can_define = JSReceiver::CheckIfCanDefine (
1871
+ isolate (), &it, value, Nothing<ShouldThrow>());
1872
+ if (can_define.IsNothing () || !can_define.FromJust ()) {
1873
+ return MaybeHandle<Object>();
1874
+ }
1875
+ }
1876
+
1788
1877
if (use_ic) {
1789
1878
UpdateCaches (&it, value, store_origin);
1790
1879
} else if (state () == NO_FEEDBACK) {
@@ -1793,7 +1882,21 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
1793
1882
: TraceIC (" StoreIC" , name);
1794
1883
}
1795
1884
1796
- MAYBE_RETURN_NULL (Object::SetProperty (&it, value, store_origin));
1885
+ // TODO(joyee): IsStoreOwnIC() is true in [[DefineOwnProperty]]
1886
+ // operations during initialization of object literals and class
1887
+ // fields. In both paths, Rename the operations properly to avoid
1888
+ // confusion.
1889
+ // ES #sec-definefield
1890
+ // ES #sec-runtime-semantics-propertydefinitionevaluation
1891
+ if (IsStoreOwnIC ()) {
1892
+ // Private property should be defined via DefineOwnIC (as private names) or
1893
+ // stored via other store ICs through private symbols.
1894
+ DCHECK (!name->IsPrivate ());
1895
+ MAYBE_RETURN_NULL (DefineOwnDataProperty (
1896
+ &it, original_state, value, Nothing<ShouldThrow>(), store_origin));
1897
+ } else {
1898
+ MAYBE_RETURN_NULL (Object::SetProperty (&it, value, store_origin));
1899
+ }
1797
1900
return value;
1798
1901
}
1799
1902
@@ -1871,11 +1974,14 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
1871
1974
1872
1975
// If the interceptor is on the receiver...
1873
1976
if (lookup->HolderIsReceiverOrHiddenPrototype () && !info.non_masking ()) {
1874
- // ...return a store interceptor Smi handler if there is one...
1875
- if (!info.setter ().IsUndefined (isolate ())) {
1977
+ // ...return a store interceptor Smi handler if there is a setter
1978
+ // interceptor and it's not StoreOwnIC (which should call the
1979
+ // definer)...
1980
+ if (!info.setter ().IsUndefined (isolate ()) && !IsStoreOwnIC ()) {
1876
1981
return MaybeObjectHandle (StoreHandler::StoreInterceptor (isolate ()));
1877
1982
}
1878
- // ...otherwise return a slow-case Smi handler.
1983
+ // ...otherwise return a slow-case Smi handler, which invokes the
1984
+ // definer for StoreOwnIC.
1879
1985
return MaybeObjectHandle (StoreHandler::StoreSlow (isolate ()));
1880
1986
}
1881
1987
@@ -2055,6 +2161,14 @@ MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
2055
2161
Handle <JSReceiver> receiver =
2056
2162
Handle <JSReceiver>::cast (lookup->GetReceiver ());
2057
2163
Handle <JSProxy> holder = lookup->GetHolder <JSProxy>();
2164
+
2165
+ // IsStoreOwnIC() is true when we are defining public fields on a Proxy.
2166
+ // In that case use the slow stub to invoke the define trap.
2167
+ if (IsStoreOwnIC ()) {
2168
+ TRACE_HANDLER_STATS (isolate (), StoreIC_SlowStub);
2169
+ return MaybeObjectHandle (StoreHandler::StoreSlow (isolate ()));
2170
+ }
2171
+
2058
2172
return MaybeObjectHandle (StoreHandler::StoreProxy (
2059
2173
isolate (), lookup_start_object_map (), holder, receiver));
2060
2174
}
@@ -2766,9 +2880,10 @@ RUNTIME_FUNCTION(Runtime_StoreOwnIC_Slow) {
2766
2880
2767
2881
PropertyKey lookup_key (isolate, key);
2768
2882
LookupIterator it (isolate, object, lookup_key, LookupIterator::OWN);
2769
- MAYBE_RETURN (JSObject::DefineOwnPropertyIgnoreAttributes (
2770
- &it, value, NONE, Nothing<ShouldThrow>()),
2771
- ReadOnlyRoots (isolate).exception ());
2883
+
2884
+ MAYBE_RETURN (
2885
+ JSReceiver::CreateDataProperty (&it, value, Nothing<ShouldThrow>()),
2886
+ ReadOnlyRoots (isolate).exception ());
2772
2887
return *value;
2773
2888
}
2774
2889
0 commit comments