Files
avmplus/shell/DomainClass.cpp
dmcallis 65a0592776 Initial source code drop
Source code drop for the Actionscript virtual machine in the Adobe
Flash Player for December 2013
2013-12-02 16:04:04 -08:00

181 lines
6.4 KiB
C++

/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
/* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "avmshell.h"
#ifndef AVMSHELL_BUILD
#error "This file is only for use with avmshell"
#endif
namespace avmplus
{
using namespace avmshell;
DomainObject::DomainObject(VTable *vtable, ScriptObject *delegate)
: ScriptObject(vtable, delegate)
, domainEnv(delegate->core()->codeContext()->domainEnv())
, domainToplevel(delegate->toplevel())
{
}
void DomainObject::init(DomainObject* parentDomain)
{
ShellCore* core = (ShellCore*) this->core();
DomainEnv* baseDomainEnv = parentDomain ?
(DomainEnv*)parentDomain->domainEnv :
(DomainEnv*)NULL;
Domain* baseDomain = baseDomainEnv ?
baseDomainEnv->domain() :
NULL;
domainToplevel = parentDomain ?
(Toplevel*)parentDomain->domainToplevel :
core->createShellToplevel();
Domain* domain = Domain::newDomain(core, baseDomain);
domainEnv = DomainEnv::newDomainEnv(core, domain, parentDomain ? (DomainEnv*)parentDomain->domainEnv : (DomainEnv*)NULL);
}
Atom DomainObject::loadBytes(ByteArrayObject* b, uint32_t swfVersion)
{
AvmCore* core = this->core();
if (!b)
toplevel()->throwTypeError(kNullArgumentError, core->toErrorString("bytes"));
// parse new bytecode
size_t len = b->get_length();
ScriptBuffer code = core->newScriptBuffer(len);
VMPI_memcpy(code.getBuffer(), &b->GetByteArray()[0], len);
Toplevel* toplevel = domainToplevel;
ApiVersion apiVersion = core->getApiVersionFromCallStack();
// parse constants and attributes.
PoolObject* pool = core->parseActionBlock(code,
/*start*/0,
toplevel,
domainEnv->domain(),
/*ninit*/NULL,
apiVersion);
// by default, use the same bugCompatibility as the builtins use
const BugCompatibility* bugCompatibility = toplevel->abcEnv()->codeContext()->bugCompatibility();
if (swfVersion != 0)
{
// ...unless specified otherwise.
for (int j = 0; j < BugCompatibility::VersionCount; ++j)
{
if (BugCompatibility::kNames[j] == swfVersion)
{
bugCompatibility = core->createBugCompatibility((BugCompatibility::Version)j);
goto done;
}
}
// if we get here, didn't find a valid name
toplevel->throwTypeError(kInvalidArgumentError, core->toErrorString("swfVersion"));
}
done:
ShellCodeContext* codeContext = new (core->GetGC()) ShellCodeContext(domainEnv, bugCompatibility);
return core->handleActionPool(pool, toplevel, codeContext);
}
ScriptObject* DomainObject::finddef(const Multiname& multiname,
DomainEnv* domainEnv)
{
Toplevel* toplevel = this->toplevel();
ScriptEnv* script = core()->domainMgr()->findScriptEnvInDomainEnvByMultiname(domainEnv, multiname);
if (script == (ScriptEnv*)BIND_AMBIGUOUS)
toplevel->throwReferenceError(kAmbiguousBindingError, multiname);
if (script == (ScriptEnv*)BIND_NONE)
toplevel->throwReferenceError(kUndefinedVarError, multiname);
if (script->global == NULL)
{
script->initGlobal();
script->coerceEnter(script->global->atom());
}
return script->global;
}
ClassClosure* DomainObject::getClass(Stringp name)
{
Toplevel* toplevel = this->toplevel();
AvmCore* core = toplevel->core();
if (name == NULL) {
toplevel->throwArgumentError(kNullArgumentError, core->toErrorString("name"));
}
// Search for a dot from the end.
int dot = name->lastIndexOf(core->cachedChars[(int)'.']);
// If there is a '.', this is a fully-qualified
// class name in a package. Must turn it into
// a namespace-qualified multiname.
Namespace* ns;
Stringp className;
if (dot >= 0) {
Stringp uri = core->internString(name->substring(0, dot));
ns = core->internNamespace(core->newNamespace(uri, Namespace::NS_Public, core->getApiVersionFromCallStack()));
className = core->internString(name->substring(dot+1, name->length()));
} else {
ns = core->findPublicNamespace();
className = core->internString(name);
}
Multiname multiname(ns, className);
ScriptObject *container = finddef(multiname, domainEnv);
if (!container) {
toplevel->throwTypeError(kClassNotFoundError, core->toErrorString(&multiname));
}
Atom atom = toplevel->getproperty(container->atom(),
&multiname,
container->vtable);
// Note: this used to throw "kClassNotFoundError" if the class wasn't
// found; now it throws "kCheckTypeFailedError" (by way of coerceToType).
// This probably doesn't matter since this is a shell-only class, and it
// gives us a testcase for coerceToType.
return toplevel->builtinClasses()->get_ClassClass()->coerceToType(atom);
}
DomainClass::DomainClass(VTable *cvtable)
: ClassClosure(cvtable)
{
createVanillaPrototype();
}
DomainObject* DomainClass::get_currentDomain()
{
return (DomainObject*) newInstance();
}
int DomainClass::get_MIN_DOMAIN_MEMORY_LENGTH()
{
return DomainEnv::GLOBAL_MEMORY_MIN_SIZE;
}
ByteArrayObject* DomainObject::get_domainMemory() const
{
return (ByteArrayObject*)domainEnv->get_globalMemory();
}
void DomainObject::set_domainMemory(ByteArrayObject* mem)
{
if(!domainEnv->set_globalMemory(mem))
toplevel()->throwError(kEndOfFileError);
}
}