当前位置: 首页>>代码示例>>C++>>正文


C++ JSFunction::script方法代码示例

本文整理汇总了C++中JSFunction::script方法的典型用法代码示例。如果您正苦于以下问题:C++ JSFunction::script方法的具体用法?C++ JSFunction::script怎么用?C++ JSFunction::script使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在JSFunction的用法示例。


在下文中一共展示了JSFunction::script方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: fprintf

static void
DumpFunctionCountMap(const char *title, JSRuntime::FunctionCountMap &map, FILE *fp)
{
    fprintf(fp, "\n%s count map:\n", title);

    for (JSRuntime::FunctionCountMap::Range r = map.all(); !r.empty(); r.popFront()) {
        JSFunction *fun = r.front().key;
        int32 count = r.front().value;

        fprintf(fp, "%10d %s:%u\n", count, fun->script()->filename, fun->script()->lineno);
    }
}
开发者ID:,项目名称:,代码行数:12,代码来源:

示例2: JSOp

static StackFrame *
PushInlinedFrame(JSContext *cx, StackFrame *callerFrame)
{
    // Grab the callee object out of the caller's frame, which has already been restored.
    // N.B. we currently assume that the caller frame is at a JSOP_CALL pc for the caller frames,
    // which will not be the case when we inline getters (in which case it would be a
    // JSOP_GETPROP). That will have to be handled differently.
    FrameRegs &regs = cx->regs();
    JS_ASSERT(JSOp(*regs.pc) == JSOP_CALL || JSOp(*regs.pc) == JSOP_NEW);
    int callerArgc = GET_ARGC(regs.pc);
    const Value &calleeVal = regs.sp[-callerArgc - 2];

    JSFunction *fun = calleeVal.toObject().toFunction();
    JSScript *script = fun->script();
    CallArgs inlineArgs = CallArgsFromSp(callerArgc, regs.sp);
    
    // Bump the stack pointer to make it look like the inline args have been pushed, but they will
    // really get filled in by RestoreOneFrame.
    regs.sp = inlineArgs.end();

    InitialFrameFlags flags = INITIAL_NONE;
    if (JSOp(*regs.pc) == JSOP_NEW)
        flags = INITIAL_CONSTRUCT;

    if (!cx->stack.pushInlineFrame(cx, regs, inlineArgs, *fun, script, flags, DONT_REPORT_ERROR))
        return NULL;

    StackFrame *fp = cx->stack.fp();
    JS_ASSERT(fp == regs.fp());
    JS_ASSERT(fp->prev() == callerFrame);
    
    fp->formals()[-2].setObject(*fun);

    return fp;
}
开发者ID:mikeaich,项目名称:releases-mozilla-central,代码行数:35,代码来源:Bailouts.cpp

示例3: CallArgsFromSp

/*
 * This function must only be called after the early prologue, since it depends
 * on fp->exec.fun.
 */
void * JS_FASTCALL
stubs::FixupArity(VMFrame &f, uint32_t nactual)
{
    JSContext *cx = f.cx;
    StackFrame *oldfp = f.fp();

    JS_ASSERT(nactual != oldfp->numFormalArgs());

    /*
     * Grossssss! *move* the stack frame. If this ends up being perf-critical,
     * we can figure out how to spot-optimize it. Be careful to touch only the
     * members that have been initialized by the caller and early prologue.
     */
    InitialFrameFlags initial = oldfp->initialFlags();
    JSFunction *fun           = oldfp->fun();
    JSScript *script          = fun->script();
    void *ncode               = oldfp->nativeReturnAddress();

    /* Pop the inline frame. */
    f.regs.popPartialFrame((Value *)oldfp);

    /* Reserve enough space for a callee frame. */
    CallArgs args = CallArgsFromSp(nactual, f.regs.sp);
    StackFrame *fp = cx->stack.getFixupFrame(cx, DONT_REPORT_ERROR, args, fun,
                                             script, ncode, initial, &f.stackLimit);

    if (!fp) {
        f.regs.updateForNcode(f.jit(), ncode);
        js_ReportOverRecursed(cx);
        THROWV(NULL);
    }

    /* The caller takes care of assigning fp to regs. */
    return fp;
}
开发者ID:,项目名称:,代码行数:39,代码来源:

示例4: THROWV

void * JS_FASTCALL
stubs::CompileFunction(VMFrame &f, uint32 nactual)
{
    /*
     * We have a partially constructed frame. That's not really good enough to
     * compile though because we could throw, so get a full, adjusted frame.
     */
    JSContext *cx = f.cx;
    JSStackFrame *fp = f.fp();

    /*
     * Since we can only use members set by initCallFrameCallerHalf,
     * we must carefully extract the callee from the nactual.
     */
    JSObject &callee = fp->formalArgsEnd()[-(int(nactual) + 2)].toObject();
    JSFunction *fun = callee.getFunctionPrivate();
    JSScript *script = fun->script();

    /*
     * FixupArity/RemovePartialFrame expect to be called after the early
     * prologue.
     */
    fp->initCallFrameEarlyPrologue(fun, nactual);

    if (nactual != fp->numFormalArgs()) {
        fp = (JSStackFrame *)FixupArity(f, nactual);
        if (!fp)
            return NULL;
    }

    /* Finish frame initialization. */
    fp->initCallFrameLatePrologue();

    /* These would have been initialized by the prologue. */
    f.regs.fp = fp;
    f.regs.sp = fp->base();
    f.regs.pc = script->code;

    if (fun->isHeavyweight() && !js::CreateFunCallObject(cx, fp))
        THROWV(NULL);

    CompileStatus status = CanMethodJIT(cx, script, fp, CompileRequest_JIT);
    if (status == Compile_Okay)
        return script->getJIT(fp->isConstructing())->invokeEntry;

    /* Function did not compile... interpret it. */
    JSBool ok = Interpret(cx, fp);
    InlineReturn(f);

    if (!ok)
        THROWV(NULL);

    return NULL;
}
开发者ID:LittleForker,项目名称:mozilla-central,代码行数:54,代码来源:InvokeHelpers.cpp

示例5: SetValueRangeToUndefined

static inline bool
UncachedInlineCall(VMFrame &f, uint32 flags, void **pret, bool *unjittable, uint32 argc)
{
    JSContext *cx = f.cx;
    Value *vp = f.regs.sp - (argc + 2);
    JSObject &callee = vp->toObject();
    JSFunction *newfun = callee.getFunctionPrivate();
    JSScript *newscript = newfun->script();

    /* Get pointer to new frame/slots, prepare arguments. */
    StackSpace &stack = cx->stack();
    JSStackFrame *newfp = stack.getInlineFrameWithinLimit(cx, f.regs.sp, argc,
                                                          newfun, newscript, &flags,
                                                          f.entryfp, &f.stackLimit);
    if (JS_UNLIKELY(!newfp))
        return false;

    /* Initialize frame, locals. */
    newfp->initCallFrame(cx, callee, newfun, argc, flags);
    SetValueRangeToUndefined(newfp->slots(), newscript->nfixed);

    /* Officially push the frame. */
    stack.pushInlineFrame(cx, newscript, newfp, &f.regs);
    JS_ASSERT(newfp == f.regs.fp);

    /* Scope with a call object parented by callee's parent. */
    if (newfun->isHeavyweight() && !js::CreateFunCallObject(cx, newfp))
        return false;

    /* Try to compile if not already compiled. */
    if (newscript->getJITStatus(newfp->isConstructing()) == JITScript_None) {
        CompileStatus status = CanMethodJIT(cx, newscript, newfp, CompileRequest_Interpreter);
        if (status == Compile_Error) {
            /* A runtime exception was thrown, get out. */
            InlineReturn(f);
            return false;
        }
        if (status == Compile_Abort)
            *unjittable = true;
    }

    /* If newscript was successfully compiled, run it. */
    if (JITScript *jit = newscript->getJIT(newfp->isConstructing())) {
        *pret = jit->invokeEntry;
        return true;
    }

    /* Otherwise, run newscript in the interpreter. */
    bool ok = !!Interpret(cx, cx->fp());
    InlineReturn(f);

    *pret = NULL;
    return ok;
}
开发者ID:LittleForker,项目名称:mozilla-central,代码行数:54,代码来源:InvokeHelpers.cpp

示例6: script

bool
MarkInnerAndOuterFunctions(JSContext *cx, JSScript* script_)
{
    Rooted<JSScript*> script(cx, script_);

    Vector<JSScript *, 16> worklist(cx);
    if (!worklist.append(script.reference()))
        return false;

    while (worklist.length()) {
        JSScript *outer = worklist.back();
        worklist.popBack();

        /*
         * If outer has an extensible scope, its slots may be resized which
         * will invalidate nesting->varArray/argArray.
         */
        if (outer->funHasExtensibleScope)
            continue;

        if (outer->hasObjects()) {
            ObjectArray *arr = outer->objects();

            /*
             * If this is an eval script, don't treat the saved caller function
             * stored in the first object slot as an inner function.
             */
            size_t start = outer->savedCallerFun ? 1 : 0;

            for (size_t i = start; i < arr->length; i++) {
                JSObject *obj = arr->vector[i];
                if (!obj->isFunction())
                    continue;
                JSFunction *fun = obj->toFunction();
                JS_ASSERT(fun->isInterpreted());
                JSScript *inner = fun->script();
                if (outer->function() && outer->function()->isHeavyweight()) {
                    outer->isOuterFunction = true;
                    inner->isInnerFunction = true;
                }
                if (!inner->hasObjects())
                    continue;
                if (!worklist.append(inner))
                    return false;
            }
        }
    }

    return true;
}
开发者ID:msliu,项目名称:mozilla-central,代码行数:50,代码来源:BytecodeCompiler.cpp

示例7: fstate

JS_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
{
    XDRScriptState fstate(xdr);

    if (xdr->mode == JSXDR_ENCODE) {
        JSFunction* fun = (*objp)->getFunctionPrivate();
        if (!fun)
            return false;

        fstate.filename = fun->script()->filename;
    }

    return js_XDRFunctionObject(xdr, objp);
}
开发者ID:moussa1,项目名称:mozilla-central,代码行数:14,代码来源:jsxdrapi.cpp

示例8: CalleeTokenToScript

static JSScript*
GetBailedJSScript(JSContext *cx)
{
    // Just after the frame conversion, we can safely interpret the ionTop as JS
    // frame because it targets the bailed JS frame converted to an exit frame.
    IonJSFrameLayout *frame = reinterpret_cast<IonJSFrameLayout*>(cx->runtime->ionTop);
    switch (GetCalleeTokenTag(frame->calleeToken())) {
      case CalleeToken_Function: {
        JSFunction *fun = CalleeTokenToFunction(frame->calleeToken());
        return fun->script();
      }
      case CalleeToken_Script:
        return CalleeTokenToScript(frame->calleeToken());
      default:
        JS_NOT_REACHED("unexpected callee token kind");
        return NULL;
    }
}
开发者ID:mikeaich,项目名称:releases-mozilla-central,代码行数:18,代码来源:Bailouts.cpp

示例9: root

bool
MarkInnerAndOuterFunctions(JSContext *cx, JSScript* script)
{
    Root<JSScript*> root(cx, &script);

    Vector<JSScript *, 16> worklist(cx);
    if (!worklist.append(script))
        return false;

    while (worklist.length()) {
        JSScript *outer = worklist.back();
        worklist.popBack();

        if (outer->hasObjects()) {
            ObjectArray *arr = outer->objects();

            /*
             * If this is an eval script, don't treat the saved caller function
             * stored in the first object slot as an inner function.
             */
            size_t start = outer->savedCallerFun ? 1 : 0;

            for (size_t i = start; i < arr->length; i++) {
                JSObject *obj = arr->vector[i];
                if (!obj->isFunction())
                    continue;
                JSFunction *fun = obj->toFunction();
                JS_ASSERT(fun->isInterpreted());
                JSScript *inner = fun->script();
                if (outer->function() && outer->function()->isHeavyweight()) {
                    outer->isOuterFunction = true;
                    inner->isInnerFunction = true;
                }
                if (!inner->hasObjects())
                    continue;
                if (!worklist.append(inner))
                    return false;
            }
        }
    }

    return true;
}
开发者ID:,项目名称:,代码行数:43,代码来源:

示例10: CallArgsFromSp

static inline bool
UncachedInlineCall(VMFrame &f, MaybeConstruct construct, void **pret, bool *unjittable, uint32 argc)
{
    JSContext *cx = f.cx;
    CallArgs args = CallArgsFromSp(argc, f.regs.sp);
    JSObject &callee = args.callee();
    JSFunction *newfun = callee.getFunctionPrivate();
    JSScript *newscript = newfun->script();

    /* Get pointer to new frame/slots, prepare arguments. */
    if (!cx->stack.pushInlineFrame(cx, f.regs, args, callee, newfun, newscript, construct, &f.stackLimit))
        return false;

    /* Scope with a call object parented by callee's parent. */
    if (newfun->isHeavyweight() && !js::CreateFunCallObject(cx, f.fp()))
        return false;

    /* Try to compile if not already compiled. */
    if (newscript->getJITStatus(f.fp()->isConstructing()) == JITScript_None) {
        CompileStatus status = CanMethodJIT(cx, newscript, f.fp(), CompileRequest_Interpreter);
        if (status == Compile_Error) {
            /* A runtime exception was thrown, get out. */
            InlineReturn(f);
            return false;
        }
        if (status == Compile_Abort)
            *unjittable = true;
    }

    /* If newscript was successfully compiled, run it. */
    if (JITScript *jit = newscript->getJIT(f.fp()->isConstructing())) {
        *pret = jit->invokeEntry;
        return true;
    }

    /* Otherwise, run newscript in the interpreter. */
    bool ok = !!Interpret(cx, cx->fp());
    InlineReturn(f);

    *pret = NULL;
    return ok;
}
开发者ID:Egyptghost1,项目名称:DOMinator,代码行数:42,代码来源:InvokeHelpers.cpp

示例11:

JSBool
CallObject::setArgOp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
{
    CallObject &callobj = obj->asCall();
    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
    unsigned i = (uint16_t) JSID_TO_INT(id);

    if (StackFrame *fp = callobj.maybeStackFrame())
        fp->formalArg(i) = *vp;
    else
        callobj.setArg(i, *vp);

    JSFunction *fun = callobj.getCalleeFunction();
    JSScript *script = fun->script();
    if (!script->ensureHasTypes(cx))
        return false;

    TypeScript::SetArgument(cx, script, i, *vp);

    return true;
}
开发者ID:Anachid,项目名称:mozilla-central,代码行数:21,代码来源:ScopeObject.cpp

示例12: ToFrameFlags

bool
ContextStack::pushInvokeFrame(JSContext *cx, const CallArgs &args,
                              InitialFrameFlags initial, InvokeFrameGuard *ifg)
{
    JS_ASSERT(onTop());
    JS_ASSERT(space().firstUnused() == args.end());

    JSObject &callee = args.callee();
    JSFunction *fun = callee.toFunction();
    JSScript *script = fun->script();

    StackFrame::Flags flags = ToFrameFlags(initial);
    StackFrame *fp = getCallFrame(cx, REPORT_ERROR, args, fun, script, &flags);
    if (!fp)
        return false;

    fp->initCallFrame(cx, *fun, script, args.length(), flags);
    ifg->regs_.prepareToRun(*fp, script);

    ifg->prevRegs_ = seg_->pushRegs(ifg->regs_);
    JS_ASSERT(space().firstUnused() == ifg->regs_.sp);
    ifg->setPushed(*this);
    return true;
}
开发者ID:,项目名称:,代码行数:24,代码来源:

示例13: space

/*
 * This helper function brings the ContextStack to the top of the thread stack
 * (so that it can be extended to push a frame and/or arguments) by potentially
 * pushing a StackSegment. The 'pushedSeg' outparam indicates whether such a
 * segment was pushed (and hence whether the caller needs to call popSegment).
 *
 * Additionally, to minimize calls to ensureSpace, ensureOnTop ensures that
 * there is space for nvars slots on top of the stack.
 */
Value *
ContextStack::ensureOnTop(JSContext *cx, MaybeReportError report, unsigned nvars,
                          MaybeExtend extend, bool *pushedSeg, JSCompartment *dest)
{
    Value *firstUnused = space().firstUnused();

#ifdef JS_METHODJIT
    /*
     * The only calls made by inlined methodjit frames can be to other JIT
     * frames associated with the same VMFrame. If we try to Invoke(),
     * Execute() or so forth, any topmost inline frame will need to be
     * expanded (along with other inline frames in the compartment).
     * To avoid pathological behavior here, make sure to mark any topmost
     * function as uninlineable, which will expand inline frames if there are
     * any and prevent the function from being inlined in the future.
     */
    if (FrameRegs *regs = cx->maybeRegs()) {
        JSFunction *fun = NULL;
        if (InlinedSite *site = regs->inlined()) {
            mjit::JITChunk *chunk = regs->fp()->jit()->chunk(regs->pc);
            fun = chunk->inlineFrames()[site->inlineIndex].fun;
        } else {
            StackFrame *fp = regs->fp();
            if (fp->isFunctionFrame()) {
                JSFunction *f = fp->fun();
                if (f->isInterpreted())
                    fun = f;
            }
        }

        if (fun) {
            fun->script()->uninlineable = true;
            types::MarkTypeObjectFlags(cx, fun, types::OBJECT_FLAG_UNINLINEABLE);
        }
    }
    JS_ASSERT_IF(cx->hasfp(), !cx->regs().inlined());
#endif

    if (onTop() && extend) {
        if (!space().ensureSpace(cx, report, firstUnused, nvars, dest))
            return NULL;
        return firstUnused;
    }

    if (!space().ensureSpace(cx, report, firstUnused, VALUES_PER_STACK_SEGMENT + nvars, dest))
        return NULL;

    FrameRegs *regs;
    CallArgsList *calls;
    if (seg_ && extend) {
        regs = seg_->maybeRegs();
        calls = seg_->maybeCalls();
    } else {
        regs = NULL;
        calls = NULL;
    }

    seg_ = new(firstUnused) StackSegment(seg_, space().seg_, regs, calls);
    space().seg_ = seg_;
    *pushedSeg = true;
    return seg_->slotsBegin();
}
开发者ID:,项目名称:,代码行数:71,代码来源:

示例14: iter

static JSBool
fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, Value *vp)
{
    JSObject *obj = obj_;
    while (!obj->isFunction()) {
        obj = obj->getProto();
        if (!obj)
            return true;
    }
    JSFunction *fun = obj->toFunction();

    /*
     * Mark the function's script as uninlineable, to expand any of its
     * frames on the stack before we go looking for them. This allows the
     * below walk to only check each explicit frame rather than needing to
     * check any calls that were inlined.
     */
    if (fun->isInterpreted()) {
        fun->script()->uninlineable = true;
        MarkTypeObjectFlags(cx, fun, OBJECT_FLAG_UNINLINEABLE);
    }

    /* Set to early to null in case of error */
    vp->setNull();

    /* Find fun's top-most activation record. */
    StackIter iter(cx);
    for (; !iter.done(); ++iter) {
        if (!iter.isFunctionFrame() || iter.isEvalFrame())
            continue;
        if (iter.callee() == fun)
            break;
    }
    if (iter.done())
        return true;

    StackFrame *fp = iter.fp();

    if (JSID_IS_ATOM(id, cx->runtime->atomState.argumentsAtom)) {
        if (fun->hasRest()) {
            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_FUNCTION_ARGUMENTS_AND_REST);
            return false;
        }
        /* Warn if strict about f.arguments or equivalent unqualified uses. */
        if (!JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING | JSREPORT_STRICT, js_GetErrorMessage,
                                          NULL, JSMSG_DEPRECATED_USAGE, js_arguments_str)) {
            return false;
        }

        ArgumentsObject *argsobj = ArgumentsObject::createUnexpected(cx, fp);
        if (!argsobj)
            return false;

        *vp = ObjectValue(*argsobj);
        return true;
    }

#ifdef JS_METHODJIT
    if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom) && fp && fp->prev()) {
        /*
         * If the frame was called from within an inlined frame, mark the
         * innermost function as uninlineable to expand its frame and allow us
         * to recover its callee object.
         */
        JSInlinedSite *inlined;
        jsbytecode *prevpc = fp->prev()->pcQuadratic(cx->stack, fp, &inlined);
        if (inlined) {
            mjit::JITChunk *chunk = fp->prev()->jit()->chunk(prevpc);
            JSFunction *fun = chunk->inlineFrames()[inlined->inlineIndex].fun;
            fun->script()->uninlineable = true;
            MarkTypeObjectFlags(cx, fun, OBJECT_FLAG_UNINLINEABLE);
        }
    }
#endif

    if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom)) {
        StackIter prev(iter);
        do {
            ++prev;
        } while (!prev.done() && prev.isImplicitNativeCall());

        if (prev.done() || !prev.isFunctionFrame()) {
            JS_ASSERT(vp->isNull());
            return true;
        }
        *vp = prev.calleev();

        /* Censor the caller if it is from another compartment. */
        JSObject &caller = vp->toObject();
        if (caller.compartment() != cx->compartment) {
            vp->setNull();
        } else if (caller.isFunction()) {
            JSFunction *callerFun = caller.toFunction();
            if (callerFun->isInterpreted() && callerFun->inStrictMode()) {
                JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
                                             JSMSG_CALLER_IS_STRICT);
                return false;
            }
        }

//.........这里部分代码省略.........
开发者ID:,项目名称:,代码行数:101,代码来源:

示例15: parent

bool
js::XDRInterpretedFunction(XDRState<mode> *xdr, JSObject **objp, JSScript *parentScript)
{
    /* NB: Keep this in sync with CloneInterpretedFunction. */
    JSFunction *fun;
    JSAtom *atom;
    uint32_t firstword;           /* flag telling whether fun->atom is non-null,
                                   plus for fun->u.i.skipmin, fun->u.i.wrapper,
                                   and 14 bits reserved for future use */
    uint32_t flagsword;           /* word for argument count and fun->flags */

    JSContext *cx = xdr->cx();
    JSScript *script;
    if (mode == XDR_ENCODE) {
        fun = (*objp)->toFunction();
        if (!fun->isInterpreted()) {
            JSAutoByteString funNameBytes;
            if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_SCRIPTED_FUNCTION,
                                     name);
            }
            return false;
        }
        firstword = !!fun->atom;
        flagsword = (fun->nargs << 16) | fun->flags;
        atom = fun->atom;
        script = fun->script();
    } else {
        RootedObject parent(cx, NULL);
        fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, parent, NULL);
        if (!fun)
            return false;
        if (!fun->clearParent(cx))
            return false;
        if (!fun->clearType(cx))
            return false;
        atom = NULL;
        script = NULL;
    }

    if (!xdr->codeUint32(&firstword))
        return false;
    if ((firstword & 1U) && !XDRAtom(xdr, &atom))
        return false;
    if (!xdr->codeUint32(&flagsword))
        return false;

    if (!XDRScript(xdr, &script, parentScript))
        return false;

    if (mode == XDR_DECODE) {
        fun->nargs = flagsword >> 16;
        JS_ASSERT((flagsword & JSFUN_KINDMASK) >= JSFUN_INTERPRETED);
        fun->flags = uint16_t(flagsword);
        fun->atom.init(atom);
        fun->initScript(script);
        if (!script->typeSetFunction(cx, fun))
            return false;
        JS_ASSERT(fun->nargs == fun->script()->bindings.numArgs());
        js_CallNewScriptHook(cx, fun->script(), fun);
        *objp = fun;
    }
开发者ID:,项目名称:,代码行数:62,代码来源:


注:本文中的JSFunction::script方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。