зеркало из https://github.com/mozilla/pjs.git
Instance & Dynamic property map changes to HashTable complete.
This commit is contained in:
Родитель
5b25aee5db
Коммит
33651b5beb
|
@ -283,27 +283,19 @@ js2val dump(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint
|
|||
printFrameBindings(c);
|
||||
|
||||
stdOut << " Instance Bindings:\n";
|
||||
for (InstanceBindingIterator rib = c->instanceReadBindings.begin(), riend = c->instanceReadBindings.end(); (rib != riend); rib++) {
|
||||
stdOut << "\t" << *rib->second->qname.nameSpace->name << "::" << *rib->second->qname.id;
|
||||
bool found = false;
|
||||
for (InstanceBindingIterator wib = c->instanceWriteBindings.begin(), wiend = c->instanceWriteBindings.end(); (wib != wiend); wib++) {
|
||||
if (rib->second->qname == wib->second->qname) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
for (InstanceBindingIterator rib = c->instanceBindings.begin(), riend = c->instanceBindings.end(); (rib != riend); rib++) {
|
||||
InstanceBindingEntry *ibe = *rib;
|
||||
for (InstanceBindingEntry::NS_Iterator i = ibe->begin(), end = ibe->end(); (i != end); i++) {
|
||||
InstanceBindingEntry::NamespaceBinding ns = *i;
|
||||
stdOut << "\t" << *(ns.first->name) << "::" << ibe->name;
|
||||
if (ns.second->accesses & ReadAccess)
|
||||
if (ns.second->accesses & WriteAccess)
|
||||
stdOut << " [read/write]\n";
|
||||
else
|
||||
stdOut << " [read-only]\n";
|
||||
else
|
||||
stdOut << " [write-only]\n";
|
||||
}
|
||||
stdOut << ((found) ? " [read/write]" : " [read-only]") << "\n";
|
||||
}
|
||||
for (InstanceBindingIterator wib = c->instanceWriteBindings.begin(), wiend = c->instanceWriteBindings.end(); (wib != wiend); wib++) {
|
||||
bool found = false;
|
||||
for (InstanceBindingIterator rib = c->instanceReadBindings.begin(), riend = c->instanceReadBindings.end(); (rib != riend); rib++) {
|
||||
if (rib->second->qname == wib->second->qname) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
stdOut << "\t" << *wib->second->qname.nameSpace->name << "::" << *wib->second->qname.id << " [write-only]" << "\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -321,7 +313,8 @@ js2val dump(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint
|
|||
|
||||
stdOut << " Dynamic Properties:\n";
|
||||
for (DynamicPropertyIterator dpi = pInst->dynamicProperties.begin(), dpend = pInst->dynamicProperties.end(); (dpi != dpend); dpi++) {
|
||||
stdOut << "\t" << dpi->first << " = " << *meta->toString(dpi->second.value) << "\n";
|
||||
DynamicPropertyBinding *dpb = *dpi;
|
||||
stdOut << "\t" << dpb->name << " = " << *meta->toString(dpb->v.value) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,13 +91,13 @@ js2val setLength(JS2Metadata *meta, JS2Object *obj, uint32 newLength)
|
|||
// Can't call 'writeDynamicProperty' as that'll just cycle back here for
|
||||
// ArrayInstances.
|
||||
DynamicPropertyMap *dMap = &checked_cast<PrototypeInstance *>(obj)->dynamicProperties;
|
||||
DynamicPropertyIterator i = dMap->find(*meta->engine->length_StringAtom);
|
||||
if (i != dMap->end()) {
|
||||
i->second.value = result;
|
||||
DynamicPropertyBinding **dpbP = (*dMap)[*meta->engine->length_StringAtom];
|
||||
if (dpbP) {
|
||||
(*dpbP)->v.value = result;
|
||||
return result;
|
||||
}
|
||||
const DynamicPropertyMap::value_type e(*meta->engine->length_StringAtom, DynamicPropertyValue(result, DynamicPropertyValue::PERMANENT));
|
||||
checked_cast<PrototypeInstance *>(obj)->dynamicProperties.insert(e);
|
||||
DynamicPropertyBinding *dpb = new DynamicPropertyBinding(*meta->engine->length_StringAtom, DynamicPropertyValue(result, DynamicPropertyValue::PERMANENT));
|
||||
checked_cast<PrototypeInstance *>(obj)->dynamicProperties.insert(dpb->name, dpb);
|
||||
}
|
||||
else {
|
||||
meta->mn1->name = meta->engine->length_StringAtom;
|
||||
|
@ -128,8 +128,8 @@ js2val Array_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val *
|
|||
else {
|
||||
uint32 i;
|
||||
for (i = 0; i < argc; i++) {
|
||||
const DynamicPropertyMap::value_type e(*meta->engine->numberToString(i), DynamicPropertyValue(argv[i], DynamicPropertyValue::ENUMERATE));
|
||||
arrInst->dynamicProperties.insert(e);
|
||||
DynamicPropertyBinding *dpb = new DynamicPropertyBinding(*meta->engine->numberToString(i), DynamicPropertyValue(argv[i], DynamicPropertyValue::ENUMERATE));
|
||||
arrInst->dynamicProperties.insert(dpb->name, dpb);
|
||||
}
|
||||
setLength(meta, arrInst, i);
|
||||
}
|
||||
|
|
|
@ -1032,9 +1032,10 @@ namespace MetaData {
|
|||
if (dMap) {
|
||||
nameList = new const String *[dMap->size()];
|
||||
length = 0;
|
||||
for (DynamicPropertyIterator i = dMap->begin(), end = dMap->end(); (i != end); i++) {
|
||||
if (i->second.flags & DynamicPropertyValue::ENUMERATE)
|
||||
nameList[length++] = &i->first;
|
||||
for (DynamicPropertyIterator dpi = dMap->begin(), dpend = dMap->end(); (dpi != dpend); dpi++) {
|
||||
DynamicPropertyBinding *dpb = *dpi;
|
||||
if (dpb->v.flags & DynamicPropertyValue::ENUMERATE)
|
||||
nameList[length++] = &dpb->name;
|
||||
}
|
||||
it = 0;
|
||||
return (length != 0);
|
||||
|
|
|
@ -2092,8 +2092,9 @@ doUnary:
|
|||
*exprType = checked_cast<Variable *>(m2.localMember)->type;
|
||||
break;
|
||||
}
|
||||
if (m2.qname) { // an instance member
|
||||
InstanceMember *m = findInstanceMember(c, m2.qname, ReadAccess);
|
||||
if (m2.ns) { // an instance member
|
||||
QualifiedName qname(m2.ns, multiname->name);
|
||||
InstanceMember *m = findInstanceMember(c, &qname, ReadAccess);
|
||||
if (m) {
|
||||
if (m->kind == InstanceMember::InstanceVariableKind)
|
||||
*exprType = checked_cast<InstanceVariable *>(m)->type;
|
||||
|
@ -2186,21 +2187,25 @@ doUnary:
|
|||
MemberDescriptor m2;
|
||||
Multiname multiname(&i->name);
|
||||
if (findLocalMember(*exprType, &multiname, ReadAccess, CompilePhase, &m2)) {
|
||||
if (m2.qname) {
|
||||
InstanceMember *m = findInstanceMember(*exprType, m2.qname, ReadAccess);
|
||||
if (m2.ns) {
|
||||
QualifiedName qname(m2.ns, multiname.name);
|
||||
InstanceMember *m = findInstanceMember(*exprType, &qname, ReadAccess);
|
||||
if (m->kind == InstanceMember::InstanceVariableKind)
|
||||
returnRef = new SlotReference(checked_cast<InstanceVariable *>(m)->slotIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (returnRef == NULL)
|
||||
if (returnRef == NULL) {
|
||||
returnRef = new DotReference(&i->name);
|
||||
checked_cast<DotReference *>(returnRef)->propertyMultiname.addNamespace(cxt);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (b->op2->getKind() == ExprNode::qualify) {
|
||||
Reference *rVal = SetupExprNode(env, phase, b->op2, exprType);
|
||||
ASSERT(rVal && checked_cast<LexicalReference *>(rVal));
|
||||
returnRef = new DotReference(&((LexicalReference *)rVal)->variableMultiname);
|
||||
checked_cast<DotReference *>(returnRef)->propertyMultiname.addNamespace(cxt);
|
||||
}
|
||||
// XXX else bracketRef...
|
||||
else
|
||||
|
@ -2865,8 +2870,8 @@ doUnary:
|
|||
if (result == NULL) {
|
||||
if (regionalFrame->kind == GlobalObjectKind) {
|
||||
GlobalObject *gObj = checked_cast<GlobalObject *>(regionalFrame);
|
||||
DynamicPropertyIterator dp = gObj->dynamicProperties.find(*id);
|
||||
if (dp != gObj->dynamicProperties.end())
|
||||
DynamicPropertyBinding **dpbP = gObj->dynamicProperties[*id];
|
||||
if (dpbP)
|
||||
reportError(Exception::definitionError, "Duplicate definition {0}", p->pos, id);
|
||||
}
|
||||
else { // ParameterFrame didn't have any bindings, scan the preceding
|
||||
|
@ -3365,8 +3370,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
isPrototypeInstance = true;
|
||||
dMap = &(checked_cast<PrototypeInstance *>(obj))->dynamicProperties;
|
||||
}
|
||||
DynamicPropertyIterator i = dMap->find(*name);
|
||||
if (i != dMap->end())
|
||||
DynamicPropertyBinding **dpbP = (*dMap)[*name];
|
||||
if (dpbP)
|
||||
return obj;
|
||||
if (isPrototypeInstance) {
|
||||
PrototypeInstance *pInst = checked_cast<PrototypeInstance *>(obj);
|
||||
|
@ -3393,8 +3398,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
isPrototypeInstance = true;
|
||||
dMap = &(checked_cast<PrototypeInstance *>(obj))->dynamicProperties;
|
||||
}
|
||||
DynamicPropertyIterator i = dMap->find(*name);
|
||||
if (i != dMap->end())
|
||||
DynamicPropertyBinding **dpbP = (*dMap)[*name];
|
||||
if (dpbP)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -3424,9 +3429,9 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
}
|
||||
if (dMap == NULL)
|
||||
return false; // 'None'
|
||||
DynamicPropertyIterator i = dMap->find(*name);
|
||||
if (i != dMap->end()) {
|
||||
*rval = i->second.value;
|
||||
DynamicPropertyBinding **dpbP = (*dMap)[*name];
|
||||
if (dpbP) {
|
||||
*rval = (*dpbP)->v.value;
|
||||
return true;
|
||||
}
|
||||
if (isPrototypeInstance) {
|
||||
|
@ -3444,14 +3449,14 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
void SimpleInstance::writeProperty(JS2Metadata * /* meta */, const String *name, js2val newValue, uint32 flags)
|
||||
{
|
||||
ASSERT(dynamicProperties);
|
||||
const DynamicPropertyMap::value_type e(*name, DynamicPropertyValue(newValue, flags));
|
||||
dynamicProperties->insert(e);
|
||||
DynamicPropertyBinding *dpb = new DynamicPropertyBinding(*name, DynamicPropertyValue(newValue, flags));
|
||||
dynamicProperties->insert(dpb->name, dpb);
|
||||
}
|
||||
|
||||
void PrototypeInstance::writeProperty(JS2Metadata * /* meta */, const String *name, js2val newValue, uint32 flags)
|
||||
{
|
||||
const DynamicPropertyMap::value_type e(*name, DynamicPropertyValue(newValue, flags));
|
||||
dynamicProperties.insert(e);
|
||||
DynamicPropertyBinding *dpb = new DynamicPropertyBinding(*name, DynamicPropertyValue(newValue, flags));
|
||||
dynamicProperties.insert(dpb->name, dpb);
|
||||
}
|
||||
|
||||
void ArrayInstance::writeProperty(JS2Metadata *meta, const String *name, js2val newValue, uint32 flags)
|
||||
|
@ -3467,8 +3472,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
// (which it more typically is) rather than converted to string
|
||||
// and back.
|
||||
|
||||
const DynamicPropertyMap::value_type e(*name, DynamicPropertyValue(newValue, flags));
|
||||
dynamicProperties.insert(e);
|
||||
DynamicPropertyBinding *dpb = new DynamicPropertyBinding(*name, DynamicPropertyValue(newValue, flags));
|
||||
dynamicProperties.insert(dpb->name, dpb);
|
||||
|
||||
const char16 *numEnd;
|
||||
float64 f = stringToDouble(name->data(), name->data() + name->length(), numEnd);
|
||||
|
@ -3503,8 +3508,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
dMap = &(checked_cast<PrototypeInstance *>(container))->dynamicProperties;
|
||||
if (dMap == NULL)
|
||||
return false; // 'None'
|
||||
DynamicPropertyIterator i = dMap->find(*name);
|
||||
if (i != dMap->end()) {
|
||||
DynamicPropertyBinding **dpbP = (*dMap)[*name];
|
||||
if (dpbP) {
|
||||
// special case handling for setting 'length' property of ArrayInstances
|
||||
// XXX should handle this with dispatch to 'writeProperty' of each of
|
||||
// the different dynamic map containing objects, and change current
|
||||
|
@ -3519,15 +3524,16 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
setLength(this, container, newLength);
|
||||
}
|
||||
else
|
||||
if ((i->second.flags & DynamicPropertyValue::READONLY) == 0)
|
||||
i->second.value = newValue;
|
||||
if (((*dpbP)->v.flags & DynamicPropertyValue::READONLY) == 0)
|
||||
(*dpbP)->v.value = newValue;
|
||||
return true;
|
||||
}
|
||||
if (!createIfMissing)
|
||||
return false;
|
||||
if (container->kind == SimpleInstanceKind) {
|
||||
SimpleInstance *dynInst = checked_cast<SimpleInstance *>(container);
|
||||
InstanceBinding *ib = resolveInstanceMemberName(dynInst->type, multiname, ReadAccess, phase);
|
||||
QualifiedName qname;
|
||||
InstanceBinding *ib = resolveInstanceMemberName(dynInst->type, multiname, ReadAccess, phase, &qname);
|
||||
if (ib == NULL) {
|
||||
dynInst->writeProperty(this, name, newValue, 0);
|
||||
return true;
|
||||
|
@ -3538,8 +3544,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
GlobalObject *glob = checked_cast<GlobalObject *>(container);
|
||||
LocalMember *m = findFlatMember(glob, multiname, ReadAccess, phase);
|
||||
if (m == NULL) {
|
||||
const DynamicPropertyMap::value_type e(*name, DynamicPropertyValue(newValue));
|
||||
glob->dynamicProperties.insert(e);
|
||||
DynamicPropertyBinding *dpb = new DynamicPropertyBinding(*name, DynamicPropertyValue(newValue, DynamicPropertyValue::ENUMERATE));
|
||||
glob->dynamicProperties.insert(dpb->name, dpb);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -3632,7 +3638,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
if (JS2VAL_IS_PRIMITIVE(*containerVal)) {
|
||||
readClassProperty:
|
||||
JS2Class *c = objectType(*containerVal);
|
||||
InstanceBinding *ib = resolveInstanceMemberName(c, multiname, ReadAccess, phase);
|
||||
QualifiedName qname;
|
||||
InstanceBinding *ib = resolveInstanceMemberName(c, multiname, ReadAccess, phase, &qname);
|
||||
if ((ib == NULL) && isSimpleInstance)
|
||||
return readDynamicProperty(JS2VAL_TO_OBJECT(*containerVal), multiname, lookupKind, phase, rval);
|
||||
else {
|
||||
|
@ -3641,7 +3648,7 @@ readClassProperty:
|
|||
if (!JS2VAL_IS_OBJECT(*containerVal))
|
||||
*containerVal = toObject(*containerVal);
|
||||
else
|
||||
return readInstanceMember(*containerVal, c, (ib) ? &ib->qname : NULL, phase, rval);
|
||||
return readInstanceMember(*containerVal, c, (ib) ? &qname : NULL, phase, rval);
|
||||
}
|
||||
}
|
||||
container = JS2VAL_TO_OBJECT(*containerVal);
|
||||
|
@ -3753,7 +3760,8 @@ readClassProperty:
|
|||
// 'this' is {generic}
|
||||
// XXX is ??? in spec.
|
||||
}
|
||||
return readInstanceMember(thisObject, objectType(thisObject), m2.qname, phase, rval);
|
||||
QualifiedName qname(m2.ns, multiname->name);
|
||||
return readInstanceMember(thisObject, objectType(thisObject), &qname, phase, rval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3774,11 +3782,12 @@ readClassProperty:
|
|||
case SimpleInstanceKind:
|
||||
{
|
||||
JS2Class *c = checked_cast<SimpleInstance *>(container)->type;
|
||||
InstanceBinding *ib = resolveInstanceMemberName(c, multiname, WriteAccess, phase);
|
||||
QualifiedName qname;
|
||||
InstanceBinding *ib = resolveInstanceMemberName(c, multiname, WriteAccess, phase, &qname);
|
||||
if (ib == NULL)
|
||||
return writeDynamicProperty(container, multiname, createIfMissing, newValue, phase);
|
||||
else
|
||||
return writeInstanceMember(containerVal, c, (ib) ? &ib->qname : NULL, newValue, phase);
|
||||
return writeInstanceMember(containerVal, c, (ib) ? &qname : NULL, newValue, phase);
|
||||
}
|
||||
|
||||
case SystemKind:
|
||||
|
@ -3865,7 +3874,8 @@ readClassProperty:
|
|||
// 'this' is {generic}
|
||||
// XXX is ??? in spec.
|
||||
}
|
||||
return writeInstanceMember(thisObject, objectType(thisObject), m2.qname, newValue, phase);
|
||||
QualifiedName qname(m2.ns, multiname->name);
|
||||
return writeInstanceMember(thisObject, objectType(thisObject), &qname, newValue, phase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3877,11 +3887,12 @@ readClassProperty:
|
|||
if (JS2VAL_IS_PRIMITIVE(containerVal)) {
|
||||
deleteClassProperty:
|
||||
JS2Class *c = objectType(containerVal);
|
||||
InstanceBinding *ib = resolveInstanceMemberName(c, multiname, ReadAccess, phase);
|
||||
QualifiedName qname;
|
||||
InstanceBinding *ib = resolveInstanceMemberName(c, multiname, ReadAccess, phase, &qname);
|
||||
if ((ib == NULL) && isSimpleInstance)
|
||||
return deleteDynamicProperty(JS2VAL_TO_OBJECT(containerVal), multiname, lookupKind, result);
|
||||
else
|
||||
return deleteInstanceMember(c, (ib) ? &ib->qname : NULL, result);
|
||||
return deleteInstanceMember(c, (ib) ? &qname : NULL, result);
|
||||
}
|
||||
JS2Object *container = JS2VAL_TO_OBJECT(containerVal);
|
||||
switch (container->kind) {
|
||||
|
@ -3943,7 +3954,8 @@ deleteClassProperty:
|
|||
*result = false;
|
||||
return true;
|
||||
}
|
||||
return deleteInstanceMember(objectType(thisObject), m2.qname, result);
|
||||
QualifiedName qname(m2.ns, multiname->name);
|
||||
return deleteInstanceMember(objectType(thisObject), &qname, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3965,10 +3977,10 @@ deleteClassProperty:
|
|||
else {
|
||||
dMap = &(checked_cast<PrototypeInstance *>(container))->dynamicProperties;
|
||||
}
|
||||
DynamicPropertyIterator i = dMap->find(*name);
|
||||
if (i != dMap->end()) {
|
||||
if ((i->second.flags & DynamicPropertyValue::PERMANENT) == 0) {
|
||||
dMap->erase(i);
|
||||
DynamicPropertyBinding **dpbP = (*dMap)[*name];
|
||||
if (dpbP) {
|
||||
if (((*dpbP)->v.flags & DynamicPropertyValue::PERMANENT) == 0) {
|
||||
dMap->erase(*name); // XXX more efficient scheme?
|
||||
*result = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -4031,7 +4043,7 @@ deleteClassProperty:
|
|||
bool JS2Metadata::findLocalMember(JS2Class *c, Multiname *multiname, Access access, Phase /* phase */, MemberDescriptor *result)
|
||||
{
|
||||
result->localMember = NULL;
|
||||
result->qname = NULL;
|
||||
result->ns = NULL;
|
||||
JS2Class *s = c;
|
||||
while (s) {
|
||||
LocalMember *found = NULL;
|
||||
|
@ -4042,41 +4054,33 @@ deleteClassProperty:
|
|||
if ((ns.second->accesses & access) && multiname->listContains(ns.first)) {
|
||||
if (found && (ns.second->content != found))
|
||||
reportError(Exception::propertyAccessError, "Ambiguous reference to {0}", engine->errorPos(), multiname->name);
|
||||
else
|
||||
else {
|
||||
found = ns.second->content;
|
||||
result->localMember = found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
result->localMember = found;
|
||||
result->qname = NULL;
|
||||
if (found)
|
||||
return true;
|
||||
}
|
||||
|
||||
InstanceBinding *iFound = NULL;
|
||||
InstanceBindingIterator ib, iend;
|
||||
if (access & ReadAccess) {
|
||||
ib = s->instanceReadBindings.lower_bound(*multiname->name);
|
||||
iend = s->instanceReadBindings.upper_bound(*multiname->name);
|
||||
InstanceBindingEntry **ibeP = s->instanceBindings[*multiname->name];
|
||||
if (ibeP) {
|
||||
for (InstanceBindingEntry::NS_Iterator i = (*ibeP)->begin(), end = (*ibeP)->end(); (i != end); i++) {
|
||||
InstanceBindingEntry::NamespaceBinding &ns = *i;
|
||||
if ((ns.second->accesses & access) && multiname->listContains(ns.first))
|
||||
if (iFound && (ns.second->content != iFound->content))
|
||||
reportError(Exception::propertyAccessError, "Ambiguous reference to {0}", engine->errorPos(), multiname->name);
|
||||
else {
|
||||
iFound = ns.second;
|
||||
result->ns = ns.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ib = s->instanceWriteBindings.lower_bound(*multiname->name);
|
||||
iend = s->instanceWriteBindings.upper_bound(*multiname->name);
|
||||
}
|
||||
while (ib != iend) {
|
||||
if (multiname->matches(ib->second->qname)) {
|
||||
if (iFound && (ib->second->content != iFound->content))
|
||||
reportError(Exception::propertyAccessError, "Ambiguous reference to {0}", engine->errorPos(), multiname->name);
|
||||
else
|
||||
iFound = ib->second;
|
||||
}
|
||||
ib++;
|
||||
}
|
||||
if (iFound) {
|
||||
result->localMember = NULL;
|
||||
result->qname = &iFound->qname;
|
||||
|
||||
if (iFound)
|
||||
return true;
|
||||
}
|
||||
s = s->super;
|
||||
}
|
||||
return false;
|
||||
|
@ -4087,40 +4091,26 @@ deleteClassProperty:
|
|||
* Find the binding that matches the given access and multiname, it's an error if more than one such exists.
|
||||
*
|
||||
*/
|
||||
InstanceBinding *JS2Metadata::resolveInstanceMemberName(JS2Class *c, Multiname *multiname, Access access, Phase phase)
|
||||
InstanceBinding *JS2Metadata::resolveInstanceMemberName(JS2Class *c, Multiname *multiname, Access access, Phase phase, QualifiedName *qname)
|
||||
{
|
||||
InstanceBinding *result = NULL;
|
||||
if (c->super) {
|
||||
result = resolveInstanceMemberName(c->super, multiname, access, phase);
|
||||
result = resolveInstanceMemberName(c->super, multiname, access, phase, qname);
|
||||
if (result) return result;
|
||||
}
|
||||
InstanceBindingIterator b, end;
|
||||
if (access & ReadAccess) {
|
||||
b = c->instanceReadBindings.lower_bound(*multiname->name);
|
||||
end = c->instanceReadBindings.upper_bound(*multiname->name);
|
||||
}
|
||||
else {
|
||||
b = c->instanceWriteBindings.lower_bound(*multiname->name);
|
||||
end = c->instanceWriteBindings.upper_bound(*multiname->name);
|
||||
}
|
||||
while (true) {
|
||||
if (b == end) {
|
||||
if (access == ReadWriteAccess) {
|
||||
access = WriteAccess;
|
||||
b = c->instanceWriteBindings.lower_bound(*multiname->name);
|
||||
end = c->instanceWriteBindings.upper_bound(*multiname->name);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
break;
|
||||
InstanceBindingEntry **ibeP = c->instanceBindings[*multiname->name];
|
||||
if (ibeP) {
|
||||
for (InstanceBindingEntry::NS_Iterator i = (*ibeP)->begin(), end = (*ibeP)->end(); (i != end); i++) {
|
||||
InstanceBindingEntry::NamespaceBinding &ns = *i;
|
||||
if ((ns.second->accesses & access) && multiname->listContains(ns.first))
|
||||
if (result && (ns.second->content != result->content))
|
||||
reportError(Exception::propertyAccessError, "Ambiguous reference to {0}", engine->errorPos(), multiname->name);
|
||||
else {
|
||||
result = ns.second;
|
||||
qname->id = multiname->name;
|
||||
qname->nameSpace = ns.first;
|
||||
}
|
||||
}
|
||||
if (multiname->matches(b->second->qname)) {
|
||||
if (result && (b->second->content != result->content))
|
||||
reportError(Exception::propertyAccessError, "Ambiguous reference to {0}", engine->errorPos(), multiname->name);
|
||||
else
|
||||
result = b->second;
|
||||
}
|
||||
b++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -4315,13 +4305,13 @@ deleteClassProperty:
|
|||
GCMARKOBJECT(privateNamespace)
|
||||
if (name) JS2Object::mark(name);
|
||||
GCMARKVALUE(defaultValue);
|
||||
InstanceBindingIterator ib, iend;
|
||||
for (ib = instanceReadBindings.begin(), iend = instanceReadBindings.end(); (ib != iend); ib++) {
|
||||
ib->second->content->mark();
|
||||
}
|
||||
for (ib = instanceWriteBindings.begin(), iend = instanceWriteBindings.end(); (ib != iend); ib++) {
|
||||
ib->second->content->mark();
|
||||
}
|
||||
for (InstanceBindingIterator rib = instanceBindings.begin(), riend = instanceBindings.end(); (rib != riend); rib++) {
|
||||
InstanceBindingEntry *ibe = *rib;
|
||||
for (InstanceBindingEntry::NS_Iterator i = ibe->begin(), end = ibe->end(); (i != end); i++) {
|
||||
InstanceBindingEntry::NamespaceBinding ns = *i;
|
||||
ns.second->content->mark();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return true if 'heir' is this class or is any antecedent
|
||||
|
@ -4436,8 +4426,9 @@ deleteClassProperty:
|
|||
}
|
||||
}
|
||||
if (dynamicProperties) {
|
||||
for (DynamicPropertyIterator i = dynamicProperties->begin(), end = dynamicProperties->end(); (i != end); i++) {
|
||||
GCMARKVALUE(i->second.value);
|
||||
for (DynamicPropertyIterator dpi = dynamicProperties->begin(), dpend = dynamicProperties->end(); (dpi != dpend); dpi++) {
|
||||
DynamicPropertyBinding *dpb = *dpi;
|
||||
GCMARKVALUE(dpb->v.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4497,8 +4488,9 @@ deleteClassProperty:
|
|||
void PrototypeInstance::markChildren()
|
||||
{
|
||||
GCMARKOBJECT(parent)
|
||||
for (DynamicPropertyIterator i = dynamicProperties.begin(), end = dynamicProperties.end(); (i != end); i++) {
|
||||
GCMARKVALUE(i->second.value);
|
||||
for (DynamicPropertyIterator dpi = dynamicProperties.begin(), dpend = dynamicProperties.end(); (dpi != dpend); dpi++) {
|
||||
DynamicPropertyBinding *dpb = *dpi;
|
||||
GCMARKVALUE(dpb->v.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4588,8 +4580,9 @@ deleteClassProperty:
|
|||
{
|
||||
NonWithFrame::markChildren();
|
||||
GCMARKOBJECT(internalNamespace)
|
||||
for (DynamicPropertyIterator i = dynamicProperties.begin(), end = dynamicProperties.end(); (i != end); i++) {
|
||||
GCMARKVALUE(i->second.value);
|
||||
for (DynamicPropertyIterator dpi = dynamicProperties.begin(), dpend = dynamicProperties.end(); (dpi != dpend); dpi++) {
|
||||
DynamicPropertyBinding *dpb = *dpi;
|
||||
GCMARKVALUE(dpb->v.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -239,6 +239,7 @@ public:
|
|||
// A QualifiedName is the combination of an identifier and a namespace
|
||||
class QualifiedName {
|
||||
public:
|
||||
QualifiedName() : nameSpace(NULL), id(NULL) { }
|
||||
QualifiedName(Namespace *nameSpace, const String *id) : nameSpace(nameSpace), id(id) { }
|
||||
|
||||
bool operator ==(const QualifiedName &b) { return (nameSpace == b.nameSpace) && (*id == *b.id); }
|
||||
|
@ -395,8 +396,18 @@ public:
|
|||
js2val value;
|
||||
uint32 flags;
|
||||
};
|
||||
typedef std::map<String, DynamicPropertyValue> DynamicPropertyMap;
|
||||
typedef DynamicPropertyMap::iterator DynamicPropertyIterator;
|
||||
|
||||
class DynamicPropertyBinding {
|
||||
public:
|
||||
DynamicPropertyBinding(const String name) : name(name), v(JS2VAL_VOID) { }
|
||||
DynamicPropertyBinding(const String name, DynamicPropertyValue v) : name(name), v(v) { }
|
||||
|
||||
const String name;
|
||||
DynamicPropertyValue v;
|
||||
};
|
||||
|
||||
typedef HashTable<DynamicPropertyBinding *, const String> DynamicPropertyMap;
|
||||
typedef TableIterator<DynamicPropertyBinding *, const String> DynamicPropertyIterator;
|
||||
|
||||
|
||||
// A LOCALBINDING describes the member to which one qualified name is bound in a frame. Multiple
|
||||
|
@ -1105,7 +1116,7 @@ typedef std::vector<StmtNode *>::reverse_iterator TargetListReverseIterator;
|
|||
|
||||
struct MemberDescriptor {
|
||||
LocalMember *localMember;
|
||||
QualifiedName *qname;
|
||||
Namespace *ns;
|
||||
};
|
||||
|
||||
class CompilationData {
|
||||
|
@ -1153,7 +1164,7 @@ public:
|
|||
bool relaxedHasType(js2val objVal, JS2Class *c);
|
||||
|
||||
LocalMember *findFlatMember(NonWithFrame *container, Multiname *multiname, Access access, Phase phase);
|
||||
InstanceBinding *resolveInstanceMemberName(JS2Class *js2class, Multiname *multiname, Access access, Phase phase);
|
||||
InstanceBinding *resolveInstanceMemberName(JS2Class *js2class, Multiname *multiname, Access access, Phase phase, QualifiedName *qname);
|
||||
|
||||
DynamicVariable *defineHoistedVar(Environment *env, const String *id, StmtNode *p);
|
||||
Multiname *defineLocalMember(Environment *env, const String *id, NamespaceList *namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, Access access, LocalMember *m, size_t pos);
|
||||
|
@ -1289,6 +1300,13 @@ public:
|
|||
inline bool operator==(MetaData::LocalBindingEntry *s1, const String &s2) { return s1->name == s2;}
|
||||
inline bool operator!=(MetaData::LocalBindingEntry *s1, const String &s2) { return s1->name != s2;}
|
||||
|
||||
inline bool operator==(MetaData::InstanceBindingEntry *s1, const String &s2) { return s1->name == s2;}
|
||||
inline bool operator!=(MetaData::InstanceBindingEntry *s1, const String &s2) { return s1->name != s2;}
|
||||
|
||||
inline bool operator==(MetaData::DynamicPropertyBinding *s1, const String &s2) { return s1->name == s2;}
|
||||
inline bool operator!=(MetaData::DynamicPropertyBinding *s1, const String &s2) { return s1->name != s2;}
|
||||
|
||||
|
||||
}; // namespace Javascript
|
||||
|
||||
#endif
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
push(meta->env->lexicalRead(meta, mn, phase));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case eLexicalDelete:
|
||||
|
@ -100,7 +100,7 @@
|
|||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
push(BOOLEAN_TO_JS2VAL(meta->env->lexicalDelete(meta, mn, phase)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Write the top value to the multiname in the environment, leave
|
||||
|
@ -111,7 +111,7 @@
|
|||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
meta->env->lexicalWrite(meta, mn, a, true, phase);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Write the top value to the multiname in the environment, leave
|
||||
|
@ -122,7 +122,7 @@
|
|||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
meta->env->lexicalInit(meta, mn, a);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Construct a reference pair consisting of a NULL base and the read value
|
||||
|
@ -133,7 +133,7 @@
|
|||
a = meta->env->lexicalRead(meta, mn, phase);
|
||||
push(JS2VAL_NULL);
|
||||
push(a);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Read an index property from a base object, push the value onto the stack
|
||||
|
|
|
@ -123,8 +123,8 @@
|
|||
String *name = JS2VAL_TO_STRING(a);
|
||||
const StringAtom &nameAtom = meta->world.identifiers[*name];
|
||||
b = pop();
|
||||
const DynamicPropertyMap::value_type e(nameAtom, b);
|
||||
pInst->dynamicProperties.insert(e);
|
||||
DynamicPropertyBinding *dpb = new DynamicPropertyBinding(nameAtom, DynamicPropertyValue(b, DynamicPropertyValue::ENUMERATE));
|
||||
pInst->dynamicProperties.insert(dpb->name, dpb);
|
||||
}
|
||||
push(baseVal);
|
||||
baseVal = JS2VAL_VOID;
|
||||
|
@ -139,8 +139,8 @@
|
|||
baseVal = OBJECT_TO_JS2VAL(aInst);
|
||||
for (uint16 i = 0; i < argCount; i++) {
|
||||
b = pop();
|
||||
const DynamicPropertyMap::value_type e(*numberToString((argCount - 1) - i), DynamicPropertyValue(b));
|
||||
aInst->dynamicProperties.insert(e);
|
||||
DynamicPropertyBinding *dpb = new DynamicPropertyBinding(*numberToString((argCount - 1) - i), DynamicPropertyValue(b, DynamicPropertyValue::ENUMERATE));
|
||||
aInst->dynamicProperties.insert(dpb->name, dpb);
|
||||
}
|
||||
setLength(meta, aInst, argCount);
|
||||
push(baseVal);
|
||||
|
|
|
@ -66,10 +66,11 @@ js2val String_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val
|
|||
strInst->mValue = meta->engine->allocStringPtr(meta->toString(argv[0]));
|
||||
else
|
||||
strInst->mValue = meta->engine->allocStringPtr("");
|
||||
const DynamicPropertyMap::value_type e(*meta->engine->length_StringAtom,
|
||||
|
||||
DynamicPropertyBinding *dpb = new DynamicPropertyBinding(*meta->engine->length_StringAtom,
|
||||
DynamicPropertyValue(meta->engine->allocNumber(strInst->mValue->length()),
|
||||
DynamicPropertyValue::READONLY | DynamicPropertyValue::PERMANENT));
|
||||
strInst->dynamicProperties.insert(e);
|
||||
strInst->dynamicProperties.insert(dpb->name, dpb);
|
||||
JS2Object::removeRoot(ri);
|
||||
return thatValue;
|
||||
}
|
||||
|
@ -798,10 +799,11 @@ void initStringObject(JS2Metadata *meta)
|
|||
StringInstance *strInst = new StringInstance(meta, meta->objectClass->prototype, meta->stringClass);
|
||||
meta->stringClass->prototype = strInst;
|
||||
strInst->mValue = meta->engine->allocStringPtr("");
|
||||
const DynamicPropertyMap::value_type e(*meta->engine->length_StringAtom,
|
||||
|
||||
DynamicPropertyBinding *dpb = new DynamicPropertyBinding(*meta->engine->length_StringAtom,
|
||||
DynamicPropertyValue(meta->engine->allocNumber(strInst->mValue->length()),
|
||||
DynamicPropertyValue::READONLY | DynamicPropertyValue::PERMANENT));
|
||||
strInst->dynamicProperties.insert(e);
|
||||
strInst->dynamicProperties.insert(dpb->name, dpb);
|
||||
meta->initBuiltinClass(meta->stringClass, &prototypeFunctions[0], &staticFunctions[0], String_Constructor, String_Call);
|
||||
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче