1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-06-15 23:35:34 +00:00

Merge branch 'elinks-0.12' into elinks-0.13

Conflicts:

	NEWS
	configure.in

The following files also conflicted, but they had not been manually
edited in the elinks-0.12 branch after the previous merge, so I just
kept the 0.13.GIT versions:

	doc/man/man1/elinks.1.in
	doc/man/man5/elinks.conf.5
	doc/man/man5/elinkskeys.5
	po/fr.po
	po/pl.po
This commit is contained in:
Kalle Olavi Niemitalo 2008-07-11 22:28:45 +03:00 committed by Kalle Olavi Niemitalo
commit 988cec481b
73 changed files with 10072 additions and 8814 deletions

View File

@ -282,9 +282,11 @@ Julian Kinraid <jkinraid@clear.net.nz>
QNX-related fixes
Kalle Olavi Niemitalo <kon@iki.fi>
HTTP Accept-Charset header fix
Finnish translation update
Fixed unnecessary or possibly skipped calls to bind_textdomain_codeset()
Scanning PO files for accelerator conflicts (msgaccel)
UTF-8 and terminal support enhancements
Build system fixes
Finnish translation updates
Random hacking
Kaloian Doganov <kaloian@europe.com>
Bulgarian translation

View File

@ -1,7 +1,7 @@
The ChangeLog file has been removed. You can get the equivalent information
by doing
$ cg log
$ git log
in a checked out GIT tree, or using the gitweb interface available at:

16
INSTALL
View File

@ -11,26 +11,20 @@ ECMAScript (that's JavaScript) support.
##########
In order to check out the latest tree from GIT (using Cogito):
In order to check out the latest tree from GIT:
$ cg clone check_file_SITES_for_value_of_this
$ git clone check_file_SITES_for_value_of_this
$ cd elinks
To update your existing tree to the latest GIT version, do:
$ cg update
If you downloaded a nightly snapshot, and want to check out the latest tree
from GIT in it, use the command:
$ cg clone -s check_file_SITES_for_value_of_this
$ git pull
Note that if you obtained the sources directly from GIT, you NEED to run
./autogen.sh! (It should be enough to do it once - however, if you have build
problems, try running this first.) Also, you obviously need GNU make and
autoconf installed on your system (note that autoconf-2.13 is supported, newer
ones may cause problems thanks to the autoconf developers who don't know how to
maintain backwards compatibility). Otherwise, you have to use the nightly GIT
autoconf installed on your system (for the supported versions of autoconf,
see AC_PREREQ in configure.in). Otherwise, you have to use the nightly GIT
snapshot - you don't need to do this there.

View File

@ -229,7 +229,7 @@ export TEST_LIB
TESTS = $(wildcard $(srcdir)test-*)
$(TESTS): $(addsuffix .o,$(TEST_PROGS)) $(TEST_PROGS)
@echo "*** $(notdir $@) ***"; \
@-echo "*** $(notdir $@) ***"; \
$(call shellquote,$(SHELL)) $@ $(TEST_OPTS)
test-default: $(TESTS)

187
NEWS
View File

@ -56,21 +56,26 @@ have already been considered.
- critical bug 1009: assertion failure in add_snippets()
//////////////////////////////////////////////////////////////////////
ELinks 0.12.GIT now:
--------------------
ELinks 0.12pre1.GIT now:
------------------------
To be released as ELinks 0.12.0.
To be released as 0.12pre2, 0.12rc1, or even 0.12.0. This branch
generally also includes the bug fixes made in ELinks 0.11.4.GIT.
//////////////////////////////////////////////////////////////////////
This list now contains all the important changes from ELinks 0.11.0 to
ELinks 0.12.GIT (4672bad9c73321019c1a2a7695761b8188bd1a8f) and related
bug numbers. Each section is sorted by severity and grouped by topic.
* minor bug 951: SpiderMonkey scripting objects used to prevent ELinks
from removing files from the memory cache
The list no doubt includes several changes that are not really
important enough. Please move them to the separate "should be removed
from NEWS" list below, or coalesce several changes into one entry (but
do list all bug numbers).
//////////////////////////////////////////////////////////////////////
Bugs that should be removed from NEWS before the 0.12.0 release:
* bug 955: Reset buttons no longer run FORM/@onsubmit, and
``harmless'' buttons no longer submit the form. ELinks 0.12pre1
was the first release that had these bugs.
ELinks 0.12pre1:
----------------
Released on 2008-07-01. This release also included all the bug fixes
of ELinks 0.11.4, but not the ones made in 0.11.4.GIT.
Notable new features:
@ -118,6 +123,8 @@ Miscellaneous:
decompression, and add deflate and LZMA (requires LZMA Utils)
* major bug 503: various fixes in parsing and updating of elinks.conf
* Debian bug 257762: turn terminal transparency off by default
* bug 770: when the user chooses to resume an HTTP download, abort the
automatically started one and start a new one with the right range
* bug 724: better parsing of escape sequences and control
sequences from the terminal
* bug 948: fix wrong UTF-8 output after the charset menu was used
@ -221,137 +228,20 @@ Changes in the experimental SGML/DOM implementation:
* enhancement: incremental parsing
* and more.
//////////////////////////////////////////////////////////////////////
The following changes should be removed from NEWS before ELinks 0.12.0
is released. They are currently listed here just to show that they
have already been considered.
ELinks 0.11.4.GIT now:
----------------------
* Not clear whether the bugs have been fixed:
- (bugfix 674) Reproduceable crashes while trying to unsubscribe
from a community on Orkut
- (bugfix 770) Download resuming simply restarts the download
* Only partially fixed bugs:
- (bugfix 764) int/long type punning in options
- (bugfix 890) Change colors 0-15 to match xterm defaults.
The bug report also requests asking xterm to report its palette,
but that part will be delayed to 0.13 or later.
- (bugfix 784) attributes corrupt character entity references if
terminal charset != document charset
* Fixed bugs that were not in previous versions:
- (bugfix) Fix a crash when adding a server in the cookie manager.
- (bugfix) cookies: "Add Server" ignores "cookies.accept_policy".
- (bugfix) Fix data: protocol.
- (bugfix 747) Properly deselect the main menu instead of crashing
- (bugfix 778) ELinks crashes on binary files when
document.plain.display_links is set
- (bugfix 782) UTF-8 buffer overwritten while in use
- (bugfix) switch_to_tab: Prevent "tab number out of range"
assertion failure.
- (bugfix) Fixed about:
- (bugfix 821) I cannot enter national characters in dialog boxes
- (bugfix 834) Gzip decompression doesn't work
- (bugfix) Fix out-of-bound access to the quote_char buffer
- (bugfix 827) Crash with term charset set to Unicode and UTF-8 I/O
disabled
- (bugfix 826) too small table for double-cell characters
- (bugfix 902) crash: "overflow detected realloc()" in realloc_line
- (bugfix 912) wrong color in one cell of an HTML input field
- (bugfix 835) Text in textarea is unaffected by horizontal
scrolling of document in UTF-8 mode
- (bugfix 823) Big textarea is too slow with CONFIG_UTF8
- (bugfix 754) Pressing ESC do not pop up main menu anymore.
- (bugfix 794) tab-close-all-but-current crashes
- (bugfix 781) document->buf can overflow with UTF-8 enabled
- (bugfix 882) C1 controls pass through to the terminal if written
as entity references
- (bugfix 935) Yes and No buttons override the bottom border of the
dialog.
- (bugfix in SEE) Use frame->name instead of target avoiding
possible segfault.
- (bugfix 957) crash within js_Interpret: cx->fp points to freed
memory
- (bugfix 920) assertion priority >= prev_priority failed: queue is
not sorted
- (bugfix 968) assertion width > 0 failed in copy_chars called from
justify_line
- bug 1015: incompatible pointer type for PyString_AsStringAndSize
- bug 917: Going to unopened /dev/fd/ kills select_loop
* Already backported to a previous release but not listed there:
- (enhancement) Activate link only when onClick returns true.
Fixed bug 786 in ELinks 0.11.2.
- when the configure script cleans old object files, this no longer
causes it to loop. Commit 564b67883b189a05839bcd2a30d8d4c6eb89c66d
in ELinks 0.11.1.
- don't include <sys/param.h> for MIN and MAX because it may interfere with
CONFIG_IPV6 on Linux. Commit 63797ae9b331efd91be27512bd9d5b2e2ff74741
in ELinks 0.11.1.
- Debian bug 400872: include <sys/types.h> for off_t.
(Related to bug 936 but not the same.)
Commit 135a79a3c309af36cf963f1d3c34b07f296fa2f7 in ELinks 0.11.3.
- bug 107: recognize "localhost" in file: URIs. Cannot reproduce in
earlier versions.
- fix compilation under gcc 4.x. Backported from gentoo portage.
Commit bcabd8b7951f3319199811088e607501296ee573 in ELinks 0.11.3.
- enhancement: avoid compilation of vernum.c in 'make install'
- bug 991: quote spaces in file names passed to external handlers
* Reverted changes:
- (new feature) document.write, reverted in
2c087e52e74528a720621186b91880463e039d50
- (enhancement) restore Linux console mode (UTF-8 or not), reverted
in 10d72cae7eafa6b90db1c8f303deb200555734c2
- (enhancement) wcwidth, reverted in
d050cb67aa37390ab938b0a308c7541f19578506
- (new feature) Let plain text change colors with ESC [ 31 m or
similar control sequences, reverted in
2a6125e3d0407b588eb286d4d0ff5c98c23ebda9
- (enhancement) Support for pasting from GNU screen clipboard,
reverted in 763f03f146cc1391b303c8074556f0ddea1e3c7a
- enhancement 121: if a mailcap entry indicates 'copiousoutput',
ELinks itself acts as a pager
* Unimportant changes:
- (enhancement) If select fails, save its errno.
- (bugfix) Use PF_* instead of AF_* as first parameter of socket(2).
(commits 8b7657deaf6037736d0abe88bae1865fec55fe93 in 0.12.GIT
and d9b56bad7d528a87376768572c2601c57d8afb02 in 0.11.0.GIT)
- (bugfix) Better error handling in save_form_data_to_file and
save_textarea_file.
(commit 6bdc34cfbcade0c25922c1ad96c753cc7d1c9949 and nearby)
- (bugfix) Do not call toupper with potentially out-of-range values.
(commit 9e30ee631ced843f26a264c351cfa1716e7e1941)
- (bugfix) If ELinks logs debug information to a file, it now opens
that in binary mode. (commit 4ced25779dca68c0e15ce1e695ce191b536bb05d)
- (bugfix) Kill the ESC timer when blocking the terminal.
(commit 539f756438fca4264ab937b2ccfba2351e916a16)
- (bugfix) Don't claim that the authentication is for HTTP.
(commit ef2f6383c6f0bed576e6f69030eacc4931b42a27)
- (enhancement) Reject invalid UTF-8 input from documents and
terminals
- (bugfix) Decode UTF-8 only from bytes, not from codes of special
keys.
- (enhancement) "Resize terminal" tries to use the window size
increment.
- (bugfix) Subprocess forked for SIGTSTP calls _exit, not exit.
- (enhancement) Tell the user how to move bookmarks.
- (enhancement) Localization updates. For this to be important, we
should at least list the languages.
- (enhancement) Ctrl+characters don't trigger hotkeys in menus and
dialogs.
- (bitrot) Fix two warnings on Mac OS X.
* don't use cmp -b, which FreeBSD doesn't support. This is commit
7a5f699a88c5fc89c510854b04702c16c30ece5a in src/dom/test/ which
is run only by "make test" rather than "make".
* support much longer locale-specific timestamps when formatting a
directory listing. LC_TIME=fi_FI.UTF-8 now works. Let's treat
this as part of the UTF-8 support.
* enhancement in user SMJS: elinks.alert no longer displays as an
"error"
* Really retry forever when connection.retries = 0
//////////////////////////////////////////////////////////////////////
To be released as 0.11.5.
ELinks 0.11.4rc1.GIT now:
-------------------------
* critical bug 1027 in user SMJS: make elinks.keymaps treat null and
"none" as equivalent actions, avoiding a segfault
* major bug 503: various fixes in parsing and updating of elinks.conf
* build bug 1021: fixed uninitialized variable in http_got_header
To be released as 0.11.4.
ELinks 0.11.4:
--------------
Released on 2008-06-20.
* critical bug 755: fix crashes due to dangling pointers to struct
form_state
@ -360,8 +250,10 @@ To be released as 0.11.4.
* critical bug 945: don't crash if a Lua script calls e.g. error(nil)
* critical bug 1003: don't crash if a smart URI rewrite template gets
too few parameters
* major bug 956: don't reuse pointers to SpiderMonkey objects that may
have been collected as garbage. This fix causes bug 954.
* critical bug 1016: avoid JSFunctionSpec for better compatibility
across versions of SpiderMonkey
* critical bugs 674, 956: don't reuse pointers to SpiderMonkey objects
that may have been collected as garbage. This fix causes bug 954.
* CVE-2007-2027: check if the program path contains "src/" before
using ../po files
* important Debian bug 380347: prevent a buffer overflow in entity_cache
@ -369,7 +261,6 @@ To be released as 0.11.4.
* major bug 788: don't read STRLEN n_a, which isn't initialized by
POPpx of Perl v5.8.8 and later
* fix query parsing in file: URIs for local CGI (was broken in 0.11.3)
* bug 451: fix incompatible pointer type in PERL_SYS_INIT3 call
* bug 691: don't look up bogus IPv4 addresses based on characters of a
hostname
* bug 712: GnuTLS works on https://www-s.uiuc.edu/[]
@ -378,6 +269,7 @@ To be released as 0.11.4.
* bug 939: fix FSP directory listing (some compiler options left it empty)
* bug 978: Python's webbrowser.open_new_tab(URL) works since now
* bug 1012: compile with -fno-strict-overflow or -fwrapv if available
* bug 1014: fix incompatible pointer type in Perl_sys_init3 call
* minor bug 54, Debian bug 338402: don't force the terminal to 8 bits
with no parity, and don't disable XON/XOFF flow control either
* minor bug 951 in user SMJS: garbage-collect SMJS objects on 'File ->
@ -407,15 +299,6 @@ To be released as 0.11.4.
* minor build bug 960: fix errors in loadmsgcat.c if mmap() exists but
munmap() doesn't
//////////////////////////////////////////////////////////////////////
The following changes should be removed from NEWS before ELinks 0.11.4
is released. They are currently listed here just to show that they
have already been considered.
* Fixed bugs that were not in previous versions:
- bug 975: fix int/size_t pointer type mismatch in Perl interface
//////////////////////////////////////////////////////////////////////
ELinks 0.11.3:
--------------

12
SITES
View File

@ -5,16 +5,11 @@ Fan sites:
http://starshine.org/xteddy/thomas/elinks/ (tips'n'tricks)
DEBs:
http://packages.debian.org/testing/web/elinks.html
http://packages.debian.org/unstable/web/elinks.html
http://packages.debian.org/search?keywords=elinks
RPMs:
http://rpmfind.net/linux/rpm2html/search.php?query=elinks
RISC OS binaries:
http://www.riscos.info/unix/indexes/browser.html
GIT root:
http://elinks.cz/elinks.git
git+ssh://pasky.or.cz/srv/git/elinks.git (only for developers)
@ -23,7 +18,6 @@ Mailing list:
http://elinks.cz/community.html#mailinglist
elinks-users@linuxfromscratch.org (user discussion, announcements)
elinks-dev@linuxfromscratch.org (weird development and sorcery talks)
listar@linuxfromscratch.org (Subject: subscribe elinks-users)
If you want to see the original Links as well, try:
@ -33,11 +27,9 @@ Primary site:
Mirrors:
http://links.sourceforge.net/download/
ftp://ftp.fu-berlin.de/unix/network/www/links/
DEBs:
http://packages.debian.org/stable/web/links.html
http://packages.debian.org/unstable/web/links.html
http://packages.debian.org/search?keywords=links
RPMs:
http://rpmfind.net/linux/rpm2html/search.php?query=links

View File

@ -4,8 +4,12 @@
#
# Note that this will download about 80M.
if [ -z "`which wget 2>/dev/null`" ]; then
echo "Error: You need to have wget installed so that I can fetch the history." >&2
if [ -n "`which wget 2>/dev/null`" ]; then
downloader="wget -c"
elif [ -n "`which curl 2>/dev/null`" ]; then
downloader="curl -C - -O"
else
echo "Error: You need to have wget or curl installed so that I can fetch the history." >&2
exit 1
fi
@ -24,8 +28,8 @@ echo "ELinks history converted from CVS. Keep this pack separate to speed up gi
# pack-0d6c5c67aab3b9d5d9b245da5929c15d79124a48.idx is 3163784 bytes long.
# Downloading it takes less than 6 seconds here, whereas generating it
# with git index-pack takes over 4 minutes (750 MHz Duron, git 1.5.4.1).
wget -c http://elinks.cz/elinks-history.git/objects/pack/pack-0d6c5c67aab3b9d5d9b245da5929c15d79124a48.idx
wget -c http://elinks.cz/elinks-history.git/objects/pack/pack-0d6c5c67aab3b9d5d9b245da5929c15d79124a48.pack
$downloader http://elinks.cz/elinks-history.git/objects/pack/pack-0d6c5c67aab3b9d5d9b245da5929c15d79124a48.idx
$downloader http://elinks.cz/elinks-history.git/objects/pack/pack-0d6c5c67aab3b9d5d9b245da5929c15d79124a48.pack
echo "[grafthistory] Setting up the grafts"
cd ../..

View File

@ -20,10 +20,12 @@
# set -x
echo "-------------------------------------------------"
echo "Date: $(date)"
echo "Args: $*"
echo "-------------------------------------------------"
cat <<EOF
-------------------------------------------------
Date: $(date)
Args: $*
-------------------------------------------------
EOF
# Variables used in this script:
# $GIT_DIR = option -g GIT_DIR; passed in environment to Git
@ -55,30 +57,30 @@ do
(d) docdir=$OPTARG ;;
(o) outdir=$OPTARG ;;
("?") exit 1 ;;
(*) echo >&2 "$0:$LINENO: bug found"
(*) printf >&2 "%s:%d: bug found\n" "$0" "$LINENO"
exit 1 ;;
esac
done
if [ $OPTIND -le $# ]
then
echo >&2 "$0: too many non-option arguments"
printf >&2 "%s: too many non-option arguments\n" "$0"
exit 1
fi
if [ -z "$GIT_DIR" ]
then
echo >&2 "$0: Must specify -g GIT_DIR option"
printf >&2 "%s: Must specify -g GIT_DIR option\n" "$0"
exit 1
fi
if [ -z "$outdir" ]
then
echo >&2 "$0: Must specify -o OUTDIR option"
printf >&2 "%s: Must specify -o OUTDIR option\n" "$0"
exit 1
fi
if [ -z "$rev" ]
then
echo >&2 "$0: Must specify -r REVISION option"
printf >&2 "%s: Must specify -r REVISION option\n" "$0"
exit 1
fi
if [ -z "$label" ]
@ -86,7 +88,7 @@ then
label=$rev
fi
commit=$(GIT_DIR=$GIT_DIR cg-object-id -c "$rev") || exit 1
commit=$(git --git-dir="$GIT_DIR" rev-parse --verify "$rev^{commit}") || exit 1
if [ "$snap" ]
then
@ -102,16 +104,19 @@ tmpdir=$(mktemp -d -t elinks-dist-XXXXXXXX) || exit 1
# To make it easier to compare build logs, put the source first in an
# "elinks" directory, and only move to "$tartopdir" when finished.
GIT_DIR=$GIT_DIR cg-export -r "$rev" -- "$tmpdir/elinks"
git --git-dir="$GIT_DIR" archive --format=tar --prefix="elinks/" "$rev" |
(cd -- "$tmpdir" && tar -xf -)
mkdir -- "$tmpdir/elinks/.git"
printf "%s\n" "$commit" > "$tmpdir/elinks/.git/HEAD"
printf "%s\n" "$commit" > "$tmpdir/elinks/git-commit-id"
(set -e
cd -- "$tmpdir/elinks"
./autogen.sh
mkdir build
cd build
../configure
# Enable lots of features so that their options will appear in elinks
# --config-help and doc/html/elinks.conf.5.html.
../configure --enable-bittorrent --enable-cgi --enable-fsp --enable-nntp
make -C po
mv po/*.gmo ../po/
mv contrib/elinks.spec ../contrib/
@ -122,6 +127,18 @@ if [ -n "$docdir" ]; then
cp -r -- "$docdir"/*.html* "$tmpdir/elinks/doc/html/"
# mkdir doc/pdf
# cp "$docdir"/*.pdf doc/pdf
else
make -C "$tmpdir/elinks/build"
make -C "$tmpdir/elinks/build/doc" html
mkdir -- "$tmpdir/elinks/doc/html"
mv -- "$tmpdir/elinks/build/doc"/*.html* "$tmpdir/elinks/doc/html/"
# <http://translationproject.org/html/maintainers.html>:
# "this tarball should contain an up to date POT file."
# Build that here. The Makefile also creates potfiles.list
# in the source directory; that one we don't need.
# Use rm -f so it's not an error if the file is not there.
make -C "$tmpdir/elinks/build/po" ../../po/elinks.pot
rm -f -- "$tmpdir/elinks/po/potfiles.list"
fi
rm -rf -- "$tmpdir/elinks/build"
@ -130,13 +147,14 @@ mv -- "$tmpdir/elinks" "$tmpdir/$tartopdir"
(set -e
cd -- "$tmpdir"
tar cf "$tarbasename.tar" "$tartopdir"
md5sum --binary -- "$tarbasename.tar" > "$tarbasename.md5"
bzip2 --keep -- "$tarbasename.tar"
gzip -9 -- "$tarbasename.tar"
md5sum --binary -- "$tarbasename.tar.gz" "$tarbasename.tar.bz2" >> "$tarbasename.md5"
md5sum --binary -- "$tarbasename.tar.gz" > "$tarbasename.tar.gz.md5"
md5sum --binary -- "$tarbasename.tar.bz2" > "$tarbasename.tar.bz2.md5"
) || exit 1
mv -- "$tmpdir/$tarbasename.tar.gz" "$outdir"
mv -- "$tmpdir/$tarbasename.tar.bz2" "$outdir"
mv -- "$tmpdir/$tarbasename.md5" "$outdir"
mv -- "$tmpdir/$tarbasename.tar.gz" "$outdir"
mv -- "$tmpdir/$tarbasename.tar.bz2" "$outdir"
mv -- "$tmpdir/$tarbasename.tar.gz.md5" "$outdir"
mv -- "$tmpdir/$tarbasename.tar.bz2.md5" "$outdir"
rm -rf -- "$tmpdir"

View File

@ -1,161 +1,15 @@
Methods
-------
Most of the SpiderMonkey scripting interface is documented in the
ELinks manual. This README describes only features added by
contrib/smjs/*.js.
do_file(path)
Load and evaluate the file with the given path (string). For example:
Multiple functions in the same hook
-----------------------------------
do_file("/home/me/.elinks/hooks.js");
will reload your hooks file.
elinks.alert(message)
Display the given message (string) in a message box. For example:
elinks.alert("Hello, world!");
will display a friendly greeting.
elinks.execute(command)
Execute the given command (string) on the current terminal. For example:
var quoted_uri = "'" + elinks.location.replace(/'/g, "'\\''") + "'";
elinks.execute("firefox " + quoted_uri);
will run Firefox with the URI of the current document.
Note: one must be very careful with elinks.execute, because depending
on the OS, the command may be subject to interpretation by a command shell
language. When constructing the command string, be sure to quote any
dubious parts (such as the URI of the current document, as above).
elinks.load_uri(uri, callback)
Load the given URI (string). When the URI completes loading, ELinks calls
the given callback (function). The callback is passed the cache object
that corresponds to the URI. For example:
elinks.load_uri("http://www.eldar.org/cgi-bin/fortune.pl?text_format=yes",
function (cached) { elinks.alert(cached.content); });
displays a fortune.
Properties
----------
elinks.home (string)
ELinks's 'home' directory, where it stores its configuration files.
Read-only. For example,
do_file(elinks.home + "hooks.js");
will reload your hooks file.
elinks.location (string)
The URI of the currently open document. This can be read to get a string
with the URI or set to load a different document. For example,
elinks.location = elinks.location + "/..";
will go up a directory (if the URI doesn't end in a file).
elinks.bookmarks (hash)
This is a hash, the elements of which correspond to the bookmarks.
One can delve into the bookmarks hierarchy in a reasonably nifty
fashion, just by using standard ECMAScript syntax:
elinks.bookmarks.x.children.y.children.z.children.foo.title
gets the title of the bookmark titled 'foo' under the folder 'z',
which is a subfolder of 'y', which is a subfolder of 'x'.
A bookmark object has these properties:
item.title (string)
This is the title of the bookmark. It can be read and set.
item.url (string)
This is the URI of the bookmark. It can be read and set.
item.children (hash)
This is a hash, the elements of which are the bookmarks that
are children to the item. It is read-only.
elinks.globhist (hash)
This is a hash, the elements of which correspond to entries in ELinks's
global history. The hash is indexed by URI. For example,
elinks.globhist["file:///"]
will get you the history item for your root directory.
A history item has these properties:
item.title (string)
This is the title of the history item. It can be read and set.
item.url (string)
This is the URI of the history item. It can be read and set.
item.last_visit (number)
This is the UNIX time of the last visit time for the item. UNIX time
is the number of seconds that have passed between the UNIX epoch (which
is 1970-01-01 00:00:00 UTC) and the represented time. Note that this is
_seconds_ since the epoch, whereas ECMAScript likes to use _milliseconds_
since the epoch. This property can be set or read.
elinks.keybinding (hash)
This is a hash, the elements of which correspond to ELinks's keymaps.
Currently, there are three: elinks.keybinding.main, elinks.keybinding.edit,
and elinks.keybinding.menu. These elements are also hashes, the elements of
which correspond to bindings. For example, elinks.keymaps.main["q"] is
the binding to the 'q' key in the main map. These bindings can be red,
to get the name of the action to which the key is bound, or set, either
to a string with the name of the ELinks action or to a function, which will
thenceforth be called when the key is pressed. For example,
elinks.keymaps.main["!"] = function () { elinks.alert("Hello!"); }
binds the '!' key in the main map to a function that displays a friendly
alert.
elinks.keymaps.main["/"] = "search-typeahead-text";
changes the '/' key to use the nice typeahead search function instead of
opening that ugly old search dialogue box.
Hooks
-----
These are actually properties, but a special case: one assigns functions
to them, which functions are called at certain events.
Note that the default hooks file assigns functions that provide a mechanism
to register multiple functions to each hook. When these default hooks are
called, they iterate over all functions that are registered to them, calling
each one in serial.
The default hooks file contrib/smjs/hooks.js assigns functions that
provide a mechanism to register multiple functions to each hook. When
these default hooks are called, they iterate over all functions that
are registered to them, calling each one in serial.
If you want to register a preformat_html hook, for example,
the preferred way to do so is not this:
@ -171,78 +25,8 @@ elinks.preformat_html function will iterate.
If any function in that array returns false, the default hook
will stop iteration, not calling any more handlers. This applies
to all of the default hooks.
to all of the default hooks:
elinks.preformat_html(cached, vs)
This function is called every time a document is loaded, before the document
is actually rendered, to give scripts the opportunity to modify it. The
first parameter is the cache object and the second is the view_state object
(documented below). As explained above, it is preferred to add your hook
to elinks.preformat_html_hooks rather than to assign it to
elinks.preformat_html.
elinks.goto_url_hook(url)
This function is called every time the user enters something
in the Go to URL box. The url (string) can be modified or not,
and the returned string is substituted for what the user entered.
If the value false is returned, the URL is not changed and further hooks
in ELinks are not run. As explained above, it is preferred to add your hook
to elinks.goto_url_hooks rather than to assign it to elinks.goto_url_hook.
elinks.follow_url_hook(url)
This function is called every time the user tries to load a document,
whether by following a link, by entering a URI in the Go to URL box,
by setting elinks.location, or whatever. It behaves the same as
elinks.goto_url_hook above. As explained above, it is preferred to add your
hook to elinks.follow_url_hooks rather than to assign it to
elinks.follow_url_hook.
Other Objects
-------------
cache
The cache object mentioned in the descriptions of elinks.load_uri and
elinks.preformat_html is a wrapper for the internal ELinks cache object.
Its properties are:
cached.content (string)
This is the content received from the server. It can be read and set.
cached.type (string)
This is the MIME type of the cache entry. It can be read and set.
cached.length (number)
This is the length of cached.content. It is read-only.
cached.head (string)
This is the header received from the server. It can be read and set.
cached.uri (string)
This is the URI of the cache entry. It is read-only.
view_state
The view_state object mentioned in the description of elinks.preformat_html
is a wrapper for the internal ELinks view_state object. The view state holds
information on how the current document is being displayed.
vs.plain (boolean)
Whether the current document is rendered as HTML or displayed
as plaintext. This can be read and set.
vs.uri (string)
This is the URI of the current document. It is read-only.
- elinks.preformat_html_hooks
- elinks.goto_url_hooks
- elinks.follow_url_hooks

View File

@ -113,26 +113,6 @@ Description:
Open Lua console dialog.
-------------------------------------------------------------------------------
Name: flush-caches
Managed By: The scripting subsystem/backends
Triggered When:
Elinks is going to free its caches. This happens when the user chooses
ACT_MAIN_CACHE_MINIMIZE, but currently also on ACT_MAIN_FORGET_CREDENTIALS
and when ELinks is quitting.
Arguments:
None
Description:
If scripting backends hold pointers to cache entries, they should try
to release those pointers so that ELinks can free the entries. This
may involve a full garbage collection. Also, if backends have some
caches of their own, they should flush them.
-------------------------------------------------------------------------------
Name: follow-url
Managed By: The scripting subsystem/backends
@ -249,6 +229,9 @@ Description:
add_fragment(cached, 0, new_string, new_len);
normalize_cache_entry(cached, new_len);
The caller must ensure that there is a reference to cached, so that
calling garbage_collection() from the event handler cannot free it.
-------------------------------------------------------------------------------
Name: quit
Managed By: The scripting subsystem/backends

View File

@ -3,7 +3,7 @@ Frequently Asked Questions
:Description: FAQ for the ELinks project
This is an attempt to capture some of the questions that appear once in a
while on the mailing list.
while on the mailing list or on IRC.
[[instances]]
@ -142,3 +142,35 @@ The new ELinks versions (from 0.9.0 on) send:
You should therefore check against something like /^ELinks[\/ ]/, since more
fields can be added inside the parenthesis in subsequent versions. Note that
users can change their User-Agent through the options system.
[[droppings]]
ELinks doesn't erase characters from the screen when it should!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When you scroll a web page, you may see ELinks leave some characters
on the screen even though it should have erased them. Pressing Ctrl+L
usually removes these droppings until you scroll again. There are
a few possible reasons:
- ELinks 0.11.* in a UTF-8 locale. By default, ELinks guesses the
charset of the terminal from the environment variables LANG,
LC_CTYPE, and LC_ALL. ELinks 0.11 versions do not support UTF-8
as this charset. To use ELinks 0.11 on a UTF-8 terminal, you
should instead enable UTF-8 I/O via the Setup -> Terminal options
dialog box, and choose a charset from Setup -> Character set.
This limitation has been removed in ELinks 0.12pre1.
- Web pages may use nonspacing combining characters or Unicode control
characters that ELinks does not recognize as such. This happens
especially on http://en.wikipedia.org/wiki/Special:RecentChanges[],
where the server generates U+200E LEFT-TO-RIGHT MARK characters.
ELinks 0.13.GIT now has some support for these characters; see
http://bugzilla.elinks.cz/show_bug.cgi?id=824[ELinks bug 824].
- Some versions of the Terminal application in Mac OS X appear to
have a setting that makes line-drawing characters take up the
space of two ASCII letters. ELinks does not expect this.
To avoid the incompatibility, either disable the setting in the
Terminal application or select "No frames" in the Terminal options
dialog box of ELinks.

View File

@ -59,3 +59,5 @@ include::exmode.txt[]
include::bittorrent.txt[]
include::lua-scripting.txt[]
include::smjs-scripting.txt[]

View File

@ -4,14 +4,13 @@ Release check list
When releasing a new version
----------------------------
1. Tasks in the elinks module:
1. Tasks in the elinks module (part 1):
- Go over the changes since the last release. Use git-shortlog as a template.
Write a small changelog highlighting the most important changes. Changes
by new contributors are always important!
- Update NEWS file and commit. Remember to add the new version number!
Don't add the release date yet though; it will be added after the release,
from the date in the mailing list archives.
Don't add the release date yet though; you will add it in a later step.
- Change VERSION in the top of configure.in to hold the new version number.
- Update the manpages so the will have the new release number by first
building the source, followed by making the `update-man' target in doc/.
@ -22,58 +21,73 @@ When releasing a new version
$ git tag -s -F changelog.file elinks-X.X.X
- Run script to create new tarballs (both .gz and .bz2).
$ contrib/mkdist -g "$PWD/.git" -r elinks-X.X.X -l X.X.X
This step also builds the elinks binary and documentation based on
the label, and that might fail because of some bug, so it's best to
do this before pushing anything.
- Create ASCII armored signature files.
$ gpg -b --armor elinks-X.X.X.tar.bz2
$ gpg -b --armor elinks-X.X.X.tar.gz
- Append ".GIT" to the VERSION variable in the top of configure.in.
- Commit only this change.
- Push these changes plus tag using:
$ git push
$ git push --tags
$ git push tag elinks-X.X.X
2. Tasks on http://elinks.cz/ (part 1):
- Wait until the tag etc. has been synced or force a sync of the repository
at http://elinks.cz/elinks.git/.
- Run script to create new tarballs (both .gz and .bz2).
$ mkdist elinks-X.X.X X.X.X -r
3. Tasks on localhost:
- Download new tarballs and create ASCII armored signature files.
- Copy the elinks-X.X.X.tar.* files to http://elinks.cz/download/.
- Send announcement to elinks-users mailing list. Do not format it
as multipart/signed because the linuxfromscratch archive does not
display such messages properly.
- Wait for the announcement to hit the elinks-users mailing list archive.
$ gpg -b --armor elinks-X.X.X.tar.bz2
$ gpg -b --armor elinks-X.X.X.tar.gz
4. Tasks in the elinks module (part 2):
- Copy the elinks-X.X.X.tar.*.asc files to http://elinks.cz/download/.
- Send announcement to elinks-users mailing list.
- Add the release date from the mailing list archive to NEWS.
- Commit and push that change.
4. Tasks in the elinks-web module:
5. Tasks in the elinks-web module:
- Change the version and release data in the start of website.conf.
- Wait for the announcement to hit the elinks-users mailing list archive.
Also change download.txt if necessary.
- Add paraphrased version of the first paragraph of the release announcement
as a news entry in news/latest.txt. Make the entry link to both the
archived announcement from linuxfromscratch.org and gmane.org using the
"magic numbers" expanded by the macro. Possibly, move the cut-off markers
that control which news entries to display on the front page.
- Rebuild index.html, download.html, news.html, and news.rss.
- Rebuild index.html, download.html, news.html, news.rss, and release.html.
- Update bugzilla/milestones/elinks.html if the release corresponds
to a reached milestone.
- Commit the updates HTML and asciidoc files.
- Push the commits.
5. Tasks on http://elinks.cz/ (part 2):
6. Tasks on http://elinks.cz/ (part 2):
- Wait until the elinks-web module has been synced or force a sync of the
repository.
- Checkout the new updated webpages.
6. Tasks on http://bugzilla.elinks.cz/:
7. Tasks on http://bugzilla.elinks.cz/:
- Add the new version.
- Add a comment to each bug fixed in this version. If some of them
are already VERIFIED, change them to CLOSED, unless they are also
waiting for a release in another branch.
7. Tasks external sites and resources:
8. Tasks external sites and resources:
- Add a new release to the freshmeat.net page.
- Change topic of #elinks

396
doc/smjs-scripting.txt Normal file
View File

@ -0,0 +1,396 @@
[[smjs-scripting]]
Scripting ELinks with ECMAScript
--------------------------------
As a user of ELinks, you can control its behaviour by writing scripts
in ECMAScript. Unlike <<ecmascript,scripts in SCRIPT elements of
HTML>>, these user scripts run with all the permissions of your user
account, the same as with <<lua-scripting,Lua>>. The object model is
very different too.
Support for ECMAScript user scripts was first added in ELinks 0.11.0.
The `configure` script enables it by default if the required SpiderMonkey
library has been installed, but you can disable it with `configure
\--disable-sm-scripting` or by <<CONFIG-SCRIPTING-SPIDERMONKEY,editing
features.conf>>.
WARNING: ECMAScript scripting is still a bit experimental: there seem to be
ways to crash ELinks with it, and the object model may change. However, if
you don't have a `hooks.js` file, there is not much risk in enabling the
feature at compile time.
When ELinks starts up, it evaluates the ECMAScript file `hooks.js` in
your ELinks configuration directory (thus normally `~/.elinks/hooks.js`
on Unix-like systems), or if the file does not exist there, then in
the system-wide ELinks configuration directory (the location depends
on how ELinks was built, but `/etc/elinks/hooks.js` is typical).
In the ELinks source tree, the `contrib/smjs` directory contains some
examples about scripting ELinks with ECMAScript. Please see the
`README` file in that directory for details.
[[smjs-global-object]]
Global Object
~~~~~~~~~~~~~
The global object provided to ECMAScript user scripts contains the standard
ECMAScript classes, as well as the following:
[[smjs-global-methods]]
Global Object Methods
^^^^^^^^^^^^^^^^^^^^^
[[smjs-global.do_file]] do_file(path)::
Load and evaluate the file with the given path (string). For example:
+
--
----------------------------------------------------------------------
do_file("/home/me/.elinks/hooks.js");
----------------------------------------------------------------------
will reload your hooks file.
*Compatibility:* ELinks 0.11.0
--
[[smjs-global-properties]]
Global Object Properties
^^^^^^^^^^^^^^^^^^^^^^^^
[[smjs-global.elinks]] elinks (elinks)::
A reference to the <<smjs-elinks-object,ELinks object>>.
+
*Compatibility:* ELinks 0.11.0
[[smjs-elinks-object]]
ELinks Object
~~~~~~~~~~~~~
The global <<smjs-global.elinks,'elinks'>> property refers to this object.
[[smjs-elinks-methods]]
ELinks Object Methods
^^^^^^^^^^^^^^^^^^^^^
[[smjs-elinks.alert]] elinks.alert(message)::
Display the given message (string) in a message box. For example:
+
--
----------------------------------------------------------------------
elinks.alert("Hello, world!");
----------------------------------------------------------------------
will display a friendly greeting.
*Compatibility:* ELinks 0.11.0
--
[[smjs-elinks.execute]] elinks.execute(command)::
Execute the given command (string) on the current terminal.
For example:
+
--
----------------------------------------------------------------------
var quoted_uri = "'" + elinks.location.replace(/'/g, "'\\''") + "'";
elinks.execute("firefox " + quoted_uri);
----------------------------------------------------------------------
will run Firefox with the URI of the current document.
*Compatibility:* ELinks 0.12pre1
WARNING: One must be very careful with 'elinks.execute', because depending
on the OS, the command may be subject to interpretation by a command
shell language. When constructing the command string, be sure to quote
any dubious parts (such as the URI of the current document, as above).
--
[[smjs-elinks.load_uri]] elinks.load_uri(uri, callback)::
Load the given URI (string). When the URI completes loading, ELinks
calls the given callback (function). The callback is passed the
<<smjs-cache_entry-object,cache object>> that corresponds to the URI.
For example:
+
--
----------------------------------------------------------------------
elinks.load_uri("http://www.eldar.org/cgi-bin/fortune.pl?text_format=yes",
function (cached) { elinks.alert(cached.content); });
----------------------------------------------------------------------
displays a fortune.
The <<smjs-cache_entry-object,cache object>> will not expire until after the
callback returns.
*Compatibility:* ELinks 0.12pre1
--
[[smjs-elinks-properties]]
ELinks Object Properties
^^^^^^^^^^^^^^^^^^^^^^^^
[[smjs-elinks.home]] elinks.home (string)::
ELinks's ``home'' directory, where it stores its configuration files.
Read-only. For example,
+
--
----------------------------------------------------------------------
do_file(elinks.home + "hooks.js");
----------------------------------------------------------------------
will reload your hooks file.
*Compatibility:* ELinks 0.11.0
--
[[smjs-elinks.location]] elinks.location (string)::
The URI of the currently open document. This can be read to get a
string with the URI or set to load a different document.
For example,
+
--
----------------------------------------------------------------------
elinks.location = elinks.location + "/..";
----------------------------------------------------------------------
will go up a directory (if the URI doesn't end in a file).
*Compatibility:* ELinks 0.11.0
--
[[smjs-elinks.bookmarks]] elinks.bookmarks (hash)::
This is a hash, the elements of which correspond to the bookmarks.
One can delve into the bookmarks hierarchy in a reasonably nifty
fashion, just by using standard ECMAScript syntax:
+
--
----------------------------------------------------------------------
elinks.bookmarks.x.children.y.children.z.children.foo.title
----------------------------------------------------------------------
gets the title of the bookmark titled ``foo'' under the folder ``z'',
which is a subfolder of ``y'', which is a subfolder of ``x''.
*Compatibility:* ELinks 0.11.0
[[smjs-bookmark-properties]]
A bookmark object has these properties:
[[smjs-bookmark.title]] item.title (string)::
This is the title of the bookmark. It can be read and set.
[[smjs-bookmark.url]] item.url (string)::
This is the URI of the bookmark. It can be read and set.
[[smjs-bookmark.children]] item.children (hash)::
This is a hash, the elements of which are the bookmarks that
are children to the item. It is read-only.
--
[[smjs-elinks.globhist]] elinks.globhist (hash)::
This is a hash, the elements of which correspond to entries in ELinks's
global history. The hash is indexed by URI. For example,
+
--
----------------------------------------------------------------------
elinks.globhist["file:///"]
----------------------------------------------------------------------
will get you the history item for your root directory.
*Compatibility:* ELinks 0.12pre1
[[smjs-global_history_item-properties]]
A history item has these properties:
[[smjs-global_history_item.title]] item.title (string)::
This is the title of the history item. It can be read and set.
[[smjs-global_history_item.url]] item.url (string)::
This is the URI of the history item. It can be read and set.
[[smjs-global_history_item.last_visit]] item.last_visit (number)::
This is the UNIX time of the last visit time for the item. UNIX time
is the number of seconds that have passed between the UNIX epoch
(which is 1970-01-01 00:00:00 UTC) and the represented time. Note that
this is 'seconds' since the epoch, whereas ECMAScript likes to use
'milliseconds' since the epoch. This property can be set or read.
--
[[smjs-elinks.action]] elinks.action (hash)::
This hash lets you call the built-in actions of ELinks. For example,
you can call `elinks.action.auth_manager()` to open the authentication
manager. The names of the actions are the same as in elinks.conf or
in the keybinding manager, except they have underscores instead of
dashes in order to make them valid ECMAScript identifiers.
+
--
*Compatibility:* ELinks 0.12pre1
NOTE: When you read an action function from this hash, ELinks binds it to the
current tab; any later calls to the function affect that tab. This may be
changed in a future version. It is safest to call the function right away,
rather than save it in a variable and call it later.
--
[[smjs-elinks.keymaps]] elinks.keymaps (hash)::
This is a hash, the elements of which correspond to ELinks's keymaps.
Currently, there are three: 'elinks.keymaps.main', 'elinks.keymaps.edit',
and 'elinks.keymaps.menu'. These elements are also hashes, the elements of
which correspond to bindings. For example, `elinks.keymaps.main["q"]` is
the binding to the ``q'' key in the main map. These bindings can be read,
to get the name of the action to which the key is bound, or set to one of:
+
--
- A string with the name of the ELinks action.
- A function, which will thenceforth be called when the key is pressed.
- The string `"none"`, to unbind the key. You can also use the `null`
value for this purpose, but that crashes ELinks 0.11.4 and 0.12pre1
(http://bugzilla.elinks.cz/show_bug.cgi?id=1027[bug 1027]),
so it may be best to use the string for now.
--
+
--
For example,
----------------------------------------------------------------------
elinks.keymaps.main["!"] = function () { elinks.alert("Hello!"); }
----------------------------------------------------------------------
binds the ``!'' key in the main map to a function that displays a friendly
alert.
----------------------------------------------------------------------
elinks.keymaps.main["/"] = "search-typeahead-text";
----------------------------------------------------------------------
changes the ``/'' key to use the nice typeahead search function instead of
opening that ugly old search dialogue box.
*Compatibility:* ELinks 0.11.0, unless you use `null`.
NOTE: Do not read a function from <<smjs-elinks.action,'elinks.action'>>,
e.g. `elinks.action.search_typeahead_text`, and place it in a keymap.
ELinks binds such functions to the current tab when the script reads
them from 'elinks.action', so they will not work right in other tabs.
Use the name of the action instead.
--
[[smjs-elinks.vs]] elinks.vs (view_state)::
This property refers to the <<smjs-view_state-object,view-state
object>> for the current document, if any.
+
*Compatibility:* ELinks 0.12pre1
[[smjs-elinks-hooks]]
ELinks Object Hooks
^^^^^^^^^^^^^^^^^^^
These are actually properties, but a special case: one assigns functions
to them, which functions are called at certain events.
In the ELinks source tree, `contrib/smjs/hooks.js` provides a mechanism
with which multiple scripts can add their functions to the same hooks.
Please see `contrib/smjs/README` for details.
[[smjs-elinks.preformat_html]] elinks.preformat_html(cached, vs)::
This function is called every time a document is loaded, before the
document is actually rendered, to give scripts the opportunity to
modify it. The first parameter is the <<smjs-cache_entry-object,cache
object>> and the second is the <<smjs-view_state-object,view-state
object>>.
+
--
The <<smjs-cache_entry-object,cache object>> will not expire until after this
function returns.
*Compatibility:* ELinks 0.11.1 as described. ELinks 0.11.0 did not provide
the 'vs' argument.
--
[[smjs-elinks.goto_url_hook]] elinks.goto_url_hook(url)::
This function is called every time the user enters something in the
'Go to URL' box. The url (string) can be modified or not, and the
returned string is substituted for what the user entered. If the
value `false` is returned, the URL is not changed and further hooks
in ELinks are not run.
+
*Compatibility:* ELinks 0.11.0
[[smjs-elinks.follow_url_hook]] elinks.follow_url_hook(url)::
This function is called every time the user tries to load a document,
whether by following a link, by entering a URI in the Go to URL box,
by setting <<smjs-elinks.location,'elinks.location'>>, or whatever.
It behaves the same as <<smjs-elinks.goto_url_hook,'elinks.goto_url_hook'>>
above.
+
*Compatibility:* ELinks 0.11.0
[[smjs-cache_entry-object]]
Cache Object
~~~~~~~~~~~~
The cache object mentioned in the descriptions of
<<smjs-elinks.load_uri,'elinks.load_uri'>> and
<<smjs-elinks.preformat_html,'elinks.preformat_html'>> is a wrapper for the
internal ELinks cache object. ELinks passes the ECMAScript cache object as an
argument to your ECMAScript function, and keeps the corresponding document in
the cache until the function returns. After that, ELinks may remove the
document from the cache, even if the function has saved the cache object to
some global variable. Such an expired cache object does not work but it does
not crash ELinks either.
*Compatibility:* ELinks 0.11.0
[[smjs-cache_entry-properties]]
Cache Object Properties
^^^^^^^^^^^^^^^^^^^^^^^
[[smjs-cache_entry.content]] cached.content (string)::
This is the content received from the server. It can be read and set.
[[smjs-cache_entry.type]] cached.type (string)::
This is the MIME type of the cache entry. It can be read and set.
[[smjs-cache_entry.length]] cached.length (number)::
This is the length of cached.content. It is read-only.
[[smjs-cache_entry.head]] cached.head (string)::
This is the header received from the server. It can be read and set.
[[smjs-cache_entry.uri]] cached.uri (string)::
This is the URI of the cache entry. It is read-only.
[[smjs-view_state-object]]
View-state Object
~~~~~~~~~~~~~~~~~
The view-state object mentioned in the descriptions of
<<smjs-elinks.preformat_html,'elinks.preformat_html'>> and
<<smjs-elinks.vs,'elinks.vs'>> is a wrapper for the internal ELinks view_state
object. The view state holds information on how the current document is being
displayed.
*Compatibility:* ELinks 0.11.1
[[smjs-view_state-properties]]
View-state Object Properties
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[[smjs.view_state.plain]] vs.plain (boolean)::
Whether the current document is rendered as HTML or displayed
as plaintext. This can be read and set.
[[smjs.view_state.uri]] vs.uri (string)::
This is the URI of the current document. It is read-only.

View File

@ -1,6 +1,13 @@
top_builddir=..
include $(top_builddir)/Makefile.config
# We prefer the capitalized name for Project-Id-Version.
ifeq ($(PACKAGE), elinks)
PRETTY_PACKAGE = ELinks
else
PRETTY_PACKAGE = $(PACKAGE)
endif
# Where to install the catalog files.
localedir = $(datadir)/locale
@ -48,14 +55,17 @@ all-local: $(CATALOGS)
# This pulls in _all_ .c and .h files in the src directory. Even files that has
# not been added to the git repo. Beware of junk entries!
$(srcdir)$(POTFILES_ABS_LIST): $(POTFILES_REL)
$(POTFILES_ABS_LIST): $(POTFILES_REL)
@( cd $(top_srcdir); \
find src/ -type f -name '*.[ch]' -o -name options.inc -o -name 'actions-*.inc' | sort ) \
> $(srcdir)$(POTFILES_ABS_LIST)
> $(POTFILES_ABS_LIST)
$(srcdir)$(PACKAGE).pot: $(srcdir)$(POTFILES_ABS_LIST) $(srcdir)perl/msgaccel-prepare
# xgettext --flag requires GNU gettext 0.13 or later;
# --msgid-bugs-address requires 0.12 or later.
$(srcdir)$(PACKAGE).pot: $(POTFILES_ABS_LIST) $(srcdir)perl/msgaccel-prepare
$(XGETTEXT) --default-domain=$(PACKAGE) \
--directory=$(top_srcdir) \
--msgid-bugs-address=elinks-users@linuxfromscratch.org \
--add-comments --language=C \
--keyword=_ --keyword=N_ --keyword=n_:1,2 --keyword=N__ \
--flag=msg_text:2:c-format --flag=die:1:c-format \
@ -75,10 +85,13 @@ $(srcdir)$(PACKAGE).pot: $(srcdir)$(POTFILES_ABS_LIST) $(srcdir)perl/msgaccel-pr
--flag=_:1:pass-c-format --flag=N_:1:pass-c-format \
--flag=n_:1:pass-c-format --flag=n_:2:pass-c-format \
--flag=N__:1:pass-c-format \
-f $(srcdir)$(POTFILES_ABS_LIST) \
&& test -f $(PACKAGE).po \
&& $(PERL) -I"$(srcdir)perl" $(srcdir)perl/msgaccel-prepare -S"$(top_srcdir)" $(PACKAGE).po \
&& mv -f $(PACKAGE).po $(srcdir)$(PACKAGE).pot
-f $(POTFILES_ABS_LIST)
test -f $(PACKAGE).po
$(PERL) -I"$(srcdir)perl" $(srcdir)perl/msgaccel-prepare -S"$(top_srcdir)" $(PACKAGE).po
# GNU gettext 0.17 supports xgettext --package-version but is GPLv3+.
# This rule already requires Perl so use that instead.
$(PERL) -pi -e 's/(^"Project-Id-Version: )PACKAGE VERSION/$$1$(PRETTY_PACKAGE) $(VERSION)/i and $$found=1 unless $$found' $(PACKAGE).po
mv -f $(PACKAGE).po $(srcdir)$(PACKAGE).pot
### Updating po and gmo files
@ -131,6 +144,6 @@ uninstall-local:
)
clean-local:
@rm -f $(PACKAGE).po *.new.po $(srcdir)$(POTFILES_ABS_LIST)
@rm -f $(PACKAGE).po *.new.po $(POTFILES_ABS_LIST)
include $(top_srcdir)/Makefile.lib

573
po/af.po

File diff suppressed because it is too large Load Diff

599
po/be.po

File diff suppressed because it is too large Load Diff

607
po/bg.po

File diff suppressed because it is too large Load Diff

599
po/ca.po

File diff suppressed because it is too large Load Diff

583
po/cs.po

File diff suppressed because it is too large Load Diff

795
po/da.po

File diff suppressed because it is too large Load Diff

580
po/de.po

File diff suppressed because it is too large Load Diff

599
po/el.po

File diff suppressed because it is too large Load Diff

599
po/es.po

File diff suppressed because it is too large Load Diff

599
po/et.po

File diff suppressed because it is too large Load Diff

576
po/fi.po

File diff suppressed because it is too large Load Diff

599
po/gl.po

File diff suppressed because it is too large Load Diff

599
po/hr.po

File diff suppressed because it is too large Load Diff

586
po/hu.po

File diff suppressed because it is too large Load Diff

599
po/id.po

File diff suppressed because it is too large Load Diff

599
po/is.po

File diff suppressed because it is too large Load Diff

581
po/it.po

File diff suppressed because it is too large Load Diff

599
po/lt.po

File diff suppressed because it is too large Load Diff

599
po/nb.po

File diff suppressed because it is too large Load Diff

599
po/nl.po

File diff suppressed because it is too large Load Diff

599
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

599
po/ro.po

File diff suppressed because it is too large Load Diff

599
po/ru.po

File diff suppressed because it is too large Load Diff

576
po/sk.po

File diff suppressed because it is too large Load Diff

589
po/sr.po

File diff suppressed because it is too large Load Diff

599
po/sv.po

File diff suppressed because it is too large Load Diff

599
po/tr.po

File diff suppressed because it is too large Load Diff

573
po/uk.po

File diff suppressed because it is too large Load Diff

6
src/cache/cache.c vendored
View File

@ -18,6 +18,9 @@
#include "protocol/protocol.h"
#include "protocol/proxy.h"
#include "protocol/uri.h"
#ifdef CONFIG_SCRIPTING_SPIDERMONKEY
# include "scripting/smjs/smjs.h"
#endif
#include "util/error.h"
#include "util/memory.h"
#include "util/string.h"
@ -656,6 +659,9 @@ done_cache_entry(struct cache_entry *cached)
delete_entry_content(cached);
if (cached->box_item) done_listbox_item(&cache_browser, cached->box_item);
#ifdef CONFIG_SCRIPTING_SPIDERMONKEY
if (cached->jsobject) smjs_detach_cache_entry_object(cached);
#endif
if (cached->uri) done_uri(cached->uri);
if (cached->proxy_uri) done_uri(cached->proxy_uri);

3
src/cache/cache.h vendored
View File

@ -50,6 +50,9 @@ struct cache_entry {
off_t data_size; /* The actual size of all fragments */
struct listbox_item *box_item; /* Dialog data for cache manager */
#ifdef CONFIG_SCRIPTING_SPIDERMONKEY
struct JSObject *jsobject; /* Instance of cache_entry_class */
#endif
timeval_T max_age; /* Expiration time */

View File

@ -83,6 +83,7 @@ render_dom_document(struct cache_entry *cached, struct document *document,
{
unsigned char *head = empty_string_or_(cached->head);
struct dom_renderer renderer;
struct dom_config config;
struct conv_table *convert_table;
struct sgml_parser *parser;
enum sgml_parser_type parser_type;
@ -121,7 +122,7 @@ render_dom_document(struct cache_entry *cached, struct document *document,
} else if (renderer.doctype == SGML_DOCTYPE_RSS) {
add_dom_stack_context(&parser->stack, &renderer,
&dom_rss_renderer_context_info);
add_dom_config_normalizer(&parser->stack, RSS_CONFIG_FLAGS);
add_dom_config_normalizer(&parser->stack, &config, RSS_CONFIG_FLAGS);
}
/* FIXME: When rendering this way we don't really care about the code.

View File

@ -224,7 +224,6 @@ dom_normalize_node_end(struct dom_stack *stack, struct dom_node *node, void *dat
break;
case DOM_NODE_DOCUMENT:
mem_free(config);
break;
default:
@ -285,20 +284,15 @@ static struct dom_stack_context_info dom_config_normalizer_context = {
};
struct dom_config *
add_dom_config_normalizer(struct dom_stack *stack, enum dom_config_flag flags)
add_dom_config_normalizer(struct dom_stack *stack, struct dom_config *config,
enum dom_config_flag flags)
{
struct dom_config *config;
config = mem_calloc(1, sizeof(*config));
if (!config) return NULL;
memset(config, 0, sizeof(*config));
config->flags = flags;
if (add_dom_stack_context(stack, config, &dom_config_normalizer_context))
return config;
mem_free(config);
return NULL;
}

View File

@ -86,7 +86,8 @@ struct dom_config {
};
struct dom_config *
add_dom_config_normalizer(struct dom_stack *stack, enum dom_config_flag flags);
add_dom_config_normalizer(struct dom_stack *stack, struct dom_config *config,
enum dom_config_flag flags);
enum dom_config_flag
parse_dom_config(unsigned char *flaglist, unsigned char separator);

View File

@ -252,6 +252,7 @@ main(int argc, char *argv[])
enum sgml_parser_type type = SGML_PARSER_STREAM;
enum dom_code code = 0;
enum dom_config_flag normalize_flags = 0;
struct dom_config config;
int normalize = 0;
int dump = 0;
int complete = 1;
@ -310,7 +311,7 @@ main(int argc, char *argv[])
parser->error_func = sgml_error_function;
if (normalize)
add_dom_config_normalizer(&parser->stack, normalize_flags);
add_dom_config_normalizer(&parser->stack, &config, normalize_flags);
else if (!dump)
add_dom_stack_context(&parser->stack, NULL, &sgml_parser_test_context_info);

View File

@ -184,32 +184,32 @@ spidermonkey_get_interpreter(struct ecmascript_interpreter *interpreter)
}
JS_InitStandardClasses(ctx, window_obj);
JS_DefineProperties(ctx, window_obj, (JSPropertySpec *) window_props);
JS_DefineFunctions(ctx, window_obj, (JSFunctionSpec *) window_funcs);
spidermonkey_DefineFunctions(ctx, window_obj, window_funcs);
JS_SetPrivate(ctx, window_obj, interpreter->vs); /* to @window_class */
document_obj = JS_InitClass(ctx, window_obj, NULL,
(JSClass *) &document_class, NULL, 0,
(JSPropertySpec *) document_props,
(JSFunctionSpec *) document_funcs,
NULL, NULL);
document_obj = spidermonkey_InitClass(ctx, window_obj, NULL,
(JSClass *) &document_class, NULL, 0,
(JSPropertySpec *) document_props,
document_funcs,
NULL, NULL);
forms_obj = JS_InitClass(ctx, document_obj, NULL,
(JSClass *) &forms_class, NULL, 0,
(JSPropertySpec *) forms_props,
(JSFunctionSpec *) forms_funcs,
NULL, NULL);
forms_obj = spidermonkey_InitClass(ctx, document_obj, NULL,
(JSClass *) &forms_class, NULL, 0,
(JSPropertySpec *) forms_props,
forms_funcs,
NULL, NULL);
history_obj = JS_InitClass(ctx, window_obj, NULL,
(JSClass *) &history_class, NULL, 0,
(JSPropertySpec *) NULL,
(JSFunctionSpec *) history_funcs,
NULL, NULL);
history_obj = spidermonkey_InitClass(ctx, window_obj, NULL,
(JSClass *) &history_class, NULL, 0,
(JSPropertySpec *) NULL,
history_funcs,
NULL, NULL);
location_obj = JS_InitClass(ctx, window_obj, NULL,
(JSClass *) &location_class, NULL, 0,
(JSPropertySpec *) location_props,
(JSFunctionSpec *) location_funcs,
NULL, NULL);
location_obj = spidermonkey_InitClass(ctx, window_obj, NULL,
(JSClass *) &location_class, NULL, 0,
(JSPropertySpec *) location_props,
location_funcs,
NULL, NULL);
menubar_obj = JS_InitClass(ctx, window_obj, NULL,
(JSClass *) &menubar_class, NULL, 0,

View File

@ -2,6 +2,6 @@ top_builddir=../../..
include $(top_builddir)/Makefile.config
INCLUDES += $(SPIDERMONKEY_CFLAGS)
OBJS = document.o form.o location.o navigator.o unibar.o window.o
OBJS = document.o form.o location.o navigator.o unibar.o util.o window.o
include $(top_srcdir)/Makefile.lib

View File

@ -245,7 +245,7 @@ document_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
static JSBool document_write(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool document_writeln(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
const JSFunctionSpec document_funcs[] = {
const spidermonkeyFunctionSpec document_funcs[] = {
{ "write", document_write, 1 },
{ "writeln", document_writeln, 1 },
{ NULL }

View File

@ -5,7 +5,7 @@
#include "ecmascript/spidermonkey/util.h"
extern const JSClass document_class;
extern const JSFunctionSpec document_funcs[];
extern const spidermonkeyFunctionSpec document_funcs[];
extern const JSPropertySpec document_props[];
#endif

View File

@ -133,7 +133,7 @@ static JSBool input_click(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv
static JSBool input_focus(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool input_select(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static const JSFunctionSpec input_funcs[] = {
static const spidermonkeyFunctionSpec input_funcs[] = {
{ "blur", input_blur, 0 },
{ "click", input_click, 0 },
{ "focus", input_focus, 0 },
@ -567,7 +567,7 @@ get_input_object(JSContext *ctx, JSObject *jsform, long number)
JSObject *jsinput = JS_NewObject(ctx, (JSClass *) &input_class, NULL, jsform);
JS_DefineProperties(ctx, jsinput, (JSPropertySpec *) input_props);
JS_DefineFunctions(ctx, jsinput, (JSFunctionSpec *) input_funcs);
spidermonkey_DefineFunctions(ctx, jsinput, input_funcs);
JS_SetReservedSlot(ctx, jsinput, JSRS_INPUT_FSINDEX, INT_TO_JSVAL(number));
return jsinput;;
}
@ -616,7 +616,7 @@ static const JSClass form_elements_class = {
static JSBool form_elements_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool form_elements_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static const JSFunctionSpec form_elements_funcs[] = {
static const spidermonkeyFunctionSpec form_elements_funcs[] = {
{ "item", form_elements_item, 1 },
{ "namedItem", form_elements_namedItem, 1 },
{ NULL }
@ -855,7 +855,7 @@ static const JSPropertySpec form_props[] = {
static JSBool form_reset(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool form_submit(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static const JSFunctionSpec form_funcs[] = {
static const spidermonkeyFunctionSpec form_funcs[] = {
{ "reset", form_reset, 0 },
{ "submit", form_submit, 0 },
{ NULL }
@ -933,7 +933,8 @@ form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
JSObject *jsform_elems = JS_NewObject(ctx, (JSClass *) &form_elements_class, NULL, obj);
JS_DefineProperties(ctx, jsform_elems, (JSPropertySpec *) form_elements_props);
JS_DefineFunctions(ctx, jsform_elems, (JSFunctionSpec *) form_elements_funcs);
spidermonkey_DefineFunctions(ctx, jsform_elems,
form_elements_funcs);
object_to_jsval(ctx, vp, jsform_elems);
/* SM will cache this property value for us so we create this
* just once per form. */
@ -1162,7 +1163,7 @@ get_form_object(JSContext *ctx, JSObject *jsdoc, struct form_view *fv)
JSObject *jsform = JS_NewObject(ctx, (JSClass *) &form_class, NULL, jsdoc);
JS_DefineProperties(ctx, jsform, (JSPropertySpec *) form_props);
JS_DefineFunctions(ctx, jsform, (JSFunctionSpec *) form_funcs);
spidermonkey_DefineFunctions(ctx, jsform, form_funcs);
JS_SetPrivate(ctx, jsform, fv); /* to @form_class */
fv->ecmascript_obj = jsform;
return fv->ecmascript_obj;
@ -1181,7 +1182,7 @@ const JSClass forms_class = {
static JSBool forms_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool forms_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
const JSFunctionSpec forms_funcs[] = {
const spidermonkeyFunctionSpec forms_funcs[] = {
{ "item", forms_item, 1 },
{ "namedItem", forms_namedItem, 1 },
{ NULL }

View File

@ -7,7 +7,7 @@
struct form_view;
extern const JSClass forms_class;
extern const JSFunctionSpec forms_funcs[];
extern const spidermonkeyFunctionSpec forms_funcs[];
extern const JSPropertySpec forms_props[];
JSObject *get_form_object(JSContext *ctx, JSObject *jsdoc, struct form_view *fv);

View File

@ -57,7 +57,7 @@ const JSClass history_class = {
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
};
const JSFunctionSpec history_funcs[] = {
const spidermonkeyFunctionSpec history_funcs[] = {
{ "back", history_back, 0 },
{ "forward", history_forward, 0 },
{ "go", history_go, 1 },
@ -224,7 +224,7 @@ location_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
static JSBool location_toString(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
const JSFunctionSpec location_funcs[] = {
const spidermonkeyFunctionSpec location_funcs[] = {
{ "toString", location_toString, 0 },
{ "toLocaleString", location_toString, 0 },
{ NULL }

View File

@ -7,10 +7,10 @@
struct document_view;
extern const JSClass history_class;
extern const JSFunctionSpec history_funcs[];
extern const spidermonkeyFunctionSpec history_funcs[];
extern const JSClass location_class;
extern const JSFunctionSpec location_funcs[];
extern const spidermonkeyFunctionSpec location_funcs[];
extern const JSPropertySpec location_props[];
void location_goto(struct document_view *doc_view, unsigned char *url);

View File

@ -0,0 +1,60 @@
/* Better compatibility across versions of SpiderMonkey. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "elinks.h"
#include "ecmascript/spidermonkey/util.h"
/** An ELinks-specific replacement for JS_DefineFunctions().
*
* @relates spidermonkeyFunctionSpec */
JSBool
spidermonkey_DefineFunctions(JSContext *cx, JSObject *obj,
const spidermonkeyFunctionSpec *fs)
{
for (; fs->name; fs++) {
if (!JS_DefineFunction(cx, obj, fs->name, fs->call,
fs->nargs, 0))
return JS_FALSE;
}
return JS_TRUE;
}
/** An ELinks-specific replacement for JS_InitClass().
*
* @relates spidermonkeyFunctionSpec */
JSObject *
spidermonkey_InitClass(JSContext *cx, JSObject *obj,
JSObject *parent_proto, JSClass *clasp,
JSNative constructor, uintN nargs,
JSPropertySpec *ps,
const spidermonkeyFunctionSpec *fs,
JSPropertySpec *static_ps,
const spidermonkeyFunctionSpec *static_fs)
{
JSObject *proto = JS_InitClass(cx, obj, parent_proto, clasp,
constructor, nargs,
ps, NULL, static_ps, NULL);
if (proto == NULL)
return NULL;
if (fs) {
if (!spidermonkey_DefineFunctions(cx, proto, fs))
return NULL;
}
if (static_fs) {
JSObject *cons_obj = JS_GetConstructor(cx, proto);
if (cons_obj == NULL)
return NULL;
if (!spidermonkey_DefineFunctions(cx, cons_obj, static_fs))
return NULL;
}
return proto;
}

View File

@ -99,4 +99,29 @@ jsval_to_string(JSContext *ctx, jsval *vp)
return empty_string_or_(JS_GetStringBytes(JS_ValueToString(ctx, val)));
}
/** An ELinks-specific replacement for JSFunctionSpec.
*
* Bug 1016: In SpiderMonkey 1.7 bundled with XULRunner 1.8, jsapi.h
* defines JSFunctionSpec in different ways depending on whether
* MOZILLA_1_8_BRANCH is defined, and there is no obvious way for
* ELinks to check whether MOZILLA_1_8_BRANCH was defined when the
* library was built. Avoid the unstable JSFunctionSpec definitions
* and use this ELinks-specific structure instead. */
typedef struct spidermonkeyFunctionSpec {
const char *name;
JSNative call;
uint8 nargs;
/* ELinks does not use "flags" and "extra" so omit them here. */
} spidermonkeyFunctionSpec;
JSBool spidermonkey_DefineFunctions(JSContext *cx, JSObject *obj,
const spidermonkeyFunctionSpec *fs);
JSObject *spidermonkey_InitClass(JSContext *cx, JSObject *obj,
JSObject *parent_proto, JSClass *clasp,
JSNative constructor, uintN nargs,
JSPropertySpec *ps,
const spidermonkeyFunctionSpec *fs,
JSPropertySpec *static_ps,
const spidermonkeyFunctionSpec *static_fs);
#endif

View File

@ -302,7 +302,7 @@ static JSBool window_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *arg
static JSBool window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
static JSBool window_setTimeout(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
const JSFunctionSpec window_funcs[] = {
const spidermonkeyFunctionSpec window_funcs[] = {
{ "alert", window_alert, 1 },
{ "open", window_open, 3 },
{ "setTimeout", window_setTimeout, 2 },

View File

@ -6,6 +6,6 @@
extern const JSClass window_class;
extern const JSPropertySpec window_props[];
extern const JSFunctionSpec window_funcs[];
extern const spidermonkeyFunctionSpec window_funcs[];
#endif

View File

@ -311,13 +311,6 @@ terminate_all_subsystems(void)
void
shrink_memory(int whole)
{
#ifdef CONFIG_SCRIPTING
/* The SMJS pre-format-html hook constructs an SMJS object for
* each cache entry. Give all scripting modules a cue to garbage
* collect any such objects so that the entries can be freed. */
if (whole)
trigger_event_name("flush-caches");
#endif
shrink_dns_cache(whole);
shrink_format_cache(whole);
garbage_collection(whole);

View File

@ -1493,7 +1493,7 @@ http_got_header(struct socket *socket, struct read_buffer *rb)
#endif
unsigned char *d;
struct uri *uri = conn->proxied_uri; /* Set to the real uri */
struct http_version version;
struct http_version version = { 0, 9 };
enum connection_state state = (conn->state != S_PROC ? S_GETH : S_PROC);
int a, h = 200;
int cf;
@ -1522,6 +1522,9 @@ again:
read_from_socket(conn->socket, rb, state, http_got_header);
return;
}
/* a == -2 from get_header means HTTP/0.9. In that case, skip
* the get_http_code call; @h and @version have already been
* initialized with the right values. */
if (a == -2) a = 0;
if ((a && get_http_code(rb, &h, &version))
|| h == 101) {

View File

@ -11,6 +11,7 @@
#include "protocol/uri.h"
#include "scripting/smjs/cache_object.h"
#include "scripting/smjs/core.h"
#include "scripting/smjs/smjs.h"
#include "util/error.h"
#include "util/memory.h"
@ -42,6 +43,7 @@ static JSBool
cache_entry_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
{
struct cache_entry *cached;
JSBool ret;
/* This can be called if @obj if not itself an instance of the
* appropriate class but has one in its prototype chain. Fail
@ -51,15 +53,22 @@ cache_entry_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
cached = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &cache_entry_class, NULL);
if (!cached) return JS_FALSE; /* already detached */
if (!cache_entry_is_valid(cached)) return JS_FALSE;
assert(cache_entry_is_valid(cached));
if_assert_failed return JS_FALSE;
/* Get a strong reference to the cache entry to prevent it
* from being deleted if some function called below decides to
* collect garbage. After this, all code paths must
* eventually unlock the object. */
object_lock(cached);
undef_to_jsval(ctx, vp);
if (!JSVAL_IS_INT(id))
return JS_FALSE;
switch (JSVAL_TO_INT(id)) {
ret = JS_FALSE;
else switch (JSVAL_TO_INT(id)) {
case CACHE_ENTRY_CONTENT: {
struct fragment *fragment = get_cache_fragment(cached);
@ -69,27 +78,32 @@ cache_entry_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
fragment->data,
fragment->length));
return JS_TRUE;
ret = JS_TRUE;
break;
}
case CACHE_ENTRY_TYPE:
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx,
cached->content_type));
return JS_TRUE;
ret = JS_TRUE;
break;
case CACHE_ENTRY_HEAD:
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx,
cached->head));
return JS_TRUE;
ret = JS_TRUE;
break;
case CACHE_ENTRY_LENGTH:
*vp = INT_TO_JSVAL(cached->length);
return JS_TRUE;
ret = JS_TRUE;
break;
case CACHE_ENTRY_URI:
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx,
struri(cached->uri)));
return JS_TRUE;
ret = JS_TRUE;
break;
default:
/* Unrecognized integer property ID; someone is using
* the object as an array. SMJS builtin classes (e.g.
@ -97,8 +111,12 @@ cache_entry_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
* and leave *@vp unchanged. Do the same here.
* (Actually not quite the same, as we already used
* @undef_to_jsval.) */
return JS_TRUE;
ret = JS_TRUE;
break;
}
object_unlock(cached);
return ret;
}
/* @cache_entry_class.setProperty */
@ -106,6 +124,7 @@ static JSBool
cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
{
struct cache_entry *cached;
JSBool ret;
/* This can be called if @obj if not itself an instance of the
* appropriate class but has one in its prototype chain. Fail
@ -115,13 +134,20 @@ cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
cached = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &cache_entry_class, NULL);
if (!cached) return JS_FALSE; /* already detached */
if (!cache_entry_is_valid(cached)) return JS_FALSE;
assert(cache_entry_is_valid(cached));
if_assert_failed return JS_FALSE;
/* Get a strong reference to the cache entry to prevent it
* from being deleted if some function called below decides to
* collect garbage. After this, all code paths must
* eventually unlock the object. */
object_lock(cached);
if (!JSVAL_IS_INT(id))
return JS_FALSE;
switch (JSVAL_TO_INT(id)) {
ret = JS_FALSE;
else switch (JSVAL_TO_INT(id)) {
case CACHE_ENTRY_CONTENT: {
JSString *jsstr = JS_ValueToString(smjs_ctx, *vp);
unsigned char *str = JS_GetStringBytes(jsstr);
@ -130,7 +156,8 @@ cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
add_fragment(cached, 0, str, len);
normalize_cache_entry(cached, len);
return JS_TRUE;
ret = JS_TRUE;
break;
}
case CACHE_ENTRY_TYPE: {
JSString *jsstr = JS_ValueToString(smjs_ctx, *vp);
@ -138,7 +165,8 @@ cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
mem_free_set(&cached->content_type, stracpy(str));
return JS_TRUE;
ret = JS_TRUE;
break;
}
case CACHE_ENTRY_HEAD: {
JSString *jsstr = JS_ValueToString(smjs_ctx, *vp);
@ -146,18 +174,25 @@ cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
mem_free_set(&cached->head, stracpy(str));
return JS_TRUE;
ret = JS_TRUE;
break;
}
default:
/* Unrecognized integer property ID; someone is using
* the object as an array. SMJS builtin classes (e.g.
* js_RegExpClass) just return JS_TRUE in this case.
* Do the same here. */
return JS_TRUE;
ret = JS_TRUE;
break;
}
object_unlock(cached);
return ret;
}
/* @cache_entry_class.finalize */
/** Pointed to by cache_entry_class.finalize. SpiderMonkey
* automatically finalizes all objects before it frees the JSRuntime,
* so cache_entry.jsobject won't be left dangling. */
static void
cache_entry_finalize(JSContext *ctx, JSObject *obj)
{
@ -169,25 +204,37 @@ cache_entry_finalize(JSContext *ctx, JSObject *obj)
cached = JS_GetInstancePrivate(ctx, obj,
(JSClass *) &cache_entry_class, NULL);
if (!cached) return;
if (!cached) return; /* already detached */
object_unlock(cached);
JS_SetPrivate(ctx, obj, NULL); /* perhaps not necessary */
assert(cached->jsobject == obj);
if_assert_failed return;
cached->jsobject = NULL;
}
static const JSClass cache_entry_class = {
"cache_entry",
JSCLASS_HAS_PRIVATE, /* struct cache_entry * */
JSCLASS_HAS_PRIVATE, /* struct cache_entry *; a weak reference */
JS_PropertyStub, JS_PropertyStub,
cache_entry_get_property, cache_entry_set_property,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, cache_entry_finalize
};
/** Return an SMJS object through which scripts can access @a cached.
* If there already is such an object, return that; otherwise create a
* new one. The SMJS object holds only a weak reference to @a cached;
* so if the caller wants to guarantee that @a cached exists at least
* until a script returns, it should use lock_object() and
* unlock_object(). */
JSObject *
smjs_get_cache_entry_object(struct cache_entry *cached)
{
JSObject *cache_entry_object;
if (cached->jsobject) return cached->jsobject;
assert(smjs_ctx);
if_assert_failed return NULL;
cache_entry_object = JS_NewObject(smjs_ctx,
(JSClass *) &cache_entry_class,
@ -195,14 +242,39 @@ smjs_get_cache_entry_object(struct cache_entry *cached)
if (!cache_entry_object) return NULL;
if (JS_FALSE == JS_SetPrivate(smjs_ctx, cache_entry_object, cached)) /* to @cache_entry_class */
return NULL;
object_lock(cached);
if (JS_FALSE == JS_DefineProperties(smjs_ctx, cache_entry_object,
(JSPropertySpec *) cache_entry_props))
return NULL;
/* Do this last, so that if any previous step fails, we can
* just forget the object and its finalizer won't attempt to
* access @cached. */
if (JS_FALSE == JS_SetPrivate(smjs_ctx, cache_entry_object, cached)) /* to @cache_entry_class */
return NULL;
cached->jsobject = cache_entry_object;
return cache_entry_object;
}
/** Ensure that no JSObject contains the pointer @a cached. This is
* called when the reference count of the cache entry *@a cached is
* already 0 and it is about to be freed. If a JSObject was
* previously attached to the cache entry, the object will remain in
* memory but it will no longer be able to access the cache entry. */
void
smjs_detach_cache_entry_object(struct cache_entry *cached)
{
assert(smjs_ctx);
assert(cached);
if_assert_failed return;
if (!cached->jsobject) return;
assert(JS_GetInstancePrivate(smjs_ctx, cached->jsobject,
(JSClass *) &cache_entry_class, NULL)
== cached);
if_assert_failed {}
JS_SetPrivate(smjs_ctx, cached->jsobject, NULL);
cached->jsobject = NULL;
}

View File

@ -154,6 +154,9 @@ cleanup_smjs(struct module *module)
{
if (!smjs_ctx) return;
/* These calls also finalize all JSObjects that have been
* allocated in the JSRuntime, so cache_entry_finalize gets
* called and resets each cache_entry.jsobject = NULL. */
JS_DestroyContext(smjs_ctx);
JS_DestroyRuntime(smjs_rt);
}

View File

@ -69,7 +69,7 @@ elinks_set_location(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE;
}
/* @elinks_funcs{"alert"} */
/* function "alert" in the object returned by smjs_get_elinks_object() */
static JSBool
elinks_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
@ -90,7 +90,7 @@ elinks_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
return JS_TRUE;
}
/* @elinks_funcs{"execute"} */
/* function "execute" in the object returned by smjs_get_elinks_object() */
static JSBool
elinks_execute(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
@ -117,12 +117,6 @@ static const JSClass elinks_class = {
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
};
static const JSFunctionSpec elinks_funcs[] = {
{ "alert", elinks_alert, 1 },
{ "execute", elinks_execute, 1 },
{ NULL }
};
static JSObject *
smjs_get_elinks_object(void)
{
@ -133,7 +127,22 @@ smjs_get_elinks_object(void)
jsobj = JS_InitClass(smjs_ctx, smjs_global_object, NULL,
(JSClass *) &elinks_class, NULL, 0, NULL,
(JSFunctionSpec *) elinks_funcs, NULL, NULL);
(JSFunctionSpec *) NULL, NULL, NULL);
/* Bug 1016: In SpiderMonkey 1.7 bundled with XULRunner 1.8,
* jsapi.h defines JSFunctionSpec in different ways depending
* on whether MOZILLA_1_8_BRANCH is defined, and there is no
* obvious way for ELinks to check whether MOZILLA_1_8_BRANCH
* was defined when the library was built. Avoid the unstable
* JSFunctionSpec definitions and instead use JS_DefineFunction
* directly.
*
* In elinks/src/ecmascript/spidermonkey/, there is an
* ELinks-specific replacement for JSFunctionSpec; however, to
* keep the modules independent, elinks/src/scripting/smjs/
* does not use that. */
JS_DefineFunction(smjs_ctx, jsobj, "alert", elinks_alert, 1, 0);
JS_DefineFunction(smjs_ctx, jsobj, "execute", elinks_execute, 1, 0);
JS_DefineProperty(smjs_ctx, jsobj, "location", JSVAL_NULL,
elinks_get_location, elinks_set_location,

View File

@ -89,26 +89,10 @@ end:
return ret;
}
static enum evhook_status
script_hook_flush_caches(va_list ap, void *data)
{
/* script_hook_pre_format_html() calls smjs_get_cache_entry_object()
* for each struct cache_entry. The resulting SMJS objects hold
* references to the structs, and these references prevent ELinks
* from freeing the cache entries. (The resource info dialog shows
* that the entries are "in use".) SMJS does not immediately collect
* these objects as garbage. If we're really trying to flush the
* caches then ask SMJS to run a check. */
if (smjs_ctx)
JS_GC(smjs_ctx);
return EVENT_HOOK_STATUS_NEXT;
}
struct event_hook_info smjs_scripting_hooks[] = {
{ "goto-url", 0, script_hook_url, "goto_url_hook" },
{ "follow-url", 0, script_hook_url, "follow_url_hook" },
{ "pre-format-html", 0, script_hook_pre_format_html, NULL },
{ "flush-caches", 0, script_hook_flush_caches, NULL },
NULL_EVENT_HOOK_INFO,
};

View File

@ -37,7 +37,7 @@ keymap_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
action_str = get_action_name_from_keystroke((enum keymap_id) *data,
keystroke_str);
if (!action_str) goto ret_null;
if (!action_str || !strcmp(action_str, "none")) goto ret_null;
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(ctx, action_str));
@ -106,6 +106,12 @@ keymap_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE;
} else if (JSVAL_IS_NULL(*vp)) { /* before JSVAL_IS_OBJECT */
if (bind_do(keymap_str, keystroke_str, "none", 0))
return JS_FALSE;
return JS_TRUE;
} else if (JSVAL_IS_OBJECT(*vp)) {
unsigned char *err = NULL;
int event_id;

View File

@ -32,6 +32,13 @@ smjs_loading_callback(struct download *download, void *data)
if (!download->cached) goto end;
/* download->cached->object.refcount is typically 0 here
* because no struct document uses the cache entry. Because
* the connection is no longer using the cache entry either,
* it can be garbage collected. Don't let that happen while
* the script is using it. */
object_lock(download->cached);
assert(hop->callback);
smjs_ses = hop->ses;
@ -44,6 +51,8 @@ smjs_loading_callback(struct download *download, void *data)
JS_CallFunction(smjs_ctx, NULL, hop->callback, 1, args, &rval);
end:
if (download->cached)
object_unlock(download->cached);
mem_free(download->data);
mem_free(download);

View File

@ -2,7 +2,14 @@
#define EL__SCRIPTING_SMJS_SMJS_H
struct module;
struct cache_entry;
extern struct module smjs_scripting_module;
/* TODO: Use trigger_event() for this, so that the caching code need
* not directly call the SMJS scripting module? That would require
* changes in struct cache_object though, to let a dynamic number of
* scripting modules have pointers from there to their objects. */
void smjs_detach_cache_entry_object(struct cache_entry *cached);
#endif

View File

@ -513,6 +513,17 @@ maybe_pre_format_html(struct cache_entry *cached, struct session *ses)
if (!cached || cached->preformatted)
return;
/* The script called from here may indirectly call
* garbage_collection(). If the refcount of the cache entry
* were 0, it could then be freed, and the
* cached->preformatted assignment at the end of this function
* would crash. Normally, the document has a reference to the
* cache entry, and that suffices. If the following assertion
* ever fails, object_lock(cached) and object_unlock(cached)
* must be added to this function. */
assert(cached->object.refcount > 0);
if_assert_failed return;
fragment = get_cache_fragment(cached);
if (!fragment) return;

View File

@ -910,7 +910,7 @@ call_onsubmit_and_submit(struct session *ses, struct document_view *doc_view,
* explicitly tell the ECMAScript code which of them was
* pressed. W3C DOM Level 3 doesn't seem to include such a
* feature. */
if (fc->form->onsubmit) {
if (fc->type != FC_RESET && fc->form->onsubmit) {
struct string code;
if (init_string(&code)) {
@ -958,7 +958,8 @@ goto_current_link(struct session *ses, struct document_view *doc_view, int do_re
if (link_is_form(link)) {
struct form_control *fc = link->data.form_control;
if (!call_onsubmit_and_submit(ses, doc_view, fc, do_reload))
if (fc->type != FC_BUTTON
&& !call_onsubmit_and_submit(ses, doc_view, fc, do_reload))
return NULL;
else
return link;