Implement the core of Proxy object (#3562)

- Internal routines of the of the proxy object are unimplemented
 - For-in enumerate with proxy target is currently not supported

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
Robert Fancsik
2020-02-28 14:41:59 +01:00
committed by GitHub
parent 9b393ee2ea
commit 4e136c8973
57 changed files with 3017 additions and 397 deletions
+40
View File
@@ -0,0 +1,40 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = function () {};
var handler = { apply (target) {
throw 42;
}};
var proxy = new Proxy(target, handler);
try {
// opfunc_call
proxy(5)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
var revocable = Proxy.revokable(function() {}, {});
proxy = new Proxy(revocable.proxy, {})
revocable.revoke();
proxy(5)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
+38
View File
@@ -0,0 +1,38 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = function () {};
var handler = { construct (target) {
throw 42;
}};
var proxy = new Proxy(target, handler);
try {
// opfunc_call
new proxy(5)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 22.1.2.3.4.a
Array.of.call(proxy);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
+65
View File
@@ -0,0 +1,65 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = {}
var handler = {};
var proxy = new Proxy(target, handler);
var revocable = Proxy.revocable(target, handler);
revocable.revoke();
var rev_proxy = revocable.proxy;
try {
Proxy(target, handler);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
proxy.a;
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
new Proxy(undefined, undefined);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
new Proxy(rev_proxy);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
new Proxy({}, rev_proxy);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
new Proxy(rev_proxy, {});
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
@@ -0,0 +1,32 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = function () {};
var handler = { defineProperty (target) {
throw 42;
}, construct () {
return {};
}};
var proxy = new Proxy(target, handler);
try {
// 22.1.2.3.8.c
Array.of.call(proxy, 5)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
+46
View File
@@ -0,0 +1,46 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = {};
var handler = { deleteProperty (target) {
throw 42;
}, get (object, propName) {
if (propName == "length") {
return 5;
}
}};
var proxy = new Proxy(target, handler);
var a = 5;
try {
// ecma_op_delete_binding
with (proxy) {
delete a
}
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 22.1.3.16.6.e
Array.prototype.pop.call(proxy)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
+46
View File
@@ -0,0 +1,46 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = {};
var handler = { get (target) {
throw 42;
}};
var proxy = new Proxy(target, handler);
try {
// vm_op_get_value
proxy.a
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// ecma_op_get_value_object_base
proxy[2];
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// @@toPrimitive symbol
proxy + "foo";
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
@@ -0,0 +1,80 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = {};
var handler = { getOwnPropertyDescriptor (target) {
throw 42;
}};
var proxy = new Proxy(target, handler);
try {
// 19.1.3.2.5
Object.prototype.hasOwnProperty.call(proxy);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 19.1.3.4
Object.prototype.propertyIsEnumerable.call(proxy)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 19.1.2.1.5.b.iii
Object.assign({}, proxy)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 19.1.2.6.5
Object.getOwnPropertyDescriptor(proxy)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
/* TODO: enable these test when Proxy.[[isExtensible]] has been implemted
try {
// 19.1.2.5.2.9.a.i
Object.freeze(proxy)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 19.1.2.12.2.7
Object.isFrozen(proxy)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 19.1.2.13.2.7
Object.isSealed(proxy)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
*/
@@ -0,0 +1,70 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = {};
var handler = { getPrototypeOf (target) {
throw 42;
}};
var proxy = new Proxy(target, handler);
try {
// 19.1.2.9.2
Object.getPrototypeOf(proxy);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 19.1.3.3
Object.prototype.isPrototypeOf(proxy);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
(function () {
class e extends Array {};
function f () {};
function g () {};
Object.setPrototypeOf(g, proxy);
// 7.3.19.7.b
try {
g instanceof f;
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
// ecma_op_implicit_class_constructor_has_instance [[GetPrototypeOf]]
try {
g instanceof e;
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
})();
try {
// 9.4.1.3.3
Function.prototype.bind.call(proxy);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
+52
View File
@@ -0,0 +1,52 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = {};
var handler = { has (target) {
throw 42;
}};
var proxy = new Proxy(target, handler);
try {
// 12.9.3
"foo" in proxy;
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 8.1.1.2.1
with (proxy) {
p;
assert(false);
}
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// ecma_op_put_value_lex_env_base/[[HasProperty]]
with (proxy) {
function a (){}
assert(false);
}
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
+46
View File
@@ -0,0 +1,46 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = {};
var handler = { isExtensible (target) {
throw 42;
}};
var proxy = new Proxy(target, handler);
try {
// 7.3.15
Object.isFrozen(proxy)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 7.3.15
Object.isSealed(proxy)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 7.2.5
Object.isExtensible(proxy)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
+54
View File
@@ -0,0 +1,54 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = {};
var handler = { ownKeys (target) {
throw 42;
}};
var proxy = new Proxy(target, handler);
try {
// Array.prototype.sort
Array.prototype.sort.call(proxy);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 19.1.2.14.4
Object.keys(proxy);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 19.1.2.7.1
Object.getOwnPropertyNames(proxy);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 19.1.2.8.1
Object.getOwnPropertySymbols(proxy);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
@@ -0,0 +1,39 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = {};
var handler = { preventExtensions (target) {
throw 42;
}};
var proxy = new Proxy(target, handler);
try {
// 7.3.14
Object.freeze(proxy)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 7.3.14
Object.seal(proxy)
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
+69
View File
@@ -0,0 +1,69 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = function () {};
var handler = { get (name) {
return 5;
}};
var revocable = Proxy.revocable(target, handler);
var proxy = revocable.proxy;
try {
proxy.a; // FIXME: this should return 5 when proxy.[[Get]] has been implemted
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
revocable.revoke();
try {
proxy.a;
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
Proxy.revocable();
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
Proxy.revocable(proxy);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
Proxy.revocable({}, proxy);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
Proxy.revocable(proxy, {});
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
+38
View File
@@ -0,0 +1,38 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = {};
var handler = { set (target) {
throw 42;
}};
var proxy = new Proxy(target, handler);
try {
// vm_op_set_value
proxy.a = 5
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
try {
// 22.1.3.6.11.b
Array.prototype.fill.call(proxy, 'foo', 0, 5);
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
@@ -0,0 +1,30 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// TODO: Update these tests when the internal routine has been implemented
var target = {};
var handler = { setPrototypeOf (target) {
throw 42;
}};
var proxy = new Proxy(target, handler);
try {
// 19.1.2.18
Object.setPrototypeOf(proxy, {});
assert(false);
} catch (e) {
assert(e instanceof TypeError);
}
+17 -2
View File
@@ -64,10 +64,25 @@ main (void)
TEST_ASSERT (jerry_value_is_undefined (prop_desc.getter));
TEST_ASSERT (prop_desc.is_set_defined == false);
TEST_ASSERT (jerry_value_is_undefined (prop_desc.setter));
jerry_release_value (prop_name);
jerry_release_value (global_obj_val);
jerry_free_property_descriptor_fields (&prop_desc);
jerry_release_value (global_obj_val);
if (jerry_is_feature_enabled (JERRY_FEATURE_PROXY))
{
/* Note: update this test when the internal method is implemented */
jerry_value_t target = jerry_create_object ();
jerry_value_t handler = jerry_create_object ();
jerry_value_t proxy = jerry_create_proxy (target, handler);
jerry_release_value (target);
jerry_release_value (handler);
is_ok = jerry_get_own_property_descriptor (proxy, prop_name, &prop_desc);
TEST_ASSERT (!is_ok);
jerry_release_value (proxy);
}
jerry_release_value (prop_name);
jerry_cleanup ();
return 0;
+36
View File
@@ -695,6 +695,23 @@ main (void)
jerry_release_value (proto_val);
jerry_release_value (obj_val);
if (jerry_is_feature_enabled (JERRY_FEATURE_PROXY))
{
/* Note: update this test when the internal method is implemented */
jerry_value_t target = jerry_create_object ();
jerry_value_t handler = jerry_create_object ();
jerry_value_t proxy = jerry_create_proxy (target, handler);
jerry_release_value (target);
jerry_release_value (handler);
proto_val = jerry_get_prototype (proxy);
TEST_ASSERT (jerry_value_is_error (proto_val));
error = jerry_get_value_from_error (proto_val, true);
TEST_ASSERT (jerry_get_error_type (error) == JERRY_ERROR_TYPE);
jerry_release_value (error);
jerry_release_value (proxy);
}
/* Test: jerry_set_prototype */
obj_val = jerry_create_object ();
res = jerry_set_prototype (obj_val, jerry_create_null ());
@@ -714,6 +731,25 @@ main (void)
jerry_release_value (proto_val);
jerry_release_value (obj_val);
if (jerry_is_feature_enabled (JERRY_FEATURE_PROXY))
{
/* Note: update this test when the internal method is implemented */
jerry_value_t target = jerry_create_object ();
jerry_value_t handler = jerry_create_object ();
jerry_value_t proxy = jerry_create_proxy (target, handler);
jerry_release_value (target);
jerry_release_value (handler);
new_proto = jerry_create_object ();
res = jerry_set_prototype (proxy, new_proto);
jerry_release_value (new_proto);
TEST_ASSERT (jerry_value_is_error (res));
error = jerry_get_value_from_error (res, true);
TEST_ASSERT (jerry_get_error_type (error) == JERRY_ERROR_TYPE);
jerry_release_value (error);
jerry_release_value (proxy);
}
/* Test: eval */
const jerry_char_t eval_code_src1[] = "(function () { return 123; })";
val_t = jerry_eval (eval_code_src1, sizeof (eval_code_src1) - 1, JERRY_PARSE_STRICT_MODE);