예제 #1
0
파일: define.cpp 프로젝트: cwyiu/fibjs
result_t doDefine(v8::Local<v8::Object> &mod)
{
    v8::Local<v8::Array> defs;
    {
        v8::Local<v8::Value> v;
        v8::Local<v8::String> strDefs = v8::String::NewFromUtf8(isolate, "defs");

        // get define array from default module
        v = mod->GetHiddenValue(strDefs);
        mod->DeleteHiddenValue(strDefs);

        if (!v.IsEmpty() && v->IsArray())
            defs = v8::Local<v8::Array>::Cast(v);
        else
            return 0;
    }

    int an = defs->Length(), i, j;
    std::vector<v8::Local<v8::Object> > mods;
    std::vector<std::string> modIds;
    std::set<std::string> depns;

    // cache string
    v8::Local<v8::String> strRequire = v8::String::NewFromUtf8(isolate, "require");
    v8::Local<v8::String> strExports = v8::String::NewFromUtf8(isolate, "exports");
    v8::Local<v8::String> strDeps = v8::String::NewFromUtf8(isolate, "deps");
    v8::Local<v8::String> strFactory = v8::String::NewFromUtf8(isolate, "factory");
    v8::Local<v8::String> strId = v8::String::NewFromUtf8(isolate, "id");

    // copy data to local
    mods.resize(an);
    modIds.resize(an);
    for (i = 0; i < an; i++)
    {
        mods[i] = defs->Get(i)->ToObject();
        modIds[i] = *v8::String::Utf8Value(mods[i]->Get(strId));
        depns.insert(modIds[i]);
    }

    // two step
    int doStep = 2;
    bool bNext = false;

    while (doStep)
    {
        bNext = true;

        for (i = 0; i < an; i++)
        {
            if (!modIds[i].empty())
            {
                // get deps array
                v8::Local<v8::Value> a1 = mods[i]->GetHiddenValue(strDeps);

                if (a1.IsEmpty() || !a1->IsArray())
                {
                    // not found deps array
                    depns.erase(modIds[i]);
                    modIds[i].clear();
                    bNext = false;

                    continue;
                }

                v8::Local<v8::Array> a = v8::Local<v8::Array>::Cast(a1);

                int n = a->Length();

                // check if the module depend a module defined in same script
                for (j = 0; j < n; j++)
                    if (doStep == 2
                            && depns.find(*v8::String::Utf8Value(a->Get(j)))
                            != depns.end())
                        break;

                if (j == n)
                {
                    std::vector<v8::Local<v8::Value> > deps;
                    deps.resize(n);

                    for (j = 0; j < n; j++)
                    {
                        v8::String::Utf8Value id(a->Get(j));

                        if (!qstrcmp(*id, "require"))
                            deps[j] = mods[i]->Get(strRequire);
                        else if (!qstrcmp(*id, "exports"))
                            deps[j] = mods[i]->Get(strExports);
                        else if (!qstrcmp(*id, "module"))
                            deps[j] = mods[i];
                        else
                        {
                            // load module use require
                            result_t hr = global_base::require(*id, deps[j]);
                            if (hr < 0)
                                return hr;
                        }
                    }

                    v8::Local<v8::Value> v;

                    // get factory and remove hidden value.
                    v = mods[i]->GetHiddenValue(strFactory);
                    mods[i]->DeleteHiddenValue(strFactory);
                    mods[i]->DeleteHiddenValue(strDeps);

                    if (v->IsFunction())
                    {
                        v8::Local<v8::Function> func =
                            v8::Local<v8::Function>::Cast(v);

                        v = func->Call(func, n, deps.data());
                        if (v.IsEmpty())
                            return CALL_E_JAVASCRIPT;
                    }

                    // use the result as exports if the factory return something
                    if (!IsEmpty(v))
                        mods[i]->Set(strExports, v);
                    else
                        v = mods[i]->Get(strExports);

                    InstallModule(modIds[i], v);

                    // remove id name, we don't like to call it again
                    depns.erase(modIds[i]);
                    modIds[i].clear();
                    bNext = false;
                }
            }
        }

        if (bNext)
            doStep--;
    }

    return 0;
}
예제 #2
0
bool V8HiddenValue::deleteHiddenValue(v8::Isolate* isolate, v8::Local<v8::Object> object, v8::Local<v8::String> key)
{
    return object->DeleteHiddenValue(key);
}