void DefaultGCActivityCallbackPlatformData::trigger(CFRunLoopTimerRef timer, void *info)
{
    Heap* heap = static_cast<Heap*>(info);
    APIEntryShim shim(heap->globalData());
    heap->collectAllGarbage();
    CFRunLoopTimerSetNextFireDate(timer, CFAbsoluteTimeGetCurrent() + decade);
}
예제 #2
0
/*!
  Returns true if the function was called as a constructor
  (e.g. \c{"new foo()"}); otherwise returns false.

  When a function is called as constructor, the thisObject()
  contains the newly constructed object to be initialized.

  \note This function is only guaranteed to work for a context
  corresponding to native functions.
*/
bool QScriptContext::isCalledAsConstructor() const
{
    JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this));
    QScript::APIShim shim(QScript::scriptEngineFromExec(frame));

    //For native functions, look up flags.
    uint flags = QScriptEnginePrivate::contextFlags(frame);
    if (flags & QScriptEnginePrivate::NativeContext)
        return flags & QScriptEnginePrivate::CalledAsConstructorContext;

    //Not a native function, try to look up in the bytecode if we where called from op_construct
    JSC::Instruction* returnPC = frame->returnPC();

    if (!returnPC)
        return false;

    JSC::CallFrame *callerFrame = QScriptEnginePrivate::frameForContext(parentContext());
    if (!callerFrame)
        return false;

    if (returnPC[-JSC::op_construct_length].u.opcode == frame->interpreter()->getOpcode(JSC::op_construct)) {
        //We are maybe called from the op_construct opcode which has 6 opperands.
        //But we need to check we are not called from op_call with 4 opperands

        //we make sure that the returnPC[-1] (thisRegister) is smaller than the returnPC[-3] (registerOffset)
        //as if it was an op_call, the returnPC[-1] would be the registerOffset, bigger than returnPC[-3] (funcRegister)
        return returnPC[-1].u.operand < returnPC[-3].u.operand;
    }
    return false;
}
예제 #3
0
/*!
  \overload

  Throws an error with the given \a text.
  Returns the created error object.

  \sa throwValue(), state()
*/
QScriptValue QScriptContext::throwError(const QString &text)
{
    JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
    QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
    JSC::JSObject *result = JSC::throwError(frame, JSC::GeneralError, text);
    return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result);
}
예제 #4
0
/*!
  \internal
  \since 4.5

  Adds the given \a object to the front of this context's scope chain.

  If \a object is not an object, this function does nothing.
*/
void QScriptContext::pushScope(const QScriptValue &object)
{
    activationObject(); //ensure the creation of the normal scope for native context
    if (!object.isObject())
        return;
    else if (object.engine() != engine()) {
        qWarning("QScriptContext::pushScope() failed: "
                 "cannot push an object created in "
                 "a different engine");
        return;
    }
    JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
    QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
    QScript::APIShim shim(engine);
    JSC::JSObject *jscObject = JSC::asObject(engine->scriptValueToJSCValue(object));
    if (jscObject == engine->originalGlobalObjectProxy)
        jscObject = engine->originalGlobalObject();
    JSC::ScopeChainNode *scope = frame->scopeChain();
    Q_ASSERT(scope != 0);
    if (!scope->object) {
        // pushing to an "empty" chain
        if (!jscObject->isGlobalObject()) {
            qWarning("QScriptContext::pushScope() failed: initial object in scope chain has to be the Global Object");
            return;
        }
        scope->object = jscObject;
    }
    else
        frame->setScopeChain(scope->push(jscObject));
}
예제 #5
0
/*!
  Sets the `this' object associated with this QScriptContext to be
  \a thisObject.

  If \a thisObject is not an object, this function does nothing.
*/
void QScriptContext::setThisObject(const QScriptValue &thisObject)
{
    JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
    QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
    if (!thisObject.isObject())
        return;
    if (thisObject.engine() != engine()) {
        qWarning("QScriptContext::setThisObject() failed: "
                 "cannot set an object created in "
                 "a different engine");
        return;
    }
    if (frame == frame->lexicalGlobalObject()->globalExec()) {
        engine()->setGlobalObject(thisObject);
        return;
    }
    JSC::JSValue jscThisObject = QScript::scriptEngineFromExec(frame)->scriptValueToJSCValue(thisObject);
    JSC::CodeBlock *cb = frame->codeBlock();
    if (cb != 0) {
        frame[cb->thisRegister()] = jscThisObject;
    } else {
        JSC::Register* thisRegister = QScriptEnginePrivate::thisRegisterForFrame(frame);
        thisRegister[0] = jscThisObject;
    }
}
예제 #6
0
/*!
  Throws an \a error with the given \a text.
  Returns the created error object.

  The \a text will be stored in the \c{message} property of the error
  object.

  The error object will be initialized to contain information about
  the location where the error occurred; specifically, it will have
  properties \c{lineNumber}, \c{fileName} and \c{stack}. These
  properties are described in \l {QtScript Extensions to ECMAScript}.

  \sa throwValue(), state()
*/
QScriptValue QScriptContext::throwError(Error error, const QString &text)
{
    JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
    QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
    JSC::ErrorType jscError = JSC::GeneralError;
    switch (error) {
    case UnknownError:
        break;
    case ReferenceError:
        jscError = JSC::ReferenceError;
        break;
    case SyntaxError:
        jscError = JSC::SyntaxError;
        break;
    case TypeError:
        jscError = JSC::TypeError;
        break;
    case RangeError:
        jscError = JSC::RangeError;
        break;
    case URIError:
        jscError = JSC::URIError;
        break;
    }
    JSC::JSObject *result = JSC::throwError(frame, jscError, text);
    return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result);
}
예제 #7
0
/*!
  Returns the parent context of this QScriptContext.
*/
QScriptContext *QScriptContext::parentContext() const
{
    const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
    QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
    JSC::CallFrame *callerFrame = frame->callerFrame()->removeHostCallFrameFlag();
    return QScriptEnginePrivate::contextForFrame(callerFrame);
}
예제 #8
0
void Dawg::iterate_words(const UNICHARSET &unicharset,
                         TessCallback1<const char *> *cb) const {
  std::unique_ptr<TessCallback1<const WERD_CHOICE *>> shim(
      NewPermanentTessCallback(CallWithUTF8, cb));
  WERD_CHOICE word(&unicharset);
  iterate_words_rec(word, 0, shim.get());
}
QScriptProgramPrivate::~QScriptProgramPrivate()
{
    if (engine) {
        QScript::APIShim shim(engine);
        _executable.clear();
    }
}
예제 #10
0
void HeapTimer::timerDidFire(CFRunLoopTimerRef timer, void* context)
{
    JSLock* apiLock = static_cast<JSLock*>(context);
    apiLock->lock();

    VM* vm = apiLock->vm();
    // The VM has been destroyed, so we should just give up.
    if (!vm) {
        apiLock->unlock();
        return;
    }

    HeapTimer* heapTimer = 0;
    if (vm->heap.activityCallback()->m_timer.get() == timer)
        heapTimer = vm->heap.activityCallback();
    else if (vm->heap.sweeper()->m_timer.get() == timer)
        heapTimer = vm->heap.sweeper();
    else
        RELEASE_ASSERT_NOT_REACHED();

    {
        APIEntryShim shim(vm);
        heapTimer->doWork();
    }

    apiLock->unlock();
}
예제 #11
0
/*!
  Throws an exception with the given \a value.
  Returns the value thrown (the same as the argument).

  \sa throwError(), state()
*/
QScriptValue QScriptContext::throwValue(const QScriptValue &value)
{
    JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
    QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
    JSC::JSValue jscValue = QScript::scriptEngineFromExec(frame)->scriptValueToJSCValue(value);
    frame->setException(jscValue);
    return value;
}
예제 #12
0
QScriptProgramPrivate::~QScriptProgramPrivate()
{
    if (engine) {
        QScript::APIShim shim(engine);
        _executable.clear();
        engine->unregisterScriptProgram(this);
    }
}
/*!
  Returns the flags of the last property that was jumped over using
  next() or previous().

  \sa value()
*/
QScriptValue::PropertyFlags QScriptValueIterator::flags() const
{
    Q_D(const QScriptValueIterator);
    if (!d || !d->initialized || !d->engine())
        return 0;
    QScript::APIShim shim(d->engine());
    return d->object()->propertyFlags(*d->current);
}
/*!
  Returns the value of the last property that was jumped over using
  next() or previous().

  \sa setValue(), name()
*/
QScriptValue QScriptValueIterator::value() const
{
    Q_D(const QScriptValueIterator);
    if (!d || !d->initialized || !d->engine())
        return QScriptValue();
    QScript::APIShim shim(d->engine());
    JSC::JSValue jsValue = d->object()->property(*d->current);
    return d->engine()->scriptValueFromJSCValue(jsValue);
}
예제 #15
0
QScriptDeclarativeClass::PersistentIdentifier::~PersistentIdentifier()
{
    if (engine) {
        QScript::APIShim shim(engine);
        ((JSC::Identifier &)d).JSC::Identifier::~Identifier();
    } else {
        ((JSC::Identifier &)d).JSC::Identifier::~Identifier();
    }
}
/*!
  Removes the last property that was jumped over using next()
  or previous().

  \sa setValue()
*/
void QScriptValueIterator::remove()
{
    Q_D(QScriptValueIterator);
    if (!d || !d->initialized || !d->engine())
        return;
    QScript::APIShim shim(d->engine());
    d->object()->setProperty(*d->current, JSC::JSValue());
    d->propertyNames.erase(d->current);
}
/*!
  Sets the \a value of the last property that was jumped over using
  next() or previous().

  \sa value(), name()
*/
void QScriptValueIterator::setValue(const QScriptValue &value)
{
    Q_D(QScriptValueIterator);
    if (!d || !d->initialized || !d->engine())
        return;
    QScript::APIShim shim(d->engine());
    JSC::JSValue jsValue = d->engine()->scriptValueToJSCValue(value);
    d->object()->setProperty(*d->current, jsValue);
}
 ~QScriptValueIteratorPrivate()
 {
     if (!initialized)
         return;
     QScriptEnginePrivate *eng_p = engine();
     if (!eng_p)
         return;
     QScript::APIShim shim(eng_p);
     propertyNames.clear(); //destroying the identifiers need to be done under the APIShim guard
 }
예제 #19
0
bool HeapTimer::timerEvent(void* info)
{
    HeapTimer* agent = static_cast<HeapTimer*>(info);
    
    APIEntryShim shim(agent->m_vm);
    agent->doWork();
    agent->m_timer = 0;
    
    return ECORE_CALLBACK_CANCEL;
}
예제 #20
0
/*!
  Returns the `this' object associated with this QScriptContext.
*/
QScriptValue QScriptContext::thisObject() const
{
    JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this));
    QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
    QScript::APIShim shim(engine);
    JSC::JSValue result = engine->thisForContext(frame);
    if (!result || result.isNull())
        result = frame->globalThisValue();
    return engine->scriptValueFromJSCValue(result);
}
예제 #21
0
void HeapTimer::timerEvent(QTimerEvent*)
{
    QMutexLocker lock(&m_mutex);
    if (m_newThread) {
        // We need to wait with processing until we are on the right thread.
        return;
    }

    APIEntryShim shim(m_vm);
    doWork();
}
예제 #22
0
/*!
  Returns the callee. The callee is the function object that this
  QScriptContext represents an invocation of.
*/
QScriptValue QScriptContext::callee() const
{
    const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
    QScriptEnginePrivate *eng = QScript::scriptEngineFromExec(frame);
    QScript::APIShim shim(eng);
    if (frame->callee() == eng->originalGlobalObject()) {
        // This is a pushContext()-created context; the callee is a lie.
        Q_ASSERT(QScriptEnginePrivate::contextFlags(const_cast<JSC::CallFrame*>(frame)) & QScriptEnginePrivate::NativeContext);
        return QScriptValue();
    }
    return eng->scriptValueFromJSCValue(frame->callee());
}
예제 #23
0
QScriptDeclarativeClass::PersistentIdentifier 
QScriptDeclarativeClass::createPersistentIdentifier(const Identifier &id)
{
    QScriptEnginePrivate *p = 
        static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine)); 
    QScript::APIShim shim(p);
    JSC::ExecState* exec = p->currentFrame;

    PersistentIdentifier rv(p);
    new (&rv.d) JSC::Identifier(exec, (JSC::UString::Rep *)id);
    rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep();
    return rv;
}
예제 #24
0
QScriptDeclarativeClass::Value 
QScriptDeclarativeClass::newObjectValue(QScriptEngine *engine,QScriptDeclarativeClass *scriptClass, Object *object)
{
    Q_ASSERT(engine);
    Q_ASSERT(scriptClass);

    QScriptEnginePrivate *p = QScriptEnginePrivate::cs_getPrivate(engine);
    QScript::APIShim shim(p);

    JSC::ExecState* exec = p->currentFrame;
    QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure);
    result->setDelegate(new QScript::DeclarativeObjectDelegate(scriptClass, object));
    return jscToValue(JSC::JSValue(result));
}
예제 #25
0
QScriptValue QScriptContext::activationObject() const
{
    JSC::CallFrame *frame = const_cast<JSC::ExecState*>(QScriptEnginePrivate::frameForContext(this));
    QScript::APIShim shim(QScript::scriptEngineFromExec(frame));
    JSC::JSObject *result = 0;

    uint flags = QScriptEnginePrivate::contextFlags(frame);
    if ((flags & QScriptEnginePrivate::NativeContext) && !(flags & QScriptEnginePrivate::HasScopeContext)) {
        //For native functions, lazily create it if needed
        QScript::QScriptActivationObject *scope = new (frame) QScript::QScriptActivationObject(frame);
        frame->setScopeChain(frame->scopeChain()->copy()->push(scope));
        result = scope;
        QScriptEnginePrivate::setContextFlags(frame, flags | QScriptEnginePrivate::HasScopeContext);
    } else {
        // look in scope chain
        JSC::ScopeChainNode *node = frame->scopeChain();
        JSC::ScopeChainIterator it(node);
        for (it = node->begin(); it != node->end(); ++it) {
            if ((*it) && (*it)->isVariableObject()) {
                result = *it;
                break;
            }
        }
    }
    if (!result) {
        if (!parentContext())
            return engine()->globalObject();

        qWarning("QScriptContext::activationObject:  could not get activation object for frame");
        return QScriptValue();
        /*JSC::CodeBlock *codeBlock = frame->codeBlock();
        if (!codeBlock) {
            // non-Qt native function 
            Q_ASSERT(true); //### this should in theorry not happen
            result = new (frame)QScript::QScriptActivationObject(frame);
        } else {
            // ### this is wrong
            JSC::FunctionBodyNode *body = static_cast<JSC::FunctionBodyNode*>(codeBlock->ownerNode());
            result = new (frame)JSC::JSActivation(frame, body);
        }*/
    }

    if (result && result->inherits(&QScript::QScriptActivationObject::info)
        && (static_cast<QScript::QScriptActivationObject*>(result)->delegate() != 0)) {
        // Return the object that property access is being delegated to
        result = static_cast<QScript::QScriptActivationObject*>(result)->delegate();
    }

    return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result);
}
예제 #26
0
/*!
  Sets the activation object of this QScriptContext to be the given \a
  activation.

  If \a activation is not an object, this function does nothing.

  \note For a context corresponding to a JavaScript function, this is only
  guaranteed to work if there was an QScriptEngineAgent active on the
  engine while the function was evaluated.
*/
void QScriptContext::setActivationObject(const QScriptValue &activation)
{
    if (!activation.isObject())
        return;
    else if (activation.engine() != engine()) {
        qWarning("QScriptContext::setActivationObject() failed: "
                 "cannot set an object created in "
                 "a different engine");
        return;
    }
    JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
    QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
    QScript::APIShim shim(engine);
    JSC::JSObject *object = JSC::asObject(engine->scriptValueToJSCValue(activation));
    if (object == engine->originalGlobalObjectProxy)
        object = engine->originalGlobalObject();

    uint flags = QScriptEnginePrivate::contextFlags(frame);
    if ((flags & QScriptEnginePrivate::NativeContext) && !(flags & QScriptEnginePrivate::HasScopeContext)) {
        //For native functions, we create a scope node
        JSC::JSObject *scope = object;
        if (!scope->isVariableObject()) {
            // Create a QScriptActivationObject that acts as a proxy
            scope = new (frame) QScript::QScriptActivationObject(frame, scope);
        }
        frame->setScopeChain(frame->scopeChain()->copy()->push(scope));
        QScriptEnginePrivate::setContextFlags(frame, flags | QScriptEnginePrivate::HasScopeContext);
        return;
    }

    // else replace the first activation object in the scope chain
    JSC::ScopeChainNode *node = frame->scopeChain();
    while (node != 0) {
        if (node->object && node->object->isVariableObject()) {
            if (!object->isVariableObject()) {
                if (node->object->inherits(&QScript::QScriptActivationObject::info)) {
                    static_cast<QScript::QScriptActivationObject*>(node->object)->setDelegate(object);
                } else {
                    // Create a QScriptActivationObject that acts as a proxy
                    node->object = new (frame) QScript::QScriptActivationObject(frame, object);
                }
            } else {
                node->object = object;
            }
            break;
        }
        node = node->next;
    }
}
예제 #27
0
QScriptValue QScriptDeclarativeClass::newObject(QScriptEngine *engine, 
                                                QScriptDeclarativeClass *scriptClass, 
                                                Object *object)
{
    Q_ASSERT(engine);
    Q_ASSERT(scriptClass);

    QScriptEnginePrivate *p = static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(engine));
    QScript::APIShim shim(p);

    JSC::ExecState* exec = p->currentFrame;
    QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure);
    result->setDelegate(new QScript::DeclarativeObjectDelegate(scriptClass, object));
    return p->scriptValueFromJSCValue(result);
}
예제 #28
0
QScriptDeclarativeClass::PersistentIdentifier 

QScriptDeclarativeClass::createPersistentIdentifier(const QString &str)
{
    QScriptEnginePrivate *p = QScriptEnginePrivate::cs_getPrivate(d_ptr->engine);

    QScript::APIShim shim(p);
    JSC::ExecState* exec = p->currentFrame;

    PersistentIdentifier rv(p);
    new (&rv.d) JSC::Identifier(exec, (UChar *)str.constData(), str.size());
    rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep();

    return rv;
}
예제 #29
0
void HeapTimer::timerDidFire(CFRunLoopTimerRef, void* info)
{
    HeapTimer* agent = static_cast<HeapTimer*>(info);
    agent->m_shutdownMutex.lock();
    if (!agent->m_globalData) {
        agent->m_shutdownMutex.unlock();
        delete agent;
        return;
    }
    {
        // We don't ref here to prevent us from resurrecting the ref count of a "dead" JSGlobalData.
        APIEntryShim shim(agent->m_globalData, APIEntryShimWithoutLock::DontRefGlobalData);
        agent->doWork();
    }
    agent->m_shutdownMutex.unlock();
}
예제 #30
0
/*!
  \internal
  \since 4.5

  Removes the front object from this context's scope chain, and
  returns the removed object.

  If the scope chain is already empty, this function returns an
  invalid QScriptValue.
*/
QScriptValue QScriptContext::popScope()
{
    activationObject(); //ensure the creation of the normal scope for native context
    JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(this);
    JSC::ScopeChainNode *scope = frame->scopeChain();
    Q_ASSERT(scope != 0);
    QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
    QScript::APIShim shim(engine);
    QScriptValue result = engine->scriptValueFromJSCValue(scope->object);
    if (!scope->next) {
        // We cannot have a null scope chain, so just zap the object pointer.
        scope->object = 0;
    } else {
        frame->setScopeChain(scope->pop());
    }
    return result;
}