mirror of
https://github.com/openharmony/ark_js_runtime.git
synced 2026-07-21 23:25:24 -04:00
7ffcc4b20f
Signed-off-by: zhangyukun <zhangyukun8@huawei.com>
639 lines
30 KiB
C++
639 lines
30 KiB
C++
/*
|
|
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
|
* 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.
|
|
*/
|
|
|
|
#include "ecmascript/base/builtins_base.h"
|
|
#include "ecmascript/ecma_runtime_call_info.h"
|
|
#include "ecmascript/ecma_string.h"
|
|
#include "ecmascript/ecma_vm.h"
|
|
#include "ecmascript/global_env.h"
|
|
#include "ecmascript/js_function.h"
|
|
#include "ecmascript/js_handle.h"
|
|
#include "ecmascript/js_hclass.h"
|
|
#include "ecmascript/js_proxy.h"
|
|
#include "ecmascript/js_tagged_value-inl.h"
|
|
#include "ecmascript/object_factory.h"
|
|
#include "ecmascript/tests/test_helper.h"
|
|
|
|
using namespace panda::ecmascript;
|
|
using namespace panda::ecmascript::base;
|
|
|
|
namespace panda::test {
|
|
class JSProxyTest : public testing::Test {
|
|
public:
|
|
static void SetUpTestCase()
|
|
{
|
|
GTEST_LOG_(INFO) << "SetUpTestCase";
|
|
}
|
|
|
|
static void TearDownTestCase()
|
|
{
|
|
GTEST_LOG_(INFO) << "TearDownCase";
|
|
}
|
|
|
|
void SetUp() override
|
|
{
|
|
TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
|
|
}
|
|
|
|
void TearDown() override
|
|
{
|
|
TestHelper::DestroyEcmaVMWithScope(instance, scope);
|
|
}
|
|
|
|
PandaVM *instance {nullptr};
|
|
ecmascript::EcmaHandleScope *scope {nullptr};
|
|
JSThread *thread {nullptr};
|
|
};
|
|
|
|
static JSFunction *JSObjectTestCreate(JSThread *thread)
|
|
{
|
|
EcmaVM *ecmaVM = thread->GetEcmaVM();
|
|
JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
|
|
return globalEnv->GetObjectFunction().GetObject<JSFunction>();
|
|
}
|
|
|
|
HWTEST_F_L0(JSProxyTest, ProxyCreate)
|
|
{
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> targetHandle(
|
|
thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(dynclass), dynclass));
|
|
|
|
JSHandle<JSTaggedValue> key(thread->GetEcmaVM()->GetFactory()->NewFromCanBeCompressString("x"));
|
|
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
|
|
JSObject::SetProperty(thread, targetHandle, key, value);
|
|
EXPECT_EQ(JSObject::GetProperty(thread, targetHandle, key).GetValue()->GetInt(), 1);
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(
|
|
thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
|
|
EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle, key).GetValue()->GetInt(), 1);
|
|
PropertyDescriptor desc(thread);
|
|
JSProxy::GetOwnProperty(thread, proxyHandle, key, desc);
|
|
EXPECT_EQ(desc.GetValue()->GetInt(), 1);
|
|
}
|
|
|
|
// ES6 9.5.8 [[Get]] (P, Receiver)
|
|
// Called by the following function
|
|
JSTaggedValue HandlerGetProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
return JSTaggedValue(10); // 10 : test case
|
|
}
|
|
|
|
HWTEST_F_L0(JSProxyTest, GetProperty)
|
|
{
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
// 1. handler has no "get"
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(targetHandle->IsECMAObject());
|
|
|
|
JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("x"));
|
|
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
|
|
JSObject::SetProperty(thread, targetHandle, key, value);
|
|
EXPECT_EQ(JSObject::GetProperty(thread, targetHandle, key).GetValue()->GetInt(), 1);
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
|
|
EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle, key).GetValue()->GetInt(), 1);
|
|
|
|
// 2. handler has "get"
|
|
EcmaVM *vm = thread->GetEcmaVM();
|
|
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
|
|
JSHandle<JSTaggedValue> getKey = thread->GlobalConstants()->GetHandledGetString();
|
|
JSHandle<JSTaggedValue> getHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerGetProperty)));
|
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), getKey, getHandle);
|
|
|
|
JSHandle<JSProxy> proxyHandle2(JSProxy::ProxyCreate(thread, targetHandle, handlerHandle));
|
|
EXPECT_TRUE(*proxyHandle2 != nullptr);
|
|
JSHandle<JSTaggedValue> key2(factory->NewFromCanBeCompressString("y"));
|
|
EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle2, key2).GetValue()->GetInt(), 10);
|
|
}
|
|
|
|
// ES6 9.5.5 [[GetOwnProperty]] (P)
|
|
// Called by the following function
|
|
JSTaggedValue HandlerGetOwnProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
return JSTaggedValue(JSTaggedValue::Undefined());
|
|
}
|
|
|
|
HWTEST_F_L0(JSProxyTest, GetOwnProperty)
|
|
{
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
// 1. handler has no "get"
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(targetHandle->IsECMAObject());
|
|
|
|
JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("x"));
|
|
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
|
|
JSObject::SetProperty(thread, targetHandle, key, value);
|
|
EXPECT_EQ(JSObject::GetProperty(thread, targetHandle, key).GetValue()->GetInt(), 1);
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
|
|
PropertyDescriptor desc(thread);
|
|
JSProxy::GetOwnProperty(thread, proxyHandle, key, desc);
|
|
EXPECT_EQ(desc.GetValue()->GetInt(), 1);
|
|
|
|
// 2. handler has "get"
|
|
EcmaVM *vm = thread->GetEcmaVM();
|
|
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
|
|
JSHandle<JSTaggedValue> defineKey = thread->GlobalConstants()->GetHandledGetOwnPropertyDescriptorString();
|
|
JSHandle<JSTaggedValue> defineHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerGetOwnProperty)));
|
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), defineKey, defineHandle);
|
|
|
|
JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle2 != nullptr);
|
|
JSHandle<JSTaggedValue> key2(factory->NewFromCanBeCompressString("y"));
|
|
PropertyDescriptor desc2(thread);
|
|
EXPECT_FALSE(JSProxy::GetOwnProperty(thread, proxyHandle2, key2, desc2));
|
|
}
|
|
|
|
// ES6 9.5.9 [[Set]] ( P, V, Receiver)
|
|
JSTaggedValue HandlerSetProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
return JSTaggedValue(JSTaggedValue::False());
|
|
}
|
|
|
|
HWTEST_F_L0(JSProxyTest, SetProperty)
|
|
{
|
|
// 1. handler has no "get"
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
// 1. handler has no "get"
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(targetHandle->IsECMAObject());
|
|
|
|
JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("x"));
|
|
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
|
|
EXPECT_TRUE(JSProxy::SetProperty(thread, proxyHandle, key, value));
|
|
EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle, key).GetValue()->GetInt(), 1);
|
|
EXPECT_EQ(JSObject::GetProperty(thread, targetHandle, key).GetValue()->GetInt(), 1);
|
|
|
|
// 2. handler has "set"
|
|
EcmaVM *vm = thread->GetEcmaVM();
|
|
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
|
|
JSHandle<JSTaggedValue> setKey = thread->GlobalConstants()->GetHandledSetString();
|
|
JSHandle<JSTaggedValue> setHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerSetProperty)));
|
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), setKey, setHandle);
|
|
|
|
JSHandle<JSProxy> proxyHandle2(JSProxy::ProxyCreate(thread, targetHandle, handlerHandle));
|
|
EXPECT_TRUE(*proxyHandle2 != nullptr);
|
|
JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(10));
|
|
EXPECT_FALSE(JSProxy::SetProperty(thread, proxyHandle2, key, value2));
|
|
EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle2, key).GetValue()->GetInt(), 1);
|
|
}
|
|
|
|
// ES6 9.5.6 [[DefineOwnProperty]] (P, Desc)
|
|
JSTaggedValue HandlerDefineOwnProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
return JSTaggedValue(JSTaggedValue::False());
|
|
}
|
|
|
|
HWTEST_F_L0(JSProxyTest, DefineOwnProperty)
|
|
{
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
// 1. handler has no "defineProperty"
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(targetHandle->IsECMAObject());
|
|
|
|
JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("x"));
|
|
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
|
|
PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
|
|
EXPECT_TRUE(JSProxy::DefineOwnProperty(thread, proxyHandle, key, desc));
|
|
EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle, key).GetValue()->GetInt(), 1);
|
|
EXPECT_EQ(JSObject::GetProperty(thread, targetHandle, key).GetValue()->GetInt(), 1);
|
|
|
|
// 2. handler has "defineProperty"
|
|
EcmaVM *vm = thread->GetEcmaVM();
|
|
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
|
|
JSHandle<JSTaggedValue> setKey = thread->GlobalConstants()->GetHandledDefinePropertyString();
|
|
JSHandle<JSTaggedValue> setHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerDefineOwnProperty)));
|
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), setKey, setHandle);
|
|
|
|
JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle2 != nullptr);
|
|
PropertyDescriptor desc2(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(10)));
|
|
EXPECT_FALSE(JSProxy::DefineOwnProperty(thread, proxyHandle, key, desc2));
|
|
EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle2, key).GetValue()->GetInt(), 1);
|
|
}
|
|
|
|
JSTaggedValue HandlerDeleteProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
return JSTaggedValue(JSTaggedValue::False());
|
|
}
|
|
|
|
// ES6 9.5.10 [[Delete]] (P)
|
|
HWTEST_F_L0(JSProxyTest, DeleteProperty)
|
|
{
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
// 1. handler has no "deleteProperty"
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(targetHandle->IsECMAObject());
|
|
|
|
JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("x"));
|
|
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
|
|
PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), true, true, true);
|
|
EXPECT_TRUE(JSProxy::DefineOwnProperty(thread, proxyHandle, key, desc));
|
|
EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle, key).GetValue()->GetInt(), 1);
|
|
EXPECT_EQ(JSObject::GetProperty(thread, targetHandle, key).GetValue()->GetInt(), 1);
|
|
EXPECT_TRUE(JSProxy::DeleteProperty(thread, proxyHandle, key));
|
|
PropertyDescriptor resDesc(thread);
|
|
JSProxy::GetOwnProperty(thread, proxyHandle, key, resDesc);
|
|
EXPECT_TRUE(JSTaggedValue::SameValue(resDesc.GetValue().GetTaggedValue(), JSTaggedValue::Undefined()));
|
|
|
|
// 2. handler has "deleteProperty"
|
|
EcmaVM *vm = thread->GetEcmaVM();
|
|
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
|
|
JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledDeletePropertyString();
|
|
JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerDeleteProperty)));
|
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle);
|
|
|
|
JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle2 != nullptr);
|
|
PropertyDescriptor desc2(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), true, true, true);
|
|
EXPECT_TRUE(JSProxy::DefineOwnProperty(thread, proxyHandle2, key, desc2));
|
|
EXPECT_EQ(JSProxy::GetProperty(thread, proxyHandle2, key).GetValue()->GetInt(), 1);
|
|
EXPECT_FALSE(JSProxy::DeleteProperty(thread, proxyHandle2, key));
|
|
}
|
|
|
|
JSTaggedValue HandlerGetPrototype([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
return JSTaggedValue(JSTaggedValue::Null());
|
|
}
|
|
|
|
// ES6 9.5.1 [[GetPrototypeOf]] ( )
|
|
HWTEST_F_L0(JSProxyTest, GetPrototypeOf)
|
|
{
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
// 1. handler has no "GetPrototypeOf"
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> proto(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(targetHandle->IsECMAObject());
|
|
JSObject::SetPrototype(thread, JSHandle<JSObject>(targetHandle), proto);
|
|
EXPECT_TRUE(
|
|
JSTaggedValue::SameValue(JSHandle<JSObject>(targetHandle)->GetPrototype(thread), proto.GetTaggedValue()));
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
|
|
EXPECT_TRUE(JSTaggedValue::SameValue(JSProxy::GetPrototype(thread, proxyHandle), proto.GetTaggedValue()));
|
|
|
|
// 2. handler has "GetPrototypeOf"
|
|
EcmaVM *vm = thread->GetEcmaVM();
|
|
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
|
|
JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledGetPrototypeOfString();
|
|
JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerGetPrototype)));
|
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle);
|
|
|
|
JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle2 != nullptr);
|
|
EXPECT_TRUE(JSTaggedValue::SameValue(JSProxy::GetPrototype(thread, proxyHandle2), JSTaggedValue::Null()));
|
|
}
|
|
|
|
JSTaggedValue HandlerSetPrototype([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
return JSTaggedValue(JSTaggedValue::False());
|
|
}
|
|
|
|
// ES6 9.5.2 [[SetPrototypeOf]] (V)
|
|
HWTEST_F_L0(JSProxyTest, SetPrototypeOf)
|
|
{
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
// 1. handler has no "SetPrototypeOf"
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> proto(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(targetHandle->IsECMAObject());
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
|
|
JSProxy::SetPrototype(thread, proxyHandle, proto);
|
|
EXPECT_TRUE(
|
|
JSTaggedValue::SameValue(JSHandle<JSObject>(targetHandle)->GetPrototype(thread), proto.GetTaggedValue()));
|
|
|
|
// 2. handler has "SetPrototypeOf"
|
|
EcmaVM *vm = thread->GetEcmaVM();
|
|
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
|
|
JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledSetPrototypeOfString();
|
|
JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerSetPrototype)));
|
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle);
|
|
|
|
JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle2 != nullptr);
|
|
EXPECT_FALSE(JSProxy::SetPrototype(thread, proxyHandle2, proto));
|
|
}
|
|
|
|
JSTaggedValue HandlerIsExtensible([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
return JSTaggedValue(JSTaggedValue::False());
|
|
}
|
|
|
|
// ES6 9.5.3 [[IsExtensible]] ( )
|
|
HWTEST_F_L0(JSProxyTest, IsExtensible)
|
|
{
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
// 1. handler has no "IsExtensible"
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(targetHandle->IsECMAObject());
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
|
|
bool status1 = JSProxy::IsExtensible(thread, proxyHandle);
|
|
bool status2 = JSHandle<JSObject>::Cast(targetHandle)->IsExtensible();
|
|
EXPECT_TRUE(status1 == status2);
|
|
|
|
// 2. handler has "IsExtensible"
|
|
EcmaVM *vm = thread->GetEcmaVM();
|
|
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
|
|
JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledIsExtensibleString();
|
|
JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerIsExtensible)));
|
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle);
|
|
|
|
JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle2 != nullptr);
|
|
EXPECT_FALSE(JSProxy::IsExtensible(thread, proxyHandle2));
|
|
}
|
|
|
|
JSTaggedValue HandlerPreventExtensions([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
return JSTaggedValue(JSTaggedValue::False());
|
|
}
|
|
|
|
// ES6 9.5.4 [[PreventExtensions]] ( )
|
|
HWTEST_F_L0(JSProxyTest, PreventExtensions)
|
|
{
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
// 1. handler has no "PreventExtensions"
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(targetHandle->IsECMAObject());
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
|
|
bool status1 = JSProxy::PreventExtensions(thread, proxyHandle);
|
|
EXPECT_TRUE(status1);
|
|
bool status2 = JSHandle<JSObject>::Cast(targetHandle)->IsExtensible();
|
|
EXPECT_FALSE(status2);
|
|
|
|
// 2. handler has "PreventExtensions"
|
|
EcmaVM *vm = thread->GetEcmaVM();
|
|
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
|
|
JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledPreventExtensionsString();
|
|
JSHandle<JSTaggedValue> funcHandle(
|
|
factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerPreventExtensions)));
|
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle);
|
|
|
|
JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle2 != nullptr);
|
|
EXPECT_FALSE(JSProxy::PreventExtensions(thread, proxyHandle2));
|
|
}
|
|
|
|
JSTaggedValue HandlerHasProperty([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
return JSTaggedValue(JSTaggedValue::False());
|
|
}
|
|
|
|
// ES6 9.5.7 [[HasProperty]] (P)
|
|
HWTEST_F_L0(JSProxyTest, HasProperty)
|
|
{
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
// 1. handler has no "HasProperty"
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(targetHandle->IsECMAObject());
|
|
|
|
JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("x"));
|
|
PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
|
|
JSObject::DefineOwnProperty(thread, JSHandle<JSObject>::Cast(targetHandle), key, desc);
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
|
|
EXPECT_TRUE(JSProxy::HasProperty(thread, proxyHandle, key));
|
|
|
|
// 2. handler has "HasProperty"
|
|
EcmaVM *vm = thread->GetEcmaVM();
|
|
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
|
|
JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledHasString();
|
|
JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerHasProperty)));
|
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle);
|
|
|
|
JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle2 != nullptr);
|
|
EXPECT_FALSE(JSProxy::HasProperty(thread, proxyHandle2, key));
|
|
}
|
|
|
|
JSTaggedValue HandlerOwnPropertyKeys([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
auto thread = argv->GetThread();
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
JSHandle<JSArray> arr = factory->NewJSArray();
|
|
return JSTaggedValue(arr.GetTaggedValue());
|
|
}
|
|
|
|
// ES6 9.5.12 [[OwnPropertyKeys]] ()
|
|
HWTEST_F_L0(JSProxyTest, OwnPropertyKeys)
|
|
{
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
// 1. handler has no "OwnPropertyKeys"
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> targetHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(targetHandle->IsECMAObject());
|
|
|
|
JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("x"));
|
|
PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
|
|
JSObject::DefineOwnProperty(thread, JSHandle<JSObject>::Cast(targetHandle), key, desc);
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
JSHandle<TaggedArray> res = JSProxy::OwnPropertyKeys(thread, proxyHandle);
|
|
|
|
EXPECT_TRUE(JSTaggedValue::SameValue(res->Get(0), key.GetTaggedValue()));
|
|
|
|
// 2. handler has "OwnPropertyKeys"
|
|
EcmaVM *vm = thread->GetEcmaVM();
|
|
JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
|
|
JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledOwnKeysString();
|
|
JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerOwnPropertyKeys)));
|
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle);
|
|
|
|
JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle2 != nullptr);
|
|
JSHandle<TaggedArray> res2 = JSProxy::OwnPropertyKeys(thread, proxyHandle2);
|
|
EXPECT_TRUE(res2->GetLength() == 0 || !JSTaggedValue::SameValue(res2->Get(0), key.GetTaggedValue()));
|
|
}
|
|
|
|
JSTaggedValue HandlerCall([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
return JSTaggedValue(JSTaggedValue::False());
|
|
}
|
|
JSTaggedValue HandlerFunction([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
return JSTaggedValue(JSTaggedValue::True());
|
|
}
|
|
|
|
// ES6 9.5.13 [[Call]] (thisArgument, argumentsList)
|
|
HWTEST_F_L0(JSProxyTest, Call)
|
|
{
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
|
// 1. handler has no "Call"
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> targetHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerFunction)));
|
|
EXPECT_TRUE(targetHandle->IsECMAObject());
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
JSTaggedValue res =
|
|
JSProxy::CallInternal(thread, proxyHandle, JSHandle<JSTaggedValue>::Cast(proxyHandle), 0, nullptr);
|
|
JSHandle<JSTaggedValue> taggedRes(thread, res);
|
|
|
|
EXPECT_TRUE(JSTaggedValue::SameValue(taggedRes.GetTaggedValue(), JSTaggedValue::True()));
|
|
|
|
// 2. handler has "Call"
|
|
JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledApplyString();
|
|
JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerCall)));
|
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle);
|
|
|
|
JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle2 != nullptr);
|
|
JSTaggedValue res2 =
|
|
JSProxy::CallInternal(thread, proxyHandle2, JSHandle<JSTaggedValue>::Cast(proxyHandle2), 0, nullptr);
|
|
JSHandle<JSTaggedValue> taggedRes2(thread, res2);
|
|
|
|
EXPECT_TRUE(JSTaggedValue::SameValue(taggedRes2.GetTaggedValue(), JSTaggedValue::False()));
|
|
}
|
|
|
|
JSTaggedValue HandlerConstruct([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
auto thread = argv->GetThread();
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> obj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
|
|
JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("x"));
|
|
PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(2))); // 2 : test case
|
|
JSObject::DefineOwnProperty(argv->GetThread(), JSHandle<JSObject>::Cast(obj), key, desc);
|
|
return JSTaggedValue(obj.GetTaggedValue());
|
|
}
|
|
JSTaggedValue HandlerConFunc([[maybe_unused]] EcmaRuntimeCallInfo *argv)
|
|
{
|
|
auto thread = argv->GetThread();
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> obj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
|
|
JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("x"));
|
|
PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)));
|
|
JSObject::DefineOwnProperty(argv->GetThread(), JSHandle<JSObject>::Cast(obj), key, desc);
|
|
return JSTaggedValue(obj.GetTaggedValue());
|
|
}
|
|
|
|
// ES6 9.5.14 [[Construct]] ( argumentsList, newTarget)
|
|
HWTEST_F_L0(JSProxyTest, Construct)
|
|
{
|
|
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
|
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
|
|
// 1. handler has no "Construct"
|
|
JSHandle<JSTaggedValue> dynclass(thread, JSObjectTestCreate(thread));
|
|
JSHandle<JSTaggedValue> targetHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerConFunc)));
|
|
JSHandle<JSFunction>::Cast(targetHandle)->GetJSHClass()->SetConstructor(true);
|
|
EXPECT_TRUE(targetHandle->IsECMAObject());
|
|
|
|
JSHandle<JSTaggedValue> handlerHandle(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dynclass), dynclass));
|
|
EXPECT_TRUE(handlerHandle->IsECMAObject());
|
|
|
|
JSHandle<JSProxy> proxyHandle = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle != nullptr);
|
|
JSTaggedValue res = JSProxy::ConstructInternal(thread, proxyHandle, 0, nullptr, targetHandle);
|
|
JSHandle<JSTaggedValue> taggedRes(thread, res);
|
|
JSHandle<JSTaggedValue> key(factory->NewFromCanBeCompressString("x"));
|
|
EXPECT_EQ(JSObject::GetProperty(thread, taggedRes, key).GetValue()->GetInt(), 1);
|
|
|
|
// 2. handler has "Construct"
|
|
JSHandle<JSTaggedValue> funcKey = thread->GlobalConstants()->GetHandledProxyConstructString();
|
|
JSHandle<JSTaggedValue> funcHandle(factory->NewJSFunction(env, reinterpret_cast<void *>(HandlerConstruct)));
|
|
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handlerHandle), funcKey, funcHandle);
|
|
|
|
JSHandle<JSProxy> proxyHandle2 = JSProxy::ProxyCreate(thread, targetHandle, handlerHandle);
|
|
EXPECT_TRUE(*proxyHandle2 != nullptr);
|
|
JSTaggedValue res2 = JSProxy::ConstructInternal(thread, proxyHandle2, 0, nullptr, targetHandle);
|
|
JSHandle<JSTaggedValue> taggedRes2(thread, res2);
|
|
EXPECT_EQ(JSObject::GetProperty(thread, taggedRes2, key).GetValue()->GetInt(), 2);
|
|
}
|
|
} // namespace panda::test
|