⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 js.xs

📁 caffeine-monkey java实现的js模拟引擎
💻 XS
📖 第 1 页 / 共 2 页
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** *//* * PerlConnect. Provides means for OO Perl <==> JS communications *//* This is an program written in XSUB. You need to compile it using xsubpp   *//* usually found in your perl\bin directory. On my machine I do it like this:*//*      perl c:\perl\lib\ExtUtils\xsubpp  -typemap  \                        *//*           c:\perl\lib\extutils\typemap -typemap typemap JS.xs > JS.c      *//* See perlxs man page for details.                                          *//* Don't edit the resulting C file directly. See README.html for more info   *//* on PerlConnect in general                                                 */#ifdef __cplusplus    extern "C"; {#endif#include "EXTERN.h"#include "perl.h"#include "XSUB.h"#ifdef __cplusplus    }#endif#include <jsapi.h>#include "jsperlpvt.h"#include <malloc.h>/* __REMOVE__ *//* #include <stdio.h>  *//************************************************************//* utils */static JSBoolcheckError(JSContext *cx){    if(SvTRUE(GvSV(PL_errgv))){         JS_ReportError(cx, "perl eval failed: %s",            SvPV(GvSV(PL_errgv), PL_na));        /* clear error status. there should be a way to do this faster */        perl_eval_sv(newSVpv("undef $@;", 0), G_KEEPERR);        return JS_FALSE;    }    return JS_TRUE;}static voidclearException(JSContext *cx) {    if (JS_IsExceptionPending(cx)) {        JS_ClearPendingException(cx);    }}/************************************************************//* calback stub *//* this is internal js structure needed in errorFromPrivate */typedef struct JSExnPrivate {    JSErrorReport *errorReport;} JSExnPrivate;staticJSClass global_class = {    "Global", 0,    JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub, JS_FinalizeStub};/* __PH__BEGIN  *//* perl callback structure *//* prefix PCB means Perl CallBack */struct PerlCallbackItem{    char*  name;    SV*    perl_proc;    int    param_num;    struct PerlCallbackItem *next;};typedef struct PerlCallbackItem PerlCallbackItem;struct PerlObjectItem {    char * name;    SV* pObject;    //JSObject *jsStub;    JSObject *jsObject;    JSClass *jsClass;    struct PerlCallbackItem* vector;    struct PerlObjectItem *next;};typedef struct PerlObjectItem PerlObjectItem;/* error reporter *///struct JSContextItem;//struct JSContextItem;struct  JSContextItem {    JSContext *cx;    SV *errorReporter;    PerlObjectItem *objects;    int dieFromErrors;    struct JSContextItem* next;};typedef struct JSContextItem JSContextItem;static JSContextItem *context_list = NULL;static JSContextItem*PCB_NewContextItem() {    JSContextItem *ret;    ret = (JSContextItem*)calloc(1, sizeof(JSContextItem));    return ret;}static JSContextItem*PCB_FindContextItem (JSContext *cx) {    JSContextItem *cxitem =  context_list;    while ( cxitem ) {        if (cxitem->cx == cx ) return cxitem;        cxitem = cxitem->next;    }    return NULL;}static  SV*PCB_FindErrorReporter (JSContext *cx) {    JSContextItem *cxitem;    if (cxitem = PCB_FindContextItem(cx)) {        return cxitem->errorReporter;    } else {        return NULL;    }}static voidPCB_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report){    SV *report_proc;    if ( report_proc = PCB_FindErrorReporter(cx) ) {        dSP;        PUSHMARK(SP);        XPUSHs(sv_2mortal(newSVpv((char*)message, 0)));        if ( report ) {            if ( report->filename ) {                XPUSHs(sv_2mortal(newSVpv((char*)report->filename, 0)));            }            XPUSHs(sv_2mortal(newSViv(report->lineno)));            if (report->linebuf) {                XPUSHs(sv_2mortal(newSVpv((char*)report->linebuf, 0)));                XPUSHs(sv_2mortal(newSVpv((char*)report->tokenptr, 0)));            }        }        PUTBACK;        perl_call_sv(report_proc, G_VOID | G_DISCARD);    } else {        warn(message);    }}/* perl object stuff *//* functions for callback list handling */static PerlCallbackItem*PCB_AddCallback(PerlObjectItem* object, char *name,                 SV* perl_proc, int param_num) {    PerlCallbackItem *cbk;    cbk = (PerlCallbackItem*)calloc(1, sizeof(PerlCallbackItem));    cbk->name = (char*) malloc(strlen(name) + 1);    strcpy(cbk->name, name);    SvREFCNT_inc(perl_proc);    cbk->perl_proc = perl_proc;    cbk->param_num = param_num;    cbk->next = object->vector;    object->vector = cbk;    return cbk;}/* functions for perl object list handling */static PerlObjectItem*PCB_AddObject(char *name, SV *pobj, JSContext *cx, JSObject *jso, JSClass *class) {    JSContextItem *cxitem;    PerlObjectItem *object;    /* we should always find the item */    cxitem = PCB_FindContextItem(cx);    object = (PerlObjectItem*) calloc(1, sizeof(PerlObjectItem));    object->name = (char*) malloc(strlen(name) + 1);    strcpy(object->name, name);    SvREFCNT_inc(pobj);    object->pObject = pobj;    object->jsObject = jso;    object->jsClass = class;    object->next = cxitem->objects;    cxitem->objects = object;    return object;}static PerlObjectItem*PCB_FindObject(JSContext *cx, JSObject *jso) {    JSContextItem *cxitem;    PerlObjectItem *objitem;    cxitem = PCB_FindContextItem(cx);    objitem = cxitem->objects;    while ( objitem ) {        if ( objitem->jsObject == jso ) return objitem;        objitem = objitem->next;    }    return NULL;}static PerlCallbackItem*PCB_FindCallback(PerlObjectItem *obj, const char *name) {    PerlCallbackItem *cbkitem;    cbkitem = obj->vector;    while ( cbkitem ) {        if ( strcmp(name, cbkitem->name) == 0 ) return cbkitem;        cbkitem = cbkitem->next;    }    return NULL;}/* deletion functions */static void PCB_FreeCallbackItem(PerlCallbackItem *callback) {    free(callback->name);    /* we have to decrease ref. count to proc */    SvREFCNT_dec(callback->perl_proc);    free(callback);}static void PCB_FreeObjectItem(PerlObjectItem *object) {    PerlCallbackItem *cbkitem, *next;    JSClass *class;    free(object->name);    free(object->jsClass);    SvREFCNT_dec(object->pObject);    cbkitem = object->vector;    while ( cbkitem ) {        next = cbkitem->next;        PCB_FreeCallbackItem(cbkitem);        cbkitem = next;    }    free(object);}static void PCB_FreeContextItem(JSContext *cx) {    JSContextItem *cxitem, *aux;    PerlObjectItem *objitem, *next;    cxitem = PCB_FindContextItem(cx);    objitem = cxitem->objects;    while ( objitem ) {        next = objitem->next;        PCB_FreeObjectItem(objitem);        objitem = next;    }    if (cxitem->errorReporter) {        SvREFCNT_dec(cxitem->errorReporter);    }        if ( context_list == cxitem ) {        context_list = cxitem->next;    } else {        aux = context_list;        while ( aux->next != cxitem ) aux = aux->next;        aux->next = cxitem->next;    }    free(cxitem);}/* later the object list should be bind to JS Context   in this case is needed to update destructor PerlFreeObjectList *//* property getter and setter - cooperate with AUTOLOAD */static JSBoolPCB_GetProperty(JSContext *cx, JSObject *obj, jsval name, jsval *rval) {    PerlObjectItem *po;    int i, cnt, len;    I32 ax;    SV *proc_sv;    HV *stash;    char prop_name[256];    char full_name[256];    char *foo;    GV *gv;    dSP;    /* property name */    strcpy(prop_name, JS_GetStringBytes(JSVAL_TO_STRING(name)));    if (! (po = PCB_FindObject(cx, obj)))        croak("Couldn't find stub for object");    if ( (PCB_FindCallback(po, prop_name)))        return(JS_TRUE);    stash = SvSTASH(SvRV(po->pObject));    /* strcpy(full_name, HvNAME(stash));    strcat(full_name, "::");    strcat(full_name, prop_name);    proc_sv = sv_newmortal();    sv_setpv(proc_sv, full_name); */    /* start of perl call stuff */    gv = gv_fetchmeth(stash, prop_name, strlen(prop_name), -1);    /* better check and error report should be done here */    if (!gv) return JS_FALSE;    ENTER;    SAVETMPS;    PUSHMARK(SP);    XPUSHs(po->pObject); /* self for perl AUTOLOAD */    PUTBACK;    /* cnt = perl_call_sv(proc_sv, 0); */    cnt = perl_call_sv((SV*)GvCV(gv), G_ARRAY);        SPAGAIN;    /* adjust stack for use of ST macro (see perlcall) */    SP -= cnt;    ax = (SP - PL_stack_base) + 1;    /* read value(s) */    if (cnt == 1) {        SVToJSVAL(cx, obj, ST(0), rval);    } else {        JSObject *jsarr;        jsval val;        int i;        jsarr = JS_NewArrayObject(cx, 0, NULL);        for (i = 0; i < cnt; i++) {            SVToJSVAL(cx, JS_GetGlobalObject(cx), ST(i), &val);            JS_DefineElement(cx, jsarr, i, val, NULL, NULL, 0);        }        *rval = OBJECT_TO_JSVAL(jsarr);    }    PUTBACK;    FREETMPS;    LEAVE;    return(JS_TRUE);}static JSBoolPCB_SetProperty(JSContext *cx, JSObject *obj, jsval name, jsval *rval) {    PerlObjectItem *po;    int i, cnt, len;    I32 ax;    SV *proc_sv, *value_sv;    HV *stash;    char prop_name[256];    char full_name[256];    char *foo;    dSP;    /* property name */    strcpy(prop_name, JS_GetStringBytes(JSVAL_TO_STRING(name)));    if (! (po = PCB_FindObject(cx, obj)))        croak("Couldn't find stub for object");    if ( (PCB_FindCallback(po, prop_name)))        return(JS_TRUE);    stash = SvSTASH(SvRV(po->pObject));    strcpy(full_name, HvNAME(stash));    strcat(full_name, "::");    strcat(full_name, prop_name);    proc_sv = sv_newmortal();    sv_setpv(proc_sv, full_name);    JSVALToSV(cx, obj, *rval, &value_sv);    /* start of perl call stuff */    ENTER;    SAVETMPS;    PUSHMARK(SP);    XPUSHs(po->pObject); /* self for perl AUTOLOAD */    XPUSHs(value_sv);    PUTBACK;    cnt = perl_call_sv(proc_sv, G_ARRAY);        SPAGAIN;    /* adjust stack for use of ST macro (see perlcall) */    SP -= cnt;    ax = (SP - PL_stack_base) + 1;    /* read value(s) */    if (cnt == 1) {        SVToJSVAL(cx, obj, ST(0), rval);    } else {        JSObject *jsarr;        jsval val;        int i;        jsarr = JS_NewArrayObject(cx, 0, NULL);        for (i = 0; i < cnt; i++) {            SVToJSVAL(cx, JS_GetGlobalObject(cx), ST(i), &val);            JS_DefineElement(cx, jsarr, i, val, NULL, NULL, 0);        }        *rval = OBJECT_TO_JSVAL(jsarr);    }    PUTBACK;    FREETMPS;    LEAVE;    return(JS_TRUE);}/* helper functions */ /* JSClass pointer is disposed by    JS engine during context cleanup _PH_  */voidPCB_FinalizeStub(JSContext *cx, JSObject *obj) {}static JSClass* PCB_NewStdJSClass(char *name) {	    JSClass *class;    class = (JSClass*)calloc(1, sizeof(JSClass));    class->name = name;    class->flags = JSCLASS_HAS_PRIVATE;    class->addProperty = JS_PropertyStub;    class->delProperty = JS_PropertyStub;      class->getProperty = PCB_GetProperty;      class->setProperty = PCB_SetProperty;    class->enumerate = JS_EnumerateStub;    class->resolve = JS_ResolveStub;    class->convert = JS_ConvertStub;    //class->finalize = JS_FinalizeStub;    class->finalize = PCB_FinalizeStub;    return(class);}static JSBoolPCB_UniversalStub (JSContext *cx, JSObject *obj, uintN argc,                    jsval *argv, jsval *rval) {    JSFunction *fun;    PerlObjectItem *po;    PerlCallbackItem *cbk;    int i, cnt;    I32 ax;    SV* sv;    dSP;    fun = JS_ValueToFunction(cx, argv[-2]);    if (! (po = PCB_FindObject(cx, obj)))        croak("Couldn't find stub for object");    if (! (cbk = PCB_FindCallback(po, JS_GetFunctionName(fun))))        croak("Couldn't find perl callback");    /* start of perl call stuff */    ENTER;    SAVETMPS;    PUSHMARK(SP);    XPUSHs(po->pObject); /* self for perl object method */    for (i = 0; i < argc; i++) {        JSVALToSV(cx, obj, argv[i], &sv);        XPUSHs(sv);    }    PUTBACK;    cnt = perl_call_sv(SvRV(cbk->perl_proc), G_ARRAY | G_KEEPERR | G_EVAL);    SPAGAIN;    /* adjust stack for use of ST macro (see perlcall) */    SP -= cnt;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -