<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[197539] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/197539">197539</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-03-03 18:25:30 -0800 (Thu, 03 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add Proxy tests for exceptions that depend on an object being non-extensible and having configurable properties
https://bugs.webkit.org/show_bug.cgi?id=154745

Reviewed by Geoffrey Garen.

This patch is mostly an implementation of Proxy.[[OwnPropertyKeys]] 
with respect to section 9.5.11 of the ECMAScript spec.
https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys

This patch also changes call sites of getOwnPropertyNames and
getPropertyNames to expect that an exception can be thrown.

* dfg/DFGOperations.cpp:
* inspector/JSInjectedScriptHost.cpp:
(Inspector::JSInjectedScriptHost::iteratorEntries):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
* runtime/IntlObject.cpp:
(JSC::supportedLocales):
* runtime/JSCJSValue.h:
* runtime/JSCJSValueInlines.h:
(JSC::JSValue::get):
(JSC::JSValue::put):
* runtime/JSONObject.cpp:
(JSC::Stringifier::Holder::appendNextProperty):
(JSC::Walker::walk):
* runtime/JSObject.cpp:
(JSC::JSObject::getPropertyNames):
(JSC::JSObject::getGenericPropertyNames):
* runtime/JSObject.h:
(JSC::makeIdentifier):
(JSC::createListFromArrayLike):
* runtime/JSPropertyNameEnumerator.h:
(JSC::propertyNameEnumerator):
* runtime/JSPropertyNameIterator.cpp:
(JSC::JSPropertyNameIterator::create):
* runtime/MapConstructor.cpp:
(JSC::constructMap):
* runtime/ObjectConstructor.cpp:
(JSC::defineProperties):
(JSC::objectConstructorSeal):
(JSC::objectConstructorFreeze):
(JSC::objectConstructorIsSealed):
(JSC::objectConstructorIsFrozen):
(JSC::ownPropertyKeys):
* runtime/ProxyObject.cpp:
(JSC::ProxyObject::getOwnPropertySlotByIndex):
(JSC::ProxyObject::deleteProperty):
(JSC::ProxyObject::deletePropertyByIndex):
(JSC::ProxyObject::defineOwnProperty):
(JSC::ProxyObject::performGetOwnPropertyNames):
(JSC::ProxyObject::getOwnPropertyNames):
(JSC::ProxyObject::getOwnNonIndexPropertyNames):
(JSC::ProxyObject::getStructurePropertyNames):
(JSC::ProxyObject::getGenericPropertyNames):
(JSC::ProxyObject::visitChildren):
* runtime/ProxyObject.h:
(JSC::ProxyObject::create):
(JSC::ProxyObject::createStructure):
* runtime/Structure.cpp:
(JSC::Structure::Structure):
(JSC::Structure::add):
(JSC::Structure::getPropertyNamesFromStructure):
(JSC::Structure::checkConsistency):
(JSC::Structure::canCachePropertyNameEnumerator):
(JSC::Structure::canAccessPropertiesQuicklyForEnumeration):
(JSC::Structure::canAccessPropertiesQuickly): Deleted.
* runtime/Structure.h:
* runtime/WeakMapConstructor.cpp:
(JSC::constructWeakMap):
* tests/es6.yaml:
* tests/stress/proxy-own-keys.js: Added.
(assert):
(throw.new.Error.let.handler.ownKeys):
(throw.new.Error):
(assert.let.handler.get ownKeys):
(assert.let.handler.ownKeys):
(let.handler.ownKeys):
(i.catch):
(shallowEq):
(let.handler.getOwnPropertyDescriptor):
(i.set assert):
(set add):
(set assert):
(set if):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorJSInjectedScriptHostcpp">trunk/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpretercpp">trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeIntlObjectcpp">trunk/Source/JavaScriptCore/runtime/IntlObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCJSValueh">trunk/Source/JavaScriptCore/runtime/JSCJSValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCJSValueInlinesh">trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSONObjectcpp">trunk/Source/JavaScriptCore/runtime/JSONObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjectcpp">trunk/Source/JavaScriptCore/runtime/JSObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjecth">trunk/Source/JavaScriptCore/runtime/JSObject.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorh">trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSPropertyNameIteratorcpp">trunk/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeMapConstructorcpp">trunk/Source/JavaScriptCore/runtime/MapConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeObjectConstructorcpp">trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeProxyObjectcpp">trunk/Source/JavaScriptCore/runtime/ProxyObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeProxyObjecth">trunk/Source/JavaScriptCore/runtime/ProxyObject.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructurecpp">trunk/Source/JavaScriptCore/runtime/Structure.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureh">trunk/Source/JavaScriptCore/runtime/Structure.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeWeakMapConstructorcpp">trunk/Source/JavaScriptCore/runtime/WeakMapConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoretestses6yaml">trunk/Source/JavaScriptCore/tests/es6.yaml</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressproxyownkeysjs">trunk/Source/JavaScriptCore/tests/stress/proxy-own-keys.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -1,3 +1,91 @@
</span><ins>+2016-03-03  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        Add Proxy tests for exceptions that depend on an object being non-extensible and having configurable properties
+        https://bugs.webkit.org/show_bug.cgi?id=154745
+
+        Reviewed by Geoffrey Garen.
+
+        This patch is mostly an implementation of Proxy.[[OwnPropertyKeys]] 
+        with respect to section 9.5.11 of the ECMAScript spec.
+        https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
+
+        This patch also changes call sites of getOwnPropertyNames and
+        getPropertyNames to expect that an exception can be thrown.
+
+        * dfg/DFGOperations.cpp:
+        * inspector/JSInjectedScriptHost.cpp:
+        (Inspector::JSInjectedScriptHost::iteratorEntries):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::execute):
+        * runtime/IntlObject.cpp:
+        (JSC::supportedLocales):
+        * runtime/JSCJSValue.h:
+        * runtime/JSCJSValueInlines.h:
+        (JSC::JSValue::get):
+        (JSC::JSValue::put):
+        * runtime/JSONObject.cpp:
+        (JSC::Stringifier::Holder::appendNextProperty):
+        (JSC::Walker::walk):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::getPropertyNames):
+        (JSC::JSObject::getGenericPropertyNames):
+        * runtime/JSObject.h:
+        (JSC::makeIdentifier):
+        (JSC::createListFromArrayLike):
+        * runtime/JSPropertyNameEnumerator.h:
+        (JSC::propertyNameEnumerator):
+        * runtime/JSPropertyNameIterator.cpp:
+        (JSC::JSPropertyNameIterator::create):
+        * runtime/MapConstructor.cpp:
+        (JSC::constructMap):
+        * runtime/ObjectConstructor.cpp:
+        (JSC::defineProperties):
+        (JSC::objectConstructorSeal):
+        (JSC::objectConstructorFreeze):
+        (JSC::objectConstructorIsSealed):
+        (JSC::objectConstructorIsFrozen):
+        (JSC::ownPropertyKeys):
+        * runtime/ProxyObject.cpp:
+        (JSC::ProxyObject::getOwnPropertySlotByIndex):
+        (JSC::ProxyObject::deleteProperty):
+        (JSC::ProxyObject::deletePropertyByIndex):
+        (JSC::ProxyObject::defineOwnProperty):
+        (JSC::ProxyObject::performGetOwnPropertyNames):
+        (JSC::ProxyObject::getOwnPropertyNames):
+        (JSC::ProxyObject::getOwnNonIndexPropertyNames):
+        (JSC::ProxyObject::getStructurePropertyNames):
+        (JSC::ProxyObject::getGenericPropertyNames):
+        (JSC::ProxyObject::visitChildren):
+        * runtime/ProxyObject.h:
+        (JSC::ProxyObject::create):
+        (JSC::ProxyObject::createStructure):
+        * runtime/Structure.cpp:
+        (JSC::Structure::Structure):
+        (JSC::Structure::add):
+        (JSC::Structure::getPropertyNamesFromStructure):
+        (JSC::Structure::checkConsistency):
+        (JSC::Structure::canCachePropertyNameEnumerator):
+        (JSC::Structure::canAccessPropertiesQuicklyForEnumeration):
+        (JSC::Structure::canAccessPropertiesQuickly): Deleted.
+        * runtime/Structure.h:
+        * runtime/WeakMapConstructor.cpp:
+        (JSC::constructWeakMap):
+        * tests/es6.yaml:
+        * tests/stress/proxy-own-keys.js: Added.
+        (assert):
+        (throw.new.Error.let.handler.ownKeys):
+        (throw.new.Error):
+        (assert.let.handler.get ownKeys):
+        (assert.let.handler.ownKeys):
+        (let.handler.ownKeys):
+        (i.catch):
+        (shallowEq):
+        (let.handler.getOwnPropertyDescriptor):
+        (i.set assert):
+        (set add):
+        (set assert):
+        (set if):
+
</ins><span class="cx"> 2016-03-03  Keith Miller  &lt;keith_miller@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Array prototype JS builtins should support Symbol.species
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -410,7 +410,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Use this since we know that the value is out of bounds.
</span><del>-    return JSValue::encode(JSValue(base).get(exec, index));
</del><ins>+    return JSValue::encode(JSValue(base).get(exec, static_cast&lt;unsigned&gt;(index)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByValArrayInt(ExecState* exec, JSArray* base, int32_t index)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorJSInjectedScriptHostcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -448,9 +448,11 @@
</span><span class="cx">         iterator = setIterator-&gt;clone(exec);
</span><span class="cx">     else if (JSStringIterator* stringIterator = jsDynamicCast&lt;JSStringIterator*&gt;(value))
</span><span class="cx">         iterator = stringIterator-&gt;clone(exec);
</span><del>-    else if (JSPropertyNameIterator* propertyNameIterator = jsDynamicCast&lt;JSPropertyNameIterator*&gt;(value))
</del><ins>+    else if (JSPropertyNameIterator* propertyNameIterator = jsDynamicCast&lt;JSPropertyNameIterator*&gt;(value)) {
</ins><span class="cx">         iterator = propertyNameIterator-&gt;clone(exec);
</span><del>-    else
</del><ins>+        if (UNLIKELY(exec-&gt;hadException()))
+            return JSValue();
+    } else
</ins><span class="cx">         return jsUndefined();
</span><span class="cx"> 
</span><span class="cx">     unsigned numberToFetch = 5;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -891,7 +891,7 @@
</span><span class="cx">                     continue;
</span><span class="cx">                 }
</span><span class="cx">                 case JSONPPathEntryTypeLookup: {
</span><del>-                    baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
</del><ins>+                    baseObject = baseObject.get(callFrame, static_cast&lt;unsigned&gt;(JSONPPath[i].m_pathIndex));
</ins><span class="cx">                     if (callFrame-&gt;hadException())
</span><span class="cx">                         return jsUndefined();
</span><span class="cx">                     continue;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeIntlObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/IntlObject.cpp (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/IntlObject.cpp        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/IntlObject.cpp        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -944,6 +944,8 @@
</span><span class="cx">     // 7. Let keys be subset.[[OwnPropertyKeys]]().
</span><span class="cx">     PropertyNameArray keys(&amp;state, PropertyNameMode::Strings);
</span><span class="cx">     supportedLocales-&gt;getOwnPropertyNames(supportedLocales, &amp;state, keys, EnumerationMode());
</span><ins>+    if (state.hadException())
+        return jsUndefined();
</ins><span class="cx"> 
</span><span class="cx">     PropertyDescriptor desc;
</span><span class="cx">     desc.setConfigurable(false);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCJSValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCJSValue.h (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCJSValue.h        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/JSCJSValue.h        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -275,6 +275,7 @@
</span><span class="cx">     JSValue get(ExecState*, PropertyName, PropertySlot&amp;) const;
</span><span class="cx">     JSValue get(ExecState*, unsigned propertyName) const;
</span><span class="cx">     JSValue get(ExecState*, unsigned propertyName, PropertySlot&amp;) const;
</span><ins>+    JSValue get(ExecState*, uint64_t propertyName) const;
</ins><span class="cx"> 
</span><span class="cx">     bool getPropertySlot(ExecState*, PropertyName, PropertySlot&amp;) const;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCJSValueInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -778,6 +778,13 @@
</span><span class="cx">     return jsUndefined();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE JSValue JSValue::get(ExecState* exec, uint64_t propertyName) const
+{
+    if (LIKELY(propertyName &lt;= std::numeric_limits&lt;unsigned&gt;::max()))
+        return get(exec, static_cast&lt;unsigned&gt;(propertyName));
+    return get(exec, Identifier::from(exec, static_cast&lt;double&gt;(propertyName)));
+}
+
</ins><span class="cx"> inline void JSValue::put(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot&amp; slot)
</span><span class="cx"> {
</span><span class="cx">     if (UNLIKELY(!isCell())) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSONObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSONObject.cpp (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSONObject.cpp        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/JSONObject.cpp        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -439,6 +439,8 @@
</span><span class="cx">             else {
</span><span class="cx">                 PropertyNameArray objectPropertyNames(exec, PropertyNameMode::Strings);
</span><span class="cx">                 m_object-&gt;methodTable()-&gt;getOwnPropertyNames(m_object.get(), exec, objectPropertyNames, EnumerationMode());
</span><ins>+                if (UNLIKELY(exec-&gt;hadException()))
+                    return false;
</ins><span class="cx">                 m_propertyNames = objectPropertyNames.releaseData();
</span><span class="cx">             }
</span><span class="cx">             m_size = m_propertyNames-&gt;propertyNameVector().size();
</span><span class="lines">@@ -656,6 +658,8 @@
</span><span class="cx">                 indexStack.append(0);
</span><span class="cx">                 propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
</span><span class="cx">                 object-&gt;methodTable()-&gt;getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
</span><ins>+                if (UNLIKELY(m_exec-&gt;hadException()))
+                    return jsNull();
</ins><span class="cx">             }
</span><span class="cx">             objectStartVisitMember:
</span><span class="cx">             FALLTHROUGH;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObject.cpp (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObject.cpp        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/JSObject.cpp        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -1591,6 +1591,8 @@
</span><span class="cx"> void JSObject::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><span class="cx">     object-&gt;methodTable(exec-&gt;vm())-&gt;getOwnPropertyNames(object, exec, propertyNames, mode);
</span><ins>+    if (UNLIKELY(exec-&gt;hadException()))
+        return;
</ins><span class="cx"> 
</span><span class="cx">     if (object-&gt;prototype().isNull())
</span><span class="cx">         return;
</span><span class="lines">@@ -1603,6 +1605,8 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         prototype-&gt;methodTable(vm)-&gt;getOwnPropertyNames(prototype, exec, propertyNames, mode);
</span><ins>+        if (UNLIKELY(exec-&gt;hadException()))
+            return;
</ins><span class="cx">         JSValue nextProto = prototype-&gt;prototype();
</span><span class="cx">         if (nextProto.isNull())
</span><span class="cx">             break;
</span><span class="lines">@@ -3025,6 +3029,8 @@
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     object-&gt;methodTable(vm)-&gt;getOwnPropertyNames(object, exec, propertyNames, EnumerationMode(mode, JSObjectPropertiesMode::Exclude));
</span><ins>+    if (UNLIKELY(exec-&gt;hadException()))
+        return;
</ins><span class="cx"> 
</span><span class="cx">     if (object-&gt;prototype().isNull())
</span><span class="cx">         return;
</span><span class="lines">@@ -3036,6 +3042,8 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         prototype-&gt;methodTable(vm)-&gt;getOwnPropertyNames(prototype, exec, propertyNames, mode);
</span><ins>+        if (UNLIKELY(exec-&gt;hadException()))
+            return;
</ins><span class="cx">         JSValue nextProto = prototype-&gt;prototype();
</span><span class="cx">         if (nextProto.isNull())
</span><span class="cx">             break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObject.h (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObject.h        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/JSObject.h        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> #include &quot;PropertyStorage.h&quot;
</span><span class="cx"> #include &quot;PutDirectIndexMode.h&quot;
</span><span class="cx"> #include &quot;PutPropertySlot.h&quot;
</span><ins>+#include &quot;RuntimeType.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> #include &quot;Structure.h&quot;
</span><span class="cx"> #include &quot;VM.h&quot;
</span><span class="lines">@@ -1533,6 +1534,37 @@
</span><span class="cx">     return name;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// Section 7.3.17 of the spec. 
+template &lt;typename AddFunction&gt; // Add function should have a type like: (JSValue, RuntimeType) -&gt; bool
+void createListFromArrayLike(ExecState* exec, JSValue arrayLikeValue, RuntimeTypeMask legalTypesFilter, const String&amp; errorMessage, AddFunction addFunction)
+{
+    VM&amp; vm = exec-&gt;vm();
+    Vector&lt;JSValue&gt; result;
+    JSValue lengthProperty = arrayLikeValue.get(exec, exec-&gt;vm().propertyNames-&gt;length);
+    if (vm.exception())
+        return;
+    double lengthAsDouble = lengthProperty.toLength(exec);
+    if (vm.exception())
+        return;
+    RELEASE_ASSERT(lengthAsDouble &gt;= 0.0 &amp;&amp; lengthAsDouble == std::trunc(lengthAsDouble));
+    uint64_t length = static_cast&lt;uint64_t&gt;(lengthAsDouble);
+    for (uint64_t index = 0; index &lt; length; index++) {
+        JSValue  next = arrayLikeValue.get(exec, index);
+        if (vm.exception())
+            return;
+
+        RuntimeType type = runtimeTypeForValue(next);
+        if (!(type &amp; legalTypesFilter)) {
+            throwTypeError(exec, errorMessage);
+            return;
+        }
+
+        bool exitEarly = addFunction(next, type);
+        if (exitEarly)
+            return;
+    }
+}
+
</ins><span class="cx"> bool validateAndApplyPropertyDescriptor(ExecState*, JSObject*, PropertyName, bool isExtensible,
</span><span class="cx">     const PropertyDescriptor&amp; descriptor, bool isCurrentDefined, const PropertyDescriptor&amp; current, bool throwException);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -117,17 +117,21 @@
</span><span class="cx"> 
</span><span class="cx">     PropertyNameArray propertyNames(exec, PropertyNameMode::Strings);
</span><span class="cx"> 
</span><del>-    if (structure-&gt;canAccessPropertiesQuickly() &amp;&amp; indexedLength == base-&gt;getArrayLength()) {
</del><ins>+    if (structure-&gt;canAccessPropertiesQuicklyForEnumeration() &amp;&amp; indexedLength == base-&gt;getArrayLength()) {
</ins><span class="cx">         base-&gt;methodTable(vm)-&gt;getStructurePropertyNames(base, exec, propertyNames, EnumerationMode());
</span><ins>+        ASSERT(!exec-&gt;hadException());
</ins><span class="cx"> 
</span><span class="cx">         numberStructureProperties = propertyNames.size();
</span><span class="cx"> 
</span><span class="cx">         base-&gt;methodTable(vm)-&gt;getGenericPropertyNames(base, exec, propertyNames, EnumerationMode());
</span><ins>+        ASSERT(!exec-&gt;hadException());
</ins><span class="cx">     } else {
</span><span class="cx">         // Generic property names vector contains all indexed property names.
</span><span class="cx">         // So disable indexed property enumeration phase by setting |indexedLength| to 0.
</span><span class="cx">         indexedLength = 0;
</span><span class="cx">         base-&gt;methodTable(vm)-&gt;getPropertyNames(base, exec, propertyNames, EnumerationMode());
</span><ins>+        if (UNLIKELY(exec-&gt;hadException()))
+            return nullptr;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ASSERT(propertyNames.size() &lt; UINT32_MAX);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSPropertyNameIteratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -59,7 +59,10 @@
</span><span class="cx"> 
</span><span class="cx"> JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, Structure* structure, JSObject* iteratedObject)
</span><span class="cx"> {
</span><del>-    return JSPropertyNameIterator::create(exec, structure, iteratedObject, propertyNameEnumerator(exec, iteratedObject));
</del><ins>+    JSPropertyNameEnumerator* enumerator = propertyNameEnumerator(exec, iteratedObject);
+    if (UNLIKELY(exec-&gt;hadException()))
+        return nullptr;
+    return JSPropertyNameIterator::create(exec, structure, iteratedObject, enumerator);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, Structure* structure, JSObject* iteratedObject, JSPropertyNameEnumerator* enumerator)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeMapConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/MapConstructor.cpp (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/MapConstructor.cpp        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/MapConstructor.cpp        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -108,13 +108,13 @@
</span><span class="cx">             return JSValue::encode(jsUndefined());
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        JSValue key = nextItem.get(exec, 0);
</del><ins>+        JSValue key = nextItem.get(exec, static_cast&lt;unsigned&gt;(0));
</ins><span class="cx">         if (exec-&gt;hadException()) {
</span><span class="cx">             iteratorClose(exec, iterator);
</span><span class="cx">             return JSValue::encode(jsUndefined());
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        JSValue value = nextItem.get(exec, 1);
</del><ins>+        JSValue value = nextItem.get(exec, static_cast&lt;unsigned&gt;(1));
</ins><span class="cx">         if (exec-&gt;hadException()) {
</span><span class="cx">             iteratorClose(exec, iterator);
</span><span class="cx">             return JSValue::encode(jsUndefined());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeObjectConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -408,6 +408,8 @@
</span><span class="cx"> {
</span><span class="cx">     PropertyNameArray propertyNames(exec, PropertyNameMode::StringsAndSymbols);
</span><span class="cx">     asObject(properties)-&gt;methodTable(exec-&gt;vm())-&gt;getOwnPropertyNames(asObject(properties), exec, propertyNames, EnumerationMode(DontEnumPropertiesMode::Exclude));
</span><ins>+    if (UNLIKELY(exec-&gt;hadException()))
+        return jsNull();
</ins><span class="cx">     size_t numProperties = propertyNames.size();
</span><span class="cx">     Vector&lt;PropertyDescriptor&gt; descriptors;
</span><span class="cx">     MarkedArgumentBuffer markBuffer;
</span><span class="lines">@@ -478,6 +480,8 @@
</span><span class="cx">     // 2. For each named own property name P of O,
</span><span class="cx">     PropertyNameArray properties(exec, PropertyNameMode::StringsAndSymbols);
</span><span class="cx">     object-&gt;methodTable(exec-&gt;vm())-&gt;getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
</span><ins>+    if (UNLIKELY(exec-&gt;hadException()))
+        return JSValue::encode(obj);
</ins><span class="cx">     PropertyNameArray::const_iterator end = properties.end();
</span><span class="cx">     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
</span><span class="cx">         Identifier propertyName = *iter;
</span><span class="lines">@@ -514,6 +518,8 @@
</span><span class="cx">     // 2. For each named own property name P of O,
</span><span class="cx">     PropertyNameArray properties(exec, PropertyNameMode::StringsAndSymbols);
</span><span class="cx">     object-&gt;methodTable(exec-&gt;vm())-&gt;getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
</span><ins>+    if (UNLIKELY(exec-&gt;hadException()))
+        return object;
</ins><span class="cx">     PropertyNameArray::const_iterator end = properties.end();
</span><span class="cx">     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
</span><span class="cx">         Identifier propertyName = *iter;
</span><span class="lines">@@ -580,6 +586,8 @@
</span><span class="cx">     // 2. For each named own property name P of O,
</span><span class="cx">     PropertyNameArray properties(exec, PropertyNameMode::StringsAndSymbols);
</span><span class="cx">     object-&gt;methodTable(exec-&gt;vm())-&gt;getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
</span><ins>+    if (UNLIKELY(exec-&gt;hadException()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     PropertyNameArray::const_iterator end = properties.end();
</span><span class="cx">     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
</span><span class="cx">         Identifier propertyName = *iter;
</span><span class="lines">@@ -616,6 +624,8 @@
</span><span class="cx">     // 2. For each named own property name P of O,
</span><span class="cx">     PropertyNameArray properties(exec, PropertyNameMode::StringsAndSymbols);
</span><span class="cx">     object-&gt;methodTable(exec-&gt;vm())-&gt;getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
</span><ins>+    if (UNLIKELY(exec-&gt;hadException()))
+        return JSValue::encode(JSValue());
</ins><span class="cx">     PropertyNameArray::const_iterator end = properties.end();
</span><span class="cx">     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
</span><span class="cx">         Identifier propertyName = *iter;
</span><span class="lines">@@ -661,6 +671,8 @@
</span><span class="cx"> {
</span><span class="cx">     PropertyNameArray properties(exec, propertyNameMode);
</span><span class="cx">     object-&gt;methodTable(exec-&gt;vm())-&gt;getOwnPropertyNames(object, exec, properties, EnumerationMode(dontEnumPropertiesMode));
</span><ins>+    if (exec-&gt;hadException())
+        return nullptr;
</ins><span class="cx"> 
</span><span class="cx">     JSArray* keys = constructEmptyArray(exec, 0);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeProxyObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ProxyObject.cpp (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ProxyObject.cpp        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/ProxyObject.cpp        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -341,8 +341,6 @@
</span><span class="cx"> {
</span><span class="cx">     ProxyObject* thisObject = jsCast&lt;ProxyObject*&gt;(object);
</span><span class="cx">     Identifier ident = Identifier::from(exec, propertyName); 
</span><del>-    if (exec-&gt;hadException())
-        return false;
</del><span class="cx">     return thisObject-&gt;getOwnPropertySlotCommon(exec, ident.impl(), slot);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -587,7 +585,7 @@
</span><span class="cx"> {
</span><span class="cx">     ProxyObject* thisObject = jsCast&lt;ProxyObject*&gt;(cell);
</span><span class="cx">     auto performDefaultDelete = [&amp;] () -&gt; bool {
</span><del>-        JSObject* target = jsCast&lt;JSObject*&gt;(thisObject-&gt;target());
</del><ins>+        JSObject* target = thisObject-&gt;target();
</ins><span class="cx">         return target-&gt;methodTable(exec-&gt;vm())-&gt;deleteProperty(target, exec, propertyName);
</span><span class="cx">     };
</span><span class="cx">     return thisObject-&gt;performDelete(exec, propertyName, performDefaultDelete);
</span><span class="lines">@@ -597,10 +595,8 @@
</span><span class="cx"> {
</span><span class="cx">     ProxyObject* thisObject = jsCast&lt;ProxyObject*&gt;(cell);
</span><span class="cx">     Identifier ident = Identifier::from(exec, propertyName); 
</span><del>-    if (exec-&gt;hadException())
-        return false;
</del><span class="cx">     auto performDefaultDelete = [&amp;] () -&gt; bool {
</span><del>-        JSObject* target = jsCast&lt;JSObject*&gt;(thisObject-&gt;target());
</del><ins>+        JSObject* target = thisObject-&gt;target();
</ins><span class="cx">         return target-&gt;methodTable(exec-&gt;vm())-&gt;deletePropertyByIndex(target, exec, propertyName);
</span><span class="cx">     };
</span><span class="cx">     return thisObject-&gt;performDelete(exec, ident.impl(), performDefaultDelete);
</span><span class="lines">@@ -801,6 +797,164 @@
</span><span class="cx">     return thisObject-&gt;performDefineOwnProperty(exec, propertyName, descriptor, shouldThrow);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ProxyObject::performGetOwnPropertyNames(ExecState* exec, PropertyNameArray&amp; trapResult, EnumerationMode enumerationMode)
+{
+    VM&amp; vm = exec-&gt;vm();
+    JSValue handlerValue = this-&gt;handler();
+    if (handlerValue.isNull()) {
+        throwVMTypeError(exec, ASCIILiteral(&quot;Proxy 'handler' is null. It should be an Object.&quot;));
+        return;
+    }
+
+    JSObject* handler = jsCast&lt;JSObject*&gt;(handlerValue);
+    CallData callData;
+    CallType callType;
+    JSValue ownKeysMethod = handler-&gt;getMethod(exec, callData, callType, makeIdentifier(vm, &quot;ownKeys&quot;), ASCIILiteral(&quot;'ownKeys' property of a Proxy's handler should be callable.&quot;));
+    if (exec-&gt;hadException())
+        return;
+    JSObject* target = this-&gt;target();
+    if (ownKeysMethod.isUndefined()) {
+        target-&gt;methodTable(exec-&gt;vm())-&gt;getOwnPropertyNames(target, exec, trapResult, enumerationMode);
+        return;
+    }
+
+    MarkedArgumentBuffer arguments;
+    arguments.append(target);
+    JSValue arrayLikeObject = call(exec, ownKeysMethod, callType, callData, handler, arguments);
+    if (exec-&gt;hadException())
+        return;
+
+    PropertyNameMode propertyNameMode = trapResult.mode();
+    RuntimeTypeMask resultFilter = 0;
+    switch (propertyNameMode) {
+    case PropertyNameMode::Symbols:
+        resultFilter = TypeSymbol;
+        break;
+    case PropertyNameMode::Strings:
+        resultFilter = TypeString;
+        break;
+    case PropertyNameMode::StringsAndSymbols:
+        resultFilter = TypeSymbol | TypeString;
+        break;
+    }
+    ASSERT(resultFilter);
+    RuntimeTypeMask dontThrowAnExceptionTypeFilter = TypeString | TypeSymbol;
+    HashMap&lt;UniquedStringImpl*, unsigned&gt; uncheckedResultKeys;
+    unsigned totalSize = 0;
+
+    auto addPropName = [&amp;] (JSValue value, RuntimeType type) -&gt; bool {
+        static const bool doExitEarly = true;
+        static const bool dontExitEarly = false;
+
+        if (!(type &amp; resultFilter))
+            return dontExitEarly;
+
+        Identifier ident = value.toPropertyKey(exec);
+        if (exec-&gt;hadException())
+            return doExitEarly;
+
+        ++uncheckedResultKeys.add(ident.impl(), 0).iterator-&gt;value;
+        ++totalSize;
+
+        trapResult.add(ident.impl());
+
+        return dontExitEarly;
+    };
+
+    createListFromArrayLike(exec, arrayLikeObject, dontThrowAnExceptionTypeFilter, ASCIILiteral(&quot;Proxy handler's 'ownKeys' method must return a array-like object containing only Strings and Symbols.&quot;), addPropName);
+    if (exec-&gt;hadException())
+        return;
+
+    bool targetIsExensible = target-&gt;isExtensible(exec);
+
+    PropertyNameArray targetKeys(&amp;vm, propertyNameMode);
+    target-&gt;methodTable(vm)-&gt;getOwnPropertyNames(target, exec, targetKeys, enumerationMode);
+    if (exec-&gt;hadException())
+        return;
+    Vector&lt;UniquedStringImpl*&gt; targetConfigurableKeys;
+    Vector&lt;UniquedStringImpl*&gt; targetNonConfigurableKeys;
+    for (const Identifier&amp; ident : targetKeys) {
+        PropertyDescriptor descriptor;
+        bool isPropertyDefined = target-&gt;getOwnPropertyDescriptor(exec, ident.impl(), descriptor); 
+        if (exec-&gt;hadException())
+            return;
+        if (isPropertyDefined &amp;&amp; !descriptor.configurable())
+            targetNonConfigurableKeys.append(ident.impl());
+        else
+            targetConfigurableKeys.append(ident.impl());
+    }
+
+    auto removeIfContainedInUncheckedResultKeys = [&amp;] (UniquedStringImpl* impl) -&gt; bool {
+        static const bool isContainedIn = true;
+        static const bool isNotContainedIn = false;
+
+        auto iter = uncheckedResultKeys.find(impl);
+        if (iter == uncheckedResultKeys.end())
+            return isNotContainedIn;
+
+        unsigned&amp; count = iter-&gt;value;
+        if (count == 0)
+            return isNotContainedIn;
+
+        --count;
+        --totalSize;
+        return isContainedIn;
+    };
+
+    for (UniquedStringImpl* impl : targetNonConfigurableKeys) {
+        bool contains = removeIfContainedInUncheckedResultKeys(impl);
+        if (!contains) {
+            throwVMTypeError(exec, makeString(&quot;Proxy object's 'target' has the non-configurable property '&quot;, String(impl), &quot;' that was not in the result from the 'ownKeys' trap.&quot;));
+            return;
+        }
+    }
+
+    if (targetIsExensible)
+        return;
+
+    for (UniquedStringImpl* impl : targetConfigurableKeys) {
+        bool contains = removeIfContainedInUncheckedResultKeys(impl);
+        if (!contains) {
+            throwVMTypeError(exec, makeString(&quot;Proxy object's non-extensible 'target' has configurable property '&quot;, String(impl), &quot;' that was not in the result from the 'ownKeys' trap.&quot;));
+            return;
+        }
+    }
+
+#ifndef NDEBUG
+    unsigned sum = 0;
+    for (unsigned keyCount : uncheckedResultKeys.values())
+        sum += keyCount;
+    ASSERT(sum == totalSize);
+#endif
+
+    if (totalSize) {
+        throwVMTypeError(exec, ASCIILiteral(&quot;Proxy handler's 'ownKeys' method returned a key that was not present in its target or it returned duplicate keys.&quot;));
+        return;
+    }
+}
+
+void ProxyObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNameArray, EnumerationMode enumerationMode)
+{
+    ProxyObject* thisObject = jsCast&lt;ProxyObject*&gt;(object);
+    thisObject-&gt;performGetOwnPropertyNames(exec, propertyNameArray, enumerationMode);
+}
+
+void ProxyObject::getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode)
+{
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void ProxyObject::getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode)
+{
+    // We should always go down the getOwnPropertyNames path.
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void ProxyObject::getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode)
+{
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
</ins><span class="cx"> void ProxyObject::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
</span><span class="cx"> {
</span><span class="cx">     ProxyObject* thisObject = jsCast&lt;ProxyObject*&gt;(cell);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeProxyObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ProxyObject.h (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ProxyObject.h        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/ProxyObject.h        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSGlobalObject.h&quot;
</span><span class="cx"> #include &quot;JSObject.h&quot;
</span><ins>+#include &quot;RuntimeType.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -35,7 +36,9 @@
</span><span class="cx"> public:
</span><span class="cx">     typedef JSNonFinalObject Base;
</span><span class="cx"> 
</span><del>-    const static unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | TypeOfShouldCallGetCallData | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero;
</del><ins>+    // We lie an say we override getPropertyNames() because it prevents
+    // property name enumeration caching.
+    const static unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | TypeOfShouldCallGetCallData | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames;
</ins><span class="cx"> 
</span><span class="cx">     static ProxyObject* create(ExecState* exec, Structure* structure, JSValue target, JSValue handler)
</span><span class="cx">     {
</span><span class="lines">@@ -47,7 +50,11 @@
</span><span class="cx"> 
</span><span class="cx">     static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
</span><span class="cx">     {
</span><del>-        return Structure::create(vm, globalObject, prototype, TypeInfo(ProxyObjectType, StructureFlags), info(), NonArray | MayHaveIndexedAccessors);
</del><ins>+        Structure* result = Structure::create(vm, globalObject, prototype, TypeInfo(ProxyObjectType, StructureFlags), info(), NonArray | MayHaveIndexedAccessors);
+        result-&gt;setIsQuickPropertyAccessAllowedForEnumeration(false);
+        RELEASE_ASSERT(!result-&gt;canAccessPropertiesQuicklyForEnumeration());
+        RELEASE_ASSERT(!result-&gt;canCachePropertyNameEnumerator());
+        return result;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     DECLARE_EXPORT_INFO;
</span><span class="lines">@@ -72,6 +79,10 @@
</span><span class="cx">     static bool preventExtensions(JSObject*, ExecState*);
</span><span class="cx">     static bool isExtensible(JSObject*, ExecState*);
</span><span class="cx">     static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&amp;, bool shouldThrow);
</span><ins>+    static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
+    static NO_RETURN_DUE_TO_CRASH void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
+    static NO_RETURN_DUE_TO_CRASH void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
+    static NO_RETURN_DUE_TO_CRASH void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</ins><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="cx"> 
</span><span class="cx">     bool getOwnPropertySlotCommon(ExecState*, PropertyName, PropertySlot&amp;);
</span><span class="lines">@@ -84,6 +95,7 @@
</span><span class="cx">     bool performPreventExtensions(ExecState*);
</span><span class="cx">     bool performIsExtensible(ExecState*);
</span><span class="cx">     bool performDefineOwnProperty(ExecState*, PropertyName, const PropertyDescriptor&amp;, bool shouldThrow);
</span><ins>+    void performGetOwnPropertyNames(ExecState*, PropertyNameArray&amp;, EnumerationMode);
</ins><span class="cx"> 
</span><span class="cx">     WriteBarrier&lt;JSObject&gt; m_target;
</span><span class="cx">     WriteBarrier&lt;Unknown&gt; m_handler;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructurecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Structure.cpp (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Structure.cpp        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/Structure.cpp        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -201,7 +201,7 @@
</span><span class="cx">     setHasGetterSetterProperties(classInfo-&gt;hasStaticSetterOrReadonlyProperties());
</span><span class="cx">     setHasCustomGetterSetterProperties(false);
</span><span class="cx">     setHasReadOnlyOrGetterSetterPropertiesExcludingProto(classInfo-&gt;hasStaticSetterOrReadonlyProperties());
</span><del>-    setHasNonEnumerableProperties(false);
</del><ins>+    setIsQuickPropertyAccessAllowedForEnumeration(true);
</ins><span class="cx">     setAttributesInPrevious(0);
</span><span class="cx">     setDidPreventExtensions(false);
</span><span class="cx">     setDidTransition(false);
</span><span class="lines">@@ -233,7 +233,7 @@
</span><span class="cx">     setHasGetterSetterProperties(m_classInfo-&gt;hasStaticSetterOrReadonlyProperties());
</span><span class="cx">     setHasCustomGetterSetterProperties(false);
</span><span class="cx">     setHasReadOnlyOrGetterSetterPropertiesExcludingProto(m_classInfo-&gt;hasStaticSetterOrReadonlyProperties());
</span><del>-    setHasNonEnumerableProperties(false);
</del><ins>+    setIsQuickPropertyAccessAllowedForEnumeration(true);
</ins><span class="cx">     setAttributesInPrevious(0);
</span><span class="cx">     setDidPreventExtensions(false);
</span><span class="cx">     setDidTransition(false);
</span><span class="lines">@@ -264,7 +264,7 @@
</span><span class="cx">     setHasGetterSetterProperties(previous-&gt;hasGetterSetterProperties());
</span><span class="cx">     setHasCustomGetterSetterProperties(previous-&gt;hasCustomGetterSetterProperties());
</span><span class="cx">     setHasReadOnlyOrGetterSetterPropertiesExcludingProto(previous-&gt;hasReadOnlyOrGetterSetterPropertiesExcludingProto());
</span><del>-    setHasNonEnumerableProperties(previous-&gt;hasNonEnumerableProperties());
</del><ins>+    setIsQuickPropertyAccessAllowedForEnumeration(previous-&gt;isQuickPropertyAccessAllowedForEnumeration());
</ins><span class="cx">     setAttributesInPrevious(0);
</span><span class="cx">     setDidPreventExtensions(previous-&gt;didPreventExtensions());
</span><span class="cx">     setDidTransition(true);
</span><span class="lines">@@ -986,7 +986,7 @@
</span><span class="cx"> 
</span><span class="cx">     checkConsistency();
</span><span class="cx">     if (attributes &amp; DontEnum)
</span><del>-        setHasNonEnumerableProperties(true);
</del><ins>+        setIsQuickPropertyAccessAllowedForEnumeration(false);
</ins><span class="cx"> 
</span><span class="cx">     auto rep = propertyName.uid();
</span><span class="cx"> 
</span><span class="lines">@@ -1044,7 +1044,7 @@
</span><span class="cx"> 
</span><span class="cx">     PropertyTable::iterator end = propertyTable()-&gt;end();
</span><span class="cx">     for (PropertyTable::iterator iter = propertyTable()-&gt;begin(); iter != end; ++iter) {
</span><del>-        ASSERT(hasNonEnumerableProperties() || !(iter-&gt;attributes &amp; DontEnum));
</del><ins>+        ASSERT(!isQuickPropertyAccessAllowedForEnumeration() || !(iter-&gt;attributes &amp; DontEnum));
</ins><span class="cx">         if (!(iter-&gt;attributes &amp; DontEnum) || mode.includeDontEnumProperties()) {
</span><span class="cx">             if (iter-&gt;key-&gt;isSymbol() &amp;&amp; !propertyNames.includeSymbolProperties())
</span><span class="cx">                 continue;
</span><span class="lines">@@ -1311,7 +1311,7 @@
</span><span class="cx">     if (!propertyTable())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    if (!hasNonEnumerableProperties()) {
</del><ins>+    if (isQuickPropertyAccessAllowedForEnumeration()) {
</ins><span class="cx">         PropertyTable::iterator end = propertyTable()-&gt;end();
</span><span class="cx">         for (PropertyTable::iterator iter = propertyTable()-&gt;begin(); iter != end; ++iter) {
</span><span class="cx">             ASSERT(!(iter-&gt;attributes &amp; DontEnum));
</span><span class="lines">@@ -1381,9 +1381,9 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx">     
</span><del>-bool Structure::canAccessPropertiesQuickly() const
</del><ins>+bool Structure::canAccessPropertiesQuicklyForEnumeration() const
</ins><span class="cx"> {
</span><del>-    if (hasNonEnumerableProperties())
</del><ins>+    if (!isQuickPropertyAccessAllowedForEnumeration())
</ins><span class="cx">         return false;
</span><span class="cx">     if (hasGetterSetterProperties())
</span><span class="cx">         return false;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Structure.h (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Structure.h        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/Structure.h        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -377,7 +377,7 @@
</span><span class="cx">     void setCachedPropertyNameEnumerator(VM&amp;, JSPropertyNameEnumerator*);
</span><span class="cx">     JSPropertyNameEnumerator* cachedPropertyNameEnumerator() const;
</span><span class="cx">     bool canCachePropertyNameEnumerator() const;
</span><del>-    bool canAccessPropertiesQuickly() const;
</del><ins>+    bool canAccessPropertiesQuicklyForEnumeration() const;
</ins><span class="cx"> 
</span><span class="cx">     void getPropertyNamesFromStructure(VM&amp;, PropertyNameArray&amp;, EnumerationMode);
</span><span class="cx"> 
</span><span class="lines">@@ -577,7 +577,7 @@
</span><span class="cx">     DEFINE_BITFIELD(bool, isPinnedPropertyTable, IsPinnedPropertyTable, 1, 2);
</span><span class="cx">     DEFINE_BITFIELD(bool, hasGetterSetterProperties, HasGetterSetterProperties, 1, 3);
</span><span class="cx">     DEFINE_BITFIELD(bool, hasReadOnlyOrGetterSetterPropertiesExcludingProto, HasReadOnlyOrGetterSetterPropertiesExcludingProto, 1, 4);
</span><del>-    DEFINE_BITFIELD(bool, hasNonEnumerableProperties, HasNonEnumerableProperties, 1, 5);
</del><ins>+    DEFINE_BITFIELD(bool, isQuickPropertyAccessAllowedForEnumeration, IsQuickPropertyAccessAllowedForEnumeration, 1, 5);
</ins><span class="cx">     DEFINE_BITFIELD(unsigned, attributesInPrevious, AttributesInPrevious, 14, 6);
</span><span class="cx">     DEFINE_BITFIELD(bool, didPreventExtensions, DidPreventExtensions, 1, 20);
</span><span class="cx">     DEFINE_BITFIELD(bool, didTransition, DidTransition, 1, 21);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeWeakMapConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/WeakMapConstructor.cpp (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/WeakMapConstructor.cpp        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/runtime/WeakMapConstructor.cpp        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -106,13 +106,13 @@
</span><span class="cx">             return JSValue::encode(jsUndefined());
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        JSValue key = nextItem.get(exec, 0);
</del><ins>+        JSValue key = nextItem.get(exec, static_cast&lt;unsigned&gt;(0));
</ins><span class="cx">         if (exec-&gt;hadException()) {
</span><span class="cx">             iteratorClose(exec, iterator);
</span><span class="cx">             return JSValue::encode(jsUndefined());
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        JSValue value = nextItem.get(exec, 1);
</del><ins>+        JSValue value = nextItem.get(exec, static_cast&lt;unsigned&gt;(1));
</ins><span class="cx">         if (exec-&gt;hadException()) {
</span><span class="cx">             iteratorClose(exec, iterator);
</span><span class="cx">             return JSValue::encode(jsUndefined());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestses6yaml"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/es6.yaml (197538 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/es6.yaml        2016-03-04 01:58:34 UTC (rev 197538)
+++ trunk/Source/JavaScriptCore/tests/es6.yaml        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -935,7 +935,7 @@
</span><span class="cx"> - path: es6/Proxy_internal_defineProperty_calls_[[Set]].js
</span><span class="cx">   cmd: runES6 :fail
</span><span class="cx"> - path: es6/Proxy_internal_defineProperty_calls_SetIntegrityLevel.js
</span><del>-  cmd: runES6 :fail
</del><ins>+  cmd: runES6 :normal
</ins><span class="cx"> - path: es6/Proxy_internal_deleteProperty_calls_Array.prototype.copyWithin.js
</span><span class="cx">   cmd: runES6 :normal
</span><span class="cx"> - path: es6/Proxy_internal_deleteProperty_calls_Array.prototype.pop.js
</span><span class="lines">@@ -985,9 +985,9 @@
</span><span class="cx"> - path: es6/Proxy_internal_get_calls_JSON.stringify.js
</span><span class="cx">   cmd: runES6 :fail
</span><span class="cx"> - path: es6/Proxy_internal_get_calls_Object.assign.js
</span><del>-  cmd: runES6 :fail
</del><ins>+  cmd: runES6 :normal
</ins><span class="cx"> - path: es6/Proxy_internal_get_calls_Object.defineProperties.js
</span><del>-  cmd: runES6 :fail
</del><ins>+  cmd: runES6 :normal
</ins><span class="cx"> - path: es6/Proxy_internal_get_calls_Promise_resolve_functions.js
</span><span class="cx">   cmd: runES6 :normal
</span><span class="cx"> - path: es6/Proxy_internal_get_calls_RegExp.prototype.flags.js
</span><span class="lines">@@ -1027,11 +1027,11 @@
</span><span class="cx"> - path: es6/Proxy_internal_getOwnPropertyDescriptor_calls_Object.prototype.hasOwnProperty.js
</span><span class="cx">   cmd: runES6 :normal
</span><span class="cx"> - path: es6/Proxy_internal_ownKeys_calls_SerializeJSONObject.js
</span><del>-  cmd: runES6 :fail
</del><ins>+  cmd: runES6 :normal
</ins><span class="cx"> - path: es6/Proxy_internal_ownKeys_calls_SetIntegrityLevel.js
</span><del>-  cmd: runES6 :fail
</del><ins>+  cmd: runES6 :normal
</ins><span class="cx"> - path: es6/Proxy_internal_ownKeys_calls_TestIntegrityLevel.js
</span><del>-  cmd: runES6 :fail
</del><ins>+  cmd: runES6 :normal
</ins><span class="cx"> - path: es6/Proxy_internal_set_calls_Array.from.js
</span><span class="cx">   cmd: runES6 :normal
</span><span class="cx"> - path: es6/Proxy_internal_set_calls_Array.of.js
</span><span class="lines">@@ -1059,7 +1059,7 @@
</span><span class="cx"> - path: es6/Proxy_JSON.stringify_support.js
</span><span class="cx">   cmd: runES6 :fail
</span><span class="cx"> - path: es6/Proxy_ownKeys_handler.js
</span><del>-  cmd: runES6 :fail
</del><ins>+  cmd: runES6 :normal
</ins><span class="cx"> - path: es6/Proxy_preventExtensions_handler.js
</span><span class="cx">   cmd: runES6 :normal
</span><span class="cx"> - path: es6/Proxy_Proxy.revocable.js
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressproxyownkeysjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/proxy-own-keys.js (0 => 197539)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/proxy-own-keys.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/proxy-own-keys.js        2016-03-04 02:25:30 UTC (rev 197539)
</span><span class="lines">@@ -0,0 +1,560 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad assertion.&quot;);
+}
+
+{
+    let error = null;
+    let target = { };
+    let handler = {
+        ownKeys: function() {
+            error = new Error;
+            throw error;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let threw = false;
+        try {
+            Object.keys(proxy);
+        } catch(e) {
+            threw = true;
+            assert(e === error);
+        }
+        assert(threw);
+    }
+}
+
+{
+    let error = null;
+    let target = { };
+    let handler = {
+        get ownKeys() {
+            error = new Error;
+            throw error;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let threw = false;
+        try {
+            Object.keys(proxy);
+        } catch(e) {
+            threw = true;
+            assert(e === error);
+        }
+        assert(threw);
+    }
+}
+
+{
+    let target = {
+        x: 40
+    };
+    let called = false;
+    let handler = {
+        ownKeys: function(theTarget) {
+            called = true;
+            return [&quot;1&quot;, 2, 3];
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let threw = false;
+        try {
+            Object.keys(proxy);
+        } catch(e) {
+            threw = true;
+            assert(e.toString() === &quot;TypeError: Proxy handler's 'ownKeys' method must return a array-like object containing only Strings and Symbols.&quot;);
+        }
+        assert(threw);
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = { };
+    Object.defineProperty(target, &quot;x&quot;, {
+        configurable: false,
+        enumerable: true,
+        value: 400
+    });
+    let called = false;
+    let handler = {
+        ownKeys: function(theTarget) {
+            called = true;
+            return [];
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let threw = false;
+        try {
+            Object.keys(proxy);
+        } catch(e) {
+            threw = true;
+            assert(e.toString() === &quot;TypeError: Proxy object's 'target' has the non-configurable property 'x' that was not in the result from the 'ownKeys' trap.&quot;);
+        }
+        assert(threw);
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = { };
+    Object.defineProperty(target, &quot;x&quot;, {
+        configurable: true,
+        enumerable: true,
+        value: 400
+    });
+    Object.preventExtensions(target);
+    let called = false;
+    let handler = {
+        ownKeys: function(theTarget) {
+            called = true;
+            return [];
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let threw = false;
+        try {
+            Object.keys(proxy);
+        } catch(e) {
+            threw = true;
+            assert(e.toString() === &quot;TypeError: Proxy object's non-extensible 'target' has configurable property 'x' that was not in the result from the 'ownKeys' trap.&quot;);
+        }
+        assert(threw);
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = { };
+    Object.defineProperty(target, &quot;x&quot;, {
+        configurable: true,
+        enumerable: true,
+        value: 400
+    });
+    Object.preventExtensions(target);
+    let called = false;
+    let handler = {
+        ownKeys: function(theTarget) {
+            called = true;
+            return [&quot;x&quot;, &quot;y&quot;];
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let threw = false;
+        try {
+            Object.keys(proxy);
+        } catch(e) {
+            threw = true;
+            assert(e.toString() === &quot;TypeError: Proxy handler's 'ownKeys' method returned a key that was not present in its target or it returned duplicate keys.&quot;);
+        }
+        assert(threw);
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = { };
+    Object.defineProperty(target, &quot;x&quot;, {
+        configurable: true,
+        enumerable: true,
+        value: 400
+    });
+    Object.preventExtensions(target);
+    let called = false;
+    let handler = {
+        ownKeys: function(theTarget) {
+            called = true;
+            return [&quot;x&quot;, &quot;x&quot;];
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let threw = false;
+        try {
+            Object.keys(proxy);
+        } catch(e) {
+            threw = true;
+            assert(e.toString() === &quot;TypeError: Proxy handler's 'ownKeys' method returned a key that was not present in its target or it returned duplicate keys.&quot;);
+        }
+        assert(threw);
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = { };
+    let handler = {
+        ownKeys: 45
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let threw = false;
+        try {
+            Object.keys(proxy);
+        } catch(e) {
+            threw = true;
+            assert(e.toString() === &quot;TypeError: 'ownKeys' property of a Proxy's handler should be callable.&quot;);
+        }
+        assert(threw);
+    }
+}
+
+function shallowEq(a, b) {
+    if (a.length !== b.length)
+        return false;
+    for (let i = 0; i &lt; a.length; i++) {
+        if (a[i] !== b[i])
+            return false;
+    }
+
+    return true;
+}
+
+{
+    let target = {
+        x: 40
+    };
+    let called = false;
+    let arr = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];
+    let handler = {
+        ownKeys: function(theTarget) {
+            called = true;
+            return arr;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let result = Object.keys(proxy);
+        assert(result !== arr);
+        assert(shallowEq(result, arr));
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = {
+        x: 40
+    };
+    let called = false;
+    let arr = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];
+    let handler = {
+        ownKeys: function(theTarget) {
+            called = true;
+            return arr;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let result = Reflect.ownKeys(proxy);
+        assert(result !== arr);
+        assert(shallowEq(result, arr));
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = {
+        x: 40
+    };
+    let called = false;
+    let s1 = Symbol();
+    let s2 = Symbol();
+    let arr = [&quot;a&quot;, &quot;b&quot;, s1, &quot;c&quot;, s2];
+    let handler = {
+        ownKeys: function(theTarget) {
+            called = true;
+            return arr;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let result = Object.getOwnPropertySymbols(proxy);
+        assert(shallowEq(result, [s1, s2]));
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = {
+        x: 40
+    };
+    let called = false;
+    let s1 = Symbol();
+    let s2 = Symbol();
+    let arr = [&quot;a&quot;, &quot;b&quot;, s1, &quot;c&quot;, s2];
+    let handler = {
+        ownKeys: function(theTarget) {
+            called = true;
+            return arr;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let result = Object.keys(proxy);
+        assert(shallowEq(result, [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]));
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = {
+        x: 40
+    };
+    let called = false;
+    let s1 = Symbol();
+    let s2 = Symbol();
+    let arr = [&quot;a&quot;, &quot;b&quot;, s1, &quot;c&quot;, s2];
+    let handler = {
+        ownKeys: function(theTarget) {
+            called = true;
+            return arr;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let result = Reflect.ownKeys(proxy);
+        assert(shallowEq(result, [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, s1, s2]));
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = {
+        x: 40
+    };
+    let called = false;
+    let s1 = Symbol();
+    let s2 = Symbol();
+    let arr = [&quot;a&quot;, &quot;b&quot;, s1, &quot;c&quot;, s2];
+    let handler = {
+        getOwnPropertyDescriptor: () =&gt; {
+            return { enumerable: true, configurable: true }
+        },
+        ownKeys: function(theTarget) {
+            called = true;
+            return arr;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let set = new Set;
+        for (let p in proxy)
+            set.add(p);
+        assert(set.size === 3);
+        assert(set.has(&quot;a&quot;));
+        assert(set.has(&quot;b&quot;));
+        assert(set.has(&quot;c&quot;));
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = {
+        x: 40
+    };
+    let called = false;
+    let s1 = Symbol();
+    let s2 = Symbol();
+    let arr = [&quot;a&quot;, &quot;b&quot;, s1, &quot;c&quot;, s2];
+    let handler = {
+        getOwnPropertyDescriptor: () =&gt; {
+            return { enumerable: true, configurable: true }
+        },
+        ownKeys: function(theTarget) {
+            called = true;
+            return arr;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let set = new Set;
+        for (let p in proxy)
+            set.add(p);
+        if (i === 40) { // Make sure we don't cache the result.
+            arr.push(&quot;d&quot;);
+        }
+        assert(set.size === i &gt; 40 ? 4 : 3);
+        assert(set.has(&quot;a&quot;));
+        assert(set.has(&quot;b&quot;));
+        assert(set.has(&quot;c&quot;));
+        if (i &gt; 40)
+            assert(set.has(&quot;d&quot;));
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = {
+        x: 40
+    };
+    let called = false;
+    let s1 = Symbol();
+    let s2 = Symbol();
+    let arr = [&quot;a&quot;, &quot;b&quot;, s1, &quot;c&quot;, s2];
+    let handler = {
+        getOwnPropertyDescriptor: () =&gt; {
+            return { enumerable: true, configurable: true }
+        },
+        ownKeys: function(theTarget) {
+            called = true;
+            return arr;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    let proxyish = Object.create(proxy, {
+        d: { enumerable: true, configurable: true }
+    });
+    for (let i = 0; i &lt; 500; i++) {
+        let set = new Set;
+        for (let p in proxyish)
+            set.add(p);
+        assert(set.size === 4);
+        assert(set.has(&quot;a&quot;));
+        assert(set.has(&quot;b&quot;));
+        assert(set.has(&quot;c&quot;));
+        assert(set.has(&quot;d&quot;));
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let target = {
+        x: 40
+    };
+    let called = false;
+    let s1 = Symbol();
+    let s2 = Symbol();
+    let arr = [&quot;a&quot;, &quot;b&quot;, s1, &quot;c&quot;, s2];
+    let handler = {
+        getOwnPropertyDescriptor: () =&gt; {
+            return { enumerable: true, configurable: true }
+        },
+        ownKeys: function(theTarget) {
+            called = true;
+            return arr;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    let proxyish = Object.create(proxy, {
+        d: { enumerable: true, configurable: true }
+    });
+    for (let i = 0; i &lt; 500; i++) {
+        let set = new Set;
+        for (let p in proxyish)
+            set.add(p);
+        assert(set.size === 4);
+        assert(set.has(&quot;a&quot;));
+        assert(set.has(&quot;b&quot;));
+        assert(set.has(&quot;c&quot;));
+        assert(set.has(&quot;d&quot;));
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let called = false;
+    let target = {x: 20, y: 40};
+    let handler = {
+        ownKeys: null
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let keys = Object.keys(proxy);
+        assert(keys.indexOf(&quot;x&quot;) !== -1);
+        assert(keys.indexOf(&quot;y&quot;) !== -1);
+    }
+}
+
+{
+    let called = false;
+    let target = new Proxy({}, {
+        ownKeys: function(theTarget) {
+            called = true;
+            return Reflect.ownKeys(theTarget);
+        }
+    });
+    let s1 = Symbol();
+    let s2 = Symbol();
+    let arr = [&quot;a&quot;, &quot;b&quot;, s1, &quot;c&quot;, s2];
+    let handler = {
+        ownKeys: function(theTarget) {
+            return arr;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let keys = Object.keys(proxy);
+        assert(called);
+        called = false;
+    }
+}
+
+{
+    let error = null;
+    let target = new Proxy({}, {
+        ownKeys: function(theTarget) {
+            error = new Error;
+            throw error;
+        }
+    });
+    let s1 = Symbol();
+    let s2 = Symbol();
+    let arr = [&quot;a&quot;, &quot;b&quot;, s1, &quot;c&quot;, s2];
+    let handler = {
+        ownKeys: function(theTarget) {
+            return arr;
+        }
+    };
+
+    let proxy = new Proxy(target, handler);
+    for (let i = 0; i &lt; 500; i++) {
+        let threw = false;
+        try {
+            Object.keys(proxy);
+        } catch(e) {
+            threw = true;
+            assert(e === error);
+        }
+        assert(threw);
+        error = null;
+    }
+}
</ins></span></pre>
</div>
</div>

</body>
</html>