Commit c94cbf18 authored by Lucas Almeida Rocha's avatar Lucas Almeida Rocha

Initial import.

svn path=/trunk/; revision=2
parents
Copyright (c) 2008 LiTL, LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Havoc Pennington
E-mail: hp@pobox.com
Userid: hp
Johan Bilien
E-mail: jobi@via.ecp.fr
Userid: jobi
Lucas Rocha
E-mail: lucasr@gnome.org
Userid: lucasr
Tommi Komulainen
E-mail: tommi.komulainen@iki.fi
Userid: tko
EXTRA_DIST += \
examples/clutter.js \
examples/gtk.js
lib_LTLIBRARIES += \
libgjs-gi.la
libgjs_gi_la_CFLAGS = \
$(AM_CFLAGS) \
$(GJS_CFLAGS) \
$(GOBJECT_INTROSPECTION_CFLAGS)
libgjs_gi_la_LIBADD = \
$(GOBJECT_INTROSPECTION_LIBS) \
libgjs.la
libgjs_gi_la_LDFLAGS = \
-export-symbols-regex "^[^_].*" -version-info 0:0:0 -rdynamic
noinst_HEADERS += \
gi/arg.h \
gi/boxed.h \
gi/closure.h \
gi/enumeration.h \
gi/function.h \
gi/keep-alive.h \
gi/native.h \
gi/ns.h \
gi/object.h \
gi/param.h \
gi/repo.h \
gi/value.h
libgjs_gi_la_SOURCES = \
gi/arg.c \
gi/boxed.c \
gi/closure.c \
gi/enumeration.c \
gi/function.c \
gi/keep-alive.c \
gi/native.c \
gi/ns.c \
gi/object.c \
gi/param.c \
gi/repo.c \
gi/value.c
dist_gjsjs_DATA += modules/lang.js
gjsnative_LTLIBRARIES += gi.la
JS_NATIVE_MODULE_CFLAGS = \
$(AM_CFLAGS) \
$(GJS_CFLAGS)
JS_NATIVE_MODULE_LIBADD = \
$(GJS_LIBS) \
libgjs.la
JS_NATIVE_MODULE_LDFLAGS = \
-module -avoid-version -Wl,-z,defs -rdynamic
gi_la_CFLAGS = \
$(JS_NATIVE_MODULE_CFLAGS) \
$(GOBJECT_INTROSPECTION_CFLAGS)
gi_la_LIBADD = \
libgjs-gi.la \
$(JS_NATIVE_MODULE_LIBADD) \
$(GOBJECT_INTROSPECTION_LIBS)
gi_la_LDFLAGS = \
$(JS_NATIVE_MODULE_LDFLAGS)
gi_la_SOURCES = \
modules/gi.h \
modules/gi.c
GTESTER = ${TESTS_ENVIRONMENT} gtester
########################################################################
TEST_PROGS += gjs-tests
gjs_tests_CFLAGS = \
-include $(top_srcdir)/test/test.h \
$(AM_CFLAGS) \
$(GJSTESTS_CFLAGS) \
$(gjs_directory_defines) \
-I$(top_srcdir)/test
## -rdynamic makes backtraces work
gjs_tests_LDFLAGS = -rdynamic
gjs_tests_LDADD = \
$(GJSTESTS_LIBS) \
libgjs.la
gjs_tests_SOURCES = \
test/gjs-tests.c \
test/test.h \
$(gjstest_files_with_tests)
nodist_gjs_tests_SOURCES = \
gjstest.c \
gjstest.h
## make-tests always updates the ".stamp" files, but only modifies the
## actual gjstest.[hc] if they change. make-tests creates both
## .h.stamp and .c.stamp but if we listed both, make would run
## make-tests twice.
gjstest.h.stamp : scripts/make-tests $(gjstest_files_with_tests)
$(TESTS_ENVIRONMENT) $(top_srcdir)/scripts/make-tests $(builddir) $(gjstest_files_with_tests)
gjstest.h gjstest.c : gjstest.h.stamp
@true
BUILT_SOURCES += $(nodist_gjs_tests_SOURCES)
CLEANFILES += \
$(nodist_gjs_tests_SOURCES) \
gjstest.c.stamp \
gjstest.h.stamp
EXTRA_DIST += \
scripts/make-tests
########################################################################
TESTS_ENVIRONMENT = \
abs_top_srcdir="$(abs_top_srcdir)" \
LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):$(FIREFOX_JS_LIBDIR)"
test: ${TEST_PROGS}
@test -z "${TEST_PROGS}" || ${GTESTER} --verbose ${TEST_PROGS}
check: test
bin_PROGRAMS =
lib_LTLIBRARIES =
noinst_LTLIBRARIES =
dist_gjsjs_DATA =
gjsnative_LTLIBRARIES =
BUILT_SOURCES =
CLEANFILES =
EXTRA_DIST =
gjstest_files_with_tests =
TEST_PROGS =
check_PROGRAMS = $(TEST_PROGS)
gjsjsdir = @gjsjsdir@
gjsnativedir = @gjsnativedir@
gjsincludedir = $(includedir)/gjs-1.0
########################################################################
nobase_gjsinclude_HEADERS = \
gjs/context.h \
gjs/gjs.h \
gjs/jsapi-util.h \
gjs/native.h
noinst_HEADERS = \
gjs/context-jsapi.h \
gjs/importer.h \
gjs/mem.h \
util/dirs.h \
util/error.h \
util/glib.h \
util/log.h \
util/misc.h
########################################################################
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = gjs-1.0.pc
EXTRA_DIST += \
gjs-1.0.pc.in
########################################################################
gjs_directory_defines = \
-DGJS_TOP_SRCDIR=\"$(abs_top_srcdir)\" \
-DGJS_BUILDDIR=\"$(abs_top_builddir)\" \
-DGJS_JS_DIR=\"$(gjsjsdir)\" \
-DGJS_NATIVE_DIR=\"$(gjsnativedir)\"
########################################################################
lib_LTLIBRARIES += libgjs.la
libgjs_la_CPPFLAGS = \
$(AM_CPPFLAGS) \
$(gjs_directory_defines)
libgjs_la_CFLAGS = \
$(AM_CFLAGS) \
$(GJS_CFLAGS)
libgjs_la_LDFLAGS = \
-export-symbols-regex "^[^_]" -version-info 0:0:0 \
-R $(FIREFOX_JS_LIBDIR) -rdynamic
libgjs_la_LIBADD = \
$(GJS_LIBS)
libgjs_la_SOURCES = \
gjs/context.c \
gjs/importer.c \
gjs/jsapi-util.c \
gjs/jsapi-util-array.c \
gjs/jsapi-util-error.c \
gjs/jsapi-util-string.c \
gjs/mem.c \
gjs/native.c \
util/dirs.c \
util/error.c \
util/glib.c \
util/log.c \
util/misc.c
gjstest_files_with_tests += \
gjs/jsapi-util-array.c \
gjs/jsapi-util-error.c \
gjs/jsapi-util-string.c \
util/dirs.c \
util/glib.c
include Makefile-gi.am
include Makefile-modules.am
include Makefile-examples.am
########################################################################
bin_PROGRAMS += gjs-console
gjs_console_CFLAGS = \
$(AM_CFLAGS) \
$(GJS_CFLAGS)
gjs_console_LDADD = \
libgjs.la
gjs_console_SOURCES = gjs/console.c
include Makefile-test.am
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="gjs"
REQUIRED_AUTOCONF_VERSION=2.53
REQUIRED_AUTOMAKE_VERSION=1.7.2
(test -f $srcdir/configure.ac \
&& test -f $srcdir/autogen.sh) || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
echo " top-level $PKG_NAME directory"
exit 1
}
DIE=0
# This is a bit complicated here since we can't use gnome-config yet.
# It'll be easier after switching to pkg-config since we can then
# use pkg-config to find the gnome-autogen.sh script.
gnome_autogen=
gnome_datadir=
ifs_save="$IFS"; IFS=":"
for dir in $PATH ; do
test -z "$dir" && dir=.
if test -f $dir/gnome-autogen.sh ; then
gnome_autogen="$dir/gnome-autogen.sh"
gnome_datadir=`echo $dir | sed -e 's,/bin$,/share,'`
break
fi
done
IFS="$ifs_save"
if test -z "$gnome_autogen" ; then
echo "You need to install the gnome-common module and make"
echo "sure the gnome-autogen.sh script is in your \$PATH."
exit 1
fi
GNOME_DATADIR="$gnome_datadir" USE_GNOME2_MACROS=1 . $gnome_autogen
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
AC_INIT([gjs], [0.1], BUG-REPORT-ADDRESS)
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([gjs/console.c])
AC_CONFIG_HEADER([config.h])
GETTEXT_PACKAGE=gjs
AC_SUBST([GETTEXT_PACKAGE])
AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"], [The name of the gettext domain])
AM_MAINTAINER_MODE
AC_PROG_CC
AM_PROG_CC_C_O
AC_ISC_POSIX
AC_HEADER_STDC
# no stupid static libraries
AM_DISABLE_STATIC
# avoid libtool for LTCOMPILE, use it only to link
AC_PROG_LIBTOOL
dnl DOLT
# Checks for libraries.
m4_define(gobject_required_version, 2.16.0)
## spidermonkey .pc file name varies across distributions
PKG_CHECK_EXISTS([firefox-js], [JS_PACKAGE=firefox-js],
[PKG_CHECK_EXISTS([xulrunner-js], [JS_PACKAGE=xulrunner-js], [JS_PACKAGE=mozilla-js])])
PKG_CHECK_MODULES(JS, $JS_PACKAGE)
AC_SUBST(JS_PACKAGE)
AC_CHECK_LIB([mozjs], [JS_CallTracer], :,
[AC_MSG_ERROR([SpiderMonkey is too old, Firefox 3 is required])],
[$JS_LIBS])
gjs_packages="gmodule-2.0 gobject-2.0 >= gobject_required_version $JS_PACKAGE"
gjstests_packages="$gjstests_packages $gjs_packages"
PKG_CHECK_MODULES([GJS], [$gjs_packages])
## some flavors of Firefox .pc only set sdkdir, not libdir
FIREFOX_JS_SDKDIR=`$PKG_CONFIG --variable=sdkdir $JS_PACKAGE`
FIREFOX_JS_LIBDIR=`$PKG_CONFIG --variable=libdir $JS_PACKAGE`
## Ubuntu does not set libdir in mozilla-js.pc
if test x"$FIREFOX_JS_LIBDIR" = x ; then
## Ubuntu returns xulrunner-devel as the sdkdir, but for the
## libdir we want the runtime location on the target system,
## so can't use -devel.
## The library is in the non-devel directory also.
## Don't ask me why it's in two places.
FIREFOX_JS_LIBDIR=`echo "$FIREFOX_JS_SDKDIR" | sed -e 's/-devel//g'`
if ! test -d "$FIREFOX_JS_LIBDIR" ; then
FIREFOX_JS_LIBDIR=
fi
fi
if test x"$FIREFOX_JS_LIBDIR" = x ; then
AC_MSG_ERROR([Could not figure out where Firefox JavaScript library lives])
fi
AC_SUBST(FIREFOX_JS_LIBDIR)
## workaround for Ubuntu Hardy bug where mozilla-js.pc gives CFLAGS
## -I.../stable while jsapi.h is in .../unstable
js_include_dir=`$PKG_CONFIG --variable=includedir $JS_PACKAGE`/unstable
GJS_CFLAGS="$GJS_CFLAGS -I$js_include_dir"
AC_SUBST([js_include_dir])
PKG_CHECK_MODULES([GOBJECT_INTROSPECTION], [gobject-introspection-1.0])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
gjsjsdir="\${datadir}/gjs-1.0"
gjsnativedir="\${libdir}/gjs-1.0"
AC_SUBST([gjsjsdir])
AC_SUBST([gjsnativedir])
# gjs-tests links against everything
PKG_CHECK_MODULES([GJSTESTS], [$gjstests_packages])
GJSTESTS_CFLAGS="$GJSTESTS_CFLAGS -I$js_include_dir"
AC_CONFIG_FILES([Makefile gjs-1.0.pc])
AC_OUTPUT
In order to run those example scripts, do:
gjs-console script-filename.js
const Clutter = imports.gi.clutter;
Clutter.init(null, null);
let stage = new Clutter.Stage();
let texture = new Clutter.Texture({ filename: '' });
stage.add_actor(texture);
stage.show();
Clutter.main();
const Gtk = imports.gi.Gtk;
// This is a callback function. The data arguments are ignored
// in this example. More on callbacks below.
function hello(widget) {
log("Hello World");
}
function delete_event(widget, event) {
// If you return FALSE in the "delete_event" signal handler,
// GTK will emit the "destroy" signal. Returning TRUE means
// you don't want the window to be destroyed.
// This is useful for popping up 'are you sure you want to quit?'
// type dialogs.
log("delete event occurred");
// Change FALSE to TRUE and the main window will not be destroyed
// with a "delete_event".
return false;
}
function destroy(widget) {
log("destroy signal occurred");
Gtk.main_quit();
}
Gtk.init(0, null);
// create a new window
let win = new Gtk.Window({ type: Gtk.WindowType.toplevel });
// When the window is given the "delete_event" signal (this is given
// by the window manager, usually by the "close" option, or on the
// titlebar), we ask it to call the delete_event () function
// as defined above.
win.connect("delete-event", delete_event);
// Here we connect the "destroy" event to a signal handler.
// This event occurs when we call gtk_widget_destroy() on the window,
// or if we return FALSE in the "delete_event" callback.
win.connect("destroy", destroy);
// Sets the border width of the window.
win.set_border_width(10)
// Creates a new button with the label "Hello World".
let button = new Gtk.Button({ label: "Hello World" });
// When the button receives the "clicked" signal, it will call the
// function hello(). The hello() function is defined above.
button.connect("clicked", hello);
// This will cause the window to be destroyed by calling
// gtk_widget_destroy(window) when "clicked". Again, the destroy
// signal could come from here, or the window manager.
button.connect("clicked", function() {
win.destroy();
});
// This packs the button into the window (a GTK container).
win.add(button)
// The final step is to display this newly created widget.
button.show()
// and the window
win.show()
// All gtk applications must have a Gtk.main(). Control ends here
// and waits for an event to occur (like a key press or mouse event).
Gtk.main();
This diff is collapsed.
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/*
* Copyright (c) 2008 LiTL, LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef __GJS_ARG_H__
#define __GJS_ARG_H__
#include <glib.h>
#include <jsapi.h>
#include <girepository.h>
G_BEGIN_DECLS
JSBool gjs_value_to_g_arg (JSContext *context,
jsval value,
GIArgInfo *arg_info,
GArgument *arg);
JSBool gjs_value_from_g_arg (JSContext *context,
jsval *value_p,
GITypeInfo *type_info,
GArgument *arg);
JSBool gjs_g_arg_release (JSContext *context,
GITransfer transfer,
GITypeInfo *type_info,
GArgument *arg);
JSBool _gjs_flags_value_is_valid (JSContext *context,
GFlagsClass *klass,
guint value);
G_END_DECLS
#endif /* __GJS_ARG_H__ */
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/*
* Copyright (c) 2008 LiTL, LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <config.h>
#include <string.h>
#include "boxed.h"
#include "arg.h"
#include "object.h"
#include <gjs/mem.h>
#include <gjs/jsapi-util.h>
#include "repo.h"
#include "function.h"
#include <util/log.h>
#include <jsapi.h>
#include <girepository.h>
typedef struct {
GIBoxedInfo *info;
void *gboxed; /* NULL if we are the prototype and not an instance */
} Boxed;
static Boxed unthreadsafe_template_for_constructor = { NULL, NULL };
static struct JSClass gjs_boxed_class;
GJS_DEFINE_DYNAMIC_PRIV_FROM_JS(Boxed, gjs_boxed_class)
/*
* Like JSResolveOp, but flags provide contextual information as follows:
*
* JSRESOLVE_QUALIFIED a qualified property id: obj.id or obj[id], not id
* JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment
* JSRESOLVE_DETECTING 'if (o.p)...' or similar detection opcode sequence
* JSRESOLVE_DECLARING var, const, or boxed prolog declaration opcode
* JSRESOLVE_CLASSNAME class name used when constructing
*
* The *objp out parameter, on success, should be null to indicate that id
* was not resolved; and non-null, referring to obj or one of its prototypes,
* if id was resolved.
*/
static JSBool
boxed_new_resolve(JSContext *context,
JSObject *obj,
jsval id,
uintN flags,
JSObject **objp)
{
Boxed *priv;
const char *name;
*objp = NULL;
if (!gjs_get_string_id(id, &name))
return JS_TRUE; /* not resolved, but no error */
priv = priv_from_js(context, obj);
gjs_debug_jsprop(GJS_DEBUG_GBOXED, "Resolve prop '%s' hook obj %p priv %p", name, obj, priv);
if (priv == NULL)
return JS_FALSE; /* wrong class */
if (priv->gboxed == NULL) {
/* We are the prototype, so look for methods and other class properties */
GIFunctionInfo *method_info;
method_info = g_struct_info_find_method((GIStructInfo*) priv->info,
name);
if (method_info != NULL) {
JSObject *boxed_proto;
const char *method_name;
#if GJS_VERBOSE_ENABLE_GI_USAGE
_gjs_log_info_usage((GIBaseInfo*) method_info);
#endif
method_name = g_base_info_get_name( (GIBaseInfo*) method_info);
gjs_debug(GJS_DEBUG_GBOXED,
"Defining method %s in prototype for %s.%s",
method_name,
g_base_info_get_namespace( (GIBaseInfo*) priv->info),
g_base_info_get_name( (GIBaseInfo*) priv->info));
boxed_proto = obj;
if (gjs_define_function(context, boxed_proto, method_info) == NULL) {
g_base_info_unref( (GIBaseInfo*) method_info);
return JS_FALSE;
}
*objp = boxed_proto; /* we defined the prop in object_proto */
g_base_info_unref( (GIBaseInfo*) method_info);
}
} else {
/* We are an instance, not a prototype, so look for
* per-instance props that we want to define on the
* JSObject. Generally we do not want to cache these in JS, we
* want to always pull them from the C object, or JS would not
* see any changes made from C. So we use the get/set prop
* hooks, not this resolve hook.
*/
}
return JS_TRUE;
}
static void*
boxed_new(JSContext *context,
JSObject *obj, /* "this" for constructor */
GIBoxedInfo *info)
{
int n_methods;
int i;
/* Find a zero-args constructor and call it */
n_methods = g_struct_info_get_n_methods(info);
for (i = 0; i < n_methods; ++i) {
GIFunctionInfo *func_info;
GIFunctionInfoFlags flags;
func_info = g_struct_info_get_method(info, i);
flags = g_function_info_get_flags(func_info);
if ((flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0 &&
g_callable_info_get_n_args((GICallableInfo*) func_info) == 0) {
jsval rval;
rval = JSVAL_NULL;
gjs_invoke_c_function(context, func_info, obj,
0, NULL, &rval);
g_base_info_unref((GIBaseInfo*) func_info);
/* We are somewhat wasteful here; invoke_c_function() above
* creates a JSObject wrapper for the boxed that we immediately
* discard.
*/
if (JSVAL_IS_NULL(rval))
return NULL;
else
return gjs_g_boxed_from_boxed(context, JSVAL_TO_OBJECT(rval));
}
g_base_info_unref((GIBaseInfo*) func_info);
}
gjs_throw(context, "Unable to construct boxed type %s since it has no zero-args <constructor>, can only wrap an existing one",
g_base_info_get_name((GIBaseInfo*) info));
return NULL;
}
/* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
* the prototype in addition to on each instance. When called on the
* prototype, "obj" is the prototype, and "retval" is the prototype
* also, but can be replaced with another object to use instead as the
* prototype. If we don't set JSCLASS_CONSTRUCT_PROTOTYPE we can
* identify the prototype as an object of our class with NULL private
* data.
*/
static JSBool
boxed_constructor(JSContext *context,
JSObject *obj,
uintN argc,
jsval *argv,
jsval *retval)
{