Atom FunctionObject::get_coerced_receiver(Atom a) { if (AvmCore::isNullOrUndefined(a)) { // use callee's global object as this. // see E3 15.3.4.4 a = _call->scope()->getScope(0); } MethodSignaturep ms = _call->method->getMethodSignature(); return toplevel()->coerce(a, ms->paramTraits(0)); }
static bool hasTypedArgs(MethodSignaturep ms) { int32_t param_count = ms->param_count(); for (int32_t i = 1; i <= param_count; i++) { if (ms->paramTraits(i) != NULL) { // at least one parameter is typed; need full coerceEnter return true; } } return false; }
ScriptObject* TypeDescriber::describeTraits(Traitsp traits, uint32_t flags, Toplevel* toplevel) { if (!(flags & INCLUDE_TRAITS)) return NULL; AvmCore* core = m_toplevel->core(); GC* gc = core->GetGC(); TraitsBindingsp tb = traits->getTraitsBindings(); TraitsMetadatap tm = traits->getTraitsMetadata(); ScriptObject* o = new_object(); ArrayObject* bases = NULL; ArrayObject* metadata = NULL; ArrayObject* interfaces = NULL; ArrayObject* methods = NULL; ArrayObject* accessors = NULL; ArrayObject* variables = NULL; ScriptObject* constructor = NULL; if (flags & INCLUDE_METADATA) { metadata = new_array(); PoolObject* class_mdpool; const uint8_t* class_md = tm->getMetadataPos(class_mdpool); if (class_md) addDescribeMetadata(metadata, class_mdpool, class_md); } if (flags & INCLUDE_BASES) { bases = new_array(); for (Traitsp b = traits->base; b; b = b->base) pushstr(bases, describeClassName(b)); } if (flags & INCLUDE_INTERFACES) { interfaces = new_array(); for (InterfaceIterator iter(traits); iter.hasNext();) { Traits* ti = iter.next(); pushstr(interfaces, describeClassName(ti)); } } // constructor if (flags & INCLUDE_CONSTRUCTOR) { MethodInfo* initMethod = traits->init; if (initMethod) { initMethod->resolveSignature(toplevel); MethodSignaturep ms = initMethod->getMethodSignature(); if (ms->param_count() > 0) { constructor = describeParams(initMethod, ms); } } } if (flags & (INCLUDE_ACCESSORS | INCLUDE_METHODS | INCLUDE_VARIABLES)) { // recover slot/method metadata and method-declarer information. // make a flattened set of bindings so we don't have to check for overrides as we go. // This is not terribly efficient, but doesn't need to be. MultinameBindingHashtable* mybind = MultinameBindingHashtable::create(gc); addBindings(m_toplevel->core(), mybind, tb, flags); // Don't want interface methods, so post-process and wipe out any // bindings that were added. for (InterfaceIterator ifc_iter(traits); ifc_iter.hasNext();) { Traitsp ti = ifc_iter.next(); TraitsBindingsp tbi = ti->getTraitsBindings(); StTraitsBindingsIterator iter(tbi); while (iter.next()) { if (!iter.key()) continue; mybind->add(iter.key(), iter.ns(), BIND_NONE); } } // yuck, replicate buggy behavior in FP9/10 RCList<Namespace> nsremoval(gc, kListInitialCapacity); if (flags & HIDE_NSURI_METHODS) { for (TraitsBindingsp tbi = tb->base; tbi; tbi = tbi->base) { StTraitsBindingsIterator iter(tbi); while (iter.next()) { if (!iter.key()) continue; Namespacep ns = iter.ns(); if (ns->getURI()->length() > 0 && nsremoval.indexOf(ns) < 0) { nsremoval.add(ns); } } } } StMNHTBindingIterator iter(mybind); while (iter.next()) { if (!iter.key()) continue; Stringp name = iter.key(); Namespacep ns = iter.ns(); Binding binding = iter.value(); Stringp nsuri = ns->getURI(); TraitsMetadata::MetadataPtr md1 = NULL; TraitsMetadata::MetadataPtr md2 = NULL; PoolObject* md1pool = NULL; PoolObject* md2pool = NULL; // We only display public members -- exposing private namespaces could compromise security. if (ns->getType() != Namespace::NS_Public) { continue; } if ((flags & HIDE_NSURI_METHODS) && nsremoval.indexOf(ns) >= 0) { continue; } ScriptObject* v = new_object(); const BindingKind bk = AvmCore::bindingKind(binding); switch (bk) { case BKIND_CONST: case BKIND_VAR: { if (!(flags & INCLUDE_VARIABLES)) continue; const uint32_t slotID = AvmCore::bindingToSlotId(binding); const KVPair props[] = { { kstrid_access, strAtom(str(bk == BKIND_CONST ? kstrid_readonly : kstrid_readwrite)) }, { kstrid_type, strAtom(describeClassName(tb->getSlotTraits(slotID))) }, }; setpropmulti(v, props, elem_count(props)); if (!variables) variables = new_array(); pushobj(variables, v); md1 = tm->getSlotMetadataPos(slotID, md1pool); break; } case BKIND_METHOD: { if (!(flags & INCLUDE_METHODS)) continue; const uint32_t methodID = AvmCore::bindingToMethodId(binding); MethodInfo* mi = tb->getMethod(methodID); mi->resolveSignature(toplevel); MethodSignaturep ms = mi->getMethodSignature(); Traitsp declaringTraits = mi->declaringTraits(); const KVPair props[] = { { kstrid_declaredBy, strAtom(describeClassName(declaringTraits)) }, { kstrid_returnType, strAtom(describeClassName(ms->returnTraits())) }, { kstrid_parameters, objAtom(describeParams(mi, ms)) }, }; setpropmulti(v, props, elem_count(props)); if (!methods) methods = new_array(); pushobj(methods, v); md1 = tm->getMethodMetadataPos(methodID, md1pool); break; } case BKIND_GET: case BKIND_SET: case BKIND_GETSET: { if (!(flags & INCLUDE_ACCESSORS)) continue; const uint32_t methodID = AvmCore::hasGetterBinding(binding) ? AvmCore::bindingToGetterId(binding) : AvmCore::bindingToSetterId(binding); MethodInfo* mi = tb->getMethod(methodID); mi->resolveSignature(toplevel); MethodSignaturep ms = mi->getMethodSignature(); Traitsp declaringTraits = mi->declaringTraits(); // The verifier does not check the signature of a setter // except when it is invoked. We must be prepared for the // case in which it has no arguments. Traitsp accessorType; if (AvmCore::hasGetterBinding(binding)) { accessorType = ms->returnTraits(); } else { // If setter is malformed, just use '*' as a placeholder. accessorType = (ms->param_count() < 1) ? NULL : ms->paramTraits(1); } static const uint8_t bk2str[8] = { uint8_t(kstrid_emptyString), // BKIND_NONE uint8_t(kstrid_emptyString), // BKIND_METHOD uint8_t(kstrid_emptyString), // BKIND_VAR uint8_t(kstrid_emptyString), // BKIND_CONST uint8_t(kstrid_emptyString), // unused uint8_t(kstrid_readonly), // BKIND_GET uint8_t(kstrid_writeonly), // BKIND_SET uint8_t(kstrid_readwrite) // BKIND_GETSET }; const KVPair props[] = { { kstrid_declaredBy, strAtom(describeClassName(declaringTraits)) }, { kstrid_access, strAtom(str(StringId(bk2str[bk]))) }, { kstrid_type, strAtom(describeClassName(accessorType)) }, }; setpropmulti(v, props, elem_count(props)); if (AvmCore::hasGetterBinding(binding)) md1 = tm->getMethodMetadataPos(AvmCore::bindingToGetterId(binding), md1pool); if (AvmCore::hasSetterBinding(binding)) md2 = tm->getMethodMetadataPos(AvmCore::bindingToSetterId(binding), md2pool); if (!accessors) accessors = new_array(); pushobj(accessors, v); break; } case BKIND_NONE: break; default: break; } ArrayObject* vm = NULL; if ((flags & INCLUDE_METADATA) && (md1 || md2)) { vm = new_array(); addDescribeMetadata(vm, md1pool, md1); addDescribeMetadata(vm, md2pool, md2); } const KVPair props[] = { { kstrid_name, strAtom(name) }, { kstrid_uri, strAtom(nsuri->length() == 0 ? NULL : nsuri) }, { kstrid_metadata, objAtom(vm) }, }; setpropmulti(v, props, elem_count(props)); } } const KVPair props[] = { { kstrid_bases, objAtom(bases) }, { kstrid_interfaces, objAtom(interfaces) }, { kstrid_metadata, objAtom(metadata) }, { kstrid_accessors, objAtom(accessors) }, { kstrid_methods, objAtom(methods) }, { kstrid_variables, objAtom(variables) }, { kstrid_constructor, objAtom(constructor) }, }; setpropmulti(o, props, elem_count(props)); return o; }