void HoverHandler::handleImport(const ScopeChain &scopeChain, AST::UiImport *node) { const Imports *imports = scopeChain.context()->imports(scopeChain.document().data()); if (!imports) return; foreach (const Import &import, imports->all()) { if (import.info.ast() == node) { if (import.info.type() == ImportInfo::LibraryImport && !import.libraryPath.isEmpty()) { QString msg = tr("Library at %1").arg(import.libraryPath); const LibraryInfo &libraryInfo = scopeChain.context()->snapshot().libraryInfo(import.libraryPath); if (libraryInfo.pluginTypeInfoStatus() == LibraryInfo::DumpDone) { msg += QLatin1Char('\n'); msg += tr("Dumped plugins successfully."); } else if (libraryInfo.pluginTypeInfoStatus() == LibraryInfo::TypeInfoFileDone) { msg += QLatin1Char('\n'); msg += tr("Read typeinfo files successfully."); } setToolTip(msg); } else { setToolTip(import.info.name()); } break; } } }
TextEditor::HelpItem HoverHandler::qmlHelpItem(const ScopeChain &scopeChain, AST::Node *node) const { QString name; if (const ObjectValue *scope = isMember(scopeChain, node, &name)) { // maybe it's a type? if (!name.isEmpty() && name.at(0).isUpper()) { const QString maybeHelpId(QLatin1String("QML.") + name); if (!Core::HelpManager::instance()->linksForIdentifier(maybeHelpId).isEmpty()) return TextEditor::HelpItem(maybeHelpId, name, TextEditor::HelpItem::QmlComponent); } // otherwise, it's probably a property const ObjectValue *lastScope; scope->lookupMember(name, scopeChain.context(), &lastScope); PrototypeIterator iter(scope, scopeChain.context()); while (iter.hasNext()) { const ObjectValue *cur = iter.next(); const QString className = cur->className(); if (!className.isEmpty()) { const QString maybeHelpId(className + QLatin1String("::") + name); if (!Core::HelpManager::instance()->linksForIdentifier(maybeHelpId).isEmpty()) return TextEditor::HelpItem(maybeHelpId, name, TextEditor::HelpItem::QmlProperty); } if (cur == lastScope) break; } } return TextEditor::HelpItem(); }
Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue thisValue) { //zyc /* ofstream out("fromCompletion.txt", ios::app); char *output = source.toString().ascii(); out<<output<<endl; out.close();*/ //done zyc //out.write(output.utf8().data(),output.utf8().length()); //out.write('\n',1); JSLock lock(exec); ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable()); RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source); JSObject* error = program->compile(exec, scopeChain.node()); if (error) return Completion(Throw, error); JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec); JSValue exception; JSValue result = exec->interpreter()->execute(program.get(), exec, scopeChain.node(), thisObj, &exception); if (exception) { ComplType exceptionType = Throw; if (exception.isObject()) exceptionType = asObject(exception)->exceptionType(); return Completion(exceptionType, exception); } return Completion(Normal, result); }
void HoverHandler::handleOrdinaryMatch(const ScopeChain &scopeChain, AST::Node *node) { if (node && !(AST::cast<AST::StringLiteral *>(node) != 0 || AST::cast<AST::NumericLiteral *>(node) != 0)) { const Value *value = scopeChain.evaluate(node); prettyPrintTooltip(value, scopeChain.context()); } }
void invalidate() { base.invalidate(); ScopeChain::Iterator it = context.begin(); while (it != context.end()) { (*it).invalidate(); it++; } }
bool HoverHandler::matchColorItem(const ScopeChain &scopeChain, const Document::Ptr &qmlDocument, const QList<AST::Node *> &astPath, unsigned pos) { AST::UiObjectInitializer *initializer = nodeInitializer(astPath.last()); if (!initializer) return false; AST::UiObjectMember *member = 0; for (AST::UiObjectMemberList *list = initializer->members; list; list = list->next) { if (posIsInSource(pos, list->member)) { member = list->member; break; } } if (!member) return false; QString color; const Value *value = 0; if (const AST::UiScriptBinding *binding = AST::cast<const AST::UiScriptBinding *>(member)) { if (binding->qualifiedId && posIsInSource(pos, binding->statement)) { value = scopeChain.evaluate(binding->qualifiedId); if (value && value->asColorValue()) { color = textAt(qmlDocument, binding->statement->firstSourceLocation(), binding->statement->lastSourceLocation()); } } } else if (const AST::UiPublicMember *publicMember = AST::cast<const AST::UiPublicMember *>(member)) { if (!publicMember->name.isEmpty() && posIsInSource(pos, publicMember->statement)) { value = scopeChain.lookup(publicMember->name.toString()); if (const Reference *ref = value->asReference()) value = scopeChain.context()->lookupReference(ref); if (value && value->asColorValue()) { color = textAt(qmlDocument, publicMember->statement->firstSourceLocation(), publicMember->statement->lastSourceLocation()); } } } if (!color.isEmpty()) { color.remove(QLatin1Char('\'')); color.remove(QLatin1Char('\"')); color.remove(QLatin1Char(';')); m_colorTip = QmlJS::toQColor(color); if (m_colorTip.isValid()) { setToolTip(color); return true; } } return false; }
ScopeChain QSEnv::scope() const { ScopeChain chain; ScopeChain::const_iterator it = scopeChain->begin(); while (it != scopeChain->end() && (*it).isValid()) { chain.push_back(*it); it++; } return chain; }
/*static*/ ScopeChain* ScopeChain::create(MMgc::GC* gc, const ScopeTypeChain* scopeTraits, const ScopeChain* outer, Namespacep dxns) { const int scopeTraitsSize = scopeTraits->size; const int outerSize = outer ? outer->_scopeTraits->size : 0; const size_t padSize = scopeTraitsSize > 0 ? sizeof(Atom) * (scopeTraitsSize-1) : 0; ScopeChain* nscope = new(gc, padSize) ScopeChain(scopeTraits, dxns); for (int i=0; i < outerSize; i ++) { nscope->setScope(gc, i, outer->_scopes[i]); } return nscope; }
QSObject QSFuncRefClass::createReference( const QSObject &base, const QSMember &mem ) const { ScopeChain chain = env()->scope(); // Reversed order for simplified iteration later. ScopeChain context; ScopeChain::const_iterator it = chain.begin(); while( it!=chain.end() ) { context.push_front( *it ); it++; } return env()->createShared( this, new QSReferenceData( context, base, mem ) ); }
void JSHTMLElement::pushEventHandlerScope(ExecState* exec, ScopeChain& scope) const { HTMLElement* element = impl(); // The document is put on first, fall back to searching it only after the element and form. scope.push(static_cast<JSObject*>(toJS(exec, element->ownerDocument()))); // The form is next, searched before the document, but after the element itself. if (HTMLFormElement* form = element->form()) scope.push(static_cast<JSObject*>(toJS(exec, form))); // The element is on top, searched first. scope.push(static_cast<JSObject*>(toJS(exec, element))); }
/*static*/ CreateInstanceProc ClassClosure::calcCreateInstanceProc(VTable* cvtable) { VTable* ivtable = cvtable->ivtable; if (ivtable && ivtable->base) { ScopeChain* scope = cvtable->init->scope(); if (scope->getSize()) { Atom baseAtom = scope->getScope(scope->getSize()-1); if (!AvmCore::isObject(baseAtom)) cvtable->toplevel()->throwVerifyError(kCorruptABCError); ScriptObject* base = AvmCore::atomToScriptObject(baseAtom); // make sure scope object is base type's class object AvmAssert(base->traits()->itraits == cvtable->traits->itraits->base); if (base->traits()->itraits->isAbstractBase) { // If we get here, it means that we descend from an abstract base class, // but don't have a native createInstanceProc of our own; in that case, we // should just create a plain old ScriptObject. (Note that this can // happen for abstract and abstract-restricted; for the latter, we will do // a second check in checkForRestrictedInheritance() and may reject it anyway.) goto create_normal; } // ...otherwise, we're done. ClassClosure* base_cc = base->toClassClosure(); AvmAssert(base_cc != NULL); CreateInstanceProc proc = base_cc->m_createInstanceProc; // If the proc is SemiSealedArrayObject, revert back to normal Array, // and let checkForRestrictedInheritance() choose the proper proc: // we might be a dynamic subclass of a non-dynamic subclass of Array. if (proc == SemiSealedArrayObject::createInstanceProc) proc = ArrayClass::createInstanceProc; // Bugzilla 688486: don't use unsubclassed-specialized // instance creator to create subclassed instances. if (proc == ArrayClass::createUnsubclassedInstanceProc) proc = ArrayClass::createInstanceProc; return proc; } } create_normal: return ClassClosure::createScriptObjectProc; }
bool hasStatePrototype(Node *ast) { Bind *bind = m_scopeChain.document()->bind(); const ObjectValue *v = bind->findQmlObject(ast); if (!v) return false; PrototypeIterator it(v, m_scopeChain.context()); while (it.hasNext()) { const ObjectValue *proto = it.next(); const CppComponentValue *qmlProto = value_cast<CppComponentValue>(proto); if (!qmlProto) continue; if (qmlProto->metaObject() == m_statePrototype->metaObject()) return true; } return false; }
Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue thisValue) { JSLock lock(exec); ASSERT(exec->globalData().identifierTable == currentIdentifierTable()); RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source); JSObject* error = program->compile(exec, scopeChain.node()); if (error) return Completion(Throw, error); JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec); JSValue exception; JSValue result = exec->interpreter()->execute(program.get(), exec, scopeChain.node(), thisObj, &exception); if (exception) { if (exception.isObject() && asObject(exception)->isWatchdogException()) return Completion(Interrupted, exception); return Completion(Throw, exception); } return Completion(Normal, result); }
void CallStackNode::enumerateScopeChainAtoms(IScopeChainEnumerator& scb) { // First, get the "dynamic" portion of the scope chain, that is, the // part that is modified on-the-fly within the function. This includes // activation objects for try/catch blocks and "with" clauses. if (m_info) { MethodSignaturep const ms = m_info->getMethodSignature(); for (int i = (ms->max_scope() + ms->local_count() - 1), n = ms->local_count(); i >= n; --i) { Atom const scope = m_info->boxOneLocal(m_framep, i, m_traits); AvmAssert(atomKind(scope) != kUnusedAtomTag); // go ahead and call addScope, even if null or undefined. scb.addScope(scope); } } // Next, get the "static" portion of the scope chain, that is, the // part that is defined as part of the definition of the function. This // includes the locals of any functions that enclose this one, and the "this" // object, if any. ScopeChain* scopeChain = m_env ? m_env->scope() : NULL; if (scopeChain) { int scopeChainLength = scopeChain->getSize(); for (int i = scopeChainLength - 1; i >= 0; --i) { Atom scope = scopeChain->getScope(i); if (AvmCore::isObject(scope)) { scb.addScope(scope); } } } }
CollectStateNames(const ScopeChain &scopeChain) : m_scopeChain(scopeChain) { m_statePrototype = scopeChain.context()->valueOwner()->cppQmlTypes().objectByCppName(QLatin1String("QDeclarativeState")); }
ClassClosure *SamplerScript::getType(Toplevel* ss_toplevel, SamplerObjectType sot, const void *ptr) { Toplevel* tl; switch (sotGetKind(sot)) { case kSOT_String: { // toplevel can be null here if there was no CodeContext active // when the sample was taken (ie, string was allocated from C++ code). // in that case, use the TL from the SamplerScript itself... it isn't // technically the right one to use, but is adequate for our purposes here // (it will return a stringClass or namespaceClass that will be valid // for the sampler) tl = sotGetToplevel(sot); if (!tl) tl = ss_toplevel; return tl->stringClass(); } case kSOT_Namespace: { tl = sotGetToplevel(sot); if (!tl) tl = ss_toplevel; return tl->namespaceClass(); } default: AvmAssert(0); case kSOT_Object: break; } VTable* vt = sotGetVTable(sot); tl = vt->toplevel(); AvmCore* core = tl->core(); ClassClosure *type; ScriptObject* obj = (ScriptObject*)ptr; if (obj && AvmCore::istype(obj->atom(), core->traits.class_itraits)) { type = tl->classClass(); } else if (obj && AvmCore::istype(obj->atom(), core->traits.function_itraits)) { type = tl->functionClass(); } else if (obj && obj->traits()->isActivationTraits()) { type = tl->objectClass; } else { // fallback answer type = tl->objectClass; // note that note all types will have an init method, // so those types may get reported as "objectClass" rather // than something more specific. However, it's not clear // that the Sampler ever really cared about reporting those // objects well in the first place (eg activation or catch objects), // so it doesn't seem we're a lot worse off than before. ScopeChain* sc = NULL; if (vt->init) sc = vt->init->scope(); if (sc && sc->getSize() <= 1) { if(sc->getSize() == 1) type = tl->classClass(); } else if (sc) { Atom ccAtom = sc->getScope(sc->getSize()-1); if(AvmCore::isObject(ccAtom)) { type = (ClassClosure*) AvmCore::atomToScriptObject(ccAtom); if(!AvmCore::istype(type->atom(), core->traits.class_itraits)) { // obj is a ClassClosure type = tl->classClass(); } } } } AvmAssert(AvmCore::istype(type->atom(), core->traits.class_itraits)); return type; }
// ECMA 15.3.2 The Function Constructor JSObject *FunctionObjectImp::construct(ExecState *exec, const List &args, const Identifier &functionName, const UString &sourceURL, int lineNumber) { UString p(""); UString body; int argsSize = args.size(); if (argsSize == 0) { body = ""; } else if (argsSize == 1) { body = args[0]->toString(exec); } else { p = args[0]->toString(exec); for (int k = 1; k < argsSize - 1; k++) { p += "," + args[k]->toString(exec); } body = args[argsSize - 1]->toString(exec); } // parse the source code int sourceId; int errLine; UString errMsg; RefPtr<FunctionBodyNode> functionBody = parser().parseFunctionBody(sourceURL, lineNumber, body.data(), body.size(), &sourceId, &errLine, &errMsg); // notify debugger that source has been parsed Debugger *dbg = exec->dynamicInterpreter()->debugger(); if (dbg) { // make sure to pass in sourceURL, since it's useful for lazy event listeners, and empty for actual function ctor dbg->reportSourceParsed(exec, functionBody.get(), sourceId, sourceURL, body, lineNumber, errLine, errMsg); } // no program node == syntax error - throw a syntax error if (!functionBody) // we can't return a Completion(Throw) here, so just set the exception // and return it { return throwError(exec, SyntaxError, errMsg, errLine, sourceId, sourceURL); } ScopeChain scopeChain; scopeChain.push(exec->lexicalInterpreter()->globalObject()); FunctionImp *fimp = new FunctionImp(exec, functionName, functionBody.get(), scopeChain); // parse parameter list. throw syntax error on illegal identifiers int len = p.size(); const UChar *c = p.data(); int i = 0, params = 0; UString param; while (i < len) { while (*c == ' ' && i < len) { c++, i++; } if (Lexer::isIdentStart(c->uc)) { // else error param = UString(c, 1); c++, i++; while (i < len && (Lexer::isIdentPart(c->uc))) { param += UString(c, 1); c++, i++; } while (i < len && *c == ' ') { c++, i++; } if (i == len) { functionBody->addParam(Identifier(param)); params++; break; } else if (*c == ',') { functionBody->addParam(Identifier(param)); params++; c++, i++; continue; } // else error } return throwError(exec, SyntaxError, "Syntax error in parameter list"); } List consArgs; JSObject *objCons = exec->lexicalInterpreter()->builtinObject(); JSObject *prototype = objCons->construct(exec, List::empty()); prototype->put(exec, exec->propertyNames().constructor, fimp, DontEnum | DontDelete | ReadOnly); // ECMA Edition 5.1r6 - 15.3.5.2 - [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false fimp->put(exec, exec->propertyNames().prototype, prototype, Internal | DontDelete | DontEnum); return fimp; }