Commit 0a0ad98a authored by legendecas's avatar legendecas Committed by V8 LUCI CQ

[ShadowRealm] WrappedFunction properties

Implement WrappedFunction properties name/length.

Bug: v8:11989
Change-Id: I050af5814537552ef6c2077802ffc726f2e08fa3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3507201Reviewed-by: 's avatarShu-yu Guo <syg@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Chengzhong Wu <legendecas@gmail.com>
Cr-Commit-Position: refs/heads/main@{#79628}
parent 2ee36e4c
......@@ -1989,6 +1989,7 @@ filegroup(
"src/runtime/runtime-proxy.cc",
"src/runtime/runtime-regexp.cc",
"src/runtime/runtime-scopes.cc",
"src/runtime/runtime-shadow-realm.cc",
"src/runtime/runtime-strings.cc",
"src/runtime/runtime-symbol.cc",
"src/runtime/runtime-test.cc",
......
......@@ -4449,6 +4449,7 @@ v8_source_set("v8_base_without_compiler") {
"src/runtime/runtime-proxy.cc",
"src/runtime/runtime-regexp.cc",
"src/runtime/runtime-scopes.cc",
"src/runtime/runtime-shadow-realm.cc",
"src/runtime/runtime-strings.cc",
"src/runtime/runtime-symbol.cc",
"src/runtime/runtime-test.cc",
......
......@@ -763,6 +763,57 @@ Handle<AccessorInfo> Accessors::MakeBoundFunctionNameInfo(Isolate* isolate) {
&BoundFunctionNameGetter, &ReconfigureToDataProperty);
}
//
// Accessors::WrappedFunctionLength
//
void Accessors::WrappedFunctionLengthGetter(
v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
RCS_SCOPE(isolate, RuntimeCallCounterId::kBoundFunctionLengthGetter);
HandleScope scope(isolate);
Handle<JSWrappedFunction> function =
Handle<JSWrappedFunction>::cast(Utils::OpenHandle(*info.Holder()));
int length = 0;
if (!JSWrappedFunction::GetLength(isolate, function).To(&length)) {
isolate->OptionalRescheduleException(false);
return;
}
Handle<Object> result(Smi::FromInt(length), isolate);
info.GetReturnValue().Set(Utils::ToLocal(result));
}
Handle<AccessorInfo> Accessors::MakeWrappedFunctionLengthInfo(
Isolate* isolate) {
return MakeAccessor(isolate, isolate->factory()->length_string(),
&WrappedFunctionLengthGetter, &ReconfigureToDataProperty);
}
//
// Accessors::WrappedFunctionName
//
void Accessors::WrappedFunctionNameGetter(
v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
RCS_SCOPE(isolate, RuntimeCallCounterId::kWrappedFunctionNameGetter);
HandleScope scope(isolate);
Handle<JSWrappedFunction> function =
Handle<JSWrappedFunction>::cast(Utils::OpenHandle(*info.Holder()));
Handle<Object> result;
if (!JSWrappedFunction::GetName(isolate, function).ToHandle(&result)) {
isolate->OptionalRescheduleException(false);
return;
}
info.GetReturnValue().Set(Utils::ToLocal(result));
}
Handle<AccessorInfo> Accessors::MakeWrappedFunctionNameInfo(Isolate* isolate) {
return MakeAccessor(isolate, isolate->factory()->name_string(),
&WrappedFunctionNameGetter, &ReconfigureToDataProperty);
}
//
// Accessors::ErrorStack
//
......
......@@ -44,7 +44,12 @@ class JavaScriptFrame;
kHasSideEffectToReceiver) \
V(_, function_prototype, FunctionPrototype, kHasNoSideEffect, \
kHasSideEffectToReceiver) \
V(_, string_length, StringLength, kHasNoSideEffect, kHasSideEffectToReceiver)
V(_, string_length, StringLength, kHasNoSideEffect, \
kHasSideEffectToReceiver) \
V(_, wrapped_function_length, WrappedFunctionLength, kHasNoSideEffect, \
kHasSideEffectToReceiver) \
V(_, wrapped_function_name, WrappedFunctionName, kHasNoSideEffect, \
kHasSideEffectToReceiver)
#define ACCESSOR_SETTER_LIST(V) \
V(ArrayLengthSetter) \
......
......@@ -869,9 +869,9 @@ namespace internal {
\
/* ShadowRealm */ \
CPP(ShadowRealmConstructor) \
TFS(ShadowRealmGetWrappedValue, kCreationContext, kTargetContext, kValue) \
CPP(ShadowRealmPrototypeEvaluate) \
CPP(ShadowRealmPrototypeImportValue) \
TFS(ShadowRealmGetWrappedValue, kCreationContext, kValue) \
\
/* SharedArrayBuffer */ \
CPP(SharedArrayBufferPrototypeGetByteLength) \
......
......@@ -206,72 +206,13 @@ Object DoFunctionBind(Isolate* isolate, BuiltinArguments args) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, function,
isolate->factory()->NewJSBoundFunction(target, this_arg, argv));
// Setup the "length" property based on the "length" of the {target}.
// If the targets length is the default JSFunction accessor, we can keep the
// accessor that's installed by default on the JSBoundFunction. It lazily
// computes the value from the underlying internal length.
Handle<AccessorInfo> function_length_accessor =
isolate->factory()->function_length_accessor();
LookupIterator length_lookup(isolate, target,
isolate->factory()->length_string(), target,
LookupIterator::OWN);
if (!target->IsJSFunction() ||
length_lookup.state() != LookupIterator::ACCESSOR ||
!length_lookup.GetAccessors().is_identical_to(function_length_accessor)) {
Handle<Object> length(Smi::zero(), isolate);
Maybe<PropertyAttributes> attributes =
JSReceiver::GetPropertyAttributes(&length_lookup);
if (attributes.IsNothing()) return ReadOnlyRoots(isolate).exception();
if (attributes.FromJust() != ABSENT) {
Handle<Object> target_length;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_length,
Object::GetProperty(&length_lookup));
if (target_length->IsNumber()) {
length = isolate->factory()->NewNumber(std::max(
0.0, DoubleToInteger(target_length->Number()) - argv.length()));
}
}
LookupIterator it(isolate, function, isolate->factory()->length_string(),
function);
DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
RETURN_FAILURE_ON_EXCEPTION(isolate,
JSObject::DefineOwnPropertyIgnoreAttributes(
&it, length, it.property_attributes()));
}
// Setup the "name" property based on the "name" of the {target}.
// If the target's name is the default JSFunction accessor, we can keep the
// accessor that's installed by default on the JSBoundFunction. It lazily
// computes the value from the underlying internal name.
Handle<AccessorInfo> function_name_accessor =
isolate->factory()->function_name_accessor();
LookupIterator name_lookup(isolate, target, isolate->factory()->name_string(),
target);
if (!target->IsJSFunction() ||
name_lookup.state() != LookupIterator::ACCESSOR ||
!name_lookup.GetAccessors().is_identical_to(function_name_accessor) ||
(name_lookup.IsFound() && !name_lookup.HolderIsReceiver())) {
Handle<Object> target_name;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_name,
Object::GetProperty(&name_lookup));
Handle<String> name;
if (target_name->IsString()) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, name,
Name::ToFunctionName(isolate, Handle<String>::cast(target_name)));
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, name,
isolate->factory()->NewConsString(isolate->factory()->bound__string(),
name));
} else {
name = isolate->factory()->bound__string();
}
LookupIterator it(isolate, function, isolate->factory()->name_string());
DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
RETURN_FAILURE_ON_EXCEPTION(isolate,
JSObject::DefineOwnPropertyIgnoreAttributes(
&it, name, it.property_attributes()));
Maybe<bool> result =
JSFunctionOrBoundFunctionOrWrappedFunction::CopyNameAndLength(
isolate, function, target, isolate->factory()->bound__string(),
argv.length());
if (result.IsNothing()) {
DCHECK(isolate->has_pending_exception());
return ReadOnlyRoots(isolate).exception();
}
return *function;
}
......
......@@ -59,9 +59,9 @@ BUILTIN(ShadowRealmConstructor) {
namespace {
// https://tc39.es/proposal-shadowrealm/#sec-getwrappedvalue
MaybeHandle<Object> GetWrappedValue(Isolate* isolate, Handle<Object> value,
MaybeHandle<Object> GetWrappedValue(Isolate* isolate,
Handle<NativeContext> creation_context,
Handle<NativeContext> target_context) {
Handle<Object> value) {
// 1. If Type(value) is Object, then
if (!value->IsJSReceiver()) {
// 2. Return value.
......@@ -69,6 +69,8 @@ MaybeHandle<Object> GetWrappedValue(Isolate* isolate, Handle<Object> value,
}
// 1a. If IsCallable(value) is false, throw a TypeError exception.
if (!value->IsCallable()) {
// The TypeError thrown is created with creation Realm's TypeError
// constructor instead of the executing Realm's.
THROW_NEW_ERROR_RETURN_VALUE(
isolate,
NewError(Handle<JSFunction>(creation_context->type_error_function(),
......@@ -77,34 +79,8 @@ MaybeHandle<Object> GetWrappedValue(Isolate* isolate, Handle<Object> value,
{});
}
// 1b. Return ? WrappedFunctionCreate(callerRealm, value).
// WrappedFunctionCreate
// https://tc39.es/proposal-shadowrealm/#sec-wrappedfunctioncreate
// The intermediate wrapped functions are not user-visible. And calling a
// wrapped function won't cause a side effect in the creation realm.
// Unwrap here to avoid nested unwrapping at the call site.
if (value->IsJSWrappedFunction()) {
Handle<JSWrappedFunction> target_wrapped =
Handle<JSWrappedFunction>::cast(value);
value = Handle<Object>(target_wrapped->wrapped_target_function(), isolate);
}
// 1. Let internalSlotsList be the internal slots listed in Table 2, plus
// [[Prototype]] and [[Extensible]].
// 2. Let wrapped be ! MakeBasicObject(internalSlotsList).
// 3. Set wrapped.[[Prototype]] to
// callerRealm.[[Intrinsics]].[[%Function.prototype%]].
// 4. Set wrapped.[[Call]] as described in 2.1.
// 5. Set wrapped.[[WrappedTargetFunction]] to Target.
// 6. Set wrapped.[[Realm]] to callerRealm.
// 7. Let result be CopyNameAndLength(wrapped, Target, "wrapped").
// 8. If result is an Abrupt Completion, throw a TypeError exception.
Handle<JSWrappedFunction> wrapped =
isolate->factory()->NewJSWrappedFunction(creation_context, value);
// 9. Return wrapped.
return wrapped;
return JSWrappedFunction::Create(isolate, creation_context,
Handle<JSReceiver>::cast(value));
}
} // namespace
......@@ -213,6 +189,7 @@ BUILTIN(ShadowRealmPrototypeEvaluate) {
}
if (result.is_null()) {
DCHECK(isolate->has_pending_exception());
Handle<Object> pending_exception =
Handle<Object>(isolate->pending_exception(), isolate);
isolate->clear_pending_exception();
......@@ -225,7 +202,9 @@ BUILTIN(ShadowRealmPrototypeEvaluate) {
*factory->NewError(isolate->syntax_error_function(), message));
}
// 21. If result.[[Type]] is not normal, throw a TypeError exception.
// TODO(v8:11989): provide a non-observable inspection.
// TODO(v8:11989): provide a non-observable inspection on the
// pending_exception to the newly created TypeError.
// https://github.com/tc39/proposal-shadowrealm/issues/353
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kCallShadowRealmFunctionThrown));
}
......@@ -233,8 +212,7 @@ BUILTIN(ShadowRealmPrototypeEvaluate) {
Handle<Object> wrapped_result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, wrapped_result,
GetWrappedValue(isolate, result.ToHandleChecked(), caller_context,
eval_context));
GetWrappedValue(isolate, caller_context, result.ToHandleChecked()));
return *wrapped_result;
}
......
......@@ -5,6 +5,7 @@
#include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/builtins.h"
#include "src/codegen/code-stub-assembler.h"
#include "src/objects/descriptor-array.h"
namespace v8 {
namespace internal {
......@@ -15,25 +16,44 @@ class ShadowRealmBuiltinsAssembler : public CodeStubAssembler {
: CodeStubAssembler(state) {}
protected:
TNode<JSObject> AllocateJSWrappedFunction(TNode<Context> context);
TNode<JSObject> AllocateJSWrappedFunction(TNode<Context> context,
TNode<Object> target);
void CheckAccessor(TNode<DescriptorArray> array, TNode<IntPtrT> index,
TNode<Name> name, Label* bailout);
};
TNode<JSObject> ShadowRealmBuiltinsAssembler::AllocateJSWrappedFunction(
TNode<Context> context) {
TNode<Context> context, TNode<Object> target) {
TNode<NativeContext> native_context = LoadNativeContext(context);
TNode<Map> map = CAST(
LoadContextElement(native_context, Context::WRAPPED_FUNCTION_MAP_INDEX));
return AllocateJSObjectFromMap(map);
TNode<JSObject> wrapped = AllocateJSObjectFromMap(map);
StoreObjectFieldNoWriteBarrier(
wrapped, JSWrappedFunction::kWrappedTargetFunctionOffset, target);
StoreObjectFieldNoWriteBarrier(wrapped, JSWrappedFunction::kContextOffset,
context);
return wrapped;
}
void ShadowRealmBuiltinsAssembler::CheckAccessor(TNode<DescriptorArray> array,
TNode<IntPtrT> index,
TNode<Name> name,
Label* bailout) {
TNode<Name> key = LoadKeyByDescriptorEntry(array, index);
GotoIfNot(TaggedEqual(key, name), bailout);
TNode<Object> value = LoadValueByDescriptorEntry(array, index);
GotoIfNot(IsAccessorInfo(CAST(value)), bailout);
}
// https://tc39.es/proposal-shadowrealm/#sec-getwrappedvalue
TF_BUILTIN(ShadowRealmGetWrappedValue, ShadowRealmBuiltinsAssembler) {
auto context = Parameter<Context>(Descriptor::kContext);
auto creation_context = Parameter<Context>(Descriptor::kCreationContext);
auto target_context = Parameter<Context>(Descriptor::kTargetContext);
auto value = Parameter<Object>(Descriptor::kValue);
Label if_primitive(this), if_callable(this), unwrap(this), wrap(this),
bailout(this, Label::kDeferred);
slow_wrap(this, Label::kDeferred), bailout(this, Label::kDeferred);
// 2. Return value.
GotoIf(TaggedIsSmi(value), &if_primitive);
......@@ -64,28 +84,68 @@ TF_BUILTIN(ShadowRealmGetWrappedValue, ShadowRealmBuiltinsAssembler) {
Goto(&wrap);
BIND(&wrap);
// Disallow wrapping of slow-mode functions. We need to figure out
// whether the length and name property are in the original state.
TNode<Map> map = LoadMap(CAST(target.value()));
GotoIf(IsDictionaryMap(map), &slow_wrap);
// Check whether the length and name properties are still present as
// AccessorInfo objects. If so, their value can be recomputed even if
// the actual value on the object changes.
TNode<Uint32T> bit_field3 = LoadMapBitField3(map);
TNode<IntPtrT> number_of_own_descriptors = Signed(
DecodeWordFromWord32<Map::Bits3::NumberOfOwnDescriptorsBits>(bit_field3));
GotoIf(IntPtrLessThan(
number_of_own_descriptors,
IntPtrConstant(JSFunction::kMinDescriptorsForFastBindAndWrap)),
&slow_wrap);
// We don't need to check the exact accessor here because the only case
// custom accessor arise is with function templates via API, and in that
// case the object is in dictionary mode
TNode<DescriptorArray> descriptors = LoadMapInstanceDescriptors(map);
CheckAccessor(
descriptors,
IntPtrConstant(
JSFunctionOrBoundFunctionOrWrappedFunction::kLengthDescriptorIndex),
LengthStringConstant(), &slow_wrap);
CheckAccessor(
descriptors,
IntPtrConstant(
JSFunctionOrBoundFunctionOrWrappedFunction::kNameDescriptorIndex),
NameStringConstant(), &slow_wrap);
// Verify that prototype matches the function prototype of the target
// context.
TNode<Object> prototype = LoadMapPrototype(map);
TNode<Object> function_map =
LoadContextElement(target_context, Context::WRAPPED_FUNCTION_MAP_INDEX);
TNode<Object> function_prototype = LoadMapPrototype(CAST(function_map));
GotoIf(TaggedNotEqual(prototype, function_prototype), &slow_wrap);
// 1. Let internalSlotsList be the internal slots listed in Table 2, plus
// [[Prototype]] and [[Extensible]].
// 2. Let wrapped be ! MakeBasicObject(internalSlotsList).
// 3. Set wrapped.[[Prototype]] to
// callerRealm.[[Intrinsics]].[[%Function.prototype%]].
// 4. Set wrapped.[[Call]] as described in 2.1.
TNode<JSObject> wrapped = AllocateJSWrappedFunction(creation_context);
// 5. Set wrapped.[[WrappedTargetFunction]] to Target.
StoreObjectFieldNoWriteBarrier(
wrapped, JSWrappedFunction::kWrappedTargetFunctionOffset, target.value());
// 6. Set wrapped.[[Realm]] to callerRealm.
StoreObjectFieldNoWriteBarrier(wrapped, JSWrappedFunction::kContextOffset,
creation_context);
// 7. Let result be CopyNameAndLength(wrapped, Target, "wrapped").
// 8. If result is an Abrupt Completion, throw a TypeError exception.
// TODO(v8:11989): https://github.com/tc39/proposal-shadowrealm/pull/348
// Installed with default accessors.
TNode<JSObject> wrapped =
AllocateJSWrappedFunction(creation_context, target.value());
// 9. Return wrapped.
Return(wrapped);
BIND(&slow_wrap);
{
Return(CallRuntime(Runtime::kShadowRealmWrappedFunctionCreate, context,
creation_context, target.value()));
}
BIND(&bailout);
ThrowTypeError(context, MessageTemplate::kNotCallable, value);
}
......@@ -132,7 +192,7 @@ TF_BUILTIN(CallWrappedFunction, ShadowRealmBuiltinsAssembler) {
// Create wrapped value in the target realm.
TNode<Object> wrapped_receiver =
CallBuiltin(Builtin::kShadowRealmGetWrappedValue, caller_context,
target_context, receiver);
target_context, caller_context, receiver);
StoreFixedArrayElement(wrapped_args, 0, wrapped_receiver);
// 7. For each element arg of argumentsList, do
BuildFastLoop<IntPtrT>(
......@@ -142,7 +202,7 @@ TF_BUILTIN(CallWrappedFunction, ShadowRealmBuiltinsAssembler) {
// Create wrapped value in the target realm.
TNode<Object> wrapped_value =
CallBuiltin(Builtin::kShadowRealmGetWrappedValue, caller_context,
target_context, args.AtIndex(index));
target_context, caller_context, args.AtIndex(index));
// 7b. Append wrappedValue to wrappedArgs.
StoreFixedArrayElement(
wrapped_args, IntPtrAdd(index, IntPtrConstant(1)), wrapped_value);
......@@ -167,13 +227,15 @@ TF_BUILTIN(CallWrappedFunction, ShadowRealmBuiltinsAssembler) {
// 10a. Return ? GetWrappedValue(callerRealm, result.[[Value]]).
TNode<Object> wrapped_result =
CallBuiltin(Builtin::kShadowRealmGetWrappedValue, caller_context,
caller_context, result);
caller_context, target_context, result);
args.PopAndReturn(wrapped_result);
// 11. Else,
BIND(&call_exception);
// 11a. Throw a TypeError exception.
// TODO(v8:11989): provide a non-observable inspection.
// TODO(v8:11989): provide a non-observable inspection on the
// pending_exception to the newly created TypeError.
// https://github.com/tc39/proposal-shadowrealm/issues/353
ThrowTypeError(context, MessageTemplate::kCallShadowRealmFunctionThrown,
var_exception.value());
......
......@@ -741,8 +741,8 @@ Cast<Zero|PromiseReaction>(implicit context: Context)(o: Object): Zero|
}
}
Cast<JSFunction|JSBoundFunction>(implicit context: Context)(o: Object):
JSFunction|JSBoundFunction labels CastError {
Cast<JSFunction|JSBoundFunction|JSWrappedFunction>(implicit context: Context)(
o: Object): JSFunction|JSBoundFunction|JSWrappedFunction labels CastError {
typeswitch (o) {
case (o: JSFunction): {
return o;
......@@ -750,6 +750,9 @@ Cast<JSFunction|JSBoundFunction>(implicit context: Context)(o: Object):
case (o: JSBoundFunction): {
return o;
}
case (o: JSWrappedFunction): {
return o;
}
case (Object): {
goto CastError;
}
......
......@@ -22,8 +22,8 @@ const kLengthDescriptorIndex: constexpr int32
const kNameDescriptorIndex: constexpr int32
generates 'JSFunctionOrBoundFunctionOrWrappedFunction::kNameDescriptorIndex'
;
const kMinDescriptorsForFastBind:
constexpr int31 generates 'JSFunction::kMinDescriptorsForFastBind';
const kMinDescriptorsForFastBindAndWrap: constexpr int31
generates 'JSFunction::kMinDescriptorsForFastBindAndWrap';
macro CheckAccessor(implicit context: Context)(
array: DescriptorArray, index: constexpr int32,
......@@ -44,7 +44,7 @@ FastFunctionPrototypeBind(
const argc: intptr = arguments.actual_count;
try {
typeswitch (receiver) {
case (fn: JSFunction|JSBoundFunction): {
case (fn: JSFunction|JSBoundFunction|JSWrappedFunction): {
// Disallow binding of slow-mode functions. We need to figure out
// whether the length and name property are in the original state.
Comment('Disallow binding of slow-mode functions');
......@@ -55,7 +55,7 @@ FastFunctionPrototypeBind(
// the actual value on the object changes.
if (fn.map.bit_field3.number_of_own_descriptors <
kMinDescriptorsForFastBind) {
kMinDescriptorsForFastBindAndWrap) {
goto Slow;
}
......
......@@ -8295,6 +8295,13 @@ TNode<Uint32T> CodeStubAssembler::LoadDetailsByDescriptorEntry(
DescriptorArray::ToDetailsIndex(descriptor_entry) * kTaggedSize));
}
TNode<Object> CodeStubAssembler::LoadValueByDescriptorEntry(
TNode<DescriptorArray> container, TNode<IntPtrT> descriptor_entry) {
return LoadDescriptorArrayElement<Object>(
container, DescriptorEntryToIndex(descriptor_entry),
DescriptorArray::ToValueIndex(0) * kTaggedSize);
}
TNode<Object> CodeStubAssembler::LoadValueByDescriptorEntry(
TNode<DescriptorArray> container, int descriptor_entry) {
return LoadDescriptorArrayElement<Object>(
......
......@@ -3995,6 +3995,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<DescriptorArray> descriptors, TNode<IntPtrT> descriptor);
TNode<Uint32T> LoadDetailsByDescriptorEntry(
TNode<DescriptorArray> descriptors, int descriptor);
TNode<Object> LoadValueByDescriptorEntry(TNode<DescriptorArray> descriptors,
TNode<IntPtrT> descriptor);
TNode<Object> LoadValueByDescriptorEntry(TNode<DescriptorArray> descriptors,
int descriptor);
TNode<MaybeObject> LoadFieldTypeByDescriptorEntry(
......
......@@ -68,6 +68,7 @@ namespace internal {
T(CannotFreezeArrayBufferView, \
"Cannot freeze array buffer views with elements") \
T(CannotSeal, "Cannot seal") \
T(CannotWrap, "Cannot wrap target callable") \
T(CircularStructure, "Converting circular structure to JSON%") \
T(ConstructAbstractClass, "Abstract class % not directly constructable") \
T(ConstAssign, "Assignment to constant variable.") \
......
......@@ -382,6 +382,14 @@ class StackMemory;
#define MAYBE_RETURN_NULL(call) MAYBE_RETURN(call, MaybeHandle<Object>())
#define MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value) \
do { \
if (!(call).To(&dst)) { \
DCHECK((isolate)->has_pending_exception()); \
return value; \
} \
} while (false)
#define MAYBE_ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call) \
do { \
Isolate* __isolate__ = (isolate); \
......
......@@ -4453,13 +4453,14 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_intl_best_fit_matcher)
void Genesis::InitializeGlobal_harmony_shadow_realm() {
if (!FLAG_harmony_shadow_realm) return;
Factory* factory = isolate()->factory();
// -- S h a d o w R e a l m
// #sec-shadowrealm-objects
Handle<JSGlobalObject> global(native_context()->global_object(), isolate());
Handle<JSFunction> shadow_realm_fun = InstallFunction(
isolate_, global, "ShadowRealm", JS_SHADOW_REALM_TYPE,
JSShadowRealm::kHeaderSize, 0, factory()->the_hole_value(),
Builtin::kShadowRealmConstructor);
Handle<JSFunction> shadow_realm_fun =
InstallFunction(isolate_, global, "ShadowRealm", JS_SHADOW_REALM_TYPE,
JSShadowRealm::kHeaderSize, 0, factory->the_hole_value(),
Builtin::kShadowRealmConstructor);
shadow_realm_fun->shared().set_length(0);
shadow_realm_fun->shared().DontAdaptArguments();
......@@ -4467,7 +4468,7 @@ void Genesis::InitializeGlobal_harmony_shadow_realm() {
Handle<JSObject> prototype(
JSObject::cast(shadow_realm_fun->instance_prototype()), isolate());
InstallToStringTag(isolate_, prototype, factory()->ShadowRealm_string());
InstallToStringTag(isolate_, prototype, factory->ShadowRealm_string());
SimpleInstallFunction(isolate_, prototype, "evaluate",
Builtin::kShadowRealmPrototypeEvaluate, 1, true);
......@@ -4475,15 +4476,38 @@ void Genesis::InitializeGlobal_harmony_shadow_realm() {
Builtin::kShadowRealmPrototypeImportValue, 2, true);
{ // --- W r a p p e d F u n c t i o n
Handle<Map> map = factory()->NewMap(JS_WRAPPED_FUNCTION_TYPE,
JSWrappedFunction::kHeaderSize,
TERMINAL_FAST_ELEMENTS_KIND, 0);
Handle<Map> map = factory->NewMap(JS_WRAPPED_FUNCTION_TYPE,
JSWrappedFunction::kHeaderSize,
TERMINAL_FAST_ELEMENTS_KIND, 0);
map->SetConstructor(native_context()->object_function());
map->set_is_callable(true);
Handle<JSObject> empty_function(native_context()->function_prototype(),
isolate());
Map::SetPrototype(isolate(), map, empty_function);
PropertyAttributes roc_attribs =
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
Map::EnsureDescriptorSlack(isolate_, map, 2);
{ // length
STATIC_ASSERT(
JSFunctionOrBoundFunctionOrWrappedFunction::kLengthDescriptorIndex ==
0);
Descriptor d = Descriptor::AccessorConstant(
factory->length_string(), factory->wrapped_function_length_accessor(),
roc_attribs);
map->AppendDescriptor(isolate(), &d);
}
{ // name
STATIC_ASSERT(
JSFunctionOrBoundFunctionOrWrappedFunction::kNameDescriptorIndex ==
1);
Descriptor d = Descriptor::AccessorConstant(
factory->name_string(), factory->wrapped_function_name_accessor(),
roc_attribs);
map->AppendDescriptor(isolate(), &d);
}
native_context()->set_wrapped_function_map(*map);
}
}
......
......@@ -487,7 +487,9 @@ class RuntimeCallTimer final {
V(WebSnapshotDeserialize_Functions) \
V(WebSnapshotDeserialize_Maps) \
V(WebSnapshotDeserialize_Objects) \
V(WebSnapshotDeserialize_Strings)
V(WebSnapshotDeserialize_Strings) \
V(WrappedFunctionLengthGetter) \
V(WrappedFunctionNameGetter)
#define FOR_EACH_HANDLER_COUNTER(V) \
V(KeyedLoadIC_KeyedLoadSloppyArgumentsStub) \
......
......@@ -158,6 +158,8 @@ extern enum ContextSlot extends intptr constexpr 'Context::Field' {
BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX: Slot<NativeContext, Map>,
BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX: Slot<NativeContext, Map>,
WRAPPED_FUNCTION_MAP_INDEX: Slot<NativeContext, Map>,
MIN_CONTEXT_SLOTS,
...
}
......
This diff is collapsed.
......@@ -26,6 +26,12 @@ class JSFunctionOrBoundFunctionOrWrappedFunction
static const int kLengthDescriptorIndex = 0;
static const int kNameDescriptorIndex = 1;
// https://tc39.es/proposal-shadowrealm/#sec-copynameandlength
static Maybe<bool> CopyNameAndLength(
Isolate* isolate,
Handle<JSFunctionOrBoundFunctionOrWrappedFunction> function,
Handle<JSReceiver> target, Handle<String> prefix, int arg_count);
STATIC_ASSERT(kHeaderSize == JSObject::kHeaderSize);
TQ_OBJECT_CONSTRUCTORS(JSFunctionOrBoundFunctionOrWrappedFunction)
};
......@@ -56,6 +62,15 @@ class JSWrappedFunction
: public TorqueGeneratedJSWrappedFunction<
JSWrappedFunction, JSFunctionOrBoundFunctionOrWrappedFunction> {
public:
static MaybeHandle<String> GetName(Isolate* isolate,
Handle<JSWrappedFunction> function);
static Maybe<int> GetLength(Isolate* isolate,
Handle<JSWrappedFunction> function);
// https://tc39.es/proposal-shadowrealm/#sec-wrappedfunctioncreate
static MaybeHandle<Object> Create(Isolate* isolate,
Handle<NativeContext> creation_context,
Handle<JSReceiver> value);
// Dispatched behavior.
DECL_PRINTER(JSWrappedFunction)
DECL_VERIFIER(JSWrappedFunction)
......@@ -80,7 +95,7 @@ class JSFunction : public TorqueGeneratedJSFunction<
DECL_RELAXED_GETTER(shared, SharedFunctionInfo)
// Fast binding requires length and name accessors.
static const int kMinDescriptorsForFastBind = 2;
static const int kMinDescriptorsForFastBindAndWrap = 2;
// [context]: The context for this function.
inline Context context();
......@@ -90,7 +105,7 @@ class JSFunction : public TorqueGeneratedJSFunction<
inline NativeContext native_context();
inline int length();
static Handle<Object> GetName(Isolate* isolate, Handle<JSFunction> function);
static Handle<String> GetName(Isolate* isolate, Handle<JSFunction> function);
// [code]: The generated code object for this function. Executed
// when the function is invoked, e.g. foo() or new foo(). See
......
......@@ -494,6 +494,9 @@ MaybeHandle<String> Object::NoSideEffectsToMaybeString(Isolate* isolate,
Handle<String> fun_str;
if (input->IsJSBoundFunction()) {
fun_str = JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(input));
} else if (input->IsJSWrappedFunction()) {
fun_str =
JSWrappedFunction::ToString(Handle<JSWrappedFunction>::cast(input));
} else {
DCHECK(input->IsJSFunction());
fun_str = JSFunction::ToString(Handle<JSFunction>::cast(input));
......@@ -549,9 +552,8 @@ MaybeHandle<String> Object::NoSideEffectsToMaybeString(Isolate* isolate,
isolate, Handle<JSBoundFunction>::cast(ctor))
.ToHandleChecked();
} else if (ctor->IsJSFunction()) {
Handle<Object> ctor_name_obj =
ctor_name =
JSFunction::GetName(isolate, Handle<JSFunction>::cast(ctor));
ctor_name = AsStringOrEmpty(isolate, ctor_name_obj);
}
if (ctor_name->length() != 0) {
......
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/execution/arguments-inl.h"
#include "src/objects/js-function.h"
namespace v8 {
namespace internal {
RUNTIME_FUNCTION(Runtime_ShadowRealmWrappedFunctionCreate) {
DCHECK_EQ(2, args.length());
HandleScope scope(isolate);
Handle<NativeContext> native_context = args.at<NativeContext>(0);
Handle<JSReceiver> value = args.at<JSReceiver>(1);
RETURN_RESULT_OR_FAILURE(
isolate, JSWrappedFunction::Create(isolate, native_context, value));
}
} // namespace internal
} // namespace v8
......@@ -439,6 +439,9 @@ namespace internal {
F(StoreLookupSlot_Strict, 2, 1) \
F(ThrowConstAssignError, 0, 1)
#define FOR_EACH_INTRINSIC_SHADOW_REALM(F, I) \
F(ShadowRealmWrappedFunctionCreate, 2, 1)
#define FOR_EACH_INTRINSIC_STRINGS(F, I) \
F(FlattenString, 1, 1) \
F(GetSubstitution, 5, 1) \
......@@ -696,6 +699,7 @@ namespace internal {
FOR_EACH_INTRINSIC_PROXY(F, I) \
FOR_EACH_INTRINSIC_REGEXP(F, I) \
FOR_EACH_INTRINSIC_SCOPES(F, I) \
FOR_EACH_INTRINSIC_SHADOW_REALM(F, I) \
FOR_EACH_INTRINSIC_STRINGS(F, I) \
FOR_EACH_INTRINSIC_SYMBOL(F, I) \
FOR_EACH_INTRINSIC_TEST(F, I) \
......
......@@ -83,7 +83,7 @@ bytecodes: [
/* 48 E> */ B(DefineKeyedOwnProperty), R(this), R(0), U8(0),
/* 53 S> */ B(LdaImmutableCurrentContextSlot), U8(3),
/* 58 E> */ B(GetKeyedProperty), R(this), U8(2),
B(Wide), B(LdaSmi), I16(296),
B(Wide), B(LdaSmi), I16(297),
B(Star2),
B(LdaConstant), U8(0),
B(Star3),
......@@ -115,7 +115,7 @@ bytecodes: [
/* 41 E> */ B(DefineKeyedOwnProperty), R(this), R(0), U8(0),
/* 46 S> */ B(LdaImmutableCurrentContextSlot), U8(3),
/* 51 E> */ B(GetKeyedProperty), R(this), U8(2),
B(Wide), B(LdaSmi), I16(295),
B(Wide), B(LdaSmi), I16(296),
B(Star2),
B(LdaConstant), U8(0),
B(Star3),
......@@ -149,7 +149,7 @@ bytecodes: [
B(Star2),
B(LdaImmutableCurrentContextSlot), U8(3),
/* 58 E> */ B(GetKeyedProperty), R(this), U8(2),
B(Wide), B(LdaSmi), I16(296),
B(Wide), B(LdaSmi), I16(297),
B(Star3),
B(LdaConstant), U8(0),
B(Star4),
......@@ -181,7 +181,7 @@ bytecodes: [
/* 41 E> */ B(DefineKeyedOwnProperty), R(this), R(0), U8(0),
/* 46 S> */ B(LdaImmutableCurrentContextSlot), U8(3),
/* 51 E> */ B(GetKeyedProperty), R(this), U8(2),
B(Wide), B(LdaSmi), I16(295),
B(Wide), B(LdaSmi), I16(296),
B(Star2),
B(LdaConstant), U8(0),
B(Star3),
......
......@@ -58,7 +58,7 @@ bytecodes: [
B(Star2),
B(LdaImmutableCurrentContextSlot), U8(3),
/* 54 E> */ B(GetKeyedProperty), R(this), U8(2),
B(Wide), B(LdaSmi), I16(294),
B(Wide), B(LdaSmi), I16(295),
B(Star3),
B(LdaConstant), U8(0),
B(Star4),
......@@ -91,7 +91,7 @@ bytecodes: [
/* 44 E> */ B(DefineKeyedOwnProperty), R(this), R(0), U8(0),
/* 49 S> */ B(LdaImmutableCurrentContextSlot), U8(3),
/* 54 E> */ B(GetKeyedProperty), R(this), U8(2),
B(Wide), B(LdaSmi), I16(294),
B(Wide), B(LdaSmi), I16(295),
B(Star2),
B(LdaConstant), U8(0),
B(Star3),
......
......@@ -24,7 +24,7 @@ bytecodes: [
B(TestReferenceEqual), R(this),
B(Mov), R(this), R(1),
B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(288),
B(Wide), B(LdaSmi), I16(289),
B(Star2),
B(LdaConstant), U8(0),
B(Star3),
......@@ -61,13 +61,13 @@ bytecodes: [
B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(288),
B(Wide), B(LdaSmi), I16(289),
B(Star2),
B(LdaConstant), U8(0),
B(Star3),
/* 61 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2),
B(Throw),
B(Wide), B(LdaSmi), I16(294),
B(Wide), B(LdaSmi), I16(295),
B(Star2),
B(LdaConstant), U8(1),
B(Star3),
......@@ -99,13 +99,13 @@ bytecodes: [
B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(288),
B(Wide), B(LdaSmi), I16(289),
B(Star1),
B(LdaConstant), U8(0),
B(Star2),
/* 61 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(1), U8(2),
B(Throw),
B(Wide), B(LdaSmi), I16(294),
B(Wide), B(LdaSmi), I16(295),
B(Star1),
B(LdaConstant), U8(1),
B(Star2),
......@@ -145,7 +145,7 @@ bytecodes: [
B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(288),
B(Wide), B(LdaSmi), I16(289),
B(Star2),
B(LdaConstant), U8(0),
B(Star3),
......@@ -167,7 +167,7 @@ bytecodes: [
B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(288),
B(Wide), B(LdaSmi), I16(289),
B(Star3),
B(LdaConstant), U8(0),
B(Star4),
......@@ -182,7 +182,7 @@ bytecodes: [
B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(288),
B(Wide), B(LdaSmi), I16(289),
B(Star2),
B(LdaConstant), U8(0),
B(Star3),
......@@ -216,13 +216,13 @@ bytecodes: [
B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(288),
B(Wide), B(LdaSmi), I16(289),
B(Star1),
B(LdaConstant), U8(0),
B(Star2),
/* 65 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(1), U8(2),
B(Throw),
B(Wide), B(LdaSmi), I16(296),
B(Wide), B(LdaSmi), I16(297),
B(Star1),
B(LdaConstant), U8(1),
B(Star2),
......@@ -253,13 +253,13 @@ bytecodes: [
B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(288),
B(Wide), B(LdaSmi), I16(289),
B(Star1),
B(LdaConstant), U8(0),
B(Star2),
/* 58 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(1), U8(2),
B(Throw),
B(Wide), B(LdaSmi), I16(295),
B(Wide), B(LdaSmi), I16(296),
B(Star1),
B(LdaConstant), U8(1),
B(Star2),
......@@ -292,13 +292,13 @@ bytecodes: [
B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(16),
B(Wide), B(LdaSmi), I16(288),
B(Wide), B(LdaSmi), I16(289),
B(Star2),
B(LdaConstant), U8(0),
B(Star3),
/* 65 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2),
B(Throw),
B(Wide), B(LdaSmi), I16(296),
B(Wide), B(LdaSmi), I16(297),
B(Star2),
B(LdaConstant), U8(1),
B(Star3),
......@@ -327,7 +327,7 @@ bytecode array length: 19
bytecodes: [
/* 46 S> */ B(LdaImmutableCurrentContextSlot), U8(3),
/* 51 E> */ B(GetKeyedProperty), R(this), U8(0),
B(Wide), B(LdaSmi), I16(295),
B(Wide), B(LdaSmi), I16(296),
B(Star1),
B(LdaConstant), U8(0),
B(Star2),
......
......@@ -817,3 +817,64 @@ TEST(BindFunctionTemplateSetNativeDataProperty) {
CHECK(try_catch.HasCaught());
}
}
namespace {
v8::MaybeLocal<v8::Context> TestHostCreateShadowRealmContextCallback(
v8::Local<v8::Context> initiator_context) {
v8::Isolate* isolate = initiator_context->GetIsolate();
v8::Local<v8::FunctionTemplate> global_constructor =
v8::FunctionTemplate::New(isolate);
v8::Local<v8::ObjectTemplate> global_template =
global_constructor->InstanceTemplate();
// Check that getter is called on Function.prototype.bind.
global_template->SetNativeDataProperty(
v8_str("func1"), [](v8::Local<v8::String> property,
const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
v8::Local<v8::FunctionTemplate> templ =
v8::FunctionTemplate::New(isolate);
templ->SetNativeDataProperty(v8_str("name"), FunctionNativeGetter);
info.GetReturnValue().Set(
templ->GetFunction(isolate->GetCurrentContext()).ToLocalChecked());
});
// Check that getter is called on Function.prototype.bind.
global_template->SetNativeDataProperty(
v8_str("func2"), [](v8::Local<v8::String> property,
const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
v8::Local<v8::FunctionTemplate> templ =
v8::FunctionTemplate::New(isolate);
templ->SetNativeDataProperty(v8_str("length"), FunctionNativeGetter);
info.GetReturnValue().Set(
templ->GetFunction(isolate->GetCurrentContext()).ToLocalChecked());
});
return v8::Context::New(isolate, nullptr, global_template);
}
} // namespace
TEST(WrapFunctionTemplateSetNativeDataProperty) {
i::FLAG_harmony_shadow_realm = true;
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
isolate->SetHostCreateShadowRealmContextCallback(
TestHostCreateShadowRealmContextCallback);
v8::HandleScope scope(isolate);
// Check that getter is called on WrappedFunctionCreate.
{
v8::TryCatch try_catch(isolate);
CHECK(
CompileRun("new ShadowRealm().evaluate('globalThis.func1')").IsEmpty());
CHECK(try_catch.HasCaught());
}
// Check that getter is called on WrappedFunctionCreate.
{
v8::TryCatch try_catch(isolate);
CHECK(
CompileRun("new ShadowRealm().evaluate('globalThis.func2')").IsEmpty());
CHECK(try_catch.HasCaught());
}
}
......@@ -55,10 +55,8 @@ revoke();
assertThrows(() => wrapped(), TypeError, "Cannot perform 'apply' on a proxy that has been revoked");
// revoked proxy
var wrapped = shadowRealm.evaluate(`
assertThrows(() => shadowRealm.evaluate(`
var revocable = Proxy.revocable(() => 1, {});
revocable.revoke();
revocable.proxy;
`);
var revoke = shadowRealm.evaluate('globalThis.revoke');
assertThrows(() => wrapped(), TypeError, "Cannot perform 'apply' on a proxy that has been revoked");
`), TypeError, "Cannot wrap target callable");
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-shadow-realm
const shadowRealm = new ShadowRealm();
// bind
var wrapped = shadowRealm.evaluate('function foo(bar, quz) {}; foo');
assertEquals(wrapped.name, 'foo');
assertEquals(wrapped.length, 2);
var bound = wrapped.bind(undefined, 'bar');
assertEquals(bound.name, 'bound foo');
assertEquals(bound.length, 1);
// proxy
var wrapped = shadowRealm.evaluate('function foo(bar, quz) {}; foo');
assertEquals(wrapped.name, 'foo');
assertEquals(wrapped.length, 2);
var proxy = new Proxy(wrapped, {});
assertEquals(proxy.name, 'foo');
assertEquals(proxy.length, 2);
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-shadow-realm
(function TestWrappedFunctionNameStackOverflow() {
const shadowRealm = new ShadowRealm();
let otherBind = shadowRealm.evaluate('function foo(fn) { return fn.bind(1); }; foo');
let fn = () => {};
for(let i = 0; i < 1024 * 50; i++) {
fn = otherBind(fn.bind(1));
}
assertThrows(() => {
fn.name;
}, RangeError, 'Maximum call stack size exceeded');
})();
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-shadow-realm --allow-natives-syntax
// Test wrapped function returned from ShadowRealm.prototype.evaluate
function shadowRealmEvaluate(sourceText) {
var shadowRealm = new ShadowRealm();
shadowRealm.evaluate(`function makeSlow(o) {
for (var i = 0; i < 1200; i++) {
o["o"+i] = 0;
}
if (%HasFastProperties(o)) {
throw new Error('o should be slow');
}
return o;
}`);
return shadowRealm.evaluate(sourceText);
}
// Test wrapped function returned from WrappedFunction.[[Call]]
function wrappedFunctionEvaluate(sourceText) {
var shadowRealm = new ShadowRealm();
shadowRealm.evaluate(`function makeSlow(o) {
for (var i = 0; i < 1200; i++) {
o["o"+i] = 0;
}
if (%HasFastProperties(o)) {
throw new Error('o should be slow');
}
return o;
}`);
// Create a wrapped function from sourceText in the shadow realm and return it.
return shadowRealm.evaluate('text => eval(text)')(sourceText);
}
suite(shadowRealmEvaluate);
suite(wrappedFunctionEvaluate);
function suite(evaluate) {
// function
var wrapped = evaluate('function foo() {}; foo');
assertEquals(wrapped.name, 'foo');
assertEquals(wrapped.length, 0);
// The properties should be accessor infos.
assertTrue(%HasFastProperties(wrapped));
var wrapped = evaluate('function foo(bar) {}; foo');
assertEquals(wrapped.length, 1);
// builtin function
var wrapped = evaluate('String.prototype.substring');
assertEquals(wrapped.name, 'substring');
assertEquals(wrapped.length, 2);
// callable proxy
var wrapped = evaluate('new Proxy(function foo(arg) {}, {})');
assertEquals(wrapped.name, 'foo');
assertEquals(wrapped.length, 1);
// nested callable proxy
var wrapped = evaluate('new Proxy(new Proxy(new Proxy(function foo(arg) {}, {}), {}), {})');
assertEquals(wrapped.name, 'foo');
assertEquals(wrapped.length, 1);
// bound function
var wrapped = evaluate('(function foo(arg) { return this.a }).bind({ a: 1 })');
assertEquals(wrapped.name, 'bound foo');
assertEquals(wrapped.length, 1);
// nested bound function
var wrapped = evaluate('(function foo(arg) { return this.a }).bind({ a: 1 }).bind().bind()');
assertEquals(wrapped.name, 'bound bound bound foo');
assertEquals(wrapped.length, 1);
// bound function with args
var wrapped = evaluate('(function foo(arg1, arg2) { return this.a }).bind({ a: 1 }, 1)');
assertEquals(wrapped.name, 'bound foo');
assertEquals(wrapped.length, 1);
// function with length modified
var wrapped = evaluate('function foo(arg) {}; Object.defineProperty(foo, "length", {value: 123}); foo');
assertEquals(wrapped.name, 'foo');
assertEquals(wrapped.length, 123);
var wrapped = evaluate('function foo(arg) {}; Object.defineProperty(foo, "length", {value: "123"}); foo');
assertEquals(wrapped.name, 'foo');
assertEquals(wrapped.length, 0);
var wrapped = evaluate('function foo(arg) {}; delete foo.length; foo');
assertEquals(wrapped.name, 'foo');
assertEquals(wrapped.length, 0);
var wrapped = evaluate('function foo(arg) {}; Object.defineProperty(foo, "length", {value: 123}); makeSlow(foo)');
assertEquals(wrapped.name, 'foo');
assertEquals(wrapped.length, 123);
// function with name modified
var wrapped = evaluate('function foo(arg) {}; Object.defineProperty(foo, "name", {value: "bar"}); foo');
assertEquals(wrapped.name, 'bar');
assertEquals(wrapped.length, 1);
var wrapped = evaluate('function foo(arg) {}; Object.defineProperty(foo, "name", {value: new String("bar")}); foo');
assertEquals(wrapped.name, '');
assertEquals(wrapped.length, 1);
var wrapped = evaluate('function foo(arg) {}; delete foo.name; foo');
assertEquals(wrapped.name, '');
assertEquals(wrapped.length, 1);
// function with prototype modified
var wrapped = evaluate('function foo(arg) {}; Object.setPrototypeOf(foo, Object); foo');
assertEquals(wrapped.name, 'foo');
assertEquals(wrapped.length, 1);
// function with additional properties
var wrapped = evaluate('function foo(arg) {}; foo.bar = 123; foo');
assertEquals(wrapped.name, 'foo');
assertEquals(wrapped.length, 1);
}
......@@ -2800,10 +2800,6 @@
'built-ins/ShadowRealm/prototype/importValue/throws-typeerror-import-syntax-error': [FAIL],
'built-ins/ShadowRealm/prototype/importValue/throws-typeerror-import-throws': [FAIL],
'built-ins/ShadowRealm/prototype/importValue/validates-realm-object': [FAIL],
'built-ins/ShadowRealm/WrappedFunction/length': [FAIL],
'built-ins/ShadowRealm/WrappedFunction/length-throws-typeerror': [FAIL],
'built-ins/ShadowRealm/WrappedFunction/name': [FAIL],
'built-ins/ShadowRealm/WrappedFunction/name-throws-typeerror': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=12085
'language/statements/class/subclass/derived-class-return-override-catch-finally': [FAIL],
......
......@@ -511,51 +511,53 @@ KNOWN_OBJECTS = {
("old_space", 0x0443d): "FunctionLengthAccessor",
("old_space", 0x04481): "FunctionPrototypeAccessor",
("old_space", 0x044c5): "StringLengthAccessor",
("old_space", 0x04509): "InvalidPrototypeValidityCell",
("old_space", 0x04511): "EmptyScript",
("old_space", 0x04551): "ManyClosuresCell",
("old_space", 0x0455d): "ArrayConstructorProtector",
("old_space", 0x04571): "NoElementsProtector",
("old_space", 0x04585): "MegaDOMProtector",
("old_space", 0x04599): "IsConcatSpreadableProtector",
("old_space", 0x045ad): "ArraySpeciesProtector",
("old_space", 0x045c1): "TypedArraySpeciesProtector",
("old_space", 0x045d5): "PromiseSpeciesProtector",
("old_space", 0x045e9): "RegExpSpeciesProtector",
("old_space", 0x045fd): "StringLengthProtector",
("old_space", 0x04611): "ArrayIteratorProtector",
("old_space", 0x04625): "ArrayBufferDetachingProtector",
("old_space", 0x04639): "PromiseHookProtector",
("old_space", 0x0464d): "PromiseResolveProtector",
("old_space", 0x04661): "MapIteratorProtector",
("old_space", 0x04675): "PromiseThenProtector",
("old_space", 0x04689): "SetIteratorProtector",
("old_space", 0x0469d): "StringIteratorProtector",
("old_space", 0x046b1): "SingleCharacterStringCache",
("old_space", 0x04ab9): "StringSplitCache",
("old_space", 0x04ec1): "RegExpMultipleCache",
("old_space", 0x052c9): "BuiltinsConstantsTable",
("old_space", 0x056f5): "AsyncFunctionAwaitRejectSharedFun",
("old_space", 0x05719): "AsyncFunctionAwaitResolveSharedFun",
("old_space", 0x0573d): "AsyncGeneratorAwaitRejectSharedFun",
("old_space", 0x05761): "AsyncGeneratorAwaitResolveSharedFun",
("old_space", 0x05785): "AsyncGeneratorYieldResolveSharedFun",
("old_space", 0x057a9): "AsyncGeneratorReturnResolveSharedFun",
("old_space", 0x057cd): "AsyncGeneratorReturnClosedRejectSharedFun",
("old_space", 0x057f1): "AsyncGeneratorReturnClosedResolveSharedFun",
("old_space", 0x05815): "AsyncIteratorValueUnwrapSharedFun",
("old_space", 0x05839): "PromiseAllResolveElementSharedFun",
("old_space", 0x0585d): "PromiseAllSettledResolveElementSharedFun",
("old_space", 0x05881): "PromiseAllSettledRejectElementSharedFun",
("old_space", 0x058a5): "PromiseAnyRejectElementSharedFun",
("old_space", 0x058c9): "PromiseCapabilityDefaultRejectSharedFun",
("old_space", 0x058ed): "PromiseCapabilityDefaultResolveSharedFun",
("old_space", 0x05911): "PromiseCatchFinallySharedFun",
("old_space", 0x05935): "PromiseGetCapabilitiesExecutorSharedFun",
("old_space", 0x05959): "PromiseThenFinallySharedFun",
("old_space", 0x0597d): "PromiseThrowerFinallySharedFun",
("old_space", 0x059a1): "PromiseValueThunkFinallySharedFun",
("old_space", 0x059c5): "ProxyRevokeSharedFun",
("old_space", 0x04509): "WrappedFunctionLengthAccessor",
("old_space", 0x0454d): "WrappedFunctionNameAccessor",
("old_space", 0x04591): "InvalidPrototypeValidityCell",
("old_space", 0x04599): "EmptyScript",
("old_space", 0x045d9): "ManyClosuresCell",
("old_space", 0x045e5): "ArrayConstructorProtector",
("old_space", 0x045f9): "NoElementsProtector",
("old_space", 0x0460d): "MegaDOMProtector",
("old_space", 0x04621): "IsConcatSpreadableProtector",
("old_space", 0x04635): "ArraySpeciesProtector",
("old_space", 0x04649): "TypedArraySpeciesProtector",
("old_space", 0x0465d): "PromiseSpeciesProtector",
("old_space", 0x04671): "RegExpSpeciesProtector",
("old_space", 0x04685): "StringLengthProtector",
("old_space", 0x04699): "ArrayIteratorProtector",
("old_space", 0x046ad): "ArrayBufferDetachingProtector",
("old_space", 0x046c1): "PromiseHookProtector",
("old_space", 0x046d5): "PromiseResolveProtector",
("old_space", 0x046e9): "MapIteratorProtector",
("old_space", 0x046fd): "PromiseThenProtector",
("old_space", 0x04711): "SetIteratorProtector",
("old_space", 0x04725): "StringIteratorProtector",
("old_space", 0x04739): "SingleCharacterStringCache",
("old_space", 0x04b41): "StringSplitCache",
("old_space", 0x04f49): "RegExpMultipleCache",
("old_space", 0x05351): "BuiltinsConstantsTable",
("old_space", 0x0577d): "AsyncFunctionAwaitRejectSharedFun",
("old_space", 0x057a1): "AsyncFunctionAwaitResolveSharedFun",
("old_space", 0x057c5): "AsyncGeneratorAwaitRejectSharedFun",
("old_space", 0x057e9): "AsyncGeneratorAwaitResolveSharedFun",
("old_space", 0x0580d): "AsyncGeneratorYieldResolveSharedFun",
("old_space", 0x05831): "AsyncGeneratorReturnResolveSharedFun",
("old_space", 0x05855): "AsyncGeneratorReturnClosedRejectSharedFun",
("old_space", 0x05879): "AsyncGeneratorReturnClosedResolveSharedFun",
("old_space", 0x0589d): "AsyncIteratorValueUnwrapSharedFun",
("old_space", 0x058c1): "PromiseAllResolveElementSharedFun",
("old_space", 0x058e5): "PromiseAllSettledResolveElementSharedFun",
("old_space", 0x05909): "PromiseAllSettledRejectElementSharedFun",
("old_space", 0x0592d): "PromiseAnyRejectElementSharedFun",
("old_space", 0x05951): "PromiseCapabilityDefaultRejectSharedFun",
("old_space", 0x05975): "PromiseCapabilityDefaultResolveSharedFun",
("old_space", 0x05999): "PromiseCatchFinallySharedFun",
("old_space", 0x059bd): "PromiseGetCapabilitiesExecutorSharedFun",
("old_space", 0x059e1): "PromiseThenFinallySharedFun",
("old_space", 0x05a05): "PromiseThrowerFinallySharedFun",
("old_space", 0x05a29): "PromiseValueThunkFinallySharedFun",
("old_space", 0x05a4d): "ProxyRevokeSharedFun",
}
# Lower 32 bits of first page addresses for various heap spaces.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment