Compare commits
10 Commits
NETSCAPE_7
...
EXP_DEBUGG
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4ffa41ca0 | ||
|
|
71eac19bd9 | ||
|
|
c91ef3e25d | ||
|
|
d912f6c544 | ||
|
|
f066ed34eb | ||
|
|
75c0a6d536 | ||
|
|
6374a47cb5 | ||
|
|
87a77bdb54 | ||
|
|
01bdc9a81a | ||
|
|
cf3aa1ee61 |
@@ -1,132 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
|
||||
This file overrides all option settings in the IDE. It is an attempt to allow all builds
|
||||
to have the same options.
|
||||
|
||||
Note: We can't use ConditionalMacros.h in this file because it will conflict with
|
||||
the PowerPlant precompiled headers.
|
||||
|
||||
*/
|
||||
|
||||
/* warning pragmas */
|
||||
#pragma warn_hidevirtual on
|
||||
#pragma warn_emptydecl on
|
||||
#pragma warn_unusedvar on
|
||||
#pragma warn_extracomma on
|
||||
#pragma warn_illpragma on
|
||||
#pragma warn_possunwant on
|
||||
#pragma warn_unusedarg off /* turned off to reduce warnings */
|
||||
|
||||
#pragma check_header_flags on
|
||||
|
||||
/* Language features that must be the same across libraries... */
|
||||
#pragma enumsalwaysint on
|
||||
#pragma unsigned_char off
|
||||
#pragma exceptions on
|
||||
#pragma bool on
|
||||
#pragma wchar_type on
|
||||
#pragma RTTI on
|
||||
|
||||
|
||||
/* Save as much space as possible with strings... */
|
||||
#pragma pool_strings on
|
||||
#pragma dont_reuse_strings off
|
||||
|
||||
#pragma options align=native
|
||||
#pragma sym on /* Takes no memory. OK in non-debug. */
|
||||
|
||||
|
||||
|
||||
#ifdef powerc /* ...generating PowerPC */
|
||||
#pragma toc_data on
|
||||
#pragma fp_contract on
|
||||
#pragma readonly_strings on
|
||||
|
||||
#ifdef DEBUG
|
||||
#pragma profile off /* Turn this on to profile the application. */
|
||||
/* Look for more details about profiling in nsMacMessagePump.cpp. */
|
||||
#pragma traceback on
|
||||
#pragma global_optimizer off
|
||||
#pragma scheduling off
|
||||
#pragma peephole off
|
||||
#pragma optimize_for_size off
|
||||
#else
|
||||
|
||||
#if TARGET_CARBON
|
||||
#pragma traceback on /* should always be ON for Carbon builds */
|
||||
#else
|
||||
#pragma traceback off /* leave on until the final release, so MacsBug logs are interpretable */
|
||||
#endif
|
||||
|
||||
#pragma global_optimizer on
|
||||
#pragma optimization_level 4
|
||||
#pragma scheduling 603
|
||||
#pragma peephole on
|
||||
#pragma optimize_for_size on
|
||||
|
||||
#pragma opt_strength_reduction on
|
||||
#pragma opt_propagation on
|
||||
#pragma opt_loop_invariants on
|
||||
#pragma opt_lifetimes on
|
||||
#pragma opt_dead_code on
|
||||
#pragma opt_dead_assignments on
|
||||
#pragma opt_common_subs on
|
||||
#endif
|
||||
|
||||
#else /* ...generating 68k */
|
||||
#pragma code68020 on
|
||||
#pragma code68881 off
|
||||
|
||||
/* Far everything... */
|
||||
#pragma far_code
|
||||
#pragma far_data on
|
||||
#pragma far_strings on
|
||||
#pragma far_vtables on
|
||||
|
||||
#pragma fourbyteints on /* 4-byte ints */
|
||||
#pragma IEEEdoubles on /* 8-byte doubles (as required by Java and NSPR) */
|
||||
|
||||
#ifdef DEBUG
|
||||
#pragma macsbug on
|
||||
#pragma oldstyle_symbols off
|
||||
#else
|
||||
#pragma macsbug off
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,5 +0,0 @@
|
||||
#
|
||||
# This is a list of local files which get copied to the mozilla:dist directory
|
||||
#
|
||||
|
||||
IDE_Options.h
|
||||
@@ -1,59 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#error "DonÕt use me!"
|
||||
|
||||
#define OLDROUTINELOCATIONS 0
|
||||
#define XP_MAC 1
|
||||
#define NSPR20 1
|
||||
#define _NO_FAST_STRING_INLINES_ 1
|
||||
#define HAVE_BOOLEAN 1
|
||||
#define NETSCAPE 1
|
||||
#define OTUNIXERRORS 1 /* We want OpenTransport error codes */
|
||||
|
||||
#define OJI 1
|
||||
|
||||
/*
|
||||
This compiles in heap dumping utilities and other good stuff
|
||||
for developers -- maybe we only want it in for a special SDK
|
||||
nspr/java runtime(?):
|
||||
*/
|
||||
#define DEVELOPER_DEBUG 1
|
||||
|
||||
#define MAX(_a,_b) ((_a) < (_b) ? (_b) : (_a))
|
||||
#define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
|
||||
Binary file not shown.
@@ -1,80 +0,0 @@
|
||||
#!perl
|
||||
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Simon Fraser <sfraser@netscape.com>
|
||||
#
|
||||
|
||||
require 5.004;
|
||||
|
||||
use strict;
|
||||
|
||||
use Cwd;
|
||||
use Moz::BuildUtils;
|
||||
use Moz::BuildCore;
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# Where have the build options gone?
|
||||
#
|
||||
# The various build flags have been centralized into one place.
|
||||
# The master list of options is in MozBuildFlags.txt. However,
|
||||
# you should never need to edit that file, or this one.
|
||||
#
|
||||
# To customize what gets built, or where to start the build,
|
||||
# edit the $prefs_file_name file in
|
||||
# System Folder:Preferences:Mozilla build prefs:
|
||||
# Documentation is provided in that file.
|
||||
#-------------------------------------------------------------
|
||||
|
||||
my($prefs_file_name) = "Mozilla opt build prefs";
|
||||
my($config_header_file_name) = ":mozilla:config:mac:DefinesOptions.h";
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# hashes to hold build options
|
||||
#-------------------------------------------------------------
|
||||
my(%build);
|
||||
my(%options);
|
||||
my(%filepaths);
|
||||
my(%optiondefines);
|
||||
|
||||
# Hash of input files for this build. Eventually, there will be
|
||||
# input files for manifests, and projects too.
|
||||
my(%inputfiles) = (
|
||||
"buildflags", "MozillaBuildFlags.txt",
|
||||
"checkoutdata", "MozillaCheckoutList.txt",
|
||||
"buildprogress", "¥ Mozilla opt progress",
|
||||
"buildmodule", "MozillaBuildList.pm",
|
||||
"checkouttime", "Mozilla last checkout"
|
||||
);
|
||||
#-------------------------------------------------------------
|
||||
# end build hashes
|
||||
#-------------------------------------------------------------
|
||||
|
||||
# set the build root directory, which is the the dir above mozilla
|
||||
SetupBuildRootDir(":mozilla:build:mac:build_scripts");
|
||||
|
||||
# Set up all the flags on $main::, like DEBUG, CARBON etc.
|
||||
# Override the defaults using the preferences files.
|
||||
SetupDefaultBuildOptions(0, ":mozilla:dist:viewer:", $config_header_file_name);
|
||||
|
||||
my($do_checkout) = 0;
|
||||
my($do_build) = 1;
|
||||
|
||||
RunBuild($do_checkout, $do_build, \%inputfiles, $prefs_file_name);
|
||||
@@ -1,80 +0,0 @@
|
||||
#!perl
|
||||
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Simon Fraser <sfraser@netscape.com>
|
||||
#
|
||||
|
||||
require 5.004;
|
||||
|
||||
use strict;
|
||||
|
||||
use Cwd;
|
||||
use Moz::BuildUtils;
|
||||
use Moz::BuildCore;
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# Where have the build options gone?
|
||||
#
|
||||
# The various build flags have been centralized into one place.
|
||||
# The master list of options is in MozBuildFlags.txt. However,
|
||||
# you should never need to edit that file, or this one.
|
||||
#
|
||||
# To customize what gets built, or where to start the build,
|
||||
# edit the $prefs_file_name file in
|
||||
# System Folder:Preferences:Mozilla build prefs:
|
||||
# Documentation is provided in that file.
|
||||
#-------------------------------------------------------------
|
||||
|
||||
my($prefs_file_name) = "Mozilla debug build prefs";
|
||||
my($config_header_file_name) = ":mozilla:config:mac:DefinesOptionsDebug.h";
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# hashes to hold build options
|
||||
#-------------------------------------------------------------
|
||||
my(%build);
|
||||
my(%options);
|
||||
my(%filepaths);
|
||||
my(%optiondefines);
|
||||
|
||||
# Hash of input files for this build. Eventually, there will be
|
||||
# input files for manifests, and projects too.
|
||||
my(%inputfiles) = (
|
||||
"buildflags", "MozillaBuildFlags.txt",
|
||||
"checkoutdata", "MozillaCheckoutList.txt",
|
||||
"buildprogress", "¥ Mozilla debug progress",
|
||||
"buildmodule", "MozillaBuildList.pm",
|
||||
"checkouttime", "Mozilla last checkout"
|
||||
);
|
||||
#-------------------------------------------------------------
|
||||
# end build hashes
|
||||
#-------------------------------------------------------------
|
||||
|
||||
# set the build root directory, which is the the dir above mozilla
|
||||
SetupBuildRootDir(":mozilla:build:mac:build_scripts");
|
||||
|
||||
# Set up all the flags on $main::, like DEBUG, CARBON etc.
|
||||
# Override the defaults using the preferences files.
|
||||
SetupDefaultBuildOptions(1, ":mozilla:dist:viewer_debug:", $config_header_file_name);
|
||||
|
||||
my($do_pull) = 0; # overridden by flags and prefs
|
||||
my($do_build) = 1;
|
||||
|
||||
RunBuild($do_pull, $do_build, \%inputfiles, $prefs_file_name);
|
||||
@@ -1,595 +0,0 @@
|
||||
#!perl -w
|
||||
package Moz::BuildCore;
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
use strict;
|
||||
use vars qw( @ISA @EXPORT );
|
||||
|
||||
# perl includes
|
||||
use Cwd;
|
||||
use POSIX;
|
||||
use Time::Local;
|
||||
use File::Basename;
|
||||
use LWP::Simple;
|
||||
|
||||
# homegrown
|
||||
use Moz::Moz;
|
||||
use Moz::Jar;
|
||||
use Moz::BuildFlags;
|
||||
use Moz::BuildUtils;
|
||||
use Moz::CodeWarriorLib;
|
||||
|
||||
# use MozillaBuildList; # eventually, this should go away, and be replaced by data input
|
||||
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(
|
||||
RunBuild
|
||||
);
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// DoPrebuildCheck
|
||||
#//
|
||||
#// Check the build tools etc before running the build.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub DoPrebuildCheck()
|
||||
{
|
||||
SanityCheckBuildOptions();
|
||||
|
||||
# launch codewarrior and persist its location. Have to call this before first
|
||||
# call to getCodeWarriorPath().
|
||||
my($ide_path_file) = $main::filepaths{"idepath"};
|
||||
$ide_path_file = full_path_to($ide_path_file);
|
||||
LaunchCodeWarrior($ide_path_file);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// SanityCheckBuildOptions
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub SanityCheckBuildOptions()
|
||||
{
|
||||
my($bad_options) = 0;
|
||||
|
||||
# Jar options
|
||||
if (!$main::options{chrome_jars} && !$main::options{chrome_files})
|
||||
{
|
||||
print "Warning: Both \$options{chrome_jars} and \$options{chrome_files} are off. You won't get any chrome.\n";
|
||||
$bad_options = 1;
|
||||
}
|
||||
|
||||
if (!$main::options{chrome_jars} && $main::options{use_jars})
|
||||
{
|
||||
print "Warning: \$options{chrome_jars} is off but \$options{use_jars} is on. Your build won't run (expects jars, got files).\n";
|
||||
$bad_options = 1;
|
||||
}
|
||||
|
||||
if (!$main::options{chrome_files} && !$main::options{use_jars})
|
||||
{
|
||||
print "Warning: \$options{chrome_jars} is off but \$options{chrome_files} is on. Your build won't run (expects files, got jars).\n";
|
||||
$bad_options = 1;
|
||||
}
|
||||
|
||||
if ($main::options{ldap_experimental} && !$main::options{ldap})
|
||||
{
|
||||
print "Warning: \$options{ldap_experimental} is on but \$options{ldap} is off. LDAP experimental features will not be built.\n";
|
||||
$bad_options = 1;
|
||||
}
|
||||
|
||||
if ($main::options{wsp} && !$main::options{xmlextras})
|
||||
{
|
||||
print "Warning: \$options{wsp} is on but \$options{xmlextras} is off. wsp will not be built.\n";
|
||||
$bad_options = 1;
|
||||
}
|
||||
|
||||
if ($bad_options) {
|
||||
print "Build will start in 5 seconds. Press command-. to stop\n";
|
||||
|
||||
DelayFor(5);
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GenBuildSystemInfo
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub GenBuildSystemInfo()
|
||||
{
|
||||
# always rebuild the configuration program.
|
||||
BuildProjectClean(":mozilla:build:mac:tools:BuildSystemInfo:BuildSystemInfo.mcp", "BuildSystemInfo");
|
||||
|
||||
# delete the configuration file.
|
||||
unlink(":mozilla:build:mac:BuildSystemInfo.pm");
|
||||
|
||||
# run the program.
|
||||
system(":mozilla:build:mac:BuildSystemInfo");
|
||||
|
||||
# wait for the file to be created.
|
||||
while (!(-e ":mozilla:build:mac:BuildSystemInfo.pm")) { WaitNextEvent(); }
|
||||
|
||||
# wait for BuildSystemInfo to finish, so that we see correct results.
|
||||
while (IsProcessRunning("BuildSystemInfo")) { WaitNextEvent(); }
|
||||
|
||||
# now, evaluate the contents of the file.
|
||||
open(F, ":mozilla:build:mac:BuildSystemInfo.pm");
|
||||
while (<F>) { eval; }
|
||||
close(F);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Make library aliases
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub MakeLibAliases()
|
||||
{
|
||||
my($dist_dir) = GetBinDirectory();
|
||||
|
||||
#// ProfilerLib
|
||||
if ($main::PROFILE)
|
||||
{
|
||||
my($profilerlibpath) = Moz::CodeWarriorLib::getCodeWarriorPath("MacOS Support:Profiler:Profiler Common:ProfilerLib");
|
||||
MakeAlias("$profilerlibpath", "$dist_dir"."Essential Files:");
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ConfigureBuildSystem
|
||||
#//
|
||||
#// defines some build-system configuration variables.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub ConfigureBuildSystem()
|
||||
{
|
||||
#// In the future, we may want to do configurations based on the actual build system itself.
|
||||
#// GenBuildSystemInfo();
|
||||
|
||||
#// For now, if we discover a newer header file than existed in Universal Interfaces 3.2,
|
||||
#// we'll assume that 3.3 or later is in use.
|
||||
my($universal_interfaces) = Moz::CodeWarriorLib::getCodeWarriorPath("MacOS Support:Universal:Interfaces:CIncludes:");
|
||||
if (-e ($universal_interfaces . "ControlDefinitions.h")) {
|
||||
$main::UNIVERSAL_INTERFACES_VERSION = 0x0330;
|
||||
}
|
||||
|
||||
#// Rename IC SDK folder in the Mac OS Support folder
|
||||
my($ic_sdk_folder) = Moz::CodeWarriorLib::getCodeWarriorPath("MacOS Support:ICProgKit2.0.2");
|
||||
if( -e $ic_sdk_folder)
|
||||
{
|
||||
my($new_ic_folder_name) = Moz::CodeWarriorLib::getCodeWarriorPath("MacOS Support:(ICProgKit2.0.2)");
|
||||
rename ($ic_sdk_folder, $new_ic_folder_name);
|
||||
# note that CodeWarrior doesn't descend into folders with () the name
|
||||
print "Mozilla no longer needs the Internet Config SDK to build:\n Renaming the 'ICProgKit2.0.2' folder to '(ICProgKit2.0.2)'\n";
|
||||
}
|
||||
|
||||
printf("UNIVERSAL_INTERFACES_VERSION = 0x%04X\n", $main::UNIVERSAL_INTERFACES_VERSION);
|
||||
|
||||
# alias required CodeWarrior libs into the Essential Files folder (only the Profiler lib now)
|
||||
MakeLibAliases();
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// CheckOutModule. Takes variable number of args; first two are required
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub CheckOutModule($$$$)
|
||||
{
|
||||
my($session, $module, $revision, $date) = @_;
|
||||
|
||||
my($result) = $session->checkout($module, $revision, $date);
|
||||
|
||||
# result of 1 is success
|
||||
if ($result) { return; }
|
||||
|
||||
my($checkout_err) = $session->getLastError();
|
||||
if ($checkout_err == 708) {
|
||||
die "Error: Checkout was cancelled.\n";
|
||||
} elsif ($checkout_err == 911) {
|
||||
die "Error: CVS session settings are incorrect. Check your password, and the CVS root settings.\n";
|
||||
} elsif ($checkout_err == 703) {
|
||||
die "Error: CVS checkout failed. Unknown module, unknown tag, bad username, or other CVS error.\n";
|
||||
} elsif ($checkout_err == 711) {
|
||||
print "Checkout of '$module' failed.\n";
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getScriptFolder
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getScriptFolder()
|
||||
{
|
||||
return dirname($0);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getScriptFolder
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub get_url_contents($)
|
||||
{
|
||||
my($url) = @_;
|
||||
|
||||
my($url_contents) = LWP::Simple::get($url);
|
||||
$url_contents =~ s/\r\n/\n/g; # normalize linebreaks
|
||||
$url_contents =~ s/\r/\n/g; # normalize linebreaks
|
||||
return $url_contents;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// get_files_from_content
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub uniq
|
||||
{
|
||||
my $lastval;
|
||||
grep(($_ ne $lastval, $lastval = $_)[$[], @_);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// get_files_from_content
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub get_files_from_content($)
|
||||
{
|
||||
my($content) = @_;
|
||||
|
||||
my(@jscalls) = grep (/return js_file_menu[^{]*/, split(/\n/, $content));
|
||||
my $i;
|
||||
|
||||
for ($i = 0; $i < @jscalls ; $i++)
|
||||
{
|
||||
$jscalls[$i] =~ s/.*\(|\).*//g;
|
||||
my(@callparams) = split(/,/, $jscalls[$i]);
|
||||
my ($repos, $dir, $file, $rev) = grep(s/['\s]//g, @callparams);
|
||||
$jscalls[$i] = "$dir/$file";
|
||||
}
|
||||
|
||||
&uniq(sort(@jscalls));
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getLastUpdateTime
|
||||
#//
|
||||
#// Get the last time we updated. Return 0 on failure
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getLastUpdateTime($)
|
||||
{
|
||||
my($timestamp_file) = @_;
|
||||
|
||||
my($time_string);
|
||||
|
||||
local(*TIMESTAMP_FILE);
|
||||
unless (open(TIMESTAMP_FILE, "< $timestamp_file")) { return 0; }
|
||||
|
||||
while (<TIMESTAMP_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
|
||||
# ignore comments and empty lines
|
||||
if ($line =~ /^\#/ || $line =~ /^\s*$/) {
|
||||
next;
|
||||
}
|
||||
|
||||
$time_string = $line;
|
||||
}
|
||||
|
||||
# get the epoch seconds
|
||||
my($last_update_secs) = $time_string;
|
||||
$last_update_secs =~ s/\s#.+$//;
|
||||
|
||||
print "FAST_UPDATE found that you last updated at ".localtime($last_update_secs)."\n";
|
||||
|
||||
# how long ago was this, in hours?
|
||||
my($gm_now) = time();
|
||||
my($update_hours) = 1 + ceil(($gm_now - $last_update_secs) / (60 * 60));
|
||||
|
||||
return $update_hours;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// saveCheckoutTimestamp
|
||||
#//
|
||||
#// Create a file on disk containing the current time. Param is time(), which is an Epoch seconds
|
||||
#// (and therefore in GMT).
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub saveCheckoutTimestamp($$)
|
||||
{
|
||||
my($gm_secs, $timestamp_file) = @_;
|
||||
|
||||
local(*TIMESTAMP_FILE);
|
||||
open(TIMESTAMP_FILE, ">$timestamp_file") || die "Failed to open $timestamp_file\n";
|
||||
print(TIMESTAMP_FILE "# time of last checkout or update, in GMT. Used by FAST_UPDATE\n");
|
||||
print(TIMESTAMP_FILE "$gm_secs \# around ".localtime()." local time\n");
|
||||
close(TIMESTAMP_FILE);
|
||||
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// FastUpdate
|
||||
#//
|
||||
#// Use Bonsai url data to update only those dirs which have new files
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub FastUpdate($$)
|
||||
{
|
||||
my($modules, $timestamp_file) = @_; # list of modules to check out
|
||||
|
||||
my($num_hours) = getLastUpdateTime($timestamp_file);
|
||||
if ($num_hours == 0 || $num_hours > 170) {
|
||||
print "Can't fast_update; last update was too long ago, or never. Doing normal checkout.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
print "Doing fast update, pulling files changed in the last $num_hours hours\n";
|
||||
|
||||
my($cvsfile) = AskAndPersistFile($main::filepaths{"sessionpath"});
|
||||
my($session) = Moz::MacCVS->new( $cvsfile );
|
||||
unless (defined($session)) { die "Error: Checkout aborted. Cannot create session file: $session" }
|
||||
|
||||
# activate MacCVS
|
||||
ActivateApplication('Mcvs');
|
||||
|
||||
my($checkout_start_time) = time();
|
||||
|
||||
#print "Time now is $checkout_start_time ($checkout_start_time + 0)\n";
|
||||
|
||||
my($this_co);
|
||||
foreach $this_co (@$modules)
|
||||
{
|
||||
my($module, $revision, $date) = ($this_co->[0], $this_co->[1], $this_co->[2]);
|
||||
|
||||
# assume that things pulled by date wont change
|
||||
if ($date ne "") {
|
||||
print "$module is pulled by date, so ignoring in FastUpdate.\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my($search_type) = "hours";
|
||||
my($min_date) = "";
|
||||
my($max_date) = "";
|
||||
my($url) = "http://bonsai.mozilla.org/cvsquery.cgi?treeid=default&module=${module}&branch=${revision}&branchtype=match&dir=&file=&filetype=match&who=&whotype=match&sortby=Date&hours=${num_hours}&date=${search_type}&mindate=${min_date}&maxdate=${max_date}&cvsroot=%2Fcvsroot";
|
||||
|
||||
if ($revision eq "") {
|
||||
print "Getting list of checkins to $module from Bonsai...\n";
|
||||
} else {
|
||||
print "Getting list of checkins to $module on branch $revision from Bonsai...\n";
|
||||
}
|
||||
my(@files) = &get_files_from_content(&get_url_contents($url));
|
||||
|
||||
if ($#files > 0)
|
||||
{
|
||||
my(@cvs_co_list);
|
||||
|
||||
my($co_file);
|
||||
foreach $co_file (@files)
|
||||
{
|
||||
print "Updating $co_file\n";
|
||||
push(@cvs_co_list, $co_file);
|
||||
}
|
||||
|
||||
my($result) = $session->update($revision, \@cvs_co_list);
|
||||
# result of 1 is success
|
||||
if (!$result) { die "Error: Fast update failed\n"; }
|
||||
} else {
|
||||
print "No files in this module changed\n";
|
||||
}
|
||||
}
|
||||
|
||||
saveCheckoutTimestamp($checkout_start_time, $timestamp_file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Checkout
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub CheckoutModules($$$)
|
||||
{
|
||||
my($modules, $pull_date, $timestamp_file) = @_; # list of modules to check out
|
||||
|
||||
my($start_time) = TimeStart();
|
||||
|
||||
# assertRightDirectory();
|
||||
my($cvsfile) = AskAndPersistFile($main::filepaths{"sessionpath"});
|
||||
my($session) = Moz::MacCVS->new( $cvsfile );
|
||||
unless (defined($session)) { die "Error: Checkout aborted. Cannot create session file: $session" }
|
||||
|
||||
my($checkout_start_time) = time();
|
||||
|
||||
# activate MacCVS
|
||||
ActivateApplication('Mcvs');
|
||||
|
||||
my($this_co);
|
||||
foreach $this_co (@$modules)
|
||||
{
|
||||
my($module, $revision, $date) = ($this_co->[0], $this_co->[1], $this_co->[2]);
|
||||
if ($date eq "") {
|
||||
$date = $pull_date;
|
||||
}
|
||||
CheckOutModule($session, $module, $revision, $date);
|
||||
# print "Checking out $module with ref $revision, date $date\n";
|
||||
}
|
||||
|
||||
saveCheckoutTimestamp($checkout_start_time, $timestamp_file);
|
||||
TimeEnd($start_time, "Checkout");
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ReadCheckoutModulesFile
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub ReadCheckoutModulesFile($$)
|
||||
{
|
||||
my($modules_file, $co_list) = @_;
|
||||
|
||||
my($checkout_file) = getScriptFolder().":".$modules_file;
|
||||
local(*CHECKOUT_FILE);
|
||||
open(CHECKOUT_FILE, "< $checkout_file") || die "Error: failed to open checkout list $checkout_file\n";
|
||||
while (<CHECKOUT_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
|
||||
# ignore comments and empty lines
|
||||
if ($line =~ /^\#/ || $line =~ /^\s*$/) {
|
||||
next;
|
||||
}
|
||||
|
||||
my(@cvs_co) = ["", "", ""];
|
||||
|
||||
my($module, $revision, $date) = (0, 1, 2);
|
||||
|
||||
if ($line =~ /\s*([^#,\s]+)\s*\,\s*([^#,\s]+)\s*\,\s*([^#]+)/)
|
||||
{
|
||||
@cvs_co[$module] = $1;
|
||||
@cvs_co[$revision] = $2;
|
||||
@cvs_co[$date] = $3;
|
||||
}
|
||||
elsif ($line =~ /\s*([^#,\s]+)\s*\,\s*([^#,\s]+)\s*(#.+)?/)
|
||||
{
|
||||
@cvs_co[$module] = $1;
|
||||
@cvs_co[$revision] = $2;
|
||||
}
|
||||
elsif ($line =~ /\s*([^#,\s]+)\s*\,\s*,\s*([^#,]+)/)
|
||||
{
|
||||
@cvs_co[$module] = $1;
|
||||
@cvs_co[$date] = $2;
|
||||
}
|
||||
elsif ($line =~ /\s*([^#,\s]+)/)
|
||||
{
|
||||
@cvs_co[$module] = $1;
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Error: unrecognized line '$line' in $modules_file\n";
|
||||
}
|
||||
|
||||
# strip surrounding space from date
|
||||
@cvs_co[$date] =~ s/^\s*|\s*$//g;
|
||||
|
||||
# print "Going to check out '@cvs_co[$module]', '@cvs_co[$revision]', '@cvs_co[$date]'\n";
|
||||
push(@$co_list, \@cvs_co);
|
||||
}
|
||||
|
||||
close(CHECKOUT_FILE);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// PullFromCVS
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub PullFromCVS($$)
|
||||
{
|
||||
unless ( $main::build{pull} ) { return; }
|
||||
|
||||
my($modules_file, $timestamp_file) = @_;
|
||||
|
||||
StartBuildModule("pull");
|
||||
|
||||
my(@cvs_co_list);
|
||||
ReadCheckoutModulesFile($modules_file, \@cvs_co_list);
|
||||
|
||||
if ($main::FAST_UPDATE && $main::options{pull_by_date})
|
||||
{
|
||||
die "Error: you can't use FAST_UPDATE if you are pulling by date.\n";
|
||||
}
|
||||
|
||||
my($did_fast_update) = $main::FAST_UPDATE && FastUpdate(\@cvs_co_list, $timestamp_file);
|
||||
if (!$did_fast_update)
|
||||
{
|
||||
my($pull_date) = "";
|
||||
if ($main::options{pull_by_date})
|
||||
{
|
||||
# acceptable CVS date formats are (in local time):
|
||||
# ISO8601 (e.g. "1972-09-24 20:05") and Internet (e.g. "24 Sep 1972 20:05").
|
||||
# Perl's localtime() string format also seems to work.
|
||||
$pull_date = localtime().""; # force string interp.
|
||||
print "Pulling by date $pull_date\n";
|
||||
}
|
||||
|
||||
CheckoutModules(\@cvs_co_list, $pull_date, $timestamp_file);
|
||||
}
|
||||
|
||||
EndBuildModule("pull");
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// RunBuild
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub RunBuild($$$$)
|
||||
{
|
||||
my($do_pull, $do_build, $input_files, $build_prefs) = @_;
|
||||
|
||||
InitBuildProgress($input_files->{"buildprogress"});
|
||||
|
||||
# if we are pulling, we probably want to do a full build, so clear the build progress
|
||||
if ($do_pull) {
|
||||
ClearBuildProgress();
|
||||
}
|
||||
|
||||
# read local prefs, and the build progress file, and set flags to say what to build
|
||||
SetupBuildParams(\%main::build,
|
||||
\%main::options,
|
||||
\%main::optiondefines,
|
||||
\%main::filepaths,
|
||||
$input_files->{"buildflags"},
|
||||
$build_prefs);
|
||||
|
||||
# If we were told to pull, make sure we do, overriding prefs etc.
|
||||
if ($do_pull)
|
||||
{
|
||||
$main::build{"pull"} = 1;
|
||||
}
|
||||
|
||||
# transfer this flag
|
||||
$CodeWarriorLib::CLOSE_PROJECTS_FIRST = $main::CLOSE_PROJECTS_FIRST;
|
||||
|
||||
# setup the build log
|
||||
SetupBuildLog($main::filepaths{"buildlogfilepath"}, $main::USE_TIMESTAMPED_LOGS);
|
||||
StopForErrors();
|
||||
|
||||
if ($main::LOG_TO_FILE) {
|
||||
RedirectOutputToFile($main::filepaths{"scriptlogfilepath"});
|
||||
}
|
||||
|
||||
# run a pre-build check to see that the tools etc are in order
|
||||
DoPrebuildCheck();
|
||||
|
||||
# do the pull
|
||||
PullFromCVS($input_files->{"checkoutdata"}, $input_files->{"checkouttime"});
|
||||
|
||||
unless ($do_build) { return; }
|
||||
|
||||
my($build_start) = TimeStart();
|
||||
|
||||
# check the build environment
|
||||
ConfigureBuildSystem();
|
||||
|
||||
# here we load and call methods in the build module indirectly.
|
||||
# we have to use indirection because the build module can be named
|
||||
# differently for different builds.
|
||||
chdir(dirname($0)); # change to the script dir
|
||||
my($build_module) = $input_files->{"buildmodule"};
|
||||
# load the build module
|
||||
require $build_module;
|
||||
{ # scope for no strict 'refs'
|
||||
no strict 'refs';
|
||||
|
||||
my($package_name) = $build_module;
|
||||
$package_name =~ s/\.pm$//;
|
||||
|
||||
chdir($main::MOZ_SRC);
|
||||
&{$package_name."::BuildDist"}();
|
||||
|
||||
chdir($main::MOZ_SRC);
|
||||
&{$package_name."::BuildProjects"}();
|
||||
}
|
||||
|
||||
# the build finished, so clear the build progress state
|
||||
ClearBuildProgress();
|
||||
|
||||
TimeEnd($build_start, "Build");
|
||||
print "Build complete\n";
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -1,425 +0,0 @@
|
||||
#!perl -w
|
||||
package Moz::BuildFlags;
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
# Package that attempts to read a file from the Preferences folder,
|
||||
# and get build settings out of it
|
||||
|
||||
use strict;
|
||||
use Exporter;
|
||||
|
||||
use Cwd;
|
||||
use File::Basename;
|
||||
|
||||
use Moz::Moz;
|
||||
use Moz::Prefs;
|
||||
|
||||
use vars qw(@ISA @EXPORT);
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(
|
||||
SetupBuildParams
|
||||
InitBuildProgress
|
||||
WriteBuildProgress
|
||||
ClearBuildProgress
|
||||
ReadBuildProgress
|
||||
);
|
||||
|
||||
|
||||
my(@build_flags);
|
||||
my(@options_flags);
|
||||
my(@filepath_flags);
|
||||
|
||||
my(%arrays_list) = (
|
||||
"build_flags", \@build_flags,
|
||||
"options_flags", \@options_flags,
|
||||
"filepath_flags", \@filepath_flags
|
||||
);
|
||||
|
||||
my($progress_file) = "¥ÊBuild progress";
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# appendArrayFlag
|
||||
#
|
||||
# Set a flag in the array
|
||||
#-------------------------------------------------------------------------------
|
||||
sub appendArrayFlag(@)
|
||||
{
|
||||
my($array_name) = shift;
|
||||
my($setting) = shift;
|
||||
my($value) = shift;
|
||||
|
||||
my(@optional_values);
|
||||
foreach (@_) {
|
||||
push(@optional_values, $_);
|
||||
}
|
||||
|
||||
my(@this_flag) = [$setting, $value, @optional_values];
|
||||
my($flags_array) = $arrays_list{$array_name};
|
||||
if ($flags_array)
|
||||
{
|
||||
push(@{$flags_array}, @this_flag) || die "Failed to append\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Error: unknown build flags array $array_name\n";
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# readFlagsFile
|
||||
#
|
||||
# Read the file of build flags from disk. File path is relative to the
|
||||
# script directory.
|
||||
#-------------------------------------------------------------------------------
|
||||
sub readFlagsFile($)
|
||||
{
|
||||
my($flags_file) = @_;
|
||||
|
||||
my($file_path) = $0;
|
||||
$file_path =~ s/[^:]+$/$flags_file/;
|
||||
|
||||
print "Reading build flags from '$file_path'\n";
|
||||
|
||||
local(*FLAGS_FILE);
|
||||
open(FLAGS_FILE, "< $file_path") || die "Error: failed to open flags file $file_path\n";
|
||||
|
||||
my($cur_array) = "";
|
||||
|
||||
while(<FLAGS_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
|
||||
# ignore comments and empty lines
|
||||
if ($line =~ /^\#/ || $line =~ /^\s*$/) {
|
||||
next;
|
||||
}
|
||||
|
||||
# 1-word line, probably array name
|
||||
if ($line =~ /^([^#\s]+)\s*$/)
|
||||
{
|
||||
$cur_array = $1;
|
||||
next;
|
||||
}
|
||||
elsif ($line =~ /^([^#\s]+)\s+\"(.+)\"(\s+#.+)?$/) # quoted option, possible comment
|
||||
{
|
||||
my($flag) = $1;
|
||||
my($setting) = $2;
|
||||
|
||||
appendArrayFlag($cur_array, $flag, $setting);
|
||||
}
|
||||
elsif ($line =~ /^([^#\s]+)((\s+[^#\s]+)+)(\s+#.+)?$/) # multiple word line, possible comment
|
||||
{
|
||||
my($flag) = $1;
|
||||
|
||||
appendArrayFlag($cur_array, $flag, split(' ', $2));
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Error: unknown build flag at '$line'\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
close(FLAGS_FILE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# flagsArrayToHash
|
||||
#
|
||||
# Utility routine to migrate flag from a 2D array to a hash, where
|
||||
# item[n][0] is the hash entry name, and item[n][1] is the hash entry value.
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub flagsArrayToHash($$)
|
||||
{
|
||||
my($src_array, $dest_hash) = @_;
|
||||
|
||||
my($item);
|
||||
foreach $item (@$src_array)
|
||||
{
|
||||
$dest_hash->{$item->[0]} = $item->[1];
|
||||
}
|
||||
}
|
||||
|
||||
#-----------------------------------------------
|
||||
# printHash
|
||||
#
|
||||
# Utility routine to print a hash
|
||||
#-----------------------------------------------
|
||||
sub printHash($)
|
||||
{
|
||||
my($hash_ref) = @_;
|
||||
|
||||
print "Printing hash:\n";
|
||||
|
||||
my($key, $value);
|
||||
|
||||
while (($key, $value) = each (%$hash_ref))
|
||||
{
|
||||
print " $key $value\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-----------------------------------------------
|
||||
# printBuildArray
|
||||
#
|
||||
# Utility routine to print a 2D array
|
||||
#-----------------------------------------------
|
||||
sub printBuildArray($)
|
||||
{
|
||||
my($build_array) = @_;
|
||||
|
||||
my($entry);
|
||||
foreach $entry (@$build_array)
|
||||
{
|
||||
print "$entry->[0] = $entry->[1]\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# SetBuildFlags
|
||||
#-------------------------------------------------------------------------------
|
||||
sub SetBuildFlags($)
|
||||
{
|
||||
my($build) = @_;
|
||||
|
||||
flagsArrayToHash(\@build_flags, $build);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# SetBuildOptions
|
||||
#-------------------------------------------------------------------------------
|
||||
sub SetBuildOptions($)
|
||||
{
|
||||
my($options) = @_;
|
||||
|
||||
flagsArrayToHash(\@options_flags, $options);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# SetFilepathFlags
|
||||
#-------------------------------------------------------------------------------
|
||||
sub SetFilepathFlags($)
|
||||
{
|
||||
my($filepath) = @_;
|
||||
|
||||
flagsArrayToHash(\@filepath_flags, $filepath);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# SetOptionDefines
|
||||
#-------------------------------------------------------------------------------
|
||||
sub SetOptionDefines($)
|
||||
{
|
||||
my($optiondefines) = @_;
|
||||
|
||||
foreach my $entry (@options_flags)
|
||||
{
|
||||
if (defined($entry->[2])) {
|
||||
$optiondefines->{$entry->[0]}{$entry->[2]} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# PropagateAllFlags
|
||||
#-------------------------------------------------------------------------------
|
||||
sub PropagateAllFlags($)
|
||||
{
|
||||
my($build_array) = @_;
|
||||
|
||||
# if "all" is set, set all the flags to 1
|
||||
unless ($build_array->[0][0] eq "all") { die "Error: 'all' must come first in the flags array\n"; }
|
||||
|
||||
if ($build_array->[0][1] == 1)
|
||||
{
|
||||
my($index);
|
||||
foreach $index (@$build_array)
|
||||
{
|
||||
$index->[1] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// _getBuildProgressFile
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub _getBuildProgressFile()
|
||||
{
|
||||
return $progress_file;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// setBuildProgressStart
|
||||
#//
|
||||
#// This automagically sets $build{"all"} to 0
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub setBuildProgressStart($$)
|
||||
{
|
||||
my($build_array, $name) = @_;
|
||||
|
||||
my($index);
|
||||
foreach $index (@$build_array)
|
||||
{
|
||||
$index->[1] = 0;
|
||||
if ($index->[0] eq $name) {
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
print "Building from module after $name, as specified by build progress\n";
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// InitBuildProgress
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub InitBuildProgress($)
|
||||
{
|
||||
my($prog_file) = @_;
|
||||
if ($prog_file ne "") {
|
||||
$progress_file = full_path_to($prog_file);
|
||||
print "Writing build progress to $progress_file\n";
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// WriteBuildProgress
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub WriteBuildProgress($)
|
||||
{
|
||||
my($module_built) = @_;
|
||||
|
||||
my($progress_file) = _getBuildProgressFile();
|
||||
|
||||
if ($progress_file ne "")
|
||||
{
|
||||
open(PROGRESS_FILE, ">>$progress_file") || die "Failed to open $progress_file\n";
|
||||
print(PROGRESS_FILE "$module_built\n");
|
||||
close(PROGRESS_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ClearBuildProgress
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub ClearBuildProgress()
|
||||
{
|
||||
my($progress_file) = _getBuildProgressFile();
|
||||
if ($progress_file ne "") {
|
||||
unlink $progress_file;
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// WipeBuildProgress
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub WipeBuildProgress()
|
||||
{
|
||||
print "Ignoring build progress\n";
|
||||
ClearBuildProgress();
|
||||
$progress_file = "";
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ReadBuildProgress
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub ReadBuildProgress($)
|
||||
{
|
||||
my($build_array) = @_;
|
||||
my($progress_file) = _getBuildProgressFile();
|
||||
|
||||
my($last_module);
|
||||
|
||||
if (open(PROGRESS_FILE, "< $progress_file"))
|
||||
{
|
||||
print "Getting build progress from $progress_file\n";
|
||||
|
||||
while (<PROGRESS_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
$last_module = $line;
|
||||
}
|
||||
|
||||
close(PROGRESS_FILE);
|
||||
}
|
||||
|
||||
if ($last_module)
|
||||
{
|
||||
setBuildProgressStart($build_array, $last_module);
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# clearOldBuildSettings
|
||||
#-------------------------------------------------------------------------------
|
||||
sub clearOldBuildSettings($$$$)
|
||||
{
|
||||
my($build, $options, $optiondefines, $filepaths) = @_;
|
||||
|
||||
# empty the arrays in case we're being called twice
|
||||
@build_flags = ();
|
||||
@options_flags = ();
|
||||
@filepath_flags = ();
|
||||
|
||||
# and empty the hashes
|
||||
%$build = ();
|
||||
%$options = ();
|
||||
%$optiondefines = ();
|
||||
%$filepaths = ();
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# SetupBuildParams
|
||||
#-------------------------------------------------------------------------------
|
||||
sub SetupBuildParams($$$$$$)
|
||||
{
|
||||
my($build, $options, $optiondefines, $filepaths, $flags_file, $prefs_file) = @_;
|
||||
|
||||
# Empty the hashes and arrays, to wipe out any stale data.
|
||||
# Needed because these structures persist across two build scripts
|
||||
# called using 'do' from a parent script.
|
||||
clearOldBuildSettings($build, $options, $optiondefines, $filepaths);
|
||||
|
||||
# Read from the flags file, which sets up the various arrays
|
||||
readFlagsFile($flags_file);
|
||||
|
||||
# If 'all' is set in the build array, propagate that to all entries
|
||||
PropagateAllFlags(\@build_flags);
|
||||
|
||||
# read the user pref file, that can change values in the array
|
||||
ReadMozUserPrefs($prefs_file, \@build_flags, \@options_flags, \@filepath_flags);
|
||||
|
||||
# If build progress exists, this clears flags in the array up to a certain point
|
||||
if ($main::USE_BUILD_PROGRESS) {
|
||||
ReadBuildProgress(\@build_flags);
|
||||
} else {
|
||||
WipeBuildProgress();
|
||||
}
|
||||
|
||||
# printBuildArray(\@build_flags);
|
||||
# printBuildArray(\@options_flags);
|
||||
|
||||
SetBuildFlags($build);
|
||||
SetBuildOptions($options);
|
||||
SetOptionDefines($optiondefines);
|
||||
SetFilepathFlags($filepaths);
|
||||
|
||||
# printHash($build);
|
||||
# printHash($options);
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
@@ -1,786 +0,0 @@
|
||||
|
||||
package Moz::BuildUtils;
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
# Package that contains build util functions specific to the Mozilla build
|
||||
# process.
|
||||
|
||||
use strict;
|
||||
use Exporter;
|
||||
|
||||
use Cwd;
|
||||
use File::Path;
|
||||
use File::Basename;
|
||||
|
||||
use Mac::Events;
|
||||
use Mac::StandardFile;
|
||||
|
||||
use Moz::Moz;
|
||||
use Moz::BuildFlags;
|
||||
use Moz::MacCVS;
|
||||
#use Moz::ProjectXML; #optional; required for static build only
|
||||
|
||||
use vars qw(@ISA @EXPORT);
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(
|
||||
SetupDefaultBuildOptions
|
||||
SetupBuildRootDir
|
||||
StartBuildModule
|
||||
EndBuildModule
|
||||
GetBinDirectory
|
||||
BuildOneProjectWithOutput
|
||||
BuildOneProject
|
||||
BuildProject
|
||||
BuildProjectClean
|
||||
BuildIDLProject
|
||||
BuildFolderResourceAliases
|
||||
AskAndPersistFile
|
||||
DelayFor
|
||||
TimeStart
|
||||
TimeEnd
|
||||
EmptyTree
|
||||
SetupBuildLog
|
||||
SetBuildNumber
|
||||
SetTimeBomb
|
||||
UpdateConfigHeader
|
||||
);
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// SetupDefaultBuildOptions
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub SetupDefaultBuildOptions($$$)
|
||||
{
|
||||
my($debug, $bin_dir, $config_header_file_name) = @_;
|
||||
|
||||
# Here we set up defaults for the various build flags.
|
||||
# If you want to override any of these, it's best to do
|
||||
# so via the relevant preferences file, which lives in
|
||||
# System Folder:Preferences:Mozilla build prefs:{build prefs file}.
|
||||
# For the name of the prefs file, see the .pl script that you
|
||||
# run to start this build. The prefs files are created when
|
||||
# you run the build, and contain some documentation.
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# configuration variables that globally affect what is built
|
||||
#-------------------------------------------------------------
|
||||
$main::DEBUG = $debug;
|
||||
$main::PROFILE = 0;
|
||||
$main::RUNTIME = 0; # turn on to just build runtime support and NSPR projects
|
||||
$main::GC_LEAK_DETECTOR = 0; # turn on to use GC leak detection
|
||||
$main::MOZILLA_OFFICIAL = 0; # generate build number
|
||||
$main::LOG_TO_FILE = 0; # write perl output to a file
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# configuration variables that affect the manner of building,
|
||||
# but possibly affecting the outcome.
|
||||
#-------------------------------------------------------------
|
||||
$main::ALIAS_SYM_FILES = $main::DEBUG;
|
||||
$main::CLOBBER_LIBS = 1; # turn on to clobber existing libs and .xSYM files before
|
||||
# building each project
|
||||
# The following two options will delete all dist files (if you have $main::build{dist} turned on),
|
||||
# but leave the directory structure intact.
|
||||
$main::CLOBBER_DIST_ALL = 1; # turn on to clobber all aliases/files inside dist (headers/xsym/libs)
|
||||
$main::CLOBBER_DIST_LIBS = 0; # turn on to clobber only aliases/files for libraries/sym files in dist
|
||||
$main::CLOBBER_IDL_PROJECTS = 0; # turn on to clobber all IDL projects.
|
||||
$main::CLOBBER_PROJECTS = 0; # turn on to remove object code from each project before building it
|
||||
|
||||
$main::UNIVERSAL_INTERFACES_VERSION = 0x0320;
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# configuration variables that are preferences for the build,
|
||||
# style and do not affect what is built.
|
||||
#-------------------------------------------------------------
|
||||
$main::CLOSE_PROJECTS_FIRST = 0;
|
||||
# 1 = close then make (for development),
|
||||
# 0 = make then close (for tinderbox).
|
||||
$main::USE_TIMESTAMPED_LOGS = 0;
|
||||
$main::USE_BUILD_PROGRESS = 1; # track build progress for restartable builds
|
||||
#-------------------------------------------------------------
|
||||
# END OF CONFIG SWITCHES
|
||||
#-------------------------------------------------------------
|
||||
|
||||
$main::BIN_DIRECTORY = $bin_dir;
|
||||
$main::DEFINESOPTIONS_FILE = $config_header_file_name;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// SetupBuildRootDir
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub SetupBuildRootDir($)
|
||||
{
|
||||
my($rel_path_to_script) = @_;
|
||||
|
||||
my($cur_dir) = cwd();
|
||||
$cur_dir =~ s/$rel_path_to_script$//;
|
||||
chdir($cur_dir) || die "Error: failed to set build root directory to '$cur_dir'.\nYou probably need to put 'mozilla' one level down (in a folder).\n";
|
||||
$main::MOZ_SRC = cwd();
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// StartBuildModule
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub StartBuildModule($)
|
||||
{
|
||||
my($module) = @_;
|
||||
|
||||
print("---- Start of $module ----\n");
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// EndBuildModule
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub EndBuildModule($)
|
||||
{
|
||||
my($module) = @_;
|
||||
WriteBuildProgress($module);
|
||||
print("---- End of $module ----\n");
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
# GetBinDirectory
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
sub GetBinDirectory()
|
||||
{
|
||||
if ($main::BIN_DIRECTORY eq "") { die "Dist directory not set\n"; }
|
||||
return $main::BIN_DIRECTORY;
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
# AskAndPersistFile stores the information about the user pick inside
|
||||
# the file $session_storage
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
sub AskAndPersistFile($)
|
||||
{
|
||||
my ($sessionStorage) = @_;
|
||||
my $cvsfile;
|
||||
|
||||
if (( -e $sessionStorage) &&
|
||||
open( SESSIONFILE, $sessionStorage ))
|
||||
{
|
||||
# Read in the path if available
|
||||
$cvsfile = <SESSIONFILE>;
|
||||
chomp $cvsfile;
|
||||
close SESSIONFILE;
|
||||
if ( ! -e $cvsfile )
|
||||
{
|
||||
print STDERR "$cvsfile has disappeared\n";
|
||||
undef $cvsfile;
|
||||
}
|
||||
}
|
||||
unless (defined ($cvsfile))
|
||||
{
|
||||
# make sure that MacPerl is a front process
|
||||
ActivateApplication('McPL');
|
||||
MacPerl::Answer("Could not find your MacCVS session file. Please choose one", "OK");
|
||||
|
||||
# prompt user for the file name, and store it
|
||||
my $macFile = StandardGetFile( 0, "McvD");
|
||||
if ( $macFile->sfGood() )
|
||||
{
|
||||
$cvsfile = $macFile->sfFile();
|
||||
# save the choice if we can
|
||||
if ( open (SESSIONFILE, ">" . $sessionStorage))
|
||||
{
|
||||
printf SESSIONFILE $cvsfile, "\n";
|
||||
close SESSIONFILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
print STDERR "Could not open storage file $sessionStorage for saving $cvsfile\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
return $cvsfile;
|
||||
}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
# BuildIDLProject
|
||||
#
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub BuildIDLProject($$)
|
||||
{
|
||||
my ($project_path, $module_name) = @_;
|
||||
|
||||
if ($main::CLOBBER_IDL_PROJECTS)
|
||||
{
|
||||
my (@suffix_list) = (".mcp", ".xml");
|
||||
my ($project_name, $project_dir, $suffix) = fileparse($project_path, @suffix_list);
|
||||
if ($suffix eq "") { die "Error: Project, $project_path must end in .xml or .mcp\n"; }
|
||||
|
||||
my($datafolder_path);
|
||||
if ($suffix eq ".xml")
|
||||
{
|
||||
$datafolder_path = $project_dir . "_" . $project_name . " Data:";
|
||||
}
|
||||
else {
|
||||
$datafolder_path = $project_dir . $project_name . " Data:";
|
||||
}
|
||||
|
||||
print STDERR "Deleting IDL data folder: $datafolder_path\n";
|
||||
EmptyTree($datafolder_path);
|
||||
}
|
||||
|
||||
BuildOneProject($project_path, "headers", 0, 0, 0);
|
||||
BuildOneProject($project_path, $module_name.".xpt", 1, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
# CreateStaticLibTargets
|
||||
#
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
sub CreateXMLStaticLibTargets($)
|
||||
{
|
||||
my($xml_path) = @_;
|
||||
|
||||
my (@suffix_list) = (".xml");
|
||||
my ($project_name, $project_dir, $suffix) = fileparse($xml_path, @suffix_list);
|
||||
if ($suffix eq "") { die "XML munging: $xml_path must end in .xml\n"; }
|
||||
|
||||
#sniff the file to see if we need to fix up broken Pro5-exported XML
|
||||
print "Parsing $xml_path\n";
|
||||
|
||||
my $ide_version = Moz::ProjectXML::SniffProjectXMLIDEVersion($xml_path);
|
||||
if ($ide_version eq "4.0")
|
||||
{
|
||||
my $new_file = $project_dir.$project_name."2.xml";
|
||||
|
||||
print "Cleaning up Pro 5 xml to $new_file\n";
|
||||
|
||||
Moz::ProjectXML::CleanupPro5XML($xml_path, $new_file);
|
||||
|
||||
unlink $xml_path;
|
||||
rename ($new_file, $xml_path);
|
||||
}
|
||||
|
||||
my $doc = Moz::ProjectXML::ParseXMLDocument($xml_path);
|
||||
my @target_list = Moz::ProjectXML::GetTargetsList($doc);
|
||||
my $target;
|
||||
|
||||
my %target_hash; # for easy lookups below
|
||||
foreach $target (@target_list) { $target_hash{$target} = 1; }
|
||||
|
||||
foreach $target (@target_list)
|
||||
{
|
||||
if ($target =~ /(.+).shlb$/) # if this is a shared lib target
|
||||
{
|
||||
my $target_base = $1;
|
||||
my $static_target = $target_base.".o";
|
||||
|
||||
# ensure that this does not exist already
|
||||
if ($target_hash{$static_target}) {
|
||||
print "Static target $static_target already exists in project. Not making\n";
|
||||
next;
|
||||
}
|
||||
|
||||
print "Making static target '$static_target' from target '$target'\n";
|
||||
|
||||
Moz::ProjectXML::CloneTarget($doc, $target, $static_target);
|
||||
Moz::ProjectXML::SetAsStaticLibraryTarget($doc, $static_target, $static_target);
|
||||
}
|
||||
}
|
||||
|
||||
print "Writing XML file to $xml_path\n";
|
||||
my $temp_path = $project_dir."_".$project_name.".xml";
|
||||
Moz::ProjectXML::WriteXMLDocument($doc, $temp_path, $ide_version);
|
||||
Moz::ProjectXML::DisposeXMLDocument($doc);
|
||||
|
||||
if (-e $temp_path)
|
||||
{
|
||||
unlink $xml_path;
|
||||
rename ($temp_path, $xml_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Error: Failed to add new targets to XML project\n";
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ProcessProjectXML
|
||||
#//
|
||||
#// Helper routine to allow for XML pre-processing. This should read in the XML, process it,
|
||||
#// and replace the original file with the processed version.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub ProcessProjectXML($)
|
||||
{
|
||||
my($xml_path) = @_;
|
||||
|
||||
# we need to manually load Moz::ProjectXML, becaues not everyone will have the
|
||||
# required perl modules in their distro.
|
||||
my($cur_dir) = cwd();
|
||||
|
||||
chdir(dirname($0)); # change to the script dir
|
||||
eval "require Moz::ProjectXML";
|
||||
if ($@) { die "Error: could not do Project XML munging because you do not have the correct XML modules installed. Error is:\n################\n $@################"; }
|
||||
|
||||
chdir($cur_dir);
|
||||
|
||||
CreateXMLStaticLibTargets($xml_path);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Build one project, and make the alias. Parameters are project path, target name, shared library
|
||||
#// name, make shlb alias (boolean), make xSYM alias (boolean), and is component (boolean).
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub BuildOneProjectWithOutput($$$$$$)
|
||||
{
|
||||
my ($project_path, $target_name, $output_name, $alias_lib, $alias_xSYM, $component) = @_;
|
||||
|
||||
unless ($project_path =~ m/^$main::BUILD_ROOT.+/) { return; }
|
||||
|
||||
my (@suffix_list) = (".mcp", ".xml");
|
||||
my ($project_name, $project_dir, $suffix) = fileparse($project_path, @suffix_list);
|
||||
if ($suffix eq "") { die "Error: Project, $project_path must end in .xml or .mcp\n"; }
|
||||
|
||||
my($dist_dir) = GetBinDirectory();
|
||||
|
||||
# Put libraries in "Essential Files" folder, Components in "Components" folder
|
||||
my($output_dir) = $component ? "Components:" : "Essential Files:";
|
||||
my($output_path) = $dist_dir.$output_dir;
|
||||
|
||||
if ($main::options{static_build})
|
||||
{
|
||||
if ($output_name =~ /\.o$/ || $output_name =~ /\.[Ll]ib$/)
|
||||
{
|
||||
$alias_xSYM = 0;
|
||||
$alias_lib = 1;
|
||||
$output_path = $main::DEBUG ? ":mozilla:dist:static_libs_debug:" : ":mozilla:dist:static_libs:";
|
||||
}
|
||||
}
|
||||
|
||||
# if the flag is on to export projects to XML, export and munge them
|
||||
if ($main::EXPORT_PROJECTS && !($project_path =~ /IDL\.mcp$/))
|
||||
{
|
||||
my $xml_out_path = $project_path;
|
||||
|
||||
$xml_out_path =~ s/\.mcp$/\.xml/;
|
||||
|
||||
# only do this if project is newer?
|
||||
if (! -e $xml_out_path)
|
||||
{
|
||||
ExportProjectToXML(full_path_to($project_path), full_path_to($xml_out_path));
|
||||
ProcessProjectXML($xml_out_path);
|
||||
}
|
||||
}
|
||||
|
||||
# if the flag is set to use XML projects, default to XML if the file
|
||||
# is present.
|
||||
if ($main::USE_XML_PROJECTS && !($project_path =~ /IDL\.mcp$/))
|
||||
{
|
||||
my $xml_project_path = $project_dir.$project_name.".xml";
|
||||
if (-e $xml_project_path)
|
||||
{
|
||||
$project_path = $xml_project_path;
|
||||
$suffix = ".xml";
|
||||
}
|
||||
}
|
||||
|
||||
if ($suffix eq ".xml")
|
||||
{
|
||||
my($xml_path) = $project_path;
|
||||
# Prepend an "_" onto the name of the generated project file so it doesn't conflict
|
||||
$project_path = $project_dir . "_" . $project_name . ".mcp";
|
||||
my($project_modtime) = (-e $project_path ? GetFileModDate($project_path) : 0);
|
||||
my($xml_modtime) = (-e $xml_path ? GetFileModDate($xml_path) : 0);
|
||||
|
||||
if ($xml_modtime > $project_modtime)
|
||||
{
|
||||
print("Importing $project_path from $project_name.xml.\n");
|
||||
unlink($project_path);
|
||||
# Might want to delete the "xxx.mcp Data" dir ???
|
||||
ImportXMLProject(full_path_to($xml_path), full_path_to($project_path));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($main::CLOBBER_LIBS)
|
||||
{
|
||||
unlink "$project_dir$output_name"; # it's OK if these fail
|
||||
unlink "$project_dir$output_name.xSYM";
|
||||
}
|
||||
|
||||
DoBuildProject($project_path, $target_name, $main::CLOBBER_PROJECTS);
|
||||
|
||||
$alias_lib ? MakeAlias("$project_dir$output_name", "$output_path") : 0;
|
||||
$alias_xSYM ? MakeAlias("$project_dir$output_name.xSYM", "$output_path") : 0;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// For compatiblity with existing scripts, BuildOneProject now just calls
|
||||
#// BuildOneProjectWithOutput, with the output name and target name identical.
|
||||
#// Note that this routine assumes that the target name and the shared libary name
|
||||
#// are the same.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub BuildOneProject($$$$$)
|
||||
{
|
||||
my ($project_path, $target_name, $alias_lib, $alias_xSYM, $component) = @_;
|
||||
|
||||
BuildOneProjectWithOutput($project_path, $target_name, $target_name,
|
||||
$alias_lib, $alias_xSYM, $component);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// For compatiblity with existing scripts, BuildProject now just calls
|
||||
#// BuildOneProjectWithOutput, with the output name and target name identical.
|
||||
#// Note that this routine assumes that the target name and the shared libary name
|
||||
#// are the same. No aliases of the output are made.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub BuildProject($$)
|
||||
{
|
||||
my ($project_path, $target_name) = @_;
|
||||
|
||||
BuildOneProjectWithOutput($project_path, $target_name, $target_name, 0, 0, 0);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Identical to BuildProject but clobbers the project before building it.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub BuildProjectClean($$)
|
||||
{
|
||||
my ($project_path, $target_name) = @_;
|
||||
my ($save_clobber_flag) = $main::CLOBBER_PROJECTS;
|
||||
$main::CLOBBER_PROJECTS = 1;
|
||||
BuildOneProjectWithOutput($project_path, $target_name, $target_name, 0, 0, 0);
|
||||
$main::CLOBBER_PROJECTS = $save_clobber_flag;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Make resource aliases for one directory
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub BuildFolderResourceAliases($$)
|
||||
{
|
||||
my($src_dir, $dest_dir) = @_;
|
||||
|
||||
# get a list of all the resource files
|
||||
opendir(SRCDIR, $src_dir) || die("can't open $src_dir");
|
||||
my(@resource_files) = readdir(SRCDIR);
|
||||
closedir(SRCDIR);
|
||||
|
||||
# make aliases for each one into the dest directory
|
||||
print("Placing aliases to all files from $src_dir in $dest_dir\n");
|
||||
for ( @resource_files )
|
||||
{
|
||||
next if $_ eq "CVS";
|
||||
#print(" Doing $_\n");
|
||||
if (-l $src_dir.$_)
|
||||
{
|
||||
print(" $_ is an alias\n");
|
||||
next;
|
||||
}
|
||||
my($file_name) = $src_dir . $_;
|
||||
MakeAlias($file_name, $dest_dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// DelayFor
|
||||
#//
|
||||
#// Delay for the given number of seconds, allowing the script to be cancelled
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub DelayFor($)
|
||||
{
|
||||
my($delay_secs) = @_;
|
||||
|
||||
STDOUT->autoflush(1);
|
||||
|
||||
my($end_time) = time() + $delay_secs;
|
||||
|
||||
my($last_time) = 0;
|
||||
my($cur_time) = time();
|
||||
|
||||
while ($cur_time < $end_time)
|
||||
{
|
||||
$cur_time = time();
|
||||
if ($cur_time > $last_time)
|
||||
{
|
||||
print ".";
|
||||
$last_time = $cur_time;
|
||||
}
|
||||
|
||||
WaitNextEvent();
|
||||
}
|
||||
|
||||
print "\n";
|
||||
STDOUT->autoflush(0);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// TimeStart
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub TimeStart()
|
||||
{
|
||||
return time();
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// TimeEnd
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub TimeEnd($$)
|
||||
{
|
||||
use integer;
|
||||
|
||||
my($start_time, $operation_name) = @_;
|
||||
my($end_time) = time();
|
||||
|
||||
my($tot_sec) = $end_time - $start_time;
|
||||
|
||||
my($seconds) = $tot_sec;
|
||||
|
||||
my($hours) = $seconds / (60 * 60);
|
||||
$seconds -= $hours * (60 * 60);
|
||||
|
||||
my($minutes) = $seconds / 60;
|
||||
$seconds -= $minutes * 60;
|
||||
|
||||
print "$operation_name took $hours hours $minutes minutes and $seconds seconds\n";
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Remove all files from a tree, leaving directories intact (except "CVS").
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub EmptyTree($)
|
||||
{
|
||||
my ($root) = @_;
|
||||
#print "EmptyTree($root)\n";
|
||||
opendir(DIR, $root);
|
||||
my $sub;
|
||||
foreach $sub (readdir(DIR))
|
||||
{
|
||||
my $fullpathname = $root.$sub; # -f, -d only work on full paths
|
||||
|
||||
# Don't call empty tree for the alias of a directory.
|
||||
# -d returns true for the alias of a directory, false for a broken alias)
|
||||
|
||||
if (-d $fullpathname)
|
||||
{
|
||||
if (-l $fullpathname) # delete aliases
|
||||
{
|
||||
unlink $fullpathname;
|
||||
next;
|
||||
}
|
||||
EmptyTree($fullpathname.":");
|
||||
if ($sub eq "CVS")
|
||||
{
|
||||
#print "rmdir $fullpathname\n";
|
||||
rmdir $fullpathname;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unless (unlink $fullpathname) { die "Failed to delete $fullpathname\n"; }
|
||||
}
|
||||
}
|
||||
closedir(DIR);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Recurse through a directory hierarchy, looking for MANIFEST files.
|
||||
#// Currently unused.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub ScanForManifestFiles($$$$)
|
||||
{
|
||||
my($dir, $theme_root, $theme_name, $dist_dir) = @_;
|
||||
|
||||
opendir(DIR, $dir) or die "Cannot open dir $dir\n";
|
||||
my @files = readdir(DIR);
|
||||
closedir DIR;
|
||||
|
||||
my $file;
|
||||
|
||||
foreach $file (@files)
|
||||
{
|
||||
my $filepath = $dir.":".$file;
|
||||
|
||||
if (-d $filepath)
|
||||
{
|
||||
# print "Looking for MANIFEST files in $filepath\n";
|
||||
ScanForManifestFiles($filepath, $theme_root, $theme_name, $dist_dir);
|
||||
}
|
||||
elsif ($file eq "MANIFEST")
|
||||
{
|
||||
# print "Doing manifest file $filepath\n";
|
||||
|
||||
# Get the dest path from the first line of the file
|
||||
|
||||
open(MANIFEST, $filepath) || die "Could not open file $file";
|
||||
# Read in the path if available
|
||||
my($dest_line) = <MANIFEST>;
|
||||
chomp $dest_line;
|
||||
close MANIFEST;
|
||||
|
||||
$dest_line =~ s|^#!dest[\t ]+|| || die "No destination line found in $filepath\n";
|
||||
|
||||
my($dest_path) = $dist_dir."chrome:skins:$theme_name:$dest_line";
|
||||
# print " Destination is $dest_path\n";
|
||||
|
||||
InstallResources($filepath, "$dest_path", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-----------------------------------------------
|
||||
# SetupBuildLog
|
||||
#-----------------------------------------------
|
||||
sub SetupBuildLog($$)
|
||||
{
|
||||
my($logfile_path, $timestamped_log) = @_;
|
||||
|
||||
my($logdir) = "";
|
||||
my($logfile) = $logfile_path;
|
||||
|
||||
if ($logfile_path =~ /(.+?:)([^:]+)$/) # ? for non-greedy match
|
||||
{
|
||||
$logdir = $1;
|
||||
$logfile = $2;
|
||||
|
||||
mkpath($logdir);
|
||||
}
|
||||
|
||||
if ($timestamped_log)
|
||||
{
|
||||
#Use time-stamped names so that you don't clobber your previous log file!
|
||||
my $now = localtime();
|
||||
while ($now =~ s@:@.@) {} # replace all colons by periods
|
||||
OpenErrorLog("${logdir}${now}");
|
||||
}
|
||||
else
|
||||
{
|
||||
OpenErrorLog("${logdir}${logfile}");
|
||||
}
|
||||
}
|
||||
|
||||
#-----------------------------------------------
|
||||
# SetBuildNumber
|
||||
#-----------------------------------------------
|
||||
sub SetBuildNumber($$)
|
||||
{
|
||||
my($build_num_file, $files_to_touch) = @_;
|
||||
|
||||
# Make sure we add the config dir to search, to pick up mozBDate.pm
|
||||
# Need to do this dynamically, because this module can be used before
|
||||
# mozilla/config has been checked out.
|
||||
|
||||
my ($inc_path) = $0; # $0 is the path to the parent script
|
||||
$inc_path =~ s/:build:mac:build_scripts:.+$/:config/;
|
||||
push(@INC, $inc_path);
|
||||
|
||||
require mozBDate;
|
||||
|
||||
mozBDate::UpdateBuildNumber($build_num_file, $main::MOZILLA_OFFICIAL);
|
||||
|
||||
my($file);
|
||||
foreach $file (@$files_to_touch)
|
||||
{
|
||||
print "Writing build number to $file from ${file}.in\n";
|
||||
mozBDate::SubstituteBuildNumber($file, $build_num_file, "${file}.in");
|
||||
}
|
||||
}
|
||||
|
||||
#-----------------------------------------------
|
||||
# SetTimeBomb
|
||||
#-----------------------------------------------
|
||||
sub SetTimeBomb($$)
|
||||
{
|
||||
my ($warn_days, $bomb_days) = @_;
|
||||
|
||||
system("perl :mozilla:config:mac-set-timebomb.pl $warn_days $bomb_days");
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Regenerate a configuration header file if necessary
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub UpdateConfigHeader($)
|
||||
{
|
||||
my($config_path) = @_;
|
||||
|
||||
my($config, $oldconfig) = ("", "");
|
||||
my($define, $definevalue, $defines);
|
||||
my($k, $l,);
|
||||
|
||||
foreach $k (keys(%main::options))
|
||||
{
|
||||
if ($main::options{$k})
|
||||
{
|
||||
foreach $l (keys(%{$main::optiondefines{$k}}))
|
||||
{
|
||||
$my::defines{$l} = $main::optiondefines{$k}{$l};
|
||||
print "Setting up my::defines{$l}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $config_headerfile = current_directory().$config_path;
|
||||
if (-e $config_headerfile)
|
||||
{
|
||||
open(CONFIG_HEADER, "< $config_headerfile") || die "$config_headerfile: $!\n";
|
||||
my($line);
|
||||
while ($line = <CONFIG_HEADER>)
|
||||
{
|
||||
if ($line =~ m/#define\s+([^\s]*)\s+([^\s]*)\s*\n/)
|
||||
{
|
||||
$define = $1;
|
||||
$definevalue = $2;
|
||||
|
||||
#canonicalize so that whitespace changes are not significant
|
||||
my $canon_value = "#define " . $define . " " . $definevalue . "\n";
|
||||
$oldconfig .= $canon_value;
|
||||
|
||||
if (exists ($my::defines{$define}) and ($my::defines{$define} == $definevalue))
|
||||
{
|
||||
delete $my::defines{$define};
|
||||
$config .= $canon_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
close(CONFIG_HEADER);
|
||||
}
|
||||
|
||||
if (%my::defines)
|
||||
{
|
||||
foreach $k (keys(%my::defines))
|
||||
{
|
||||
$config .= "#define " . $k . " " . $my::defines{$k} . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
my $file_name = basename($config_headerfile);
|
||||
if (($config ne $oldconfig) || (!-e $config_headerfile))
|
||||
{
|
||||
printf("Writing new configuration header $file_name\n");
|
||||
open(CONFIG_HEADER, "> $config_headerfile") || die "$config_headerfile: $!\n";
|
||||
print(CONFIG_HEADER "/* This file is auto-generated based on build options. Do not edit. */\n");
|
||||
print CONFIG_HEADER ($config);
|
||||
close(CONFIG_HEADER);
|
||||
|
||||
MacPerl::SetFileInfo("CWIE", "TEXT", $config_headerfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Configuration header $file_name is up-to-date\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
@@ -1,660 +0,0 @@
|
||||
#!perl
|
||||
package Moz::CodeWarriorLib;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
CodeWarriorLib - supply interface to CodeWarrior
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
#!perl
|
||||
use CodeWarriorLib;
|
||||
CodeWarriorLib::activate();
|
||||
$had_errors = CodeWarriorLib::build_project(
|
||||
$project_path, $target_name, $recent_errors_file, $clean_build
|
||||
);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Replaces the AppleScript library I<CodeWarriorLib>.
|
||||
|
||||
=over 4
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
|
||||
use Cwd;
|
||||
use File::Basename;
|
||||
|
||||
use Mac::Types;
|
||||
use Mac::Events;
|
||||
use Mac::AppleEvents;
|
||||
use Mac::AppleEvents::Simple;
|
||||
use Mac::Processes;
|
||||
use Mac::MoreFiles;
|
||||
use Mac::StandardFile;
|
||||
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '1.02';
|
||||
|
||||
my($app) = 'CWIE';
|
||||
my($scriptDir) = cwd(); # could use $0 for this
|
||||
my($ide_loc_file) = "";
|
||||
|
||||
# 0 == don't switch CWIE to front app in do_event(), 1 == do switch
|
||||
# note: activate() still switches when called
|
||||
$Mac::AppleEvents::Simple::SWITCH = 0;
|
||||
# $Mac::AppleEvents::Simple::WARN = 1;
|
||||
|
||||
# supply your own path to the source here
|
||||
#_test('PowerPudgeIV:mozilla:mozilla:');
|
||||
|
||||
# If you want to understand the gobbldeygook that's used to build Apple Events,
|
||||
# you should start by reading the AEGizmos documentation.
|
||||
|
||||
=pod
|
||||
|
||||
=item _get_project($full_path)
|
||||
|
||||
A private routine returning a reference to the open project with the given name,
|
||||
or else the empty string (when that project is not open)
|
||||
|
||||
full_path is a string identifying the project to be built and is of the form,
|
||||
e.g., "HD:ProjectFolder:MyProject.mcp". It must be supplied.
|
||||
|
||||
=cut
|
||||
|
||||
sub _get_project ($) {
|
||||
my(
|
||||
$full_path, $candidate_projects
|
||||
) = @_;
|
||||
$candidate_projects = _doc_named(basename($full_path, '*'));
|
||||
if ($candidate_projects) {
|
||||
my($cps) = _get_dobj($candidate_projects);
|
||||
my($num) = AECountItems($cps);
|
||||
if ($num) { # is a list
|
||||
foreach (1 .. AECountItems($cps)) {
|
||||
my($cp) = AEGetNthDesc($cps, $_);
|
||||
if (lc $full_path eq lc _full_path($cp)) {
|
||||
return($cp);
|
||||
}
|
||||
}
|
||||
} else { # is only one, not a list
|
||||
if (lc $full_path eq lc _full_path($cps)) {
|
||||
return($cps);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=item build_project
|
||||
|
||||
Build a selected target of a project, saving any errors to a file, if supplied.
|
||||
|
||||
full_path is a string identifying the project to be built and is of the form,
|
||||
e.g., "HD:ProjectFolder:MyProject.mcp". It must be supplied.
|
||||
|
||||
If target_name is the empty string, the current target of the selected project
|
||||
will be built, else, target_name should be a string matching a target name in
|
||||
the selected project.
|
||||
|
||||
If error_path is the empty string, errors will not be saved to a file,
|
||||
else, error_path should be the full path of a file to save error messages into.
|
||||
|
||||
=cut
|
||||
|
||||
$CodeWarriorLib::CLOSE_PROJECTS_FIRST = 0; # If true we close then make. If false, make then close.
|
||||
my $last_project_built = "";
|
||||
my $last_project_was_closed = 0;
|
||||
|
||||
sub build_project ($;$$$) {
|
||||
my(
|
||||
$full_path, $target_name, $error_path,
|
||||
$remove_object, $p, $project_was_closed, $had_errors
|
||||
) = @_;
|
||||
_close_errors_window();
|
||||
|
||||
if ($CodeWarriorLib::CLOSE_PROJECTS_FIRST && ($last_project_built ne $full_path))
|
||||
{
|
||||
# If we're in "close first" mode, we don't close if the current project
|
||||
# is the same as the previous one.
|
||||
if ($last_project_was_closed) {
|
||||
$p = _get_project($last_project_built);
|
||||
_close($p);
|
||||
}
|
||||
$last_project_built = $full_path;
|
||||
$last_project_was_closed = 0; # now refers to the new project
|
||||
}
|
||||
$project_was_closed = 0;
|
||||
while (1) {
|
||||
$p = _get_project($full_path);
|
||||
if (!$p) {
|
||||
if ($project_was_closed) {
|
||||
print "### Error - request for project document failed after opening\n";
|
||||
die "### possibly CW Pro 4 bug: be sure to close your Find window\n";
|
||||
}
|
||||
$project_was_closed = 1;
|
||||
$last_project_was_closed = 1;
|
||||
_open_file($full_path);
|
||||
} else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
$had_errors = 0;
|
||||
if ($target_name eq '') {
|
||||
if ($remove_object) {_remove_object($p)}
|
||||
_build($p);
|
||||
} else {
|
||||
if ($remove_object) {_remove_object($p, $target_name)}
|
||||
_build($p, $target_name);
|
||||
}
|
||||
|
||||
if ($error_path ne '') {
|
||||
_save_errors_window($error_path);
|
||||
}
|
||||
$had_errors = _close_errors_window();
|
||||
|
||||
if (!$CodeWarriorLib::CLOSE_PROJECTS_FIRST)
|
||||
{
|
||||
if ($project_was_closed) {
|
||||
$p = _get_project($full_path);
|
||||
_close($p);
|
||||
}
|
||||
}
|
||||
|
||||
return($had_errors);
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=item appIsRunning()
|
||||
|
||||
=cut
|
||||
sub _appIsRunning($)
|
||||
{
|
||||
my ($appSignature) = @_;
|
||||
my ($psi);
|
||||
my ($found) = 0;
|
||||
my ($appPSN);
|
||||
|
||||
foreach $psi (values(%Process))
|
||||
{
|
||||
if ($psi->processSignature() eq $appSignature)
|
||||
{
|
||||
$appPSN = $psi->processNumber();
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=item appIsFrontmost()
|
||||
|
||||
=cut
|
||||
sub _appIsFrontmost($)
|
||||
{
|
||||
my ($appSignature) = @_;
|
||||
my ($psi);
|
||||
my ($found) = 0;
|
||||
my ($appPSN);
|
||||
|
||||
foreach $psi (values(%Process))
|
||||
{
|
||||
if ($psi->processSignature() eq $appSignature)
|
||||
{
|
||||
$appPSN = $psi->processNumber();
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return (GetFrontProcess() == $appPSN);
|
||||
}
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=item activate()
|
||||
|
||||
Launches CodeWarrior and brings it to the front.
|
||||
|
||||
Once found, path will be saved in $idepath_file for future reference.
|
||||
Edit or delete this file to change the location of the IDE. If app is
|
||||
moved, C<activate()> will prompt for a new location.
|
||||
|
||||
First looks for an open CodeWarrior app. Second, tries to open previously
|
||||
saved location in ':idepath.txt'. Third, tries to find it and allow user
|
||||
to choose it with Navigation Services (if present). Fourth, uses good old
|
||||
GUSI routines built-in to MacPerl for a Choose Directory dialog box.
|
||||
|
||||
=cut
|
||||
|
||||
sub activate ($) {
|
||||
|
||||
$ide_loc_file = $_[0]; # save in global
|
||||
|
||||
my($filepath, $appath, $psi) = ($ide_loc_file);
|
||||
|
||||
foreach $psi (values(%Process)) {
|
||||
if ($psi->processSignature() eq $app) {
|
||||
$appath = $psi->processAppSpec();
|
||||
_save_appath($filepath, $appath);
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$appath || !-x $appath) {
|
||||
$appath = _read_appath($filepath);
|
||||
}
|
||||
|
||||
if (!$appath || ! -x $appath)
|
||||
{
|
||||
# make sure that MacPerl is a front process
|
||||
#ActivateApplication('McPL');
|
||||
MacPerl::Answer("Please locate the CodeWarrior application.", "OK");
|
||||
|
||||
# prompt user for the file name, and store it
|
||||
my $macFile = StandardGetFile( 0, "APPL");
|
||||
if ( $macFile->sfGood() )
|
||||
{
|
||||
$appath = $macFile->sfFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Operation canceled\n";
|
||||
}
|
||||
|
||||
# if (eval {require Mac::Navigation}) {
|
||||
# my($options, $nav);
|
||||
# Mac::Navigation->import();
|
||||
# $options = NavGetDefaultDialogOptions();
|
||||
# $options->message('Where is CodeWarrior IDE?');
|
||||
# $options->windowTitle('Find CodeWarrior IDE');
|
||||
# $nav = NavChooseObject($Application{$app}, $options);
|
||||
# die "CodeWarrior IDE not found.\n" if (!$nav || !$nav->file(1));
|
||||
# $appath = $nav->file(1);
|
||||
# } else {
|
||||
# local(*D);
|
||||
# my $cwd = `pwd`;
|
||||
# $appath = _get_folder(
|
||||
# 'Where is the CW IDE folder?',
|
||||
# dirname($Application{$app})
|
||||
# );
|
||||
# die "CodeWarrior IDE not found.\n" if !$appath;
|
||||
# opendir(D, $appath) or die $!;
|
||||
# chdir($appath);
|
||||
# foreach my $file (sort readdir (D)) {
|
||||
# my(@app) = MacPerl::GetFileInfo($file);
|
||||
# if ($app[0] && $app[1] &&
|
||||
# $app[1] eq 'APPL' && $app[0] eq $app
|
||||
# ) {
|
||||
# $appath .= $file;
|
||||
# last;
|
||||
# }
|
||||
# }
|
||||
# chomp($cwd);
|
||||
# chdir($cwd);
|
||||
# }
|
||||
_save_appath($filepath, $appath);
|
||||
}
|
||||
|
||||
my($lp) = LaunchParam->new(
|
||||
launchAppSpec => $appath,
|
||||
launchControlFlags => launchContinue() + launchNoFileFlags()
|
||||
);
|
||||
|
||||
unless (LaunchApplication($lp)) {
|
||||
unlink($filepath);
|
||||
die $^E;
|
||||
}
|
||||
|
||||
# wait for CodeWarrior to show up in the list of processes
|
||||
while (!_appIsRunning('CWIE'))
|
||||
{
|
||||
WaitNextEvent();
|
||||
}
|
||||
|
||||
# wait for CodeWarrior to come to the front
|
||||
while (!_appIsFrontmost('CWIE'))
|
||||
{
|
||||
WaitNextEvent();
|
||||
}
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=item getCodeWarriorPath()
|
||||
|
||||
Returns a file path relative to the CodeWarrior folder
|
||||
|
||||
=cut
|
||||
|
||||
sub getCodeWarriorPath($)
|
||||
{
|
||||
my($subfolder)=@_;
|
||||
|
||||
my($app_path) = _read_appath($ide_loc_file);
|
||||
if ($app_path eq "") { die "Error: Failed to get CodeWarrior IDE path\n"; }
|
||||
|
||||
my($codewarrior_root) = $app_path;
|
||||
$codewarrior_root =~ s/[^:]*$//;
|
||||
return ($codewarrior_root . $subfolder);
|
||||
}
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=item getCodeWarriorIDEName()
|
||||
|
||||
Returns the name of the CodeWarrior application
|
||||
|
||||
=cut
|
||||
|
||||
sub getCodeWarriorIDEName()
|
||||
{
|
||||
my($subfolder)=@_;
|
||||
|
||||
my($app_path) = _read_appath($ide_loc_file);
|
||||
if ($app_path eq "") { die "Error: Failed to get CodeWarrior IDE path\n"; }
|
||||
|
||||
my(@codewarrior_path) = split(/:/, $app_path);
|
||||
return pop(@codewarrior_path);
|
||||
}
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=item quit()
|
||||
|
||||
Quits CodeWarrior.
|
||||
|
||||
=cut
|
||||
|
||||
sub quit() {
|
||||
|
||||
$last_project_built = "";
|
||||
$last_project_was_closed = 0;
|
||||
|
||||
my($evt) = do_event(qw/aevt quit/, $app);
|
||||
}
|
||||
|
||||
|
||||
sub _build ($;$) {
|
||||
my($evt);
|
||||
if ($_[1]) {
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(TRGT), seld:TEXT(@), from:" .
|
||||
AEPrint($_[0]) . '}';
|
||||
$evt = do_event(qw/CWIE MAKE/, $app, $prm, $_[1]);
|
||||
} else {
|
||||
my($prm) = q"'----':" . AEPrint($_[0]);
|
||||
$evt = do_event(qw/CWIE MAKE/, $app, $prm);
|
||||
}
|
||||
}
|
||||
|
||||
sub _remove_object ($;$) {
|
||||
my($evt);
|
||||
if ($_[1]) {
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(TRGT), seld:TEXT(@), from:" .
|
||||
AEPrint($_[0]) . '}';
|
||||
$evt = do_event(qw/CWIE RMOB/, $app, $prm, $_[1]);
|
||||
} else {
|
||||
my($prm) = q"'----':" . AEPrint($_[0]);
|
||||
$evt = do_event(qw/CWIE RMOB/, $app, $prm);
|
||||
}
|
||||
}
|
||||
|
||||
sub _open_file ($) {
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(alis), " .
|
||||
q"seld:TEXT(@), from:'null'()}";
|
||||
|
||||
do_event(qw/aevt odoc/, $app, $prm, $_[0]);
|
||||
}
|
||||
|
||||
sub import_project ($$) {
|
||||
my($xml_file, $project_path) = @_;
|
||||
|
||||
my($prm) = "kocl:type(PRJD), rtyp:TEXT(@), data:TEXT(@), &subj:'null'()";
|
||||
|
||||
my($evt) = do_event(qw/core crel/, $app, $prm, $project_path, $xml_file);
|
||||
my($result) = _get_event_result($evt);
|
||||
|
||||
if ($result eq "") {
|
||||
_close(_get_project($project_path));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub export_project ($$) {
|
||||
my($project_path, $xml_out_path) = @_;
|
||||
my($p, $project_was_closed);
|
||||
|
||||
$project_was_closed = 0;
|
||||
while (1) {
|
||||
$p = _get_project($project_path);
|
||||
if (!$p) {
|
||||
if ($project_was_closed) {
|
||||
print "### Error - request for project document failed after opening\n";
|
||||
die "### possibly CW bug: be sure to close your Find window\n";
|
||||
}
|
||||
$project_was_closed = 1;
|
||||
_open_file($project_path);
|
||||
} else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# avoid problems with the Project Messages window
|
||||
_close_named_window("Project Messages");
|
||||
|
||||
my($prm) =
|
||||
q"'----':obj {form:indx, want:type(PRJD), " .
|
||||
q"seld:1, from:'null'()}, kfil:TEXT(@)";
|
||||
|
||||
my($evt) = do_event(qw/CWIE EXPT/, $app, $prm, $xml_out_path);
|
||||
|
||||
if ($project_was_closed) {
|
||||
$p = _get_project($project_path);
|
||||
_close($p);
|
||||
}
|
||||
|
||||
return _get_event_result($evt);
|
||||
}
|
||||
|
||||
sub _doc_named ($) {
|
||||
my($prm) =
|
||||
q"'----':obj {form:test, want:type(docu), from:'null'(), " .
|
||||
q"seld:cmpd{relo:'= ', 'obj1':obj {form:prop, want:type" .
|
||||
q"(prop), seld:type(pnam), from:'exmn'()}, 'obj2':TEXT(@)}}";
|
||||
|
||||
my($evt) = do_event(qw/core getd/, $app, $prm, $_[0]);
|
||||
return($evt->{REPLY} eq 'aevt\ansr{}' ? undef : $evt);
|
||||
}
|
||||
|
||||
sub _full_path ($) {
|
||||
my($obj) = $_[0];
|
||||
my($prm) =
|
||||
q"'----':obj {form:prop, want:type(prop), seld:type(FILE), " .
|
||||
q"from:" . AEPrint($_[0]) . q"}, rtyp:type(TEXT)";
|
||||
my($evt) = do_event(qw/core getd/, $app, $prm);
|
||||
|
||||
return MacPerl::MakePath(
|
||||
MacUnpack('fss ', (
|
||||
AEGetParamDesc($evt->{REP}, keyDirectObject()))->data()->get()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
sub _save_errors_window ($) {
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(alis), seld:TEXT(@), from:'null'()}";
|
||||
do_event(qw/MMPR SvMs/, $app, $prm, $_[0]);
|
||||
}
|
||||
|
||||
|
||||
sub _close_errors_window () {
|
||||
return _close_named_window('Errors & Warnings');
|
||||
}
|
||||
|
||||
|
||||
sub _close_named_window ($) {
|
||||
my($window_name) = @_;
|
||||
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(cwin), " .
|
||||
q"seld:TEXT(@), from:'null'()}";
|
||||
|
||||
my($evt) = do_event(qw/core clos/, $app, $prm, $window_name);
|
||||
return($evt->{REPLY} eq 'aevt\ansr{}' ? 1 : 0);
|
||||
}
|
||||
|
||||
sub _close () {
|
||||
my($prm) = q"'----':" . AEPrint($_[0]);
|
||||
do_event(qw/core clos/, $app, $prm);
|
||||
}
|
||||
|
||||
sub _get_dobj ($) {
|
||||
return(AEGetParamDesc($_[0]->{REP}, keyDirectObject()));
|
||||
}
|
||||
|
||||
sub _get_folder ($$) {
|
||||
require 'GUSI.ph';
|
||||
my($prompt, $default) = @_;
|
||||
MacPerl::Choose(
|
||||
GUSI::AF_FILE(), 0, $prompt, '',
|
||||
GUSI::CHOOSE_DIR() + ($default ? &GUSI::CHOOSE_DEFAULT : 0),
|
||||
$default
|
||||
);
|
||||
}
|
||||
|
||||
sub _get_event_result ($)
|
||||
{
|
||||
my($evt) = @_;
|
||||
|
||||
my($result) = $evt->{ERROR};
|
||||
|
||||
if ( $result eq "" && $evt->{ERRNO} != 0 )
|
||||
{
|
||||
$result = "unknown error (".$evt->{ERRNO}.")";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
sub _save_appath ($$) {
|
||||
|
||||
my($cwd) = cwd(); # remember the current working dir
|
||||
chdir($scriptDir); # change dir to the script dir
|
||||
|
||||
local(*F);
|
||||
open(F, '>' . $_[0]) or die $!;
|
||||
print F $_[1];
|
||||
close(F);
|
||||
|
||||
chdir($cwd); # restore the cwd
|
||||
}
|
||||
|
||||
sub _read_appath ($) {
|
||||
|
||||
my($filepath) = @_;
|
||||
|
||||
my($cwd) = cwd(); # remember the current working dir
|
||||
chdir($scriptDir); # change dir to the script dir
|
||||
|
||||
if (! -e $filepath) {
|
||||
return "";
|
||||
}
|
||||
|
||||
local(*F);
|
||||
open(F, $filepath);
|
||||
my($appath) = <F>;
|
||||
close(F);
|
||||
|
||||
chdir($cwd); # restore the cwd
|
||||
return($appath);
|
||||
}
|
||||
|
||||
|
||||
sub _test ($) {
|
||||
activate($ide_loc_file);
|
||||
my($path) = $_[0];
|
||||
build_project(
|
||||
"${path}modules:xml:macbuild:XML.mcp", '',
|
||||
"${path}build:mac:Mozilla.BuildLog.part"
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=back
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
=over 4
|
||||
|
||||
=item v1.02, September 23, 1998
|
||||
|
||||
Made fixes in finding and saving location of CodeWarrior IDE.
|
||||
|
||||
=item v1.01, June 1, 1998
|
||||
|
||||
Made fixes to C<chdir()> in C<activate()>, made C<activate()> more robust
|
||||
in finding CodeWarrior IDE, added global variable to NOT switch to IDE
|
||||
for each sent event, a few other fixes.
|
||||
|
||||
=item v1.00, May 30, 1998
|
||||
|
||||
First shot
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Chris Nandor F<E<lt>pudge@pobox.comE<gt>>, and the author of the
|
||||
original I<CodeWarriorLib>, Scott Collins F<E<lt>scc@netscape.comE<gt>>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
BuildProject L<Moz>.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The contents of this file are subject to the Netscape Public
|
||||
License Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License. You may obtain a copy of
|
||||
the License at http://www.mozilla.org/NPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS
|
||||
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
rights and limitations under the License.
|
||||
|
||||
The Original Code is Mozilla Communicator client code, released
|
||||
March 31, 1998.
|
||||
|
||||
The Initial Developer of the Original Code is Netscape
|
||||
Communications Corporation. Portions created by Netscape are
|
||||
Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
=cut
|
||||
@@ -1,576 +0,0 @@
|
||||
#!perl -w
|
||||
package Moz::Jar;
|
||||
|
||||
#
|
||||
# Module for creating jar files, either using a jar manifest, or
|
||||
# simply jarring up folders on disk.
|
||||
#
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
use strict;
|
||||
use Archive::Zip;
|
||||
use File::Path;
|
||||
|
||||
use Mac::Files;
|
||||
|
||||
use Moz::Moz;
|
||||
|
||||
use vars qw( @ISA @EXPORT );
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(
|
||||
CreateJarFileFromDirectory
|
||||
CreateJarFromManifest
|
||||
WriteOutJarFiles
|
||||
SanityCheckJarOptions
|
||||
);
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Add the contents of a directory to the zip file
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
sub _addDirToJar($$$$)
|
||||
{
|
||||
my($dir, $jar_root, $zip, $compress) = @_;
|
||||
|
||||
opendir(DIR, $dir) or die "Error: Cannot open dir $dir\n";
|
||||
my @files = readdir(DIR);
|
||||
closedir DIR;
|
||||
|
||||
my $unix_jar_root = $jar_root;
|
||||
$unix_jar_root =~ s|:|/|g; # colon to slash conversion
|
||||
|
||||
my $file;
|
||||
|
||||
foreach $file (@files)
|
||||
{
|
||||
my $filepath = $dir.":".$file;
|
||||
|
||||
if (-d $filepath)
|
||||
{
|
||||
print "Adding files to jar from $filepath\n";
|
||||
_addDirToJar($filepath, $jar_root, $zip, $compress);
|
||||
}
|
||||
else
|
||||
{
|
||||
my $member = Archive::Zip::Member->newFromFile($filepath);
|
||||
die "Error: Failed to create zip file member $filepath\n" unless $member;
|
||||
|
||||
my $unixName = $filepath;
|
||||
$unixName =~ s|:|/|g; # colon to slash conversion
|
||||
$unixName =~ s|^$unix_jar_root||; # relativise
|
||||
|
||||
$member->fileName($unixName);
|
||||
|
||||
# print "Adding $file as $unixName\n";
|
||||
|
||||
if ($compress) {
|
||||
$member->desiredCompressionMethod(Archive::Zip::COMPRESSION_DEFLATED);
|
||||
} else {
|
||||
$member->desiredCompressionMethod(Archive::Zip::COMPRESSION_STORED);
|
||||
}
|
||||
|
||||
$zip->addMember($member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Add the contents of a directory to the zip file
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub CreateJarFileFromDirectory($$$)
|
||||
{
|
||||
my($srcdir, $jarpath, $compress) = @_;
|
||||
|
||||
my $zip = Archive::Zip->new();
|
||||
|
||||
_addDirToJar($srcdir, $srcdir, $zip, $compress);
|
||||
|
||||
print "Saving zip file...\n";
|
||||
my $status = $zip->writeToFileNamed($jarpath);
|
||||
if ($status == 0) {
|
||||
print "Zipping completed successfully\n";
|
||||
} else {
|
||||
print "Error saving zip file\n";
|
||||
}
|
||||
|
||||
# set the file type/creator to something reasonable
|
||||
MacPerl::SetFileInfo("ZIP ", "ZIP ", $jarpath);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# printZipContents
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
sub printZipContents($)
|
||||
{
|
||||
my($zip) = @_;
|
||||
|
||||
my(@members) = $zip->memberNames();
|
||||
|
||||
print "Zip contains:\n";
|
||||
|
||||
my($member);
|
||||
foreach $member (@members)
|
||||
{
|
||||
print " $member\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# safeSaveJarFile
|
||||
#
|
||||
# Archive::Zip has a problem where you cannot save a zip file on top of
|
||||
# an existing zip file that it has open, because it holds references
|
||||
# into that zip. So we have to save to a temp file, then do a swap.
|
||||
#
|
||||
# Note that the zip will become invalid after this operation.
|
||||
# If you want to do further operations on it, you'll have to reread it.
|
||||
#-------------------------------------------------------------------------------
|
||||
sub safeSaveJarFile($$)
|
||||
{
|
||||
my($zip, $full_dest_path) = @_;
|
||||
|
||||
my($temp_file_name) = $full_dest_path."_temp";
|
||||
|
||||
($zip->writeToFileNamed($temp_file_name) == Archive::Zip::AZ_OK) || die "Error: died writing jar to temp file $temp_file_name\n";
|
||||
|
||||
unlink $full_dest_path;
|
||||
|
||||
(rename $temp_file_name, $full_dest_path) || die "Error: Failed to rename $temp_file_name\n";
|
||||
|
||||
MacPerl::SetFileInfo("ZIP ", "ZIP ", $full_dest_path);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# addToJarFile
|
||||
#
|
||||
# Add a file to a jar file
|
||||
#
|
||||
# Parameters:
|
||||
# 1. Jar ID. Unix path of jar file inside chrome.
|
||||
# 2. Abs path to jar.mn file (i.e. source) (mac breaks)
|
||||
# 3. File source, relative to jar.mn path (mac breaks)
|
||||
# 4. Abs path to the resulting .jar file (mac breaks)
|
||||
# 5. Relative file path within the jar (unix breaks)
|
||||
# 6. Reference to hash of jar files
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub addToJarFile($$$$$$$)
|
||||
{
|
||||
my($jar_id, $jar_man_dir, $file_src, $jar_path, $file_jar_path, $override, $jars) = @_;
|
||||
|
||||
# print "addToJarFile with:\n $jar_man_dir\n $file_src\n $jar_path\n $file_jar_path\n";
|
||||
|
||||
unless ($jar_path =~ m/(.+:)([^:]+)$/) { die "Error: Bad jar path $jar_path\n"; }
|
||||
|
||||
my($target_dir) = $1;
|
||||
my($jar_name) = $2;
|
||||
|
||||
$target_dir =~ s/[^:]+$//;
|
||||
|
||||
# print "¥ $target_dir $jar_name\n";
|
||||
|
||||
# find the source file
|
||||
my($src) = $jar_man_dir.":".$file_src;
|
||||
if ((!-e $src) && ($file_src =~ m/.+:([^:]+)$/)) # src does not exist. Fall back to looking for src in jar.mn dir
|
||||
{
|
||||
$file_src = $1;
|
||||
$src = $jar_man_dir.":".$file_src;
|
||||
|
||||
if (!-e $src) {
|
||||
die "Error: Can't find chrome file $src\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($main::options{chrome_jars})
|
||||
{
|
||||
my($zip) = $jars->{$jar_id};
|
||||
unless ($zip) { die "Error: Can't find Zip entry for $jar_id\n"; }
|
||||
|
||||
# print "Adding $file_src to jar file $jar_path at $file_jar_path\n";
|
||||
my($member) = Archive::Zip::Member->newFromFile($src);
|
||||
unless ($member) { die "Error: Failed to create zip file member $src\n"; }
|
||||
|
||||
$member->fileName($file_jar_path);
|
||||
|
||||
my($compress) = 1;
|
||||
if ($compress) {
|
||||
$member->desiredCompressionMethod(Archive::Zip::COMPRESSION_DEFLATED);
|
||||
$member->desiredCompressionLevel(Archive::Zip::COMPRESSION_LEVEL_DEFAULT); # defaults to 6
|
||||
} else {
|
||||
$member->desiredCompressionMethod(Archive::Zip::COMPRESSION_STORED);
|
||||
}
|
||||
|
||||
my($old_member) = $zip->memberNamed($file_jar_path);
|
||||
|
||||
if ($override)
|
||||
{
|
||||
if ($old_member)
|
||||
{
|
||||
# print "Overriding $file_jar_path in jar file $jar_id\n";
|
||||
# need to compare mod dates or use the + here
|
||||
$zip->removeMember($old_member);
|
||||
}
|
||||
|
||||
$zip->addMember($member);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($old_member)
|
||||
{
|
||||
#compare dates here
|
||||
my($member_moddate) = $old_member->lastModTime();
|
||||
my($file_moddate) = GetFileModDate($src);
|
||||
|
||||
if ($file_moddate > $member_moddate)
|
||||
{
|
||||
print "Updating older file $file_jar_path in $jar_id\n";
|
||||
$zip->removeMember($old_member);
|
||||
$zip->addMember($member);
|
||||
}
|
||||
else
|
||||
{
|
||||
print "File $file_jar_path in $jar_id is more recent. Not updating.\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$zip->addMember($member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($main::options{chrome_files}) # we install raw files too
|
||||
{
|
||||
my($rel_path) = $file_jar_path;
|
||||
$rel_path =~ s|/|:|g; # slash to colons
|
||||
|
||||
my($dir_name) = $jar_name;
|
||||
$dir_name =~ s/\.jar$//;
|
||||
|
||||
my($dst) = $target_dir.$dir_name.":".$rel_path;
|
||||
|
||||
# print "Aliassing $src\n to\n$dst\n";
|
||||
if ($override)
|
||||
{
|
||||
unlink $dst;
|
||||
MakeAlias($src, $dst); # don't check errors, otherwise we fail on replacement
|
||||
}
|
||||
else
|
||||
{
|
||||
if (-e $dst)
|
||||
{
|
||||
#compare dates here
|
||||
my($dst_moddate) = GetFileModDate($dst);
|
||||
my($file_moddate) = GetFileModDate($src);
|
||||
|
||||
if ($file_moddate > $dst_moddate)
|
||||
{
|
||||
print "Updating older file $rel_path in $dir_name\n";
|
||||
unlink $dst;
|
||||
MakeAlias($src, $dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
print "File $file_jar_path in $jar_id is more recent. Not updating.\n";
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeAlias($src, $dst);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# setupJarFile
|
||||
#
|
||||
# setup a zip for writing
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub setupJarFile($$$)
|
||||
{
|
||||
my($jar_id, $dest_path, $jar_hash) = @_;
|
||||
|
||||
# print "Creating jar file $jar_id at $jar_path\n";
|
||||
|
||||
my($jar_file) = $jar_id;
|
||||
$jar_file =~ s|/|:|g; # slash to colons
|
||||
my($full_jar_path) = full_path_to($dest_path.":".$jar_file);
|
||||
|
||||
if ($main::options{chrome_jars})
|
||||
{
|
||||
my($zip) = $jar_hash->{$jar_id};
|
||||
if (!$zip) # if we haven't made it already, do so
|
||||
{
|
||||
my($zip) = Archive::Zip->new();
|
||||
$jar_hash->{$jar_id} = $zip;
|
||||
|
||||
# does the jar file exist already? If so, read it in
|
||||
if (-e $full_jar_path)
|
||||
{
|
||||
print "Reading in jar file $jar_id\n";
|
||||
if ($zip->read($full_jar_path) != Archive::Zip::AZ_OK) { die "Error: Failed to re-read $full_jar_path\n"; }
|
||||
|
||||
# printZipContents($zip);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
# installing files.
|
||||
# nothing to do. MakeAlias creates dirs as needed.
|
||||
|
||||
# add this jar to the list
|
||||
$jar_hash->{$jar_id} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# closeJarFile
|
||||
#
|
||||
# We're done with this jar file _for this jar.mn_. We may add more entries
|
||||
# to it later, so keep it open in the hash.
|
||||
#-------------------------------------------------------------------------------
|
||||
sub closeJarFile($$)
|
||||
{
|
||||
my($jar_path, $jar_hash) = @_;
|
||||
|
||||
# print "Closing jar file $jar_path\n";
|
||||
|
||||
if ($main::options{chrome_jars})
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
# installing files.
|
||||
# nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# WriteOutJarFiles
|
||||
#
|
||||
# Now we dump out the jars
|
||||
#-------------------------------------------------------------------------------
|
||||
sub WriteOutJarFiles($$)
|
||||
{
|
||||
my($chrome_dir, $jars) = @_;
|
||||
|
||||
unless ($main::options{chrome_jars}) { return; }
|
||||
|
||||
my($full_chrome_path) = full_path_to($chrome_dir);
|
||||
|
||||
my($key);
|
||||
foreach $key (keys %$jars)
|
||||
{
|
||||
my($zip) = $jars->{$key};
|
||||
|
||||
my($rel_path) = $key;
|
||||
$rel_path =~ s/\//:/g;
|
||||
|
||||
my($output_path) = $full_chrome_path.":".$rel_path;
|
||||
|
||||
print "Writing zip file $key to $output_path\n";
|
||||
|
||||
# ensure the target dirs exist
|
||||
my($path) = $output_path;
|
||||
$path =~ s/[^:]+$//;
|
||||
mkpath($path);
|
||||
|
||||
# unlink $output_path; # remove any existing jar
|
||||
safeSaveJarFile($zip, $output_path);
|
||||
# $zip is invalid after this operation, so nuke it here
|
||||
$jars->{$key} = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# registerChromePackage
|
||||
#
|
||||
# Enter a chrome package into the installed-chrome.txt file
|
||||
#-------------------------------------------------------------------------------
|
||||
sub registerChromePackage($$$$$$)
|
||||
{
|
||||
my($jar_file, $file_path, $chrome_dir, $jar_hash, $chrome_type, $pkg_name) = @_;
|
||||
|
||||
my($manifest_subdir) = $jar_file;
|
||||
$manifest_subdir =~ s/:/\//g;
|
||||
|
||||
if (index($manifest_subdir, "-unix") == -1 && index($manifest_subdir, "-win") == -1) {
|
||||
|
||||
my($chrome_entry);
|
||||
|
||||
if ($main::options{use_jars}) {
|
||||
$chrome_entry = "$chrome_type,install,url,jar:resource:/chrome/$manifest_subdir!/$chrome_type/$pkg_name";
|
||||
} else {
|
||||
$manifest_subdir =~ s/\.jar$//;
|
||||
$chrome_entry = "$chrome_type,install,url,resource:/chrome/$manifest_subdir/$chrome_type/$pkg_name";
|
||||
}
|
||||
|
||||
# print "Entering $chrome_entry in installed-chrome.txt\n";
|
||||
|
||||
# ensure chrome_dir exists
|
||||
mkpath($chrome_dir);
|
||||
|
||||
my($inst_chrome) = ${chrome_dir}.":installed-chrome.txt";
|
||||
|
||||
if (open(CHROMEFILE, "<$inst_chrome")) {
|
||||
while (<CHROMEFILE>) {
|
||||
chomp;
|
||||
if ($_ eq $chrome_entry) {
|
||||
# $chrome_entry already appears in installed-chrome.txt file
|
||||
# just update the mod date
|
||||
my $now = time;
|
||||
utime($now, $now, $inst_chrome) || die "Error: Couldn't touch $inst_chrome";
|
||||
print "+++ updating chrome $inst_chrome\n+++\t\t$chrome_entry\n";
|
||||
close(CHROMEFILE) || die "Error: can't close $inst_chrome: $!";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
close(CHROMEFILE) || die "Error: can't close $inst_chrome: $!";
|
||||
}
|
||||
open(CHROMEFILE, ">>${inst_chrome}") || die "Error: Failed to open $inst_chrome\n";
|
||||
print(CHROMEFILE "${chrome_entry}\n");
|
||||
close(CHROMEFILE) || die "Error: Failed to close $inst_chrome\n";
|
||||
print "+++ adding chrome $inst_chrome\n+++\t\t$chrome_entry\n";
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Create or add to a jar file from a jar.mn file.
|
||||
# Both arguments are relative to the mozilla root dir.
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
sub CreateJarFromManifest($$$)
|
||||
{
|
||||
my($jar_man_path, $dest_path, $jars) = @_;
|
||||
|
||||
if ($main::options{chrome_jars}) {
|
||||
print "Jarring from $jar_man_path\n";
|
||||
}
|
||||
if ($main::options{chrome_files}) {
|
||||
print "Installing files from $jar_man_path\n";
|
||||
}
|
||||
|
||||
$jar_man_path = full_path_to($jar_man_path);
|
||||
$dest_path = full_path_to($dest_path);
|
||||
|
||||
# if the jars hash is empty, nuke installed-chrome.txt
|
||||
if (! scalar(%$jars))
|
||||
{
|
||||
print "Nuking installed-chrome.txt\n";
|
||||
my($installed_chrome) = $dest_path.":installed-chrome.txt";
|
||||
# unlink $installed_chrome;
|
||||
}
|
||||
|
||||
my $jar_man_dir = "";
|
||||
my $jar_man_file = "";
|
||||
|
||||
if ($jar_man_path =~ /(.+):([^:]+)$/)
|
||||
{
|
||||
$jar_man_dir = $1; # no trailing :
|
||||
$jar_man_file = $2;
|
||||
}
|
||||
|
||||
# Keep a hash of jar files, keyed on relative jar path (e.g. "packages/core.jar")
|
||||
# Entries are open Archive::Zips (if zipping), and installed-chrome entries.
|
||||
|
||||
my($jar_id) = ""; # Current foo/bar.jar from jar.mn file
|
||||
my($jar_file) = ""; # relative path to jar file (from $dest_path), with mac separators
|
||||
my($full_jar_path);
|
||||
|
||||
open(FILE, "<$jar_man_path") || die "Error: could not open \"$jar_man_path\": $!";
|
||||
while (<FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
|
||||
# print "$line\n";
|
||||
|
||||
if ($line =~ /^\s*\#.*$/) { # skip comments
|
||||
next;
|
||||
}
|
||||
|
||||
if ($line =~/^([\w\d.\-\_\\\/]+)\:\s*$/) # line start jar file entries
|
||||
{
|
||||
$jar_id = $1;
|
||||
$jar_file = $jar_id;
|
||||
$jar_file =~ s|/|:|g; # slash to colons
|
||||
$full_jar_path = $dest_path.":".$jar_file;
|
||||
|
||||
setupJarFile($jar_id, $dest_path, $jars);
|
||||
|
||||
}
|
||||
elsif ($line =~ /^(\+?)\s+([\w\d.\-\_\\\/]+)\s*(\([\w\d.\-\_\\\/]+\))?$\s*/) # jar file entry
|
||||
{
|
||||
my($override) = ($1 eq "+");
|
||||
my($file_dest) = $2;
|
||||
my($file_src) = $3;
|
||||
|
||||
if ($file_src) {
|
||||
$file_src = substr($file_src, 1, -1); #strip the ()
|
||||
} else {
|
||||
$file_src = $file_dest;
|
||||
}
|
||||
|
||||
$file_src =~ s|/|:|g;
|
||||
|
||||
if ($jar_file ne "") # if jar is open, add to jar
|
||||
{
|
||||
if ($file_dest =~ /([\w\d.\-\_]+)\/([\w\d.\-\_\\\/]+)contents.rdf/)
|
||||
{
|
||||
my $chrome_type = $1;
|
||||
my $pkg_name = $2;
|
||||
registerChromePackage($jar_file, $file_dest, $dest_path, $jars, $chrome_type, $pkg_name);
|
||||
}
|
||||
|
||||
addToJarFile($jar_id, $jar_man_dir, $file_src, $full_jar_path, $file_dest, $override, $jars);
|
||||
}
|
||||
else
|
||||
{
|
||||
die "Error: bad jar.mn format at $line\n";
|
||||
}
|
||||
}
|
||||
elsif ($line =~ /^\s*$/ ) # blank line
|
||||
{
|
||||
if ($jar_file ne "") #if a jar file is open, close it
|
||||
{
|
||||
closeJarFile($full_jar_path, $jars);
|
||||
|
||||
$jar_file = "";
|
||||
$full_jar_path = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(FILE);
|
||||
|
||||
if ($jar_file ne "") #if a jar file is open, close it
|
||||
{
|
||||
closeJarFile($full_jar_path, $jars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -1,228 +0,0 @@
|
||||
#!perl -w
|
||||
package Moz::MacCVS;
|
||||
|
||||
# package Mac::Apps::MacCVS; this should really be the name of the package
|
||||
# but due to our directory hierarchy in mozilla, I am not doing it
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
use strict;
|
||||
use Exporter;
|
||||
|
||||
use vars qw($VERSION @ISA @EXPORT);
|
||||
|
||||
use Cwd;
|
||||
|
||||
use File::Basename;
|
||||
|
||||
use Mac::StandardFile;
|
||||
use Mac::AppleEvents;
|
||||
use Mac::AppleEvents::Simple;
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(new describe checkout update);
|
||||
$VERSION = "1.00";
|
||||
|
||||
# If you want to understand the gobbldeygook that's used to build Apple Events,
|
||||
# you should start by reading the AEGizmos documentation.
|
||||
|
||||
|
||||
# Architecture:
|
||||
# cvs session object:
|
||||
# name - session name
|
||||
# session_file - session file
|
||||
#
|
||||
#
|
||||
|
||||
my($last_error) = 0;
|
||||
my($gAppSig) = 'Mcvs'; # MacCVS Pro
|
||||
|
||||
#
|
||||
# utility routines
|
||||
#
|
||||
|
||||
|
||||
sub _checkForEventError($)
|
||||
{
|
||||
my($evt) = @_;
|
||||
|
||||
if ($evt->{ERRNO} != 0)
|
||||
{
|
||||
print STDERR "Error. Script returned '$evt->{ERROR} (error $evt->{ERRNO})\n";
|
||||
$last_error = $evt->{ERRNO};
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1; # success
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Session object methods
|
||||
#
|
||||
|
||||
sub new
|
||||
{
|
||||
my ( $proto, $session_file) = @_;
|
||||
my $class = ref($proto) || $proto;
|
||||
my $self = {};
|
||||
|
||||
if ( defined($session_file) && ( -e $session_file) )
|
||||
{
|
||||
$self->{"name"} = basename( $session_file );
|
||||
$self->{"session_file"} = $session_file;
|
||||
bless $self, $class;
|
||||
return $self;
|
||||
}
|
||||
else
|
||||
{
|
||||
print STDERR "MacCVS->new cvs file < $session_file > does not exist\n";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
# makes sure that the session is open
|
||||
# assertSessionOpen()
|
||||
# returns 1 on success
|
||||
sub assertSessionOpen()
|
||||
{
|
||||
my ($self) = shift;
|
||||
|
||||
$last_error = 0;
|
||||
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(alis), seld:TEXT(@), from:'null'()}";
|
||||
|
||||
my($evt) = do_event(qw/aevt odoc/, $gAppSig, $prm, $self->{session_file});
|
||||
return _checkForEventError($evt);
|
||||
}
|
||||
|
||||
# prints the cvs object, used mostly for debugging
|
||||
sub describe
|
||||
{
|
||||
my($self) = shift;
|
||||
$last_error = 0;
|
||||
print "MacCVS:: name: ", $self->{name}, " session file: ", $self->{session_file}, "\n";
|
||||
}
|
||||
|
||||
# checkout( self, module, revision, date)
|
||||
# MacCVS checkout command
|
||||
# returns 1 on success.
|
||||
sub checkout()
|
||||
{
|
||||
my($self, $module, $revision, $date ) = @_;
|
||||
unless( defined ($module) ) { $module = ""; } # get rid of the pesky undefined warnings
|
||||
unless( defined ($revision) ) { $revision = ""; }
|
||||
unless( defined ($date) ) { $date = ""; }
|
||||
|
||||
$last_error = 0;
|
||||
|
||||
$self->assertSessionOpen() || die "Error: failed to open MacCVS session file at $self->{session_file}\n";
|
||||
|
||||
my($revstring) = ($revision ne "") ? $revision : "(none)";
|
||||
my($datestring) = ($date ne "") ? $date : "(none)";
|
||||
|
||||
print "Checking out $module with revision $revstring, date $datestring\n";
|
||||
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(docu), seld:TEXT(@), from:'null'()}, ".
|
||||
q"modl:'TEXT'(@), tagr:'TEXT'(@), tagd:'TEXT'(@) ";
|
||||
|
||||
my($evt) = do_event(qw/MCvs cout/, $gAppSig, $prm, $self->{name}, $module, $revision, $date);
|
||||
return _checkForEventError($evt);
|
||||
}
|
||||
|
||||
|
||||
# update( self, branch tag, list of paths)
|
||||
# MacCVS udate command
|
||||
# returns 1 on success.
|
||||
# NOTE: MacCVS Pro does not correctly support this stuff yet (as of version 2.7d5).
|
||||
sub update()
|
||||
{
|
||||
my($self, $branch, $paths ) = @_;
|
||||
|
||||
$last_error = 0;
|
||||
|
||||
$self->assertSessionOpen() || die "Error: failed to open MacCVS session file at $self->{session_file}\n";
|
||||
|
||||
if ($branch eq "HEAD") {
|
||||
$branch = "";
|
||||
}
|
||||
|
||||
my($paths_list) = "";
|
||||
|
||||
my($path);
|
||||
foreach $path (@$paths)
|
||||
{
|
||||
if ($paths_list ne "") {
|
||||
$paths_list = $paths_list.", ";
|
||||
}
|
||||
|
||||
$paths_list = $paths_list."Ò".$path."Ó";
|
||||
}
|
||||
|
||||
my($prm) =
|
||||
q"'----':obj {form:name, want:type(docu), seld:TEXT(@), from:'null'()}, ".
|
||||
q"tagr:'TEXT'(@), tFls:[";
|
||||
|
||||
$prm = $prm.$paths_list."]";
|
||||
|
||||
my($evt) = do_event(qw/MCvs updt/, $gAppSig, $prm, $self->{name}, $branch);
|
||||
return _checkForEventError($evt);
|
||||
};
|
||||
|
||||
|
||||
sub getLastError()
|
||||
{
|
||||
return $last_error;
|
||||
}
|
||||
|
||||
1;
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
MacCVS - Interface to MacCVS
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use MacCVS;
|
||||
$session = MacCVS->new( <session_file_path>) || die "cannot create session";
|
||||
$session->checkout([module] [revision] [date]) || die "Could not check out";
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a MacCVS interface for talking to MacCVS Pro client.
|
||||
MacCVSSession is the class used to manipulate the session
|
||||
|
||||
=item new
|
||||
MacCVS->new( <cvs session file path>);
|
||||
|
||||
Creates a new session. Returns undef on failure.
|
||||
|
||||
=item checkout( <module> [revision] [date] )
|
||||
|
||||
cvs checkout command. Revision and date are optional
|
||||
returns 0 on failure
|
||||
|
||||
=cut
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=over
|
||||
|
||||
=item MacCVS Home Page
|
||||
|
||||
http://www.maccvs.org/
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Aleks Totic atotic@netscape.com
|
||||
Simon Fraser sfraser@netscape.com
|
||||
|
||||
=cut
|
||||
|
||||
__END__
|
||||
@@ -1,603 +0,0 @@
|
||||
=head1 NAME
|
||||
|
||||
B<Moz> - routines for automating CodeWarrior builds, and some extra-curricular
|
||||
activities related to building Mozilla
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Moz;
|
||||
|
||||
OpenErrorLog(":::BuildLog");
|
||||
StopForErrors();
|
||||
|
||||
$Moz::QUIET = 1;
|
||||
InstallFromManifest(":projects:MANIFEST", $dist_dir);
|
||||
|
||||
BuildProjectClean(":projects:SomeProject.mcp", "SomeTarget");
|
||||
MakeAlias(":projects:SomeProject.shlb", $dist_dir);
|
||||
|
||||
DontStopForErrors();
|
||||
|
||||
BuildProject(":projects:SomeOtherProject.mcp", "SomeTarget");
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<Moz> comprises the routines needed to slap CodeWarrior around, force it
|
||||
to build a sequence of projects, report the results, and a few other things.
|
||||
This module should only contain functions that are generic to any build,
|
||||
not just the Mozilla build.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
package Moz::Moz;
|
||||
require Exporter;
|
||||
|
||||
use Cwd;
|
||||
|
||||
use File::Copy;
|
||||
use File::Path;
|
||||
use File::Basename;
|
||||
|
||||
use Mac::Types;
|
||||
use Mac::Events;
|
||||
use Mac::Processes;
|
||||
|
||||
use ExtUtils::Manifest 'maniread';
|
||||
|
||||
use Moz::CodeWarriorLib;
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
|
||||
@EXPORT = qw( LaunchCodeWarrior
|
||||
GetCodeWarriorRelativePath
|
||||
current_directory
|
||||
full_path_to
|
||||
DoBuildProject
|
||||
ImportXMLProject
|
||||
ExportProjectToXML
|
||||
OpenErrorLog
|
||||
MakeAlias
|
||||
GetFileModDate
|
||||
StopForErrors
|
||||
DontStopForErrors
|
||||
InstallFromManifest
|
||||
InstallResources
|
||||
RedirectOutputToFile
|
||||
Delay
|
||||
ActivateApplication
|
||||
IsProcessRunning);
|
||||
|
||||
@EXPORT_OK = qw(CloseErrorLog QUIET);
|
||||
|
||||
|
||||
sub current_directory()
|
||||
{
|
||||
my $current_directory = cwd();
|
||||
chop($current_directory) if ( $current_directory =~ m/:$/ );
|
||||
return $current_directory;
|
||||
}
|
||||
|
||||
sub full_path_to($)
|
||||
{
|
||||
my ($path) = @_;
|
||||
if ( $path =~ m/^[^:]+$/ )
|
||||
{
|
||||
$path = ":" . $path;
|
||||
}
|
||||
|
||||
if ( $path =~ m/^:/ )
|
||||
{
|
||||
$path = current_directory() . $path;
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
$logging = 0;
|
||||
$recent_errors_file = "";
|
||||
$stop_on_1st_error = 1;
|
||||
$QUIET = 0;
|
||||
|
||||
|
||||
|
||||
=head2 Logging all the errors and warnings - C<OpenErrorLog($log_file)>, C<CloseErrorLog()>
|
||||
|
||||
The warnings and errors generated in the course of building projects can be logged to a file.
|
||||
Tinderbox uses this facility to show why a remote build failed.
|
||||
|
||||
Logging is off by default.
|
||||
Start logging at any point in your build process with C<OpenErrorLog($log_file)>.
|
||||
Stop with C<CloseErrorLog()>.
|
||||
You never need to close the log explicitly, unless you want to just log a couple of projects in the middle of a big list.
|
||||
C<CloseErrorLog()> is not exported by default.
|
||||
|
||||
=cut
|
||||
|
||||
sub CloseErrorLog()
|
||||
{
|
||||
if ( $logging )
|
||||
{
|
||||
close(ERROR_LOG);
|
||||
$logging = 0;
|
||||
StopForErrors() if $stop_on_1st_error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub OpenErrorLog($)
|
||||
{
|
||||
my ($log_file) = @_;
|
||||
|
||||
CloseErrorLog();
|
||||
if ( $log_file )
|
||||
{
|
||||
$log_file = full_path_to($log_file);
|
||||
|
||||
open(ERROR_LOG, ">$log_file") || die "Error: Can't open $log_file\n";
|
||||
MacPerl::SetFileInfo("CWIE", "TEXT", $log_file);
|
||||
|
||||
$log_file =~ m/.+:(.+)/;
|
||||
$recent_errors_file = full_path_to("$1.part");
|
||||
$logging = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
=head2 Stopping before it's too late - C<StopForErrors()>, C<DontStopForErrors()>
|
||||
|
||||
When building a long list of projects, you decide whether to continue building subsequent projects when one fails.
|
||||
By default, your build script will C<die> after the first project that generates an error while building.
|
||||
Change this behavior with C<DontStopForErrors()>.
|
||||
Re-enable it with C<StopForErrors()>.
|
||||
|
||||
=cut
|
||||
|
||||
sub StopForErrors()
|
||||
{
|
||||
$stop_on_1st_error = 1;
|
||||
|
||||
# Can't stop for errors unless we notice them.
|
||||
# Can't notice them unless we are logging.
|
||||
# If the user didn't explicitly request logging, log to a temporary file.
|
||||
|
||||
if ( ! $recent_errors_file )
|
||||
{
|
||||
OpenErrorLog("${TMPDIR}BuildResults");
|
||||
}
|
||||
}
|
||||
|
||||
sub DontStopForErrors()
|
||||
{
|
||||
$stop_on_1st_error = 0;
|
||||
}
|
||||
|
||||
sub log_message($)
|
||||
{
|
||||
if ( $logging )
|
||||
{
|
||||
my ($message) = @_;
|
||||
print ERROR_LOG $message;
|
||||
}
|
||||
}
|
||||
|
||||
sub log_message_with_time($)
|
||||
{
|
||||
if ( $logging )
|
||||
{
|
||||
my ($message) = @_;
|
||||
my $time_stamp = localtime();
|
||||
log_message("$message ($time_stamp)\n");
|
||||
}
|
||||
}
|
||||
|
||||
sub log_recent_errors($)
|
||||
{
|
||||
my ($project_name) = @_;
|
||||
my $found_errors = 0;
|
||||
|
||||
if ( $logging )
|
||||
{
|
||||
open(RECENT_ERRORS, "<$recent_errors_file");
|
||||
|
||||
while( <RECENT_ERRORS> )
|
||||
{
|
||||
if ( /^Error/ || /^CouldnÕt find project file/ || /^Link Error/ )
|
||||
{
|
||||
# if (!$found_errors)
|
||||
# print $_;
|
||||
$found_errors = 1;
|
||||
}
|
||||
print ERROR_LOG $_;
|
||||
}
|
||||
|
||||
close(RECENT_ERRORS);
|
||||
unlink("$recent_errors_file");
|
||||
}
|
||||
|
||||
if ( $stop_on_1st_error && $found_errors )
|
||||
{
|
||||
print ERROR_LOG "### Build failed.\n";
|
||||
die "### Errors encountered building \"$project_name\".\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub DoBuildProject($$$)
|
||||
{
|
||||
my ($project_path, $target_name, $clean_build) = @_;
|
||||
$project_path = full_path_to($project_path);
|
||||
|
||||
# $project_path =~ m/.+:(.+)/;
|
||||
# my $project_name = $1;
|
||||
|
||||
log_message_with_time("### Building \"$project_path\"");
|
||||
|
||||
# Check that the given project exists
|
||||
if (! -e $project_path)
|
||||
{
|
||||
print ERROR_LOG "### Build failed.\n";
|
||||
die "### Can't find project file \"$project_path\".\n";
|
||||
}
|
||||
|
||||
print "Building \"$project_path\[$target_name\]\"\n";
|
||||
|
||||
$had_errors = Moz::CodeWarriorLib::build_project(
|
||||
$project_path, $target_name, $recent_errors_file, $clean_build
|
||||
);
|
||||
WaitNextEvent();
|
||||
|
||||
# $had_errors =
|
||||
#MacPerl::DoAppleScript(<<END_OF_APPLESCRIPT);
|
||||
# tell (load script file "$CodeWarriorLib") to BuildProject("$project_path", "$project_name", "$target_name", "$recent_errors_file", $clean_build)
|
||||
#END_OF_APPLESCRIPT
|
||||
|
||||
# Append any errors to the globally accumulated log file
|
||||
# if ( $had_errors ) # Removed this test, because we want warnings, too. -- jrm
|
||||
{
|
||||
log_recent_errors($project_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub ImportXMLProject($$)
|
||||
{
|
||||
my ($xml_path, $project_path) = @_;
|
||||
|
||||
# my ($codewarrior_ide_name) = Moz::CodeWarriorLib::getCodeWarriorIDEName();
|
||||
# my $ascript = <<EOS;
|
||||
# tell application "$codewarrior_ide_name"
|
||||
# make new (project document) as ("$project_path") with data ("$xml_path")
|
||||
# end tell
|
||||
#EOS
|
||||
# print $ascript."\n";
|
||||
# my($result) = MacPerl::DoAppleScript($ascript);
|
||||
# unless ($result) { die "Error: ImportXMLProject AppleScript failed $^E $result\n"; }
|
||||
#
|
||||
|
||||
my($import_error) = Moz::CodeWarriorLib::import_project($xml_path, $project_path);
|
||||
if ($import_error ne "") {
|
||||
die "Error: ImportXMLProject failed with error $import_error\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub ExportProjectToXML($$)
|
||||
{
|
||||
my ($project_path, $xml_path) = @_;
|
||||
|
||||
my (@suffix_list) = (".mcp");
|
||||
my ($project_name, $project_dir, $suffix) = fileparse($project_path, @suffix_list);
|
||||
if ($suffix eq "") { die "Project: $project_path doesn't look like a project file.\n"; }
|
||||
|
||||
if (-e $xml_path) {
|
||||
print "$xml_path exists - not exporting $project_path\n";
|
||||
}
|
||||
else {
|
||||
print "Exporting $project_path to $xml_path\n";
|
||||
my($export_error) = Moz::CodeWarriorLib::export_project($project_path, $xml_path);
|
||||
if ($export_error ne "") {
|
||||
die "Error: export_project failed with error '$export_error'\n";
|
||||
}
|
||||
|
||||
if (! -e $xml_path) {
|
||||
die "Error: XML export to $xml_path failed\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
=head2 Miscellaneous
|
||||
|
||||
C<MakeAlias($old_file, $new_file)> functions like C<symlink()>, except with better argument defaulting and more explicit error messages.
|
||||
|
||||
=cut
|
||||
|
||||
sub MakeAlias($$)
|
||||
{
|
||||
my ($old_file, $new_file) = @_;
|
||||
|
||||
# if the directory to hold $new_file doesn't exist, create it
|
||||
if ( ($new_file =~ m/(.+:)/) && !-d $1 )
|
||||
{
|
||||
mkpath($1);
|
||||
}
|
||||
|
||||
# if a leaf name wasn't specified for $new_file, use the leaf from $old_file
|
||||
if ( ($new_file =~ m/:$/) && ($old_file =~ m/.+:(.+)/) )
|
||||
{
|
||||
$new_file .= $1;
|
||||
}
|
||||
|
||||
my $message = "Can't create a Finder alias (at \"$new_file\")\n for \"$old_file\"; because ";
|
||||
|
||||
die "Error: $message \"$old_file\" doesn't exist.\n" unless -e $old_file;
|
||||
die "Error: $message I won't replace an existing (non-alias) file with an alias.\n" if ( -e $new_file && ! -l $new_file );
|
||||
|
||||
# now: $old_file exists; $new_file doesn't (or else, is an alias already)
|
||||
|
||||
if ( -l $new_file )
|
||||
{
|
||||
# ...then see if it already points to $old_file
|
||||
my $current_target = full_path_to(readlink($new_file));
|
||||
my $new_target = full_path_to($old_file);
|
||||
|
||||
return if ( $current_target eq $new_target );
|
||||
# if the desired alias already exists and points to the right thing, then we're done
|
||||
|
||||
unlink $new_file;
|
||||
}
|
||||
|
||||
symlink($old_file, $new_file) || die "Error: $message symlink returned an unexpected error.\n";
|
||||
}
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
C<InstallFromManifest()>
|
||||
|
||||
=cut
|
||||
|
||||
sub InstallFromManifest($;$$)
|
||||
{
|
||||
my ($manifest_file, $dest_dir, $flat) = @_;
|
||||
|
||||
$flat = 0 unless defined($flat); # if $flat, all rel. paths in MANIFEST get aliased to the root of $dest_dir
|
||||
|
||||
$dest_dir ||= ":";
|
||||
|
||||
$manifest_file =~ m/(.+):/;
|
||||
my $source_dir = $1;
|
||||
|
||||
chop($dest_dir) if $dest_dir =~ m/:$/;
|
||||
|
||||
#Mac::Events->import();
|
||||
WaitNextEvent();
|
||||
if ($flat)
|
||||
{
|
||||
print "Doing manifest on \"$manifest_file\" FLAT\n" unless $QUIET;
|
||||
}
|
||||
else
|
||||
{
|
||||
print "Doing manifest on \"$manifest_file\"\n" unless $QUIET;
|
||||
}
|
||||
|
||||
my $read = maniread(full_path_to($manifest_file));
|
||||
foreach $file (keys %$read)
|
||||
{
|
||||
next unless $file;
|
||||
|
||||
$subdir = ":";
|
||||
if (!$flat && ($file =~ /:.+:/ ))
|
||||
{
|
||||
$subdir = $&;
|
||||
}
|
||||
|
||||
$file = ":$file" unless $file =~ m/^:/;
|
||||
MakeAlias("$source_dir$file", "$dest_dir$subdir");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
C<InstallResources()>
|
||||
|
||||
=cut
|
||||
|
||||
# parameters are path to MANIFEST file, destination dir, true (to make copies) or false (to make aliases)
|
||||
sub InstallResources($;$;$)
|
||||
{
|
||||
my ($manifest_file, $dest_dir, $copy_files) = @_;
|
||||
|
||||
$dest_dir ||= ":";
|
||||
mkpath($dest_dir) if !-d $dest_dir;
|
||||
|
||||
$manifest_file =~ m/(.+):/;
|
||||
my $source_dir = $1;
|
||||
|
||||
chop($dest_dir) if $dest_dir =~ m/:$/;
|
||||
|
||||
WaitNextEvent();
|
||||
print "Installing resources from \"$manifest_file\"\n" unless $QUIET;
|
||||
|
||||
my $read = maniread(full_path_to($manifest_file));
|
||||
foreach $file (keys %$read)
|
||||
{
|
||||
next unless $file;
|
||||
|
||||
if ($copy_files)
|
||||
{
|
||||
copy("$source_dir:$file", "$dest_dir:$file");
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeAlias("$source_dir:$file", "$dest_dir:$file");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// Delay
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub Delay($)
|
||||
{
|
||||
my ($delay_seconds) = @_;
|
||||
|
||||
$now = time;
|
||||
|
||||
$exit_time = $now + $delay_seconds;
|
||||
|
||||
while ($exit_time > $now) {
|
||||
$now = time;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetFileModDate
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetFileModDate($)
|
||||
{
|
||||
my($filePath)=@_;
|
||||
my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
|
||||
$atime,$mtime,$ctime,$blksize,$blocks) = stat($filePath);
|
||||
return $mtime;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// LaunchCodeWarrior
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub LaunchCodeWarrior($)
|
||||
{
|
||||
my($idepath_file) = @_; # full path to IDE location file
|
||||
my($cur_dir) = cwd();
|
||||
|
||||
# this both launches and writes the IDE path file
|
||||
Moz::CodeWarriorLib::activate($idepath_file);
|
||||
|
||||
chdir($cur_dir);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetCodeWarriorRelativePath
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetCodeWarriorRelativePath($)
|
||||
{
|
||||
my($rel_path) = @_;
|
||||
return Moz::CodeWarriorLib::getCodeWarriorPath($rel_path);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// RedirectOutputToFile
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub RedirectOutputToFile($)
|
||||
{
|
||||
my($log_file) = @_;
|
||||
|
||||
# ensure that folders in the path exist
|
||||
my($logdir) = "";
|
||||
my($logfile) = $log_file;
|
||||
|
||||
if ($log_file =~ /(.+?:)([^:]+)$/) # ? for non-greedy match
|
||||
{
|
||||
$logdir = $1;
|
||||
$logfile = $2;
|
||||
|
||||
mkpath($logdir);
|
||||
}
|
||||
|
||||
print "Output is now being redirected to the file '$log_file'\n";
|
||||
|
||||
open(STDOUT, "> $log_file") || die "Can't redirect stdout";
|
||||
open(STDERR, ">&STDOUT") || die "Can't dup stdout";
|
||||
select(STDERR); $| = 1; # make unbuffered
|
||||
select(STDOUT); $| = 1; # make unbuffered
|
||||
|
||||
MacPerl::SetFileInfo("CWIE", "TEXT", $log_file);
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ActivateApplication
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub ActivateApplication($)
|
||||
{
|
||||
my ($appSignature) = @_;
|
||||
my ($psi, $found);
|
||||
my ($appPSN);
|
||||
|
||||
$found = 0;
|
||||
|
||||
foreach $psi (values(%Process))
|
||||
{
|
||||
if ($psi->processSignature() eq $appSignature)
|
||||
{
|
||||
$appPSN = $psi->processNumber();
|
||||
$found = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if ($found == 0 || SameProcess($appPSN, GetFrontProcess()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetFrontProcess($appPSN);
|
||||
|
||||
while (GetFrontProcess() != $appPSN)
|
||||
{
|
||||
WaitNextEvent();
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// IsProcessRunning
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub IsProcessRunning($)
|
||||
{
|
||||
my($processName, $psn, $psi) = @_;
|
||||
while ( ($psn, $psi) = each(%Process) ) {
|
||||
if ($psi->processName eq $processName) { return 1; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Scott Collins <scc@netscape.com>, Simon Fraser <sfraser@netscape.com>, Chris Yeh <cyeh@netscape.com>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
BuildMozillaDebug.pl (et al), BuildList.pm, CodeWarriorLib (an AppleScript library)
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
The contents of this file are subject to the Netscape Public
|
||||
License Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License. You may obtain a copy of
|
||||
the License at http://www.mozilla.org/NPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS
|
||||
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
rights and limitations under the License.
|
||||
|
||||
The Original Code is Mozilla Communicator client code, released
|
||||
March 31, 1998.
|
||||
|
||||
The Initial Developer of the Original Code is Netscape
|
||||
Communications Corporation. Portions created by Netscape are
|
||||
Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
=cut
|
||||
@@ -1,272 +0,0 @@
|
||||
|
||||
package Moz::Prefs;
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
# Package that attempts to read a file from the Preferences folder,
|
||||
# and get build settings out of it
|
||||
|
||||
use strict;
|
||||
|
||||
use Exporter;
|
||||
use File::Path;
|
||||
|
||||
use Mac::Files;
|
||||
|
||||
use vars qw(@ISA @EXPORT);
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(ReadMozUserPrefs);
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# GetPrefsFolder
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub GetPrefsFolder()
|
||||
{
|
||||
my($prefs_folder) = FindFolder(kOnSystemDisk, kPreferencesFolderType, 1);
|
||||
return $prefs_folder.":Mozilla build prefs";
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# SetArrayValue
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
sub SetArrayValue($$$)
|
||||
{
|
||||
my($array_ref, $index1, $index2) = @_;
|
||||
|
||||
my($index);
|
||||
foreach $index (@$array_ref)
|
||||
{
|
||||
if ($index->[0] eq $index1)
|
||||
{
|
||||
$index->[1] = $index2;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# WriteDefaultPrefsFile
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub WriteDefaultPrefsFile($)
|
||||
{
|
||||
my($file_path) = @_;
|
||||
|
||||
my($file_contents);
|
||||
$file_contents = <<'EOS';
|
||||
% You can use this file to customize the Mozilla build system.
|
||||
% The following kinds of lines are allowable:
|
||||
% Comment lines, which start with a '%' in the first column
|
||||
% Lines which modify the default build settings. For the list of flags,
|
||||
% see MozBuildFlags.pm. Examples are:
|
||||
%
|
||||
% build pull 0 % don't pull
|
||||
% options mng 1 % turn mng on
|
||||
%
|
||||
% Line containing the special 'buildfrom' flag, which specifies
|
||||
% where to start the build. Example:
|
||||
%
|
||||
% buildfrom nglayout % where to start the build
|
||||
%
|
||||
% Lines which specify the location of the files used to store paths
|
||||
% to the CodeWarrior IDE, and the MacCVS Pro session file. Note quoting
|
||||
% of paths containing whitespace. Examples:
|
||||
%
|
||||
% filepath idepath ::codewarrior.txt
|
||||
% filepath sessionpath ":Some folder:MacCVS session path.txt"
|
||||
%
|
||||
% Lines which modify the build settings like %main::DEBUG.
|
||||
% Any lines which do not match either of the above are assumed
|
||||
% to set variables on $main::. Examples:
|
||||
%
|
||||
% MOZILLA_OFFICIAL 1
|
||||
%
|
||||
EOS
|
||||
|
||||
$file_contents =~ s/%/#/g;
|
||||
|
||||
local(*PREFS_FILE);
|
||||
|
||||
open(PREFS_FILE, "> $file_path") || die "Could not write default prefs file\n";
|
||||
print PREFS_FILE ($file_contents);
|
||||
close(PREFS_FILE);
|
||||
|
||||
MacPerl::SetFileInfo("McPL", "TEXT", $file_path);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# HandlePrefSet
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
sub HandlePrefSet($$$$)
|
||||
{
|
||||
my($flags, $name, $value, $desc) = @_;
|
||||
|
||||
if (SetArrayValue($flags, $name, $value)) {
|
||||
print "Prefs set $desc flag '$name' to '$value'\n";
|
||||
} else {
|
||||
die "$desc setting '$name' is not a valid option\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# HandleBuildFromPref
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
sub HandleBuildFromPref($$)
|
||||
{
|
||||
my($build_array, $name) = @_;
|
||||
|
||||
my($setting) = 0;
|
||||
my($index);
|
||||
foreach $index (@$build_array)
|
||||
{
|
||||
if ($index->[0] eq $name) {
|
||||
$setting = 1;
|
||||
}
|
||||
|
||||
$index->[1] = $setting;
|
||||
}
|
||||
|
||||
if ($setting == 1) {
|
||||
print "Building from $name onwards, as specified by prefs\n";
|
||||
} else {
|
||||
printf "Failed to find buildfrom setting '$name'\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# ReadPrefsFile
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub ReadPrefsFile($$$$$)
|
||||
{
|
||||
my($file_path, $build_flags, $options_flags, $filepath_flags, $create_if_missing) = @_;
|
||||
|
||||
local(*PREFS_FILE);
|
||||
|
||||
if (open(PREFS_FILE, "< $file_path"))
|
||||
{
|
||||
print "Reading build prefs from '$file_path'\n";
|
||||
|
||||
while (<PREFS_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
|
||||
if ($line =~ /^\#/ || $line =~ /^\s*$/) { # ignore comments and empty lines
|
||||
next;
|
||||
}
|
||||
|
||||
if (($line =~ /^\s*([^#\s]+)\s+([^#\s]+)\s+\"(.+)\"(\s+#.+)?/) ||
|
||||
($line =~ /^\s*([^#\s]+)\s+([^#\s]+)\s+\'(.+)\'(\s+#.+)?/) ||
|
||||
($line =~ /^\s*([^#\s]+)\s+([^#\s]+)\s+([^#\s]+)(\s+#.+)?/))
|
||||
{
|
||||
my($array_name) = $1;
|
||||
my($option_name) = $2;
|
||||
my($option_value) = $3;
|
||||
|
||||
# print "Read '$array_name' '$option_name' '$option_value'\n";
|
||||
|
||||
if ($array_name eq "build")
|
||||
{
|
||||
HandlePrefSet($build_flags, $option_name, $option_value, "Build");
|
||||
}
|
||||
elsif ($array_name eq "options")
|
||||
{
|
||||
HandlePrefSet($options_flags, $option_name, $option_value, "Options");
|
||||
}
|
||||
elsif ($array_name eq "filepath" && $option_name && $option_value)
|
||||
{
|
||||
HandlePrefSet($filepath_flags, $option_name, $option_value, "Filepath");
|
||||
}
|
||||
else
|
||||
{
|
||||
print "Unknown pref option at $line\n";
|
||||
}
|
||||
}
|
||||
elsif ($line =~ /^\s*buildfrom\s+([^#\s]+)(\s+#.+)?/)
|
||||
{
|
||||
my($build_start) = $1;
|
||||
HandleBuildFromPref($build_flags, $build_start);
|
||||
}
|
||||
elsif ($line =~ /^\s*([^#\s]+)\s+([^#\s]+)(\s+#.+)?/)
|
||||
{
|
||||
my($build_var) = $1;
|
||||
my($var_setting) = $2;
|
||||
|
||||
print "Setting \$main::$build_var to $var_setting\n";
|
||||
eval "\$main::$build_var = \"$var_setting\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
print "Unrecognized input line at $line\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
close(PREFS_FILE);
|
||||
}
|
||||
elsif ($create_if_missing)
|
||||
{
|
||||
print "No prefs file found at $file_path; using defaults\n";
|
||||
|
||||
my($folder_path) = $file_path;
|
||||
$folder_path =~ s/[^:]+$//;
|
||||
mkpath($folder_path);
|
||||
WriteDefaultPrefsFile($file_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# ReadMozUserPrefs
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
sub ReadMozUserPrefs($$$$)
|
||||
{
|
||||
my($prefs_file_name, $build_flags, $options_flags, $filepath_flags) = @_;
|
||||
|
||||
if ($prefs_file_name eq "") { return; }
|
||||
|
||||
# if local prefs exist, just use those. Othewise, look in the prefs folder
|
||||
if (-e $prefs_file_name)
|
||||
{
|
||||
# read local prefs
|
||||
ReadPrefsFile($prefs_file_name, $build_flags, $options_flags, $filepath_flags, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
# first read prefs folder prefs
|
||||
my($prefs_path) = GetPrefsFolder();
|
||||
$prefs_path .= ":$prefs_file_name";
|
||||
|
||||
ReadPrefsFile($prefs_path, $build_flags, $options_flags, $filepath_flags, 1);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -1,932 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Simon Fraser <sfraser@netscape.com>
|
||||
#
|
||||
|
||||
package Moz::ProjectXML;
|
||||
|
||||
require 5.004;
|
||||
require Exporter;
|
||||
|
||||
use strict;
|
||||
use Exporter;
|
||||
|
||||
use Cwd;
|
||||
use XML::DOM;
|
||||
|
||||
use vars qw(@ISA @EXPORT);
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT = qw(
|
||||
ParseXMLDocument
|
||||
DisposeXMLDocument
|
||||
WriteXMLDocument
|
||||
CleanupPro5XML
|
||||
GetTargetsList
|
||||
CloneTarget
|
||||
SetAsSharedLibraryTarget
|
||||
SetAsStaticLibraryTarget
|
||||
AddTarget
|
||||
RemoveTarget
|
||||
GetTargetSetting
|
||||
SetTargetSetting
|
||||
getChildElementTextContents
|
||||
);
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
# A module for reading, manipulating, and writing XML-format CodeWarrior project files.
|
||||
#
|
||||
# Sample usage:
|
||||
#
|
||||
# use ProjectXML;
|
||||
#
|
||||
# my $doc = ProjectXML::ParseXMLDocument("Test.mcp.xml");
|
||||
# ProjectXML::CloneTarget($doc, "Test.shlb", "Test.lib");
|
||||
# ProjectXML::SetAsStaticLibraryTarget($doc, "Test.lib", "TestOutput.lib");
|
||||
# ProjectXML::WriteXMLDocument($doc, "Test_out.xml");
|
||||
# ProjectXML::DisposeXMLDocument($doc);
|
||||
#
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// ParseXMLDocument
|
||||
#// Note that the caller must call DisposeXMLDocument on the returned doc
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub ParseXMLDocument($)
|
||||
{
|
||||
my($doc_path) = @_;
|
||||
|
||||
my $parser = new XML::DOM::Parser(ErrorContext => 2);
|
||||
my $doc = $parser->parsefile($doc_path);
|
||||
|
||||
return $doc;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// DisposeXMLDocument
|
||||
#// Needed to avoid memory leaks - cleanup circular references for garbage collection
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub DisposeXMLDocument($)
|
||||
{
|
||||
my($doc) = @_;
|
||||
|
||||
$doc->dispose();
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// WriteXMLDocument
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
|
||||
sub _pro5_tag_compression($$)
|
||||
{
|
||||
return 1; # Pro 5 is broken and can't import XML with <foo/> style tags
|
||||
}
|
||||
|
||||
sub _pro6plus_tag_compression($$)
|
||||
{
|
||||
return 0; # Pro 6 can deal with empty XML tags like <foo/>
|
||||
}
|
||||
|
||||
sub WriteXMLDocument($$$)
|
||||
{
|
||||
my($doc, $file_path, $ide_version) = @_;
|
||||
|
||||
if ($ide_version eq "4.0")
|
||||
{
|
||||
XML::DOM::setTagCompression(\&_pro5_tag_compression);
|
||||
}
|
||||
else
|
||||
{
|
||||
XML::DOM::setTagCompression(\&_pro6plus_tag_compression);
|
||||
}
|
||||
|
||||
$doc->printToFile($file_path);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// CleanupPro5XML
|
||||
#// XML Projects exported by Pro 5 contain garbage data under the MWMerge_MacOS_skipResources
|
||||
#// setting. This routine cleans this up, saving the result to a new file
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub CleanupPro5XML($$)
|
||||
{
|
||||
my($xml_path, $out_path) = @_;
|
||||
|
||||
local(*XML_FILE);
|
||||
open(XML_FILE, "< $xml_path") || die "Error: failed to open file $xml_path\n";
|
||||
|
||||
local(*CLEANED_FILE);
|
||||
open(CLEANED_FILE, "> $out_path") || die "Error: failed to open file $out_path for writing\n";
|
||||
|
||||
my $in_skip_resources_settings = 0;
|
||||
|
||||
while(<XML_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
|
||||
if ($line =~ /^<\?codewarrior/) # is processing inst line
|
||||
{
|
||||
my $test_line = $line;
|
||||
chomp($test_line);
|
||||
|
||||
my $out_line = $test_line;
|
||||
if ($test_line =~ /^<\?codewarrior\s+exportversion=\"(.+)\"\s+ideversion=\"(.+)\"\s*\?>$/)
|
||||
{
|
||||
my $export_version = $1;
|
||||
my $ide_version = $2;
|
||||
|
||||
$ide_version = "4.0_mozilla"; # pseudo IDE version so we know we touched it
|
||||
$out_line = "<?codewarrior exportversion=\"".$export_version."\" ideversion=\"".$ide_version."\"?>";
|
||||
}
|
||||
|
||||
print CLEANED_FILE "$out_line\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($line =~ /MWMerge_MacOS_skipResources/)
|
||||
{
|
||||
$in_skip_resources_settings = 1;
|
||||
print CLEANED_FILE "$line";
|
||||
}
|
||||
elsif($in_skip_resources_settings && $line =~ /<!-- Settings for/)
|
||||
{
|
||||
# leaving bad settings lines. Write closing tag
|
||||
print CLEANED_FILE " <!-- Corrupted setting entries removed by script -->\n";
|
||||
print CLEANED_FILE " </SETTING>\n\n";
|
||||
|
||||
print CLEANED_FILE "$line";
|
||||
|
||||
$in_skip_resources_settings = 0;
|
||||
}
|
||||
elsif (!$in_skip_resources_settings)
|
||||
{
|
||||
print CLEANED_FILE "$line";
|
||||
}
|
||||
}
|
||||
|
||||
close(XML_FILE);
|
||||
close(CLEANED_FILE);
|
||||
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
# SniffProjectXMLIDEVersion
|
||||
#
|
||||
#--------------------------------------------------------------------------------------------------
|
||||
sub SniffProjectXMLIDEVersion($)
|
||||
{
|
||||
my($xml_path) = @_;
|
||||
|
||||
my $found_version = "";
|
||||
|
||||
local(*XML_FILE);
|
||||
open(XML_FILE, "< $xml_path") || die "Error: failed to open file $xml_path\n";
|
||||
|
||||
while(<XML_FILE>)
|
||||
{
|
||||
my($line) = $_;
|
||||
chomp($line);
|
||||
|
||||
if ($line =~ /^<\?codewarrior/) # is processing inst line
|
||||
{
|
||||
unless ($line =~ /^<\?codewarrior\s+exportversion=\"(.+)\"\s+ideversion=\"(.+)\"\s*\?>$/)
|
||||
{
|
||||
die "Error: Failed to find ideversion in $xml_path in line $line\n";
|
||||
}
|
||||
|
||||
my $export_version = $1;
|
||||
my $ide_version = $2;
|
||||
|
||||
$found_version = $ide_version;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
close(XML_FILE);
|
||||
|
||||
return $found_version;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetTargetsList
|
||||
#// Returns an array of target names
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetTargetsList($)
|
||||
{
|
||||
my($doc) = @_;
|
||||
|
||||
my $nodes = $doc->getElementsByTagName("TARGET");
|
||||
my $n = $nodes->getLength;
|
||||
|
||||
my @target_names;
|
||||
|
||||
for (my $i = 0; $i < $n; $i++)
|
||||
{
|
||||
my ($node) = $nodes->item($i);
|
||||
|
||||
my($target_name) = getChildElementTextContents($node, "NAME");
|
||||
push(@target_names, $target_name);
|
||||
}
|
||||
|
||||
return @target_names;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// CloneTarget
|
||||
#// Clone the named target, renaming it to 'new_name'
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub CloneTarget($$$)
|
||||
{
|
||||
my($doc, $target_name, $new_name) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
|
||||
# clone here
|
||||
my $target_clone = $target_node->cloneNode(1); # deep clone
|
||||
|
||||
# -- munge target settings --
|
||||
|
||||
# set the target name field
|
||||
setChildElementTextContents($doc, $target_clone, "NAME", $new_name);
|
||||
|
||||
# set the targetname pref
|
||||
setTargetNodeSetting($doc, $target_clone, "Targetname", $new_name);
|
||||
|
||||
# -- insert new target subtree --
|
||||
|
||||
my $target_list = $target_node->getParentNode();
|
||||
$target_list->appendChild($target_clone);
|
||||
|
||||
# -- now add to targetorder --
|
||||
my (@target_order_nodes) = getChildOfDocument($doc, "TARGETORDER");
|
||||
|
||||
my $target_order = @target_order_nodes[0];
|
||||
|
||||
my $new_order = $doc->createElement("ORDEREDTARGET");
|
||||
my $order_name = $doc->createElement("NAME");
|
||||
|
||||
$new_order->appendChild($order_name);
|
||||
|
||||
setChildElementTextContents($doc, $new_order, "NAME", $new_name);
|
||||
$target_order->appendChild($new_order);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// SetAsSharedLibraryTarget
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub SetAsSharedLibraryTarget($$$)
|
||||
{
|
||||
my($doc, $target_name, $output_name) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
|
||||
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_type", "SharedLibrary");
|
||||
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_filetype", "1936223330"); #'shlb'
|
||||
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_outfile", $output_name);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// AddFileToTarget
|
||||
#//
|
||||
#// Add a file to the specified target(s).
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub AddFileToTarget($$$)
|
||||
{
|
||||
my($doc, $target_list, $file_name) = @_;
|
||||
|
||||
# the file must be added in 3 places:
|
||||
# 1. in <TARGET><FILELIST><FILE> (with linkage flags if necessary)
|
||||
# 2. in <TARGET><LINKORDER><FILEREF>
|
||||
# 3. in <GROUPLIST><GROUP><FILEREF>
|
||||
die "Write me\n";
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// RemoveFileFromTarget
|
||||
#//
|
||||
#// Remove a file from the specified target, removing it from the entire project
|
||||
#// if no other targets reference it.
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub RemoveFileFromTarget($$$)
|
||||
{
|
||||
my($doc, $target_node, $file_name) = @_;
|
||||
|
||||
# the file must be removed in 3 places:
|
||||
# 1. in <TARGET><FILELIST><FILE>
|
||||
# 2. in <TARGET><LINKORDER><FILEREF>
|
||||
# 3. in <GROUPLIST><GROUP><FILEREF>
|
||||
|
||||
# first, remove from <FILELIST>
|
||||
my $filelist_node = getFirstChildElement($target_node, "FILELIST");
|
||||
unless ($filelist_node) { die "Error: failed to find FILELIST node\n"; }
|
||||
|
||||
my $file_node = getChildNodeByGrandchildContents($doc, $filelist_node, "FILE", "PATH", $file_name);
|
||||
unless ($file_node) { return; }
|
||||
|
||||
$filelist_node->removeChild($file_node);
|
||||
|
||||
# next, remove from <LINKORDER>
|
||||
my $linkorder_node = getFirstChildElement($target_node, "LINKORDER");
|
||||
unless ($linkorder_node) { die "Error: failed to find LINKORDER node\n"; }
|
||||
|
||||
my $fileref_node = getChildNodeByGrandchildContents($doc, $linkorder_node, "FILEREF", "PATH", $file_name);
|
||||
unless ($fileref_node) { die "Error: link order node for file $file_name not found\n"; }
|
||||
|
||||
$linkorder_node->removeChild($fileref_node);
|
||||
|
||||
# last, remove from <GROUPLIST>
|
||||
# <GROUPLIST> is cross-target, so we have to be careful here.
|
||||
my $grouplist_node = getChildOfDocument($doc, "GROUPLIST");
|
||||
unless ($grouplist_node) { die "Error: failed to find GROUPLIST node\n"; }
|
||||
|
||||
# if the file isn't in any other targets, remove it from the groups
|
||||
if (!GetFileInUse($doc, $file_name))
|
||||
{
|
||||
print "File $file_name is in no other targest. Removing from project\n";
|
||||
|
||||
my @group_nodes;
|
||||
getChildElementsOfType($doc, $grouplist_node, "GROUP", \@group_nodes);
|
||||
my $group_node;
|
||||
foreach $group_node (@group_nodes)
|
||||
{
|
||||
my @fileref_nodes;
|
||||
getChildElementsOfType($doc, $group_node, "FILEREF", \@fileref_nodes);
|
||||
|
||||
my $fileref_node;
|
||||
foreach $fileref_node (@fileref_nodes)
|
||||
{
|
||||
my $path_name = getChildElementTextContents($fileref_node, "PATH");
|
||||
if ($path_name eq $file_name)
|
||||
{
|
||||
print "Removing $file_name from project group list\n";
|
||||
$group_node->removeChild($fileref_node);
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# can a file appear in more than one group?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// SetAsStaticLibraryTarget
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub SetAsStaticLibraryTarget($$$)
|
||||
{
|
||||
my($doc, $target_name, $output_name) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
|
||||
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_type", "Library");
|
||||
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_filetype", "1061109567"); #'????'
|
||||
setTargetNodeSetting($doc, $target_node, "MWProject_PPC_outfile", $output_name);
|
||||
|
||||
# static targets don't need any library linkage, so we can remove linkage
|
||||
# with all .shlb and .Lib files.
|
||||
|
||||
my(@obsolete_files) = ("NSStdLibStubs", "InterfacesStubs", "InterfaceLib", "InternetConfigLib");
|
||||
|
||||
print " Removing libraries etc. from target\n";
|
||||
|
||||
# get all files in target
|
||||
my @target_files = GetTargetFilesList($doc, $target_name);
|
||||
my $target_file;
|
||||
foreach $target_file (@target_files)
|
||||
{
|
||||
if ($target_file =~ /(\.shlb|\.lib|\.Lib|\.o|\.exp)$/)
|
||||
{
|
||||
RemoveFileFromTarget($doc, $target_node, $target_file);
|
||||
}
|
||||
}
|
||||
|
||||
print " Removing stub libraries from target\n";
|
||||
|
||||
# then remove files with known names
|
||||
my $obs_file;
|
||||
foreach $obs_file (@obsolete_files)
|
||||
{
|
||||
RemoveFileFromTarget($doc, $target_node, $obs_file);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// AddTarget
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub AddTarget($$)
|
||||
{
|
||||
my($doc, $target_name) = @_;
|
||||
|
||||
die "Write me\n";
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// RemoveTarget
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub RemoveTarget($$)
|
||||
{
|
||||
my($doc, $target_name) = @_;
|
||||
|
||||
die "Write me\n";
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetTargetSetting
|
||||
#// Get the value for the specified setting in the specified target
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetTargetSetting($$$)
|
||||
{
|
||||
my($doc, $target_name, $setting_name) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
return getTargetNodeSetting($target_node, "VALUE");
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// SetTargetSetting
|
||||
#// Set the value for the specified setting in the specified target
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub SetTargetSetting($$$$)
|
||||
{
|
||||
my($doc, $target_name, $setting_name, $new_value) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
setTargetNodeSetting($doc, $target_node, "VALUE", $new_value);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetTargetFilesList
|
||||
#// Return an array of the files in the target (in filelist order)
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetTargetFilesList($$)
|
||||
{
|
||||
my($doc, $target_name) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
|
||||
my @files_list;
|
||||
|
||||
my $filelist_node = getFirstChildElement($target_node, "FILELIST");
|
||||
unless ($filelist_node) { die "Error: failed to find FILELIST node\n"; }
|
||||
|
||||
my @file_nodes;
|
||||
getChildElementsOfType($doc, $filelist_node, "FILE", \@file_nodes);
|
||||
|
||||
my $node;
|
||||
foreach $node (@file_nodes)
|
||||
{
|
||||
my $file_name = getChildElementTextContents($node, "PATH");
|
||||
push(@files_list, $file_name);
|
||||
}
|
||||
|
||||
return @files_list;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// FileIsInTarget
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub FileIsInTarget($$$)
|
||||
{
|
||||
my($doc, $file_name, $target_name) = @_;
|
||||
|
||||
my $target_node = getTargetNode($doc, $target_name);
|
||||
unless ($target_node) { die "Error: no target found called $target_name\n"; }
|
||||
|
||||
my $file_node = GetTargetFileNode($doc, $target_node, $file_name);
|
||||
if ($file_node) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetFileTargetsList
|
||||
#// Return an array of the targets that a file is in (expensive)
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetFileTargetsList($$)
|
||||
{
|
||||
my ($doc, $file_name) = @_;
|
||||
|
||||
my @target_list;
|
||||
|
||||
my @targets = GetTargetsList($doc);
|
||||
my $target;
|
||||
|
||||
foreach $target (@targets)
|
||||
{
|
||||
if (FileIsInTarget($doc, $file_name, $target))
|
||||
{
|
||||
push(@target_list, $target);
|
||||
}
|
||||
}
|
||||
|
||||
return @target_list;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetTargetFileNode
|
||||
#//
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetTargetFileNode($$$)
|
||||
{
|
||||
my($doc, $target_node, $file_name) = @_;
|
||||
|
||||
my $filelist_node = getFirstChildElement($target_node, "FILELIST");
|
||||
unless ($filelist_node) { die "Error: failed to find FILELIST node\n"; }
|
||||
|
||||
my $file_node = getChildNodeByGrandchildContents($doc, $filelist_node, "FILE", "PATH", $file_name);
|
||||
|
||||
return $file_node;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// GetFileInUse
|
||||
#// Return true if the file is used by any target
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub GetFileInUse($$)
|
||||
{
|
||||
my($doc, $file_name) = @_;
|
||||
|
||||
my $targetlist_node = getChildOfDocument($doc, "TARGETLIST");
|
||||
|
||||
my $target_node = $targetlist_node->getFirstChild();
|
||||
|
||||
while ($target_node)
|
||||
{
|
||||
if ($target_node->getNodeTypeName eq "ELEMENT_NODE" &&
|
||||
$target_node->getTagName() eq "TARGET")
|
||||
{
|
||||
# if this is a target node
|
||||
my $file_node = GetTargetFileNode($doc, $target_node, $file_name);
|
||||
if ($file_node) {
|
||||
return 1; # found it
|
||||
}
|
||||
}
|
||||
|
||||
$target_node = $target_node->getNextSibling();
|
||||
}
|
||||
|
||||
# not found
|
||||
return 0;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getChildOfDocument
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getChildOfDocument($$)
|
||||
{
|
||||
my($doc, $child_type) = @_;
|
||||
|
||||
return getFirstChildElement($doc->getDocumentElement(), $child_type);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getFirstChildElement
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getFirstChildElement($$)
|
||||
{
|
||||
my($node, $element_name) = @_;
|
||||
|
||||
my $found_node;
|
||||
|
||||
unless ($node) { die "getFirstChildElement called with empty node\n"; }
|
||||
|
||||
#look for the first "element_name" child
|
||||
|
||||
my $child_node = $node->getFirstChild();
|
||||
|
||||
while ($child_node)
|
||||
{
|
||||
if ($child_node->getNodeTypeName eq "ELEMENT_NODE" &&
|
||||
$child_node->getTagName() eq $element_name)
|
||||
{
|
||||
$found_node = $child_node;
|
||||
last;
|
||||
}
|
||||
|
||||
$child_node = $child_node->getNextSibling();
|
||||
}
|
||||
|
||||
return $found_node;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getChildElementsOfType
|
||||
#//
|
||||
#// Return an array of refs to child nodes of the given type
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getChildElementsOfType($$$$)
|
||||
{
|
||||
my($doc, $node, $child_type, $array_ref) = @_;
|
||||
|
||||
my $child_node = $node->getFirstChild();
|
||||
|
||||
while ($child_node)
|
||||
{
|
||||
if ($child_node->getNodeTypeName eq "ELEMENT_NODE" &&
|
||||
$child_node->getTagName() eq $child_type)
|
||||
{
|
||||
push(@$array_ref, $child_node);
|
||||
}
|
||||
|
||||
$child_node = $child_node->getNextSibling();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getChildElementTextContents
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#
|
||||
# Given <FOOPY><NERD>Hi!</NERD></FOOPY>, where $node is <FOOPY>,
|
||||
# returns "Hi!". If > 1 <NERD> node, returns the contents of the first.
|
||||
#
|
||||
sub getChildElementTextContents($$)
|
||||
{
|
||||
my($node, $tag_name) = @_;
|
||||
|
||||
my $first_element = getFirstChildElement($node, $tag_name);
|
||||
my $text_node = $first_element->getFirstChild();
|
||||
|
||||
my $text_contents = "";
|
||||
|
||||
# concat adjacent text nodes
|
||||
while ($text_node)
|
||||
{
|
||||
if ($text_node->getNodeTypeName() ne "TEXT_NODE")
|
||||
{
|
||||
last;
|
||||
}
|
||||
|
||||
$text_contents = $text_contents.$text_node->getData();
|
||||
$text_node = $text_node->getNextSibling();
|
||||
}
|
||||
|
||||
return $text_contents;
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// setChildElementTextContents
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub setChildElementTextContents($$$$)
|
||||
{
|
||||
my($doc, $node, $tag_name, $contents_text) = @_;
|
||||
|
||||
my $first_element = getFirstChildElement($node, $tag_name);
|
||||
my $new_text_node = $doc->createTextNode($contents_text);
|
||||
|
||||
# replace all child elements with a text element
|
||||
removeAllChildren($first_element);
|
||||
|
||||
$first_element->appendChild($new_text_node);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getChildNodeByContents
|
||||
#//
|
||||
#// Consider <foo><bar><baz>Foopy</baz></bar><bar><baz>Loopy</baz></bar></foo>
|
||||
#// This function, when called with getChildNodeByContents($foonode, "bar", "baz", "Loopy")
|
||||
#// returns the second <bar> node.
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getChildNodeByGrandchildContents($$$$$)
|
||||
{
|
||||
my($doc, $node, $child_type, $gc_type, $gc_contents) = @_; # gc = grandchild
|
||||
|
||||
my $found_node;
|
||||
my $child_node = $node->getFirstChild();
|
||||
while ($child_node)
|
||||
{
|
||||
if ($child_node->getNodeTypeName eq "ELEMENT_NODE" &&
|
||||
$child_node->getTagName() eq $child_type)
|
||||
{
|
||||
# check for a child of this node of type
|
||||
my $child_contents = getChildElementTextContents($child_node, $gc_type);
|
||||
|
||||
if ($child_contents eq $gc_contents)
|
||||
{
|
||||
$found_node = $child_node;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
$child_node = $child_node->getNextSibling();
|
||||
}
|
||||
|
||||
return $found_node;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getTargetNode
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getTargetNode($$)
|
||||
{
|
||||
my($doc, $target_name) = @_;
|
||||
|
||||
my $targetlist_node = getChildOfDocument($doc, "TARGETLIST");
|
||||
return getChildNodeByGrandchildContents($doc, $targetlist_node, "TARGET", "NAME", $target_name);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getTargetNamedSettingNode
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getTargetNamedSettingNode($$)
|
||||
{
|
||||
my($target_node, $setting_name) = @_;
|
||||
|
||||
my $setting_node;
|
||||
|
||||
my $settinglist_node = getFirstChildElement($target_node, "SETTINGLIST");
|
||||
my $child_node = $settinglist_node->getFirstChild();
|
||||
|
||||
while ($child_node)
|
||||
{
|
||||
if ($child_node->getNodeTypeName ne "ELEMENT_NODE")
|
||||
{
|
||||
$child_node = $child_node->getNextSibling();
|
||||
next;
|
||||
}
|
||||
|
||||
if ($child_node->getTagName() eq "SETTING")
|
||||
{
|
||||
my $set_name = getChildElementTextContents($child_node, "NAME");
|
||||
|
||||
if ($set_name eq $setting_name)
|
||||
{
|
||||
$setting_node = $child_node;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
$child_node = $child_node->getNextSibling();
|
||||
}
|
||||
|
||||
return $setting_node;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// getTargetNodeSetting
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub getTargetNodeSetting($$)
|
||||
{
|
||||
my($target_node, $setting_name) = @_;
|
||||
|
||||
my $setting_node = getTargetNamedSettingNode($target_node, $setting_name);
|
||||
return getChildElementTextContents($setting_node, "VALUE");
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// setTargetNodeSetting
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub setTargetNodeSetting($$$$)
|
||||
{
|
||||
my($doc, $target_node, $setting_name, $new_value) = @_;
|
||||
|
||||
my $setting_node = getTargetNamedSettingNode($target_node, $setting_name);
|
||||
|
||||
setChildElementTextContents($doc, $setting_node, "VALUE", $new_value);
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// elementInArray
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub elementInArray($$)
|
||||
{
|
||||
my($element, $array) = @_;
|
||||
my $test;
|
||||
foreach $test (@$array)
|
||||
{
|
||||
if ($test eq $element) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// removeAllChildren
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub removeAllChildren($)
|
||||
{
|
||||
my($node) = @_;
|
||||
|
||||
my $child_node = $node->getFirstChild();
|
||||
|
||||
while ($child_node)
|
||||
{
|
||||
$node->removeChild($child_node);
|
||||
$child_node = $node->getFirstChild();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// dumpNodeData
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub dumpNodeData($)
|
||||
{
|
||||
my($node) = @_;
|
||||
|
||||
unless ($node) { die "Null node passed to dumpNodeData\n"; }
|
||||
|
||||
print "Dumping node $node\n";
|
||||
|
||||
my($node_type) = $node->getNodeTypeName();
|
||||
|
||||
if ($node_type eq "ELEMENT_NODE")
|
||||
{
|
||||
my($node_name) = $node->getTagName();
|
||||
print "Element $node_name\n";
|
||||
}
|
||||
elsif ($node_type eq "TEXT_NODE")
|
||||
{
|
||||
my($node_data) = $node->getData;
|
||||
# my(@node_vals) = unpack("C*", $node_data);
|
||||
print "Text '$node_data'\n"; # may contain LF chars
|
||||
}
|
||||
else
|
||||
{
|
||||
print "Node $node_type\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
#// dumpNodeTree
|
||||
#//--------------------------------------------------------------------------------------------------
|
||||
sub dumpNodeTree($)
|
||||
{
|
||||
my($node) = @_;
|
||||
|
||||
my($child_node) = $node->getFirstChild();
|
||||
|
||||
unless ($child_node) { return; }
|
||||
|
||||
# recurse
|
||||
dumpNodeData($child_node);
|
||||
|
||||
# then go through child nodes
|
||||
while ($child_node)
|
||||
{
|
||||
dumpNodeTree($child_node);
|
||||
|
||||
$child_node = $child_node->getNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
1;
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# These 3 lists are the 'master lists' to control what gets built.
|
||||
#
|
||||
# Ordering in these arrays is important; it has to reflect the order in
|
||||
# which the build occurs.
|
||||
#
|
||||
# Setting containing spaces must be quoted with double quotes.
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
build_flags
|
||||
all 1
|
||||
pull 0
|
||||
dist 0
|
||||
config 0
|
||||
xpidl 0
|
||||
idl 0
|
||||
stubs 0
|
||||
runtime 0
|
||||
common 0
|
||||
imglib 0
|
||||
libimg2 0
|
||||
necko 0
|
||||
security 0
|
||||
browserutils 0
|
||||
intl 0
|
||||
nglayout 0
|
||||
accessiblity 0
|
||||
editor 0
|
||||
embedding 0
|
||||
viewer 0
|
||||
xpapp 0
|
||||
extensions 0
|
||||
plugins 0
|
||||
mailnews 0
|
||||
apprunner 0
|
||||
resources 0
|
||||
|
||||
options_flags
|
||||
pull_by_date 0
|
||||
chrome_jars 1
|
||||
chrome_files 0
|
||||
use_jars 1
|
||||
transformiix 1
|
||||
mathml 0 MOZ_MATHML
|
||||
svg 0 MOZ_SVG
|
||||
# svg requires libart, which is an lgpl library. You need to pull it
|
||||
# explicitly.
|
||||
libart_lgpl 0
|
||||
mng 1
|
||||
ldap 1 MOZ_LDAP_XPCOM
|
||||
ldap_experimental 0 MOZ_LDAP_XPCOM_EXPERIMENTAL
|
||||
xmlextras 1
|
||||
wsp 0 MOZ_WSP
|
||||
inspector 1
|
||||
mailextras 1
|
||||
xptlink 0
|
||||
psm 0 MOZ_PSM
|
||||
embedding_test 1
|
||||
embedding_chrome 0
|
||||
embedding_xulprefs 0
|
||||
embedding_xulsecurity 0
|
||||
carbon 0 TARGET_CARBON
|
||||
useimg2 1 USE_IMG2
|
||||
lowmem 0 MOZ_MAC_LOWMEM
|
||||
accessible 1 ACCESSIBILITY
|
||||
bidi 1 IBMBIDI
|
||||
p3p 0
|
||||
jsd 1
|
||||
venkman 1
|
||||
moz_logging 1 MOZ_LOGGING
|
||||
chatzilla 1
|
||||
content_packs 1
|
||||
xml_rpc 1
|
||||
cview 1
|
||||
help 1
|
||||
timeline 0 MOZ_TIMELINE
|
||||
static_build 0 MOZ_STATIC_COMPONENT_LIBS
|
||||
string_debug 0 DEBUG_STRING
|
||||
string_stats 0 DEBUG_STRING_STATS
|
||||
xpctools 0 XPC_TOOLS_SUPPORT
|
||||
smime 1
|
||||
mdn 1
|
||||
print_preview 1 NS_PRINT_PREVIEW
|
||||
moz_xul 1 MOZ_XUL
|
||||
|
||||
filepath_flags
|
||||
idepath ":CodeWarrior IDE Path.txt"
|
||||
sessionpath ":Mozilla session path.txt"
|
||||
buildlogfilepath ":Build Logs:Mozilla build log.txt" # this is a path
|
||||
scriptlogfilepath ":Build Logs:Mozilla script log.txt"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,22 +0,0 @@
|
||||
# List of modules to check out. Format is
|
||||
# module, (tag), (date)
|
||||
# where tag and date are optional (non-trailing commas are required)
|
||||
#
|
||||
# Examples:
|
||||
# mozilla/nsprpub, NSPRPUB_CLIENT_TAG
|
||||
# mozilla/gc, , 10/25/2000 12:00:00
|
||||
#
|
||||
|
||||
mozilla/nsprpub, NETSCAPE_7_02_RELEASE
|
||||
mozilla/security/nss, NETSCAPE_7_02_RELEASE
|
||||
mozilla/security/manager, NETSCAPE_7_02_RELEASE
|
||||
mozilla/accessible, NETSCAPE_7_02_RELEASE
|
||||
mozilla/directory/c-sdk, NETSCAPE_7_02_RELEASE
|
||||
mozilla/lib/mac/Instrumentation, NETSCAPE_7_02_RELEASE
|
||||
mozilla/gfx2, NETSCAPE_7_02_RELEASE
|
||||
mozilla/modules/libpr0n, NETSCAPE_7_02_RELEASE
|
||||
SeaMonkeyAll, NETSCAPE_7_02_RELEASE
|
||||
|
||||
## You need this if you want to be able to use SVG
|
||||
## Note that this library is under the LGPL, not the MPL
|
||||
#mozilla/other-licenses/libart_lgpl
|
||||
@@ -1,79 +0,0 @@
|
||||
#!perl
|
||||
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Simon Fraser <sfraser@netscape.com>
|
||||
#
|
||||
|
||||
require 5.004;
|
||||
|
||||
use strict;
|
||||
|
||||
use Cwd;
|
||||
use Moz::BuildUtils;
|
||||
use Moz::BuildCore;
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# Where have the build options gone?
|
||||
#
|
||||
# The various build flags have been centralized into one place.
|
||||
# The master list of options is in MozBuildFlags.txt. However,
|
||||
# you should never need to edit that file, or this one.
|
||||
#
|
||||
# To customize what gets built, or where to start the build,
|
||||
# edit the $prefs_file_name file in
|
||||
# System Folder:Preferences:Mozilla build prefs:
|
||||
# Documentation is provided in that file.
|
||||
#-------------------------------------------------------------
|
||||
|
||||
my($prefs_file_name) = "Mozilla pull prefs";
|
||||
|
||||
#-------------------------------------------------------------
|
||||
# hashes to hold build options
|
||||
#-------------------------------------------------------------
|
||||
my(%build);
|
||||
my(%options);
|
||||
my(%filepaths);
|
||||
my(%optiondefines);
|
||||
|
||||
# Hash of input files for this build. Eventually, there will be
|
||||
# input files for manifests, and projects too.
|
||||
my(%inputfiles) = (
|
||||
"buildflags", "MozillaBuildFlags.txt",
|
||||
"checkoutdata", "MozillaCheckoutList.txt",
|
||||
"buildprogress", "",
|
||||
"buildmodule", "MozillaBuildList.pm",
|
||||
"checkouttime", "Mozilla last checkout"
|
||||
);
|
||||
#-------------------------------------------------------------
|
||||
# end build hashes
|
||||
#-------------------------------------------------------------
|
||||
|
||||
# set the build root directory, which is the the dir above mozilla
|
||||
SetupBuildRootDir(":mozilla:build:mac:build_scripts");
|
||||
|
||||
# Set up all the flags on $main::, like DEBUG, CARBON etc.
|
||||
# Override the defaults using the preferences files.
|
||||
SetupDefaultBuildOptions(0, ":mozilla:dist:viewer:", "");
|
||||
|
||||
my($do_checkout) = 1;
|
||||
my($do_build) = 0;
|
||||
|
||||
RunBuild($do_checkout, $do_build, \%inputfiles, $prefs_file_name);
|
||||
@@ -1,4 +0,0 @@
|
||||
This directory is merely here to test the project editor server. It will go away after
|
||||
it is validated. For more information, see http://camelot.
|
||||
|
||||
Testing watchers.
|
||||
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
// test1.cpp
|
||||
@@ -1 +0,0 @@
|
||||
// test2.cpp
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
// test2.cpp
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,4 +0,0 @@
|
||||
// test2.cpp
|
||||
|
||||
as
|
||||
dfasdf
|
||||
@@ -1,12 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ConditionalMacros.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
FILE* file = fopen("BuildSystemInfo.pm", "w");
|
||||
if (file != NULL) {
|
||||
fprintf(file, "$UNIVERSAL_INTERFACES_VERSION=0x%04X;\n", UNIVERSAL_INTERFACES_VERSION);
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -1,650 +0,0 @@
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s): Stephen Lamm
|
||||
|
||||
# Build the Mozilla client.
|
||||
#
|
||||
# This needs CVSROOT set to work, e.g.,
|
||||
# setenv CVSROOT :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
|
||||
# or
|
||||
# setenv CVSROOT :pserver:username%somedomain.org@cvs.mozilla.org:/cvsroot
|
||||
#
|
||||
# To checkout and build a tree,
|
||||
# 1. cvs co mozilla/client.mk
|
||||
# 2. cd mozilla
|
||||
# 3. gmake -f client.mk
|
||||
#
|
||||
# Other targets (gmake -f client.mk [targets...]),
|
||||
# checkout
|
||||
# build
|
||||
# clean (realclean is now the same as clean)
|
||||
# distclean
|
||||
#
|
||||
# See http://www.mozilla.org/build/unix.html for more information.
|
||||
#
|
||||
# Options:
|
||||
# MOZ_OBJDIR - Destination object directory
|
||||
# MOZ_CO_DATE - Date tag to use for checkout (default: none)
|
||||
# MOZ_CO_MODULE - Module to checkout (default: SeaMonkeyAll)
|
||||
# MOZ_CVS_FLAGS - Flags to pass cvs (default: -q -z3)
|
||||
# MOZ_CO_FLAGS - Flags to pass after 'cvs co' (default: -P)
|
||||
# MOZ_MAKE_FLAGS - Flags to pass to $(MAKE)
|
||||
# MOZ_CO_BRANCH - Branch tag (Deprecated. Use MOZ_CO_TAG below.)
|
||||
#
|
||||
|
||||
#######################################################################
|
||||
# Checkout Tags
|
||||
#
|
||||
# For branches, uncomment the MOZ_CO_TAG line with the proper tag,
|
||||
# and commit this file on that tag.
|
||||
MOZ_CO_TAG = NETSCAPE_7_02_RELEASE
|
||||
NSPR_CO_TAG = NETSCAPE_7_02_RELEASE
|
||||
PSM_CO_TAG = NETSCAPE_7_02_RELEASE
|
||||
NSS_CO_TAG = NETSCAPE_7_02_RELEASE
|
||||
LDAPCSDK_CO_TAG = NETSCAPE_7_02_RELEASE
|
||||
ACCESSIBLE_CO_TAG = NETSCAPE_7_02_RELEASE
|
||||
GFX2_CO_TAG = NETSCAPE_7_02_RELEASE
|
||||
IMGLIB2_CO_TAG = NETSCAPE_7_02_RELEASE
|
||||
BUILD_MODULES = all
|
||||
|
||||
#######################################################################
|
||||
# Defines
|
||||
#
|
||||
CVS = cvs
|
||||
|
||||
CWD := $(shell pwd)
|
||||
|
||||
ifeq "$(CWD)" "/"
|
||||
CWD := /.
|
||||
endif
|
||||
|
||||
ifneq (, $(wildcard client.mk))
|
||||
# Ran from mozilla directory
|
||||
ROOTDIR := $(shell dirname $(CWD))
|
||||
TOPSRCDIR := $(CWD)
|
||||
else
|
||||
# Ran from mozilla/.. directory (?)
|
||||
ROOTDIR := $(CWD)
|
||||
TOPSRCDIR := $(CWD)/mozilla
|
||||
endif
|
||||
|
||||
# on os2, TOPSRCDIR may have two forward slashes in a row, which doesn't
|
||||
# work; replace first instance with one forward slash
|
||||
TOPSRCDIR := $(shell echo "$(TOPSRCDIR)" | sed -e 's%//%/%')
|
||||
|
||||
ifndef TOPSRCDIR_MOZ
|
||||
TOPSRCDIR_MOZ=$(TOPSRCDIR)
|
||||
endif
|
||||
|
||||
# if ROOTDIR equals only drive letter (i.e. "C:"), set to "/"
|
||||
DIRNAME := $(shell echo "$(ROOTDIR)" | sed -e 's/^.://')
|
||||
ifeq ($(DIRNAME),)
|
||||
ROOTDIR := /.
|
||||
endif
|
||||
|
||||
AUTOCONF := autoconf
|
||||
MKDIR := mkdir
|
||||
SH := /bin/sh
|
||||
ifndef MAKE
|
||||
MAKE := gmake
|
||||
endif
|
||||
|
||||
CONFIG_GUESS_SCRIPT := $(wildcard $(TOPSRCDIR)/build/autoconf/config.guess)
|
||||
ifdef CONFIG_GUESS_SCRIPT
|
||||
CONFIG_GUESS = $(shell $(CONFIG_GUESS_SCRIPT))
|
||||
else
|
||||
_IS_FIRST_CHECKOUT := 1
|
||||
endif
|
||||
|
||||
####################################
|
||||
# CVS
|
||||
|
||||
# Add the CVS root to CVS_FLAGS if needed
|
||||
CVS_ROOT_IN_TREE := $(shell cat $(TOPSRCDIR)/CVS/Root 2>/dev/null)
|
||||
ifneq ($(CVS_ROOT_IN_TREE),)
|
||||
ifneq ($(CVS_ROOT_IN_TREE),$(CVSROOT))
|
||||
CVS_FLAGS := -d $(CVS_ROOT_IN_TREE)
|
||||
endif
|
||||
endif
|
||||
|
||||
CVSCO = $(strip $(CVS) $(CVS_FLAGS) co $(CVS_CO_FLAGS))
|
||||
CVSCO_LOGFILE := $(ROOTDIR)/cvsco.log
|
||||
CVSCO_LOGFILE := $(shell echo $(CVSCO_LOGFILE) | sed s%//%/%)
|
||||
|
||||
ifdef MOZ_CO_TAG
|
||||
CVS_CO_FLAGS := -r $(MOZ_CO_TAG)
|
||||
endif
|
||||
|
||||
####################################
|
||||
# Load mozconfig Options
|
||||
|
||||
# See build pages, http://www.mozilla.org/build/unix.html,
|
||||
# for how to set up mozconfig.
|
||||
MOZCONFIG_LOADER := mozilla/build/autoconf/mozconfig2client-mk
|
||||
MOZCONFIG_FINDER := mozilla/build/autoconf/mozconfig-find
|
||||
MOZCONFIG_MODULES := mozilla/build/unix/modules.mk
|
||||
run_for_side_effects := \
|
||||
$(shell cd $(ROOTDIR); \
|
||||
if test "$(_IS_FIRST_CHECKOUT)"; then \
|
||||
$(CVSCO) $(MOZCONFIG_FINDER) $(MOZCONFIG_LOADER) $(MOZCONFIG_MODULES); \
|
||||
else true; \
|
||||
fi; \
|
||||
$(MOZCONFIG_LOADER) $(TOPSRCDIR) mozilla/.mozconfig.mk > mozilla/.mozconfig.out)
|
||||
include $(TOPSRCDIR)/.mozconfig.mk
|
||||
include $(TOPSRCDIR)/build/unix/modules.mk
|
||||
|
||||
####################################
|
||||
# Options that may come from mozconfig
|
||||
|
||||
# Change CVS flags if anonymous root is requested
|
||||
ifdef MOZ_CO_USE_MIRROR
|
||||
CVS_FLAGS := -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
|
||||
endif
|
||||
|
||||
# MOZ_CVS_FLAGS - Basic CVS flags
|
||||
ifeq "$(origin MOZ_CVS_FLAGS)" "undefined"
|
||||
CVS_FLAGS := $(CVS_FLAGS) -q -z 3
|
||||
else
|
||||
CVS_FLAGS := $(MOZ_CVS_FLAGS)
|
||||
endif
|
||||
|
||||
# This option is deprecated. The best way to have client.mk pull a tag
|
||||
# is to set MOZ_CO_TAG (see above) and commit that change on the tag.
|
||||
ifdef MOZ_CO_BRANCH
|
||||
$(warning Use MOZ_CO_TAG instead of MOZ_CO_BRANCH)
|
||||
CVS_CO_FLAGS := -r $(MOZ_CO_BRANCH)
|
||||
endif
|
||||
|
||||
# MOZ_CO_FLAGS - Anything that we should use on all checkouts
|
||||
ifeq "$(origin MOZ_CO_FLAGS)" "undefined"
|
||||
CVS_CO_FLAGS := $(CVS_CO_FLAGS) -P
|
||||
else
|
||||
CVS_CO_FLAGS := $(CVS_CO_FLAGS) $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
|
||||
ifdef MOZ_CO_DATE
|
||||
CVS_CO_DATE_FLAGS := -D "$(MOZ_CO_DATE)"
|
||||
endif
|
||||
|
||||
ifdef MOZ_OBJDIR
|
||||
OBJDIR := $(MOZ_OBJDIR)
|
||||
MOZ_MAKE := $(MAKE) $(MOZ_MAKE_FLAGS) -C $(OBJDIR)
|
||||
else
|
||||
OBJDIR := $(TOPSRCDIR)
|
||||
MOZ_MAKE := $(MAKE) $(MOZ_MAKE_FLAGS)
|
||||
endif
|
||||
|
||||
####################################
|
||||
# CVS defines for PSM
|
||||
#
|
||||
PSM_CO_MODULE= mozilla/security/manager
|
||||
PSM_CO_FLAGS := -P -A
|
||||
ifdef MOZ_CO_FLAGS
|
||||
PSM_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef PSM_CO_TAG
|
||||
PSM_CO_FLAGS := $(PSM_CO_FLAGS) -r $(PSM_CO_TAG)
|
||||
endif
|
||||
CVSCO_PSM = $(CVS) $(CVS_FLAGS) co $(PSM_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(PSM_CO_MODULE)
|
||||
|
||||
####################################
|
||||
# CVS defines for NSS
|
||||
#
|
||||
NSS_CO_MODULE = mozilla/security/nss \
|
||||
mozilla/security/coreconf \
|
||||
$(NULL)
|
||||
|
||||
NSS_CO_FLAGS := -P
|
||||
ifdef MOZ_CO_FLAGS
|
||||
NSS_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef NSS_CO_TAG
|
||||
NSS_CO_FLAGS := $(NSS_CO_FLAGS) -r $(NSS_CO_TAG)
|
||||
endif
|
||||
# Cannot pull static tags by date
|
||||
ifeq ($(NSS_CO_TAG),NSS_CLIENT_TAG)
|
||||
CVSCO_NSS = $(CVS) $(CVS_FLAGS) co $(NSS_CO_FLAGS) $(NSS_CO_MODULE)
|
||||
else
|
||||
CVSCO_NSS = $(CVS) $(CVS_FLAGS) co $(NSS_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(NSS_CO_MODULE)
|
||||
endif
|
||||
|
||||
####################################
|
||||
# CVS defines for NSPR
|
||||
#
|
||||
NSPR_CO_MODULE = mozilla/nsprpub
|
||||
NSPR_CO_FLAGS := -P
|
||||
ifdef MOZ_CO_FLAGS
|
||||
NSPR_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef NSPR_CO_TAG
|
||||
NSPR_CO_FLAGS := $(NSPR_CO_FLAGS) -r $(NSPR_CO_TAG)
|
||||
endif
|
||||
# Cannot pull static tags by date
|
||||
ifeq ($(NSPR_CO_TAG),NSPRPUB_CLIENT_TAG)
|
||||
CVSCO_NSPR = $(CVS) $(CVS_FLAGS) co $(NSPR_CO_FLAGS) $(NSPR_CO_MODULE)
|
||||
else
|
||||
CVSCO_NSPR = $(CVS) $(CVS_FLAGS) co $(NSPR_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(NSPR_CO_MODULE)
|
||||
endif
|
||||
|
||||
####################################
|
||||
# CVS defines for the C LDAP SDK
|
||||
#
|
||||
LDAPCSDK_CO_MODULE = mozilla/directory/c-sdk
|
||||
LDAPCSDK_CO_FLAGS := -P
|
||||
ifdef MOZ_CO_FLAGS
|
||||
LDAPCSDK_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef LDAPCSDK_CO_TAG
|
||||
LDAPCSDK_CO_FLAGS := $(LDAPCSDK_CO_FLAGS) -r $(LDAPCSDK_CO_TAG)
|
||||
endif
|
||||
CVSCO_LDAPCSDK = $(CVS) $(CVS_FLAGS) co $(LDAPCSDK_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(LDAPCSDK_CO_MODULE)
|
||||
|
||||
####################################
|
||||
# CVS defines for the C LDAP SDK
|
||||
#
|
||||
ACCESSIBLE_CO_MODULE = mozilla/accessible
|
||||
ACCESSIBLE_CO_FLAGS := -P
|
||||
ifdef MOZ_CO_FLAGS
|
||||
ACCESSIBLE_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef ACCESSIBLE_CO_TAG
|
||||
ACCESSIBLE_CO_FLAGS := $(ACCESSIBLE_CO_FLAGS) -r $(ACCESSIBLE_CO_TAG)
|
||||
endif
|
||||
CVSCO_ACCESSIBLE = $(CVS) $(CVS_FLAGS) co $(ACCESSIBLE_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(ACCESSIBLE_CO_MODULE)
|
||||
|
||||
####################################
|
||||
# CVS defines for gfx2
|
||||
#
|
||||
GFX2_CO_MODULE = mozilla/gfx2
|
||||
GFX2_CO_FLAGS := -P
|
||||
ifdef MOZ_CO_FLAGS
|
||||
GFX2_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef GFX2_CO_TAG
|
||||
GFX2_CO_FLAGS := $(GFX2_CO_FLAGS) -r $(GFX2_CO_TAG)
|
||||
endif
|
||||
CVSCO_GFX2 = $(CVS) $(CVS_FLAGS) co $(GFX2_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(GFX2_CO_MODULE)
|
||||
|
||||
####################################
|
||||
# CVS defines for new image library
|
||||
#
|
||||
IMGLIB2_CO_MODULE = mozilla/modules/libpr0n
|
||||
IMGLIB2_CO_FLAGS := -P
|
||||
ifdef MOZ_CO_FLAGS
|
||||
IMGLIB2_CO_FLAGS := $(MOZ_CO_FLAGS)
|
||||
endif
|
||||
ifdef IMGLIB2_CO_TAG
|
||||
IMGLIB2_CO_FLAGS := $(IMGLIB2_CO_FLAGS) -r $(IMGLIB2_CO_TAG)
|
||||
endif
|
||||
CVSCO_IMGLIB2 = $(CVS) $(CVS_FLAGS) co $(IMGLIB2_CO_FLAGS) $(CVS_CO_DATE_FLAGS) $(IMGLIB2_CO_MODULE)
|
||||
|
||||
####################################
|
||||
# CVS defines for standalone modules
|
||||
#
|
||||
ifneq ($(BUILD_MODULES),all)
|
||||
MOZ_CO_MODULE := $(filter-out $(NSPRPUB_DIR) security directory/c-sdk, $(BUILD_MODULE_CVS))
|
||||
MOZ_CO_MODULE += allmakefiles.sh client.mk aclocal.m4 configure configure.in
|
||||
MOZ_CO_MODULE += Makefile.in
|
||||
MOZ_CO_MODULE := $(addprefix mozilla/, $(MOZ_CO_MODULE))
|
||||
|
||||
NOSUBDIRS_MODULE := $(addprefix mozilla/, $(BUILD_MODULE_CVS_NS))
|
||||
ifneq ($(NOSUBDIRS_MODULE),)
|
||||
CVSCO_NOSUBDIRS := $(CVSCO) -l $(CVS_CO_DATE_FLAGS) $(NOSUBDIRS_MODULE)
|
||||
endif
|
||||
|
||||
ifeq (,$(filter $(NSPRPUB_DIR), $(BUILD_MODULE_CVS)))
|
||||
CVSCO_NSPR :=
|
||||
endif
|
||||
ifeq (,$(filter security security/manager, $(BUILD_MODULE_CVS)))
|
||||
CVSCO_PSM :=
|
||||
CVSCO_NSS :=
|
||||
endif
|
||||
ifeq (,$(filter directory/c-sdk, $(BUILD_MODULE_CVS)))
|
||||
CVSCO_LDAPCSDK :=
|
||||
endif
|
||||
ifeq (,$(filter accessible, $(BUILD_MODULE_CVS)))
|
||||
CVSCO_ACCESSIBLE :=
|
||||
endif
|
||||
ifeq (,$(filter gfx2, $(BUILD_MODULE_CVS)))
|
||||
CVSCO_GFX2 :=
|
||||
endif
|
||||
ifeq (,$(filter modules/libpr0n, $(BUILD_MODULE_CVS)))
|
||||
CVSCO_IMGLIB2 :=
|
||||
endif
|
||||
endif
|
||||
|
||||
####################################
|
||||
# CVS defines for SeaMonkey
|
||||
#
|
||||
ifeq ($(MOZ_CO_MODULE),)
|
||||
MOZ_CO_MODULE := SeaMonkeyAll
|
||||
endif
|
||||
CVSCO_SEAMONKEY := $(CVSCO) $(CVS_CO_DATE_FLAGS) $(MOZ_CO_MODULE)
|
||||
|
||||
####################################
|
||||
# CVS defined for libart (pulled and built if MOZ_INTERNAL_LIBART_LGPL is set)
|
||||
#
|
||||
CVSCO_LIBART := $(CVSCO) $(CVS_CO_DATE_FLAGS) mozilla/other-licenses/libart_lgpl
|
||||
|
||||
ifdef MOZ_INTERNAL_LIBART_LGPL
|
||||
FASTUPDATE_LIBART := fast_update $(CVSCO_LIBART)
|
||||
CHECKOUT_LIBART := cvs_co $(CVSCO_LIBART)
|
||||
else
|
||||
CHECKOUT_LIBART := true
|
||||
FASTUPDATE_LIBART := true
|
||||
endif
|
||||
|
||||
####################################
|
||||
# CVS defines for Calendar (pulled and built if MOZ_CALENDAR is set)
|
||||
#
|
||||
CVSCO_CALENDAR := $(CVSCO) $(CVS_CO_DATE_FLAGS) mozilla/calendar
|
||||
|
||||
ifdef MOZ_CALENDAR
|
||||
FASTUPDATE_CALENDAR := fast_update $(CVSCO_CALENDAR)
|
||||
CHECKOUT_CALENDAR := cvs_co $(CVSCO_CALENDAR)
|
||||
else
|
||||
CHECKOUT_CALENDAR := true
|
||||
FASTUPDATE_CALENDAR := true
|
||||
endif
|
||||
|
||||
|
||||
# because some cygwin tools can't handle native dos-drive paths & vice-versa
|
||||
# force configure to use a relative path for --srcdir
|
||||
# need a better check for win32
|
||||
# and we need to get OBJDIR earlier
|
||||
ifdef MOZ_TOOLS
|
||||
_tmpobjdir := $(shell cygpath -u $(OBJDIR))
|
||||
_abs2rel := $(shell cygpath -w $(TOPSRCDIR)/build/unix/abs2rel.pl | sed -e 's|\\|/|g')
|
||||
_OBJ2SRCPATH := $(shell $(_abs2rel) $(TOPSRCDIR) $(_tmpobjdir))
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
# Rules
|
||||
#
|
||||
|
||||
# Print out any options loaded from mozconfig.
|
||||
all build checkout clean depend distclean export libs install realclean::
|
||||
@if test -f .mozconfig.out; then \
|
||||
cat .mozconfig.out; \
|
||||
rm -f .mozconfig.out; \
|
||||
else true; \
|
||||
fi
|
||||
|
||||
ifdef _IS_FIRST_CHECKOUT
|
||||
all:: checkout build
|
||||
else
|
||||
all:: checkout alldep
|
||||
endif
|
||||
|
||||
# Windows equivalents
|
||||
pull_all: checkout
|
||||
build_all: build
|
||||
build_all_dep: alldep
|
||||
build_all_depend: alldep
|
||||
clobber clobber_all: clean
|
||||
pull_and_build_all: checkout alldep
|
||||
|
||||
# Do everything from scratch
|
||||
everything: checkout clean build
|
||||
|
||||
####################################
|
||||
# CVS checkout
|
||||
#
|
||||
checkout::
|
||||
# @: Backup the last checkout log.
|
||||
@if test -f $(CVSCO_LOGFILE) ; then \
|
||||
mv $(CVSCO_LOGFILE) $(CVSCO_LOGFILE).old; \
|
||||
else true; \
|
||||
fi
|
||||
ifdef RUN_AUTOCONF_LOCALLY
|
||||
@echo "Removing local configures" ; \
|
||||
cd $(ROOTDIR) && \
|
||||
$(RM) -f mozilla/configure mozilla/nsprpub/configure \
|
||||
mozilla/directory/c-sdk/configure
|
||||
endif
|
||||
@echo "checkout start: "`date` | tee $(CVSCO_LOGFILE)
|
||||
@echo '$(CVSCO) mozilla/client.mk mozilla/build/unix/modules.mk'; \
|
||||
cd $(ROOTDIR) && \
|
||||
$(CVSCO) mozilla/client.mk mozilla/build/unix/modules.mk
|
||||
@cd $(ROOTDIR) && $(MAKE) -f mozilla/client.mk real_checkout
|
||||
|
||||
real_checkout:
|
||||
# @: Start the checkout. Split the output to the tty and a log file. \
|
||||
# : If it fails, touch an error file because "tee" hides the error.
|
||||
@failed=.cvs-failed.tmp; rm -f $$failed*; \
|
||||
cvs_co() { echo "$$@" ; \
|
||||
("$$@" || touch $$failed) 2>&1 | tee -a $(CVSCO_LOGFILE) && \
|
||||
if test -f $$failed; then false; else true; fi; }; \
|
||||
cvs_co $(CVSCO_NSPR) && \
|
||||
cvs_co $(CVSCO_NSS) && \
|
||||
cvs_co $(CVSCO_PSM) && \
|
||||
cvs_co $(CVSCO_LDAPCSDK) && \
|
||||
cvs_co $(CVSCO_ACCESSIBLE) && \
|
||||
cvs_co $(CVSCO_GFX2) && \
|
||||
cvs_co $(CVSCO_IMGLIB2) && \
|
||||
$(CHECKOUT_CALENDAR) && \
|
||||
$(CHECKOUT_LIBART) && \
|
||||
cvs_co $(CVSCO_SEAMONKEY) && \
|
||||
cvs_co $(CVSCO_NOSUBDIRS)
|
||||
@echo "checkout finish: "`date` | tee -a $(CVSCO_LOGFILE)
|
||||
# @: Check the log for conflicts. ;
|
||||
@conflicts=`egrep "^C " $(CVSCO_LOGFILE)` ;\
|
||||
if test "$$conflicts" ; then \
|
||||
echo "$(MAKE): *** Conflicts during checkout." ;\
|
||||
echo "$$conflicts" ;\
|
||||
echo "$(MAKE): Refer to $(CVSCO_LOGFILE) for full log." ;\
|
||||
false; \
|
||||
else true; \
|
||||
fi
|
||||
ifdef RUN_AUTOCONF_LOCALLY
|
||||
@echo Generating configures using $(AUTOCONF) ; \
|
||||
cd $(TOPSRCDIR) && $(AUTOCONF) && \
|
||||
cd $(TOPSRCDIR)/nsprpub && $(AUTOCONF) && \
|
||||
cd $(TOPSRCDIR)/directory/c-sdk && $(AUTOCONF)
|
||||
endif
|
||||
|
||||
fast-update:
|
||||
# @: Backup the last checkout log.
|
||||
@if test -f $(CVSCO_LOGFILE) ; then \
|
||||
mv $(CVSCO_LOGFILE) $(CVSCO_LOGFILE).old; \
|
||||
else true; \
|
||||
fi
|
||||
ifdef RUN_AUTOCONF_LOCALLY
|
||||
@echo "Removing local configures" ; \
|
||||
cd $(ROOTDIR) && \
|
||||
$(RM) -f mozilla/configure mozilla/nsprpub/configure \
|
||||
mozilla/directory/c-sdk/configure
|
||||
endif
|
||||
@echo "checkout start: "`date` | tee $(CVSCO_LOGFILE)
|
||||
@echo '$(CVSCO) mozilla/client.mk mozilla/build/unix/modules.mk'; \
|
||||
cd $(ROOTDIR) && \
|
||||
$(CVSCO) mozilla/client.mk mozilla/build/unix/modules.mk
|
||||
@cd $(TOPSRCDIR) && \
|
||||
$(MAKE) -f client.mk real_fast-update
|
||||
|
||||
real_fast-update:
|
||||
# @: Start the update. Split the output to the tty and a log file. \
|
||||
# : If it fails, touch an error file because "tee" hides the error.
|
||||
@failed=.fast_update-failed.tmp; rm -f $$failed*; \
|
||||
fast_update() { (config/cvsco-fast-update.pl $$@ || touch $$failed) 2>&1 | tee -a $(CVSCO_LOGFILE) && \
|
||||
if test -f $$failed; then false; else true; fi; }; \
|
||||
cvs_co() { echo "$$@" ; \
|
||||
("$$@" || touch $$failed) 2>&1 | tee -a $(CVSCO_LOGFILE) && \
|
||||
if test -f $$failed; then false; else true; fi; }; \
|
||||
fast_update $(CVSCO_NSPR) && \
|
||||
cd $(ROOTDIR) && \
|
||||
failed=mozilla/.fast_update-failed.tmp && \
|
||||
cvs_co $(CVSCO_NSS) && \
|
||||
failed=.fast_update-failed.tmp && \
|
||||
cd mozilla && \
|
||||
fast_update $(CVSCO_PSM) && \
|
||||
fast_update $(CVSCO_LDAPCSDK) && \
|
||||
fast_update $(CVSCO_ACCESSIBLE) && \
|
||||
fast_update $(CVSCO_GFX2) && \
|
||||
fast_update $(CVSCO_IMGLIB2) && \
|
||||
$(FASTUPDATE_CALENDAR) && \
|
||||
$(FASTUPDATE_LIBART) && \
|
||||
fast_update $(CVSCO_SEAMONKEY) && \
|
||||
fast_update $(CVSCO_NOSUBDIRS)
|
||||
@echo "fast_update finish: "`date` | tee -a $(CVSCO_LOGFILE)
|
||||
# @: Check the log for conflicts. ;
|
||||
@conflicts=`egrep "^C " $(CVSCO_LOGFILE)` ;\
|
||||
if test "$$conflicts" ; then \
|
||||
echo "$(MAKE): *** Conflicts during fast-update." ;\
|
||||
echo "$$conflicts" ;\
|
||||
echo "$(MAKE): Refer to $(CVSCO_LOGFILE) for full log." ;\
|
||||
false; \
|
||||
else true; \
|
||||
fi
|
||||
ifdef RUN_AUTOCONF_LOCALLY
|
||||
@echo Generating configures using $(AUTOCONF) ; \
|
||||
cd $(TOPSRCDIR) && $(AUTOCONF) && \
|
||||
cd $(TOPSRCDIR)/nsprpub && $(AUTOCONF) && \
|
||||
cd $(TOPSRCDIR)/directory/c-sdk && $(AUTOCONF)
|
||||
endif
|
||||
|
||||
####################################
|
||||
# Web configure
|
||||
|
||||
WEBCONFIG_FILE := $(HOME)/.mozconfig
|
||||
|
||||
MOZCONFIG2CONFIGURATOR := build/autoconf/mozconfig2configurator
|
||||
webconfig:
|
||||
@cd $(TOPSRCDIR); \
|
||||
url=`$(MOZCONFIG2CONFIGURATOR) $(TOPSRCDIR)`; \
|
||||
echo Running mozilla with the following url: ;\
|
||||
echo ;\
|
||||
echo $$url ;\
|
||||
mozilla -remote "openURL($$url)" || \
|
||||
netscape -remote "openURL($$url)" || \
|
||||
mozilla $$url || \
|
||||
netscape $$url ;\
|
||||
echo ;\
|
||||
echo 1. Fill out the form on the browser. ;\
|
||||
echo 2. Save the results to $(WEBCONFIG_FILE)
|
||||
|
||||
#####################################################
|
||||
# First Checkout
|
||||
|
||||
ifdef _IS_FIRST_CHECKOUT
|
||||
# First time, do build target in a new process to pick up new files.
|
||||
build::
|
||||
$(MAKE) -f $(TOPSRCDIR)/client.mk build
|
||||
else
|
||||
|
||||
#####################################################
|
||||
# After First Checkout
|
||||
|
||||
|
||||
####################################
|
||||
# Configure
|
||||
|
||||
CONFIG_STATUS := $(wildcard $(OBJDIR)/config.status)
|
||||
CONFIG_CACHE := $(wildcard $(OBJDIR)/config.cache)
|
||||
|
||||
ifdef RUN_AUTOCONF_LOCALLY
|
||||
EXTRA_CONFIG_DEPS := \
|
||||
$(TOPSRCDIR)/aclocal.m4 \
|
||||
$(wildcard $(TOPSRCDIR)/build/autoconf/*.m4) \
|
||||
$(NULL)
|
||||
|
||||
$(TOPSRCDIR)/configure: $(TOPSRCDIR)/configure.in $(EXTRA_CONFIG_DEPS)
|
||||
@echo Generating $@ using autoconf
|
||||
cd $(TOPSRCDIR); $(AUTOCONF)
|
||||
endif
|
||||
|
||||
CONFIG_STATUS_DEPS_L10N := $(wildcard $(TOPSRCDIR)/l10n/makefiles.all)
|
||||
|
||||
CONFIG_STATUS_DEPS := \
|
||||
$(TOPSRCDIR)/configure \
|
||||
$(TOPSRCDIR)/allmakefiles.sh \
|
||||
$(TOPSRCDIR)/.mozconfig.mk \
|
||||
$(wildcard $(TOPSRCDIR)/nsprpub/configure) \
|
||||
$(wildcard $(TOPSRCDIR)/directory/c-sdk/configure) \
|
||||
$(wildcard $(TOPSRCDIR)/mailnews/makefiles) \
|
||||
$(CONFIG_STATUS_DEPS_L10N) \
|
||||
$(wildcard $(TOPSRCDIR)/themes/makefiles) \
|
||||
$(NULL)
|
||||
|
||||
# configure uses the program name to determine @srcdir@. Calling it without
|
||||
# $(TOPSRCDIR) will set @srcdir@ to "."; otherwise, it is set to the full
|
||||
# path of $(TOPSRCDIR).
|
||||
ifeq ($(TOPSRCDIR),$(OBJDIR))
|
||||
CONFIGURE := ./configure
|
||||
else
|
||||
CONFIGURE := $(TOPSRCDIR)/configure
|
||||
endif
|
||||
|
||||
ifdef _OBJ2SRCPATH
|
||||
CONFIGURE_ARGS := --srcdir=$(_OBJ2SRCPATH) $(CONFIGURE_ARGS)
|
||||
endif
|
||||
|
||||
$(OBJDIR)/Makefile $(OBJDIR)/config.status: $(CONFIG_STATUS_DEPS)
|
||||
@if test ! -d $(OBJDIR); then $(MKDIR) $(OBJDIR); else true; fi
|
||||
@echo cd $(OBJDIR);
|
||||
@echo $(CONFIGURE) $(CONFIGURE_ARGS)
|
||||
@cd $(OBJDIR) && $(CONFIGURE_ENV_ARGS) $(CONFIGURE) $(CONFIGURE_ARGS) \
|
||||
|| ( echo "*** Fix above errors and then restart with\
|
||||
\"$(MAKE) -f client.mk build\"" && exit 1 )
|
||||
@touch $(OBJDIR)/Makefile
|
||||
|
||||
ifdef CONFIG_STATUS
|
||||
$(OBJDIR)/config/autoconf.mk: $(TOPSRCDIR)/config/autoconf.mk.in
|
||||
cd $(OBJDIR); \
|
||||
CONFIG_FILES=config/autoconf.mk ./config.status
|
||||
endif
|
||||
|
||||
|
||||
####################################
|
||||
# Depend
|
||||
|
||||
depend:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
|
||||
$(MOZ_MAKE) export && $(MOZ_MAKE) depend
|
||||
|
||||
####################################
|
||||
# Build it
|
||||
|
||||
build:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
|
||||
$(MOZ_MAKE)
|
||||
|
||||
####################################
|
||||
# Other targets
|
||||
|
||||
# Pass these target onto the real build system
|
||||
install export libs clean realclean distclean alldep:: $(OBJDIR)/Makefile $(OBJDIR)/config.status
|
||||
$(MOZ_MAKE) $@
|
||||
|
||||
cleansrcdir:
|
||||
@cd $(TOPSRCDIR); \
|
||||
if [ -f webshell/embed/gtk/Makefile ]; then \
|
||||
$(MAKE) -C webshell/embed/gtk distclean; \
|
||||
fi; \
|
||||
if [ -f Makefile ]; then \
|
||||
$(MAKE) distclean ; \
|
||||
else \
|
||||
echo "Removing object files from srcdir..."; \
|
||||
rm -fr `find . -type d \( -name .deps -print -o -name CVS \
|
||||
-o -exec test ! -d {}/CVS \; \) -prune \
|
||||
-o \( -name '*.[ao]' -o -name '*.so' \) -type f -print`; \
|
||||
build/autoconf/clean-config.sh; \
|
||||
fi;
|
||||
|
||||
# (! IS_FIRST_CHECKOUT)
|
||||
endif
|
||||
|
||||
.PHONY: checkout real_checkout depend build export libs alldep install clean realclean distclean cleansrcdir pull_all build_all clobber clobber_all pull_and_build_all everything
|
||||
214
mozilla/js/rhino/Makefile
Normal file
214
mozilla/js/rhino/Makefile
Normal file
@@ -0,0 +1,214 @@
|
||||
#! gmake
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is Rhino code, released
|
||||
# May 6, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU Public License (the "GPL"), in which case the
|
||||
# provisions of the GPL are applicable instead of those above.
|
||||
# If you wish to allow use of your version of this file only
|
||||
# under the terms of the GPL and not to allow others to use your
|
||||
# version of this file under the NPL, indicate your decision by
|
||||
# deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this
|
||||
# file under either the NPL or the GPL.
|
||||
|
||||
#
|
||||
# Makefile for javascript in java.
|
||||
#
|
||||
|
||||
# This makefile is intended for packaging releases, and probably isn't
|
||||
# suitable for production use - it doesn't attempt to do understand
|
||||
# java dependencies beyond the package level.
|
||||
#
|
||||
# The makefiles for the subdirectories included in this package are
|
||||
# intended to be called by this makefile with the proper CLASSDIR,
|
||||
# PATH_PREFIX etc. variables. Makefiles in subdirectories are
|
||||
# actually executed in the toplevel directory, with the PATH_PREFIX
|
||||
# variable set to the subdirectory where the makefile is located.
|
||||
#
|
||||
# Initial version courtesy Mike Ang.
|
||||
# Next version by Mike McCabe
|
||||
|
||||
# Don't include SHELL define (per GNU manual recommendation) because it
|
||||
# breaks WinNT (with GNU make) builds.
|
||||
# SHELL = /bin/sh
|
||||
|
||||
# Some things we might want to tweek.
|
||||
|
||||
CLASSDIR = classes
|
||||
|
||||
PACKAGE_NAME = org.mozilla.javascript
|
||||
PACKAGE_PATH = org/mozilla/javascript
|
||||
|
||||
# jar filenames and the directories that build them.
|
||||
JS_JAR = js.jar
|
||||
JS_DIR = $(PACKAGE_PATH)
|
||||
JSTOOLS_JAR = jstools.jar
|
||||
JSTOOLS_DIR = $(PACKAGE_PATH)/tools
|
||||
|
||||
JARS = $(JS_JAR) $(JSTOOLS_JAR)
|
||||
|
||||
# It's not polite to store toplevel files in a tarball or zip files.
|
||||
# What is the name of the toplevel directory to store files in?
|
||||
# XXX we should probably add versioning to this.
|
||||
DIST_DIR = jsjava
|
||||
|
||||
# XXX test this with sj
|
||||
JAVAC = javac
|
||||
|
||||
# We don't define JFLAGS but we do export it to child
|
||||
# builds in case it's defined by the environment.
|
||||
# To build optimized (with javac) say 'make JFLAGS=-O'
|
||||
|
||||
GZIP = gzip
|
||||
ZIP = zip
|
||||
UNZIP = unzip
|
||||
|
||||
# Shouldn't need to change anything below here.
|
||||
|
||||
# For Windows NT builds (under GNU make).
|
||||
ifeq ($(OS_TARGET), WINNT)
|
||||
CLASSPATHSEP = '\\;'
|
||||
else
|
||||
CLASSPATHSEP = :
|
||||
endif
|
||||
|
||||
# Make compatibility - use these instead of gmake 'export VARIABLE'
|
||||
EXPORTS = CLASSDIR=$(CLASSDIR) JAVAC=$(JAVAC) JFLAGS=$(JFLAGS) SHELL=$(SHELL) \
|
||||
PACKAGE_PATH=$(PACKAGE_PATH) PACKAGE_NAME=$(PACKAGE_NAME)
|
||||
|
||||
helpmessage : FORCE
|
||||
@echo 'Targets include:'
|
||||
@echo ' all - make jars, examples'
|
||||
@echo ' jars - make js.jar, jstools.jar'
|
||||
@echo ' fast - quick-and-dirty "make jars", for development'
|
||||
@echo ' examples - build the .class files in the examples directory'
|
||||
@echo ' check - perform checks on the source.'
|
||||
@echo ' clean - remove intermediate files'
|
||||
@echo ' clobber - make clean, and remove .jar files'
|
||||
@echo ' zip - make a distribution .zip file'
|
||||
@echo ' zip-source - make a distribution .zip file, with source'
|
||||
@echo ' tar - make a distribution .tar.gz file'
|
||||
@echo ' tar-source - make a distribution .tar.gz, with source'
|
||||
@echo
|
||||
@echo 'Define OS_TARGET to "WINNT" to build on Windows NT with GNU make.'
|
||||
@echo
|
||||
|
||||
all : jars examples
|
||||
|
||||
jars : $(JARS)
|
||||
|
||||
fast : fast_$(JS_JAR) $(JSTOOLS_JAR)
|
||||
|
||||
# Always call the sub-Makefile - which may decide that the jar is up to date.
|
||||
$(JS_JAR) : FORCE
|
||||
$(MAKE) -f $(JS_DIR)/Makefile JAR=$(@) $(EXPORTS) \
|
||||
PATH_PREFIX=$(JS_DIR) \
|
||||
CLASSPATH=.
|
||||
|
||||
fast_$(JS_JAR) :
|
||||
$(MAKE) -f $(JS_DIR)/Makefile JAR=$(JS_JAR) $(EXPORTS) \
|
||||
PATH_PREFIX=$(JS_DIR) \
|
||||
CLASSPATH=. \
|
||||
fast
|
||||
|
||||
$(JSTOOLS_JAR) : $(JS_JAR) FORCE
|
||||
$(MAKE) -f $(JSTOOLS_DIR)/Makefile JAR=$(@) $(EXPORTS) \
|
||||
PATH_PREFIX=$(JSTOOLS_DIR) \
|
||||
CLASSPATH=./$(JS_JAR)$(CLASSPATHSEP).
|
||||
|
||||
examples : $(JS_JAR) FORCE
|
||||
$(MAKE) -f examples/Makefile $(EXPORTS) \
|
||||
PATH_PREFIX=examples \
|
||||
CLASSPATH=./$(JS_JAR)
|
||||
|
||||
# We ask the subdirs to update their MANIFESTs
|
||||
MANIFEST : FORCE
|
||||
$(MAKE) -f $(JS_DIR)/Makefile JAR=$(JS_JAR) $(EXPORTS) \
|
||||
PATH_PREFIX=$(JS_DIR) $(JS_DIR)/MANIFEST
|
||||
$(MAKE) -f $(JSTOOLS_DIR)/Makefile JAR=$(JSTOOLS_JAR) $(EXPORTS) \
|
||||
PATH_PREFIX=$(JSTOOLS_DIR) $(JSTOOLS_DIR)/MANIFEST
|
||||
$(MAKE) -f examples/Makefile $(EXPORTS) \
|
||||
PATH_PREFIX=examples examples/MANIFEST
|
||||
# so ls below always has something to work on
|
||||
touch MANIFEST
|
||||
# examples/Makefile doesn't get included in the
|
||||
# MANIFEST file, (which is used to create the non-source distribution) so
|
||||
# we include it here.
|
||||
cat examples/MANIFEST $(JS_DIR)/MANIFEST \
|
||||
$(JSTOOLS_DIR)/MANIFEST \
|
||||
| xargs ls MANIFEST README.html \
|
||||
$(JARS) \
|
||||
Makefile examples/Makefile \
|
||||
> $(@)
|
||||
|
||||
# Make a MANIFEST file containing only the binaries and documentation.
|
||||
# This could be abstracted further...
|
||||
MANIFEST_binonly : MANIFEST
|
||||
cat examples/MANIFEST \
|
||||
| xargs ls $(JARS) README.html MANIFEST > MANIFEST
|
||||
|
||||
# A subroutine - not intended to be called from outside the makefile.
|
||||
do_zip :
|
||||
# Make sure we get a fresh one
|
||||
- rm -r $(DIST_DIR)
|
||||
- mkdir $(DIST_DIR)
|
||||
- rm $(DIST_DIR).zip
|
||||
cat MANIFEST | xargs $(ZIP) -0 -q $(DIST_DIR).zip
|
||||
mv $(DIST_DIR).zip $(DIST_DIR)
|
||||
cd $(DIST_DIR) ; \
|
||||
$(UNZIP) -q $(DIST_DIR).zip ; \
|
||||
rm $(DIST_DIR).zip
|
||||
$(ZIP) -r -9 -q $(DIST_DIR).zip $(DIST_DIR)
|
||||
- rm -r $(DIST_DIR)
|
||||
|
||||
zip : check jars examples MANIFEST_binonly do_zip
|
||||
|
||||
zip-source : check jars examples MANIFEST do_zip
|
||||
|
||||
# A subroutine - not intended to be called from outside the makefile.
|
||||
do_tar :
|
||||
- rm -r $(DIST_DIR)
|
||||
- mkdir $(DIST_DIR)
|
||||
- rm $(DIST_DIR).tar $(DIST_DIR).tar.gz
|
||||
cat MANIFEST | xargs tar cf $(DIST_DIR).tar
|
||||
mv $(DIST_DIR).tar $(DIST_DIR)
|
||||
cd $(DIST_DIR) ; \
|
||||
tar xf $(DIST_DIR).tar ; \
|
||||
rm $(DIST_DIR).tar
|
||||
tar cf $(DIST_DIR).tar $(DIST_DIR)
|
||||
- rm -r $(DIST_DIR)
|
||||
$(GZIP) -9 $(DIST_DIR).tar
|
||||
|
||||
tar: check jars examples MANIFEST_binonly do_tar
|
||||
|
||||
tar-source : check jars examples MANIFEST do_tar
|
||||
|
||||
# These commands just get passed to the respective sub-Makefiles.
|
||||
clean clobber check:
|
||||
$(MAKE) -f $(JS_DIR)/Makefile $(EXPORTS) JAR=$(JS_JAR) \
|
||||
PATH_PREFIX=$(JS_DIR) $(@)
|
||||
$(MAKE) -f $(JSTOOLS_DIR)/Makefile $(EXPORTS) JAR=$(JSTOOLS_JAR) \
|
||||
PATH_PREFIX=$(JSTOOLS_DIR) $(@)
|
||||
$(MAKE) -f examples/Makefile $(EXPORTS) PATH_PREFIX=examples $(@)
|
||||
|
||||
#emulate .PHONY
|
||||
FORCE :
|
||||
46
mozilla/js/rhino/README.html
Normal file
46
mozilla/js/rhino/README.html
Normal file
@@ -0,0 +1,46 @@
|
||||
<html>
|
||||
<!--
|
||||
- The contents of this file are subject to the Netscape Public
|
||||
- License Version 1.1 (the "License"); you may not use this file
|
||||
- except in compliance with the License. You may obtain a copy of
|
||||
- the License at http://www.mozilla.org/NPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS
|
||||
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
- implied. See the License for the specific language governing
|
||||
- rights and limitations under the License.
|
||||
-
|
||||
- The Original Code is Rhino code, released
|
||||
- May 6, 1999.
|
||||
-
|
||||
- The Initial Developer of the Original Code is Netscape
|
||||
- Communications Corporation. Portions created by Netscape are
|
||||
- Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
- Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Norris Boyd
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the
|
||||
- terms of the GNU Public License (the "GPL"), in which case the
|
||||
- provisions of the GPL are applicable instead of those above.
|
||||
- If you wish to allow use of your version of this file only
|
||||
- under the terms of the GPL and not to allow others to use your
|
||||
- version of this file under the NPL, indicate your decision by
|
||||
- deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the GPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this
|
||||
- file under either the NPL or the GPL.
|
||||
-->
|
||||
<body>
|
||||
<h1>
|
||||
<span CLASS=LXRSHORTDESC>
|
||||
Rhino: JavaScript in Java<p>
|
||||
</span>
|
||||
</h1>
|
||||
<span CLASS=LXRLONGDESC>
|
||||
Rhino is an implementation of JavaScript in Java. Documentation can be found
|
||||
<a href="http://www.mozilla.org/js/rhino/rhino.html">here</a>.
|
||||
</span>
|
||||
</body>
|
||||
</html>
|
||||
105
mozilla/js/rhino/examples/Control.java
Normal file
105
mozilla/js/rhino/examples/Control.java
Normal file
@@ -0,0 +1,105 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
import org.mozilla.javascript.*;
|
||||
|
||||
/**
|
||||
* Example of controlling the JavaScript execution engine.
|
||||
*
|
||||
* We evaluate a script and then manipulate the result.
|
||||
*
|
||||
*/
|
||||
public class Control {
|
||||
|
||||
/**
|
||||
* Main entry point.
|
||||
*
|
||||
* Process arguments as would a normal Java program. Also
|
||||
* create a new Context and associate it with the current thread.
|
||||
* Then set up the execution environment and begin to
|
||||
* execute scripts.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Context cx = Context.enter();
|
||||
|
||||
// Set version to JavaScript1.2 so that we get object-literal style
|
||||
// printing instead of "[object Object]"
|
||||
cx.setLanguageVersion(Context.VERSION_1_2);
|
||||
|
||||
// Initialize the standard objects (Object, Function, etc.)
|
||||
// This must be done before scripts can be executed.
|
||||
Scriptable scope = cx.initStandardObjects(null);
|
||||
|
||||
// Now we can evaluate a script. Let's create a new object
|
||||
// using the object literal notation.
|
||||
Object result = null;
|
||||
try {
|
||||
result = cx.evaluateString(scope, "obj = {a:1, b:['x','y']}",
|
||||
"MySource", 1, null);
|
||||
}
|
||||
catch (JavaScriptException jse) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
Scriptable obj = (Scriptable) scope.get("obj", scope);
|
||||
|
||||
// Should print "obj == result" (Since the result of an assignment
|
||||
// expression is the value that was assigned)
|
||||
System.out.println("obj " + (obj == result ? "==" : "!=") +
|
||||
" result");
|
||||
|
||||
// Should print "obj.a == 1"
|
||||
System.out.println("obj.a == " + obj.get("a", obj));
|
||||
|
||||
Scriptable b = (Scriptable) obj.get("b", obj);
|
||||
|
||||
// Should print "obj.b[0] == x"
|
||||
System.out.println("obj.b[0] == " + b.get(0, b));
|
||||
|
||||
// Should print "obj.b[1] == y"
|
||||
System.out.println("obj.b[1] == " + b.get(1, b));
|
||||
|
||||
try {
|
||||
// Should print {a:1, b:["x", "y"]}
|
||||
Function fn = (Function) ScriptableObject.getProperty(obj, "toString");
|
||||
System.out.println(fn.call(cx, scope, obj, new Object[0]));
|
||||
} catch (JavaScriptException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
cx.exit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
55
mozilla/js/rhino/examples/Counter.java
Normal file
55
mozilla/js/rhino/examples/Counter.java
Normal file
@@ -0,0 +1,55 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
import org.mozilla.javascript.*;
|
||||
|
||||
public class Counter extends ScriptableObject {
|
||||
// The zero-argument constructor used by Rhino runtime to create instances
|
||||
public Counter() { }
|
||||
|
||||
// Method jsConstructor defines the JavaScript constructor
|
||||
public void jsConstructor(int a) { count = a; }
|
||||
|
||||
// The class name is defined by the getClassName method
|
||||
public String getClassName() { return "Counter"; }
|
||||
|
||||
// The method jsGet_count defines the count property.
|
||||
public int jsGet_count() { return count++; }
|
||||
|
||||
// Methods can be defined using the jsFunction_ prefix. Here we define
|
||||
// resetCount for JavaScript.
|
||||
public void jsFunction_resetCount() { count = 0; }
|
||||
|
||||
private int count;
|
||||
}
|
||||
178
mozilla/js/rhino/examples/DynamicScopes.java
Normal file
178
mozilla/js/rhino/examples/DynamicScopes.java
Normal file
@@ -0,0 +1,178 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
import org.mozilla.javascript.*;
|
||||
|
||||
/**
|
||||
* Example of controlling the JavaScript with multiple scopes and threads.
|
||||
*/
|
||||
public class DynamicScopes {
|
||||
|
||||
/**
|
||||
* Main entry point.
|
||||
*
|
||||
* Set up the shared scope and then spawn new threads that execute
|
||||
* relative to that shared scope. Try compiling functions with and
|
||||
* without dynamic scope to see the effect.
|
||||
*
|
||||
* The expected output is
|
||||
* <pre>
|
||||
* sharedScope
|
||||
* sharedScope
|
||||
* sharedScope
|
||||
* thread0
|
||||
* thread1
|
||||
* thread2
|
||||
* </pre>
|
||||
* The final three lines may be permuted in any order depending on
|
||||
* thread scheduling.
|
||||
*/
|
||||
public static void main(String[] args)
|
||||
throws JavaScriptException
|
||||
{
|
||||
Context cx = Context.enter();
|
||||
try {
|
||||
cx.setCompileFunctionsWithDynamicScope(false);
|
||||
runScripts(cx);
|
||||
cx.setCompileFunctionsWithDynamicScope(true);
|
||||
runScripts(cx);
|
||||
} finally {
|
||||
cx.exit();
|
||||
}
|
||||
}
|
||||
|
||||
static void runScripts(Context cx)
|
||||
throws JavaScriptException
|
||||
{
|
||||
// Initialize the standard objects (Object, Function, etc.)
|
||||
// This must be done before scripts can be executed. The call
|
||||
// returns a new scope that we will share.
|
||||
Scriptable scope = cx.initStandardObjects(null);
|
||||
|
||||
// Now we can evaluate a script and functions will be compiled to
|
||||
// use dynamic scope if the Context is so initialized.
|
||||
String source = "var x = 'sharedScope';" +
|
||||
"function f() { return x; }";
|
||||
cx.evaluateString(scope, source, "MySource", 1, null);
|
||||
|
||||
// Now we spawn some threads that execute a script that calls the
|
||||
// function 'f'. The scope chain looks like this:
|
||||
// <pre>
|
||||
// ------------------
|
||||
// | shared scope |
|
||||
// ------------------
|
||||
// ^
|
||||
// |
|
||||
// ------------------
|
||||
// | per-thread scope |
|
||||
// ------------------
|
||||
// ^
|
||||
// |
|
||||
// ------------------
|
||||
// | f's activation |
|
||||
// ------------------
|
||||
// </pre>
|
||||
// Both the shared scope and the per-thread scope have variables 'x'
|
||||
// defined in them. If 'f' is compiled with dynamic scope enabled,
|
||||
// the 'x' from the per-thread scope will be used. Otherwise, the 'x'
|
||||
// from the shared scope will be used. The 'x' defined in 'g' (which
|
||||
// calls 'f') should not be seen by 'f'.
|
||||
final int threadCount = 3;
|
||||
Thread[] t = new Thread[threadCount];
|
||||
for (int i=0; i < threadCount; i++) {
|
||||
String script = "function g() { var x = 'local'; return f(); }" +
|
||||
"java.lang.System.out.println(g());";
|
||||
t[i] = new Thread(new PerThread(scope, script,
|
||||
"thread" + i));
|
||||
}
|
||||
for (int i=0; i < threadCount; i++)
|
||||
t[i].start();
|
||||
// Don't return in this thread until all the spawned threads have
|
||||
// completed.
|
||||
for (int i=0; i < threadCount; i++) {
|
||||
try {
|
||||
t[i].join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class PerThread implements Runnable {
|
||||
|
||||
PerThread(Scriptable scope, String script, String x) {
|
||||
this.scope = scope;
|
||||
this.script = script;
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
// We need a new Context for this thread.
|
||||
Context cx = Context.enter();
|
||||
try {
|
||||
// We can share the scope.
|
||||
Scriptable threadScope = cx.newObject(scope);
|
||||
threadScope.setPrototype(scope);
|
||||
|
||||
// We want "threadScope" to be a new top-level
|
||||
// scope, so set its parent scope to null. This
|
||||
// means that any variables created by assignments
|
||||
// will be properties of "threadScope".
|
||||
threadScope.setParentScope(null);
|
||||
|
||||
// Create a JavaScript property of the thread scope named
|
||||
// 'x' and save a value for it.
|
||||
threadScope.put("x", threadScope, x);
|
||||
cx.evaluateString(threadScope, script, "threadScript", 1, null);
|
||||
}
|
||||
catch (NotAFunctionException jse) {
|
||||
// ignore
|
||||
}
|
||||
catch (PropertyException jse) {
|
||||
// ignore
|
||||
}
|
||||
catch (JavaScriptException jse) {
|
||||
// ignore
|
||||
}
|
||||
finally {
|
||||
Context.exit();
|
||||
}
|
||||
}
|
||||
private Scriptable scope;
|
||||
private String script;
|
||||
private String x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
356
mozilla/js/rhino/examples/File.java
Normal file
356
mozilla/js/rhino/examples/File.java
Normal file
@@ -0,0 +1,356 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
import org.mozilla.javascript.*;
|
||||
import java.io.*;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Define a simple JavaScript File object.
|
||||
*
|
||||
* This isn't intended to be any sort of definitive attempt at a
|
||||
* standard File object for JavaScript, but instead is an example
|
||||
* of a more involved definition of a host object.
|
||||
*
|
||||
* Example of use of the File object:
|
||||
* <pre>
|
||||
* js> defineClass("File")
|
||||
* js> file = new File("myfile.txt");
|
||||
* [object File]
|
||||
* js> file.writeLine("one"); <i>only now is file actually opened</i>
|
||||
* js> file.writeLine("two");
|
||||
* js> file.writeLine("thr", "ee");
|
||||
* js> file.close(); <i>must close file before we can reopen for reading</i>
|
||||
* js> var a = file.readLines(); <i>creates and fills an array with the contents of the file</i>
|
||||
* js> a;
|
||||
* one,two,three
|
||||
* js>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* File errors or end-of-file signaled by thrown Java exceptions will
|
||||
* be wrapped as JavaScript exceptions when called from JavaScript,
|
||||
* and may be caught within JavaScript.
|
||||
*
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public class File extends ScriptableObject {
|
||||
|
||||
/**
|
||||
* The zero-parameter constructor.
|
||||
*
|
||||
* When Context.defineClass is called with this class, it will
|
||||
* construct File.prototype using this constructor.
|
||||
*/
|
||||
public File() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The Java method defining the JavaScript File constructor.
|
||||
*
|
||||
* If the constructor has one or more arguments, and the
|
||||
* first argument is not undefined, the argument is converted
|
||||
* to a string as used as the filename.<p>
|
||||
*
|
||||
* Otherwise System.in or System.out is assumed as appropriate
|
||||
* to the use.
|
||||
*/
|
||||
public static Scriptable jsConstructor(Context cx, Object[] args,
|
||||
Function ctorObj,
|
||||
boolean inNewExpr)
|
||||
{
|
||||
File result = new File();
|
||||
if (args.length == 0 || args[0] == Context.getUndefinedValue()) {
|
||||
result.name = "";
|
||||
result.file = null;
|
||||
} else {
|
||||
result.name = Context.toString(args[0]);
|
||||
result.file = new java.io.File(result.name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this JavaScript class, "File".
|
||||
*/
|
||||
public String getClassName() {
|
||||
return "File";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the file.
|
||||
*
|
||||
* Used to define the "name" property.
|
||||
*/
|
||||
public String jsGet_name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the remaining lines in the file and return them in an array.
|
||||
*
|
||||
* Implements a JavaScript function.<p>
|
||||
*
|
||||
* This is a good example of creating a new array and setting
|
||||
* elements in that array.
|
||||
*
|
||||
* @exception IOException if an error occurred while accessing the file
|
||||
* associated with this object
|
||||
* @exception JavaScriptException if a JavaScript exception occurred
|
||||
* while creating the result array
|
||||
*/
|
||||
public Object jsFunction_readLines()
|
||||
throws IOException, JavaScriptException
|
||||
{
|
||||
Vector v = new Vector();
|
||||
String s;
|
||||
while ((s = jsFunction_readLine()) != null) {
|
||||
v.addElement(s);
|
||||
}
|
||||
Object[] lines = new Object[v.size()];
|
||||
v.copyInto(lines);
|
||||
|
||||
Scriptable scope = ScriptableObject.getTopLevelScope(this);
|
||||
Scriptable result;
|
||||
try {
|
||||
Context cx = Context.getCurrentContext();
|
||||
result = cx.newObject(scope, "Array", lines);
|
||||
} catch (PropertyException e) {
|
||||
throw Context.reportRuntimeError(e.getMessage());
|
||||
} catch (NotAFunctionException e) {
|
||||
throw Context.reportRuntimeError(e.getMessage());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a line.
|
||||
*
|
||||
* Implements a JavaScript function.
|
||||
* @exception IOException if an error occurred while accessing the file
|
||||
* associated with this object, or EOFException if the object
|
||||
* reached the end of the file
|
||||
*/
|
||||
public String jsFunction_readLine() throws IOException {
|
||||
return getReader().readLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a character.
|
||||
*
|
||||
* @exception IOException if an error occurred while accessing the file
|
||||
* associated with this object, or EOFException if the object
|
||||
* reached the end of the file
|
||||
*/
|
||||
public String jsFunction_readChar() throws IOException {
|
||||
int i = getReader().read();
|
||||
if (i == -1)
|
||||
return null;
|
||||
char[] charArray = { (char) i };
|
||||
return new String(charArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write strings.
|
||||
*
|
||||
* Implements a JavaScript function. <p>
|
||||
*
|
||||
* This function takes a variable number of arguments, converts
|
||||
* each argument to a string, and writes that string to the file.
|
||||
* @exception IOException if an error occurred while accessing the file
|
||||
* associated with this object
|
||||
*/
|
||||
public static void jsFunction_write(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
throws IOException
|
||||
{
|
||||
write0(thisObj, args, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write strings and a newline.
|
||||
*
|
||||
* Implements a JavaScript function.
|
||||
* @exception IOException if an error occurred while accessing the file
|
||||
* associated with this object
|
||||
*
|
||||
*/
|
||||
public static void jsFunction_writeLine(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
throws IOException
|
||||
{
|
||||
write0(thisObj, args, true);
|
||||
}
|
||||
|
||||
public int jsGet_lineNumber()
|
||||
throws FileNotFoundException
|
||||
{
|
||||
return getReader().getLineNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the file. It may be reopened.
|
||||
*
|
||||
* Implements a JavaScript function.
|
||||
* @exception IOException if an error occurred while accessing the file
|
||||
* associated with this object
|
||||
*/
|
||||
public void jsFunction_close() throws IOException {
|
||||
if (reader != null) {
|
||||
reader.close();
|
||||
reader = null;
|
||||
} else if (writer != null) {
|
||||
writer.close();
|
||||
writer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizer.
|
||||
*
|
||||
* Close the file when this object is collected.
|
||||
*/
|
||||
public void finalize() {
|
||||
try {
|
||||
jsFunction_close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Java reader.
|
||||
*/
|
||||
public Object jsFunction_getReader() {
|
||||
if (reader == null)
|
||||
return null;
|
||||
// Here we use toObject() to "wrap" the BufferedReader object
|
||||
// in a Scriptable object so that it can be manipulated by
|
||||
// JavaScript.
|
||||
Scriptable parent = ScriptableObject.getTopLevelScope(this);
|
||||
return Context.toObject(reader, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Java writer.
|
||||
*
|
||||
* @see File#jsFunction_getReader
|
||||
*
|
||||
*/
|
||||
public Object jsFunction_getWriter() {
|
||||
if (writer == null)
|
||||
return null;
|
||||
Scriptable parent = ScriptableObject.getTopLevelScope(this);
|
||||
return Context.toObject(writer, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reader, checking that we're not already writing this file.
|
||||
*/
|
||||
private LineNumberReader getReader() throws FileNotFoundException {
|
||||
if (writer != null) {
|
||||
throw Context.reportRuntimeError("already writing file \""
|
||||
+ name
|
||||
+ "\"");
|
||||
}
|
||||
if (reader == null)
|
||||
reader = new LineNumberReader(file == null
|
||||
? new InputStreamReader(System.in)
|
||||
: new FileReader(file));
|
||||
return reader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the guts of write and writeLine.
|
||||
*
|
||||
* Since the two functions differ only in whether they write a
|
||||
* newline character, move the code into a common subroutine.
|
||||
*
|
||||
*/
|
||||
private static void write0(Scriptable thisObj, Object[] args, boolean eol)
|
||||
throws IOException
|
||||
{
|
||||
File thisFile = checkInstance(thisObj);
|
||||
if (thisFile.reader != null) {
|
||||
throw Context.reportRuntimeError("already writing file \""
|
||||
+ thisFile.name
|
||||
+ "\"");
|
||||
}
|
||||
if (thisFile.writer == null)
|
||||
thisFile.writer = new BufferedWriter(
|
||||
thisFile.file == null ? new OutputStreamWriter(System.out)
|
||||
: new FileWriter(thisFile.file));
|
||||
for (int i=0; i < args.length; i++) {
|
||||
String s = Context.toString(args[i]);
|
||||
thisFile.writer.write(s, 0, s.length());
|
||||
}
|
||||
if (eol)
|
||||
thisFile.writer.newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the instanceof check and return the downcasted File object.
|
||||
*
|
||||
* This is necessary since methods may reside in the File.prototype
|
||||
* object and scripts can dynamically alter prototype chains. For example:
|
||||
* <pre>
|
||||
* js> defineClass("File");
|
||||
* js> o = {};
|
||||
* [object Object]
|
||||
* js> o.__proto__ = File.prototype;
|
||||
* [object File]
|
||||
* js> o.write("hi");
|
||||
* js: called on incompatible object
|
||||
* </pre>
|
||||
* The runtime will take care of such checks when non-static Java methods
|
||||
* are defined as JavaScript functions.
|
||||
*/
|
||||
private static File checkInstance(Scriptable obj) {
|
||||
if (obj == null || !(obj instanceof File)) {
|
||||
throw Context.reportRuntimeError("called on incompatible object");
|
||||
}
|
||||
return (File) obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Some private data for this class.
|
||||
*/
|
||||
private String name;
|
||||
private java.io.File file; // may be null, meaning to use System.out or .in
|
||||
private LineNumberReader reader;
|
||||
private BufferedWriter writer;
|
||||
}
|
||||
|
||||
168
mozilla/js/rhino/examples/Foo.java
Normal file
168
mozilla/js/rhino/examples/Foo.java
Normal file
@@ -0,0 +1,168 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
import org.mozilla.javascript.*;
|
||||
|
||||
/**
|
||||
* An example host object class.
|
||||
*
|
||||
* Here's a shell session showing the Foo object in action:
|
||||
* <pre>
|
||||
* js> defineClass("Foo")
|
||||
* js> foo = new Foo(); <i>A constructor call, see <a href="#Foo">Foo</a> below.</i>
|
||||
* [object Foo] <i>The "Foo" here comes from <a href"#getClassName">getClassName</a>.</i>
|
||||
* js> foo.counter; <i>The counter property is defined by the <code>defineProperty</code></i>
|
||||
* 0 <i>call below and implemented by the <a href="#getCounter">getCounter</a></i>
|
||||
* js> foo.counter; <i>method below.</i>
|
||||
* 1
|
||||
* js> foo.counter;
|
||||
* 2
|
||||
* js> foo.resetCounter(); <i>Results in a call to <a href="#resetCounter">resetCounter</a>.</i>
|
||||
* js> foo.counter; <i>Now the counter has been reset.</i>
|
||||
* 0
|
||||
* js> foo.counter;
|
||||
* 1
|
||||
* js> bar = new Foo(37); <i>Create a new instance.</i>
|
||||
* [object Foo]
|
||||
* js> bar.counter; <i>This instance's counter is distinct from</i>
|
||||
* 37 <i>the other instance's counter.</i>
|
||||
* js> foo.varargs(3, "hi"); <i>Calls <a href="#varargs">varargs</a>.</i>
|
||||
* this = [object Foo]; args = [3, hi]
|
||||
* js> foo[7] = 34; <i>Since we extended ScriptableObject, we get</i>
|
||||
* 34 <i>all the behavior of a JavaScript object</i>
|
||||
* js> foo.a = 23; <i>for free.</i>
|
||||
* 23
|
||||
* js> foo.a + foo[7];
|
||||
* 57
|
||||
* js>
|
||||
* </pre>
|
||||
*
|
||||
* @see org.mozilla.javascript.Context
|
||||
* @see org.mozilla.javascript.Scriptable
|
||||
* @see org.mozilla.javascript.ScriptableObject
|
||||
*
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
|
||||
public class Foo extends ScriptableObject {
|
||||
|
||||
/**
|
||||
* The zero-parameter constructor.
|
||||
*
|
||||
* When Context.defineClass is called with this class, it will
|
||||
* construct Foo.prototype using this constructor.
|
||||
*/
|
||||
public Foo() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The Java method defining the JavaScript Foo constructor.
|
||||
*
|
||||
* Takes an initial value for the counter property.
|
||||
* Note that in the example Shell session above, we didn't
|
||||
* supply a argument to the Foo constructor. This means that
|
||||
* the Undefined value is used as the value of the argument,
|
||||
* and when the argument is converted to an integer, Undefined
|
||||
* becomes 0.
|
||||
*/
|
||||
public Foo(int counterStart) {
|
||||
counter = counterStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this JavaScript class, "Foo".
|
||||
*/
|
||||
public String getClassName() {
|
||||
return "Foo";
|
||||
}
|
||||
|
||||
/**
|
||||
* The Java method defining the JavaScript resetCounter function.
|
||||
*
|
||||
* Resets the counter to 0.
|
||||
*/
|
||||
public void jsFunction_resetCounter() {
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Java method implementing the getter for the counter property.
|
||||
* <p>
|
||||
* If "setCounter" had been defined in this class, the runtime would
|
||||
* call the setter when the property is assigned to.
|
||||
*/
|
||||
public int jsGet_counter() {
|
||||
return counter++;
|
||||
}
|
||||
|
||||
/**
|
||||
* An example of a variable-arguments method.
|
||||
*
|
||||
* All variable arguments methods must have the same number and
|
||||
* types of parameters, and must be static. <p>
|
||||
* @param cx the Context of the current thread
|
||||
* @param thisObj the JavaScript 'this' value.
|
||||
* @param args the array of arguments for this call
|
||||
* @param funObj the function object of the invoked JavaScript function
|
||||
* This value is useful to compute a scope using
|
||||
* Context.getTopLevelScope().
|
||||
* @return computes the string values and types of 'this' and
|
||||
* of each of the supplied arguments and returns them in a string.
|
||||
*
|
||||
* @exception ThreadAssociationException if the current
|
||||
* thread is not associated with a Context
|
||||
* @see org.mozilla.javascript.ScriptableObject#getTopLevelScope
|
||||
*/
|
||||
public static Object jsFunction_varargs(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("this = ");
|
||||
buf.append(Context.toString(thisObj));
|
||||
buf.append("; args = [");
|
||||
for (int i=0; i < args.length; i++) {
|
||||
buf.append(Context.toString(args[i]));
|
||||
if (i+1 != args.length)
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A piece of private data for this class.
|
||||
*/
|
||||
private int counter;
|
||||
}
|
||||
|
||||
59
mozilla/js/rhino/examples/Makefile
Normal file
59
mozilla/js/rhino/examples/Makefile
Normal file
@@ -0,0 +1,59 @@
|
||||
#! gmake
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is Rhino code, released
|
||||
# May 6, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU Public License (the "GPL"), in which case the
|
||||
# provisions of the GPL are applicable instead of those above.
|
||||
# If you wish to allow use of your version of this file only
|
||||
# under the terms of the GPL and not to allow others to use your
|
||||
# version of this file under the NPL, indicate your decision by
|
||||
# deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this
|
||||
# file under either the NPL or the GPL.
|
||||
|
||||
#
|
||||
# Makefile for the examples directory.
|
||||
#
|
||||
# This Makefile just calls $(JAVAC) on all the .java files. This
|
||||
# Makefile is intended to be called from the toplevel Makefile.
|
||||
#
|
||||
|
||||
JSFILES = $(PATH_PREFIX)/*.js
|
||||
SOURCES = $(PATH_PREFIX)/*.java
|
||||
CLASSES = $(PATH_PREFIX)/*.class
|
||||
|
||||
$(CLASSES) : $(SOURCES)
|
||||
$(JAVAC) $(JFLAGS) $(SOURCES)
|
||||
|
||||
clean :
|
||||
- rm $(CLASSES) $(PATH_PREFIX)/MANIFEST
|
||||
|
||||
clobber : clean
|
||||
|
||||
check :
|
||||
|
||||
$(PATH_PREFIX)/MANIFEST : $(SOURCES) $(CLASSES) $(JSFILES)
|
||||
ls $(SOURCES) $(CLASSES) $(JSFILES) \
|
||||
> $(@)
|
||||
|
||||
# Emulate .PHONY
|
||||
FORCE :
|
||||
274
mozilla/js/rhino/examples/Matrix.java
Normal file
274
mozilla/js/rhino/examples/Matrix.java
Normal file
@@ -0,0 +1,274 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
import org.mozilla.javascript.*;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Matrix: An example host object class that implements the Scriptable interface.
|
||||
*
|
||||
* Built-in JavaScript arrays don't handle multiple dimensions gracefully: the
|
||||
* script writer must create every array in an array of arrays. The Matrix class
|
||||
* takes care of that by automatically allocating arrays for every index that
|
||||
* is accessed. What's more, the Matrix constructor takes a integer argument
|
||||
* that specifies the dimension of the Matrix. If m is a Matrix with dimension 3,
|
||||
* then m[0] will be a Matrix with dimension 1, and m[0][0] will be an Array.
|
||||
*
|
||||
* Here's a shell session showing the Matrix object in action:
|
||||
* <pre>
|
||||
* js> defineClass("Matrix")
|
||||
* js> m = new Matrix(2); <i>A constructor call, see <a href="#Matrix">Matrix</a> below.</i>
|
||||
* [object Matrix] <i>The "Matrix" here comes from <a href"#getClassName">getClassName</a>.</i>
|
||||
* js> version(120); <i>switch to JavaScript1.2 to see arrays better</i>
|
||||
* 0
|
||||
* js> m[0][0] = 3;
|
||||
* 3
|
||||
* js> m[0]; <i>an array was created automatically!</i>
|
||||
* [3]
|
||||
* js> m[1]; <i>array is created even if we don't set a value</i>
|
||||
* []
|
||||
* js> m.dim; <i>we can access the "dim" property</i>
|
||||
* 2
|
||||
* js> m.dim = 3;
|
||||
* 3
|
||||
* js> m.dim; <i>but not modify it</i>
|
||||
* 2
|
||||
* </pre>
|
||||
*
|
||||
* @see org.mozilla.javascript.Context
|
||||
* @see org.mozilla.javascript.Scriptable
|
||||
*
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public class Matrix implements Scriptable {
|
||||
|
||||
/**
|
||||
* The zero-parameter constructor.
|
||||
*
|
||||
* When Context.defineClass is called with this class, it will
|
||||
* construct Matrix.prototype using this constructor.
|
||||
*/
|
||||
public Matrix() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The Java constructor, also used to define the JavaScript constructor.
|
||||
*/
|
||||
public Matrix(int dimension) {
|
||||
if (dimension <= 0) {
|
||||
throw Context.reportRuntimeError(
|
||||
"Dimension of Matrix must be greater than zero");
|
||||
}
|
||||
dim = dimension;
|
||||
v = new Vector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this JavaScript class, "Matrix".
|
||||
*/
|
||||
public String getClassName() {
|
||||
return "Matrix";
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the "dim" property by returning true if name is
|
||||
* equal to "dim".
|
||||
* <p>
|
||||
* Defines no other properties, i.e., returns false for
|
||||
* all other names.
|
||||
*
|
||||
* @param name the name of the property
|
||||
* @param start the object where lookup began
|
||||
*/
|
||||
public boolean has(String name, Scriptable start) {
|
||||
return name.equals("dim");
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines all numeric properties by returning true.
|
||||
*
|
||||
* @param index the index of the property
|
||||
* @param start the object where lookup began
|
||||
*/
|
||||
public boolean has(int index, Scriptable start) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the named property.
|
||||
* <p>
|
||||
* Handles the "dim" property and returns NOT_FOUND for all
|
||||
* other names.
|
||||
* @param name the property name
|
||||
* @param start the object where the lookup began
|
||||
*/
|
||||
public Object get(String name, Scriptable start) {
|
||||
if (name.equals("dim"))
|
||||
return new Integer(dim);
|
||||
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the indexed property.
|
||||
* <p>
|
||||
* Look up the element in the associated vector and return
|
||||
* it if it exists. If it doesn't exist, create it.<p>
|
||||
* @param index the index of the integral property
|
||||
* @param start the object where the lookup began
|
||||
*/
|
||||
public Object get(int index, Scriptable start) {
|
||||
if (index >= v.size())
|
||||
v.setSize(index+1);
|
||||
Object result = v.elementAt(index);
|
||||
if (result != null)
|
||||
return result;
|
||||
if (dim > 2) {
|
||||
Matrix m = new Matrix(dim-1);
|
||||
m.setParentScope(getParentScope());
|
||||
m.setPrototype(getPrototype());
|
||||
result = m;
|
||||
} else {
|
||||
Context cx = Context.getCurrentContext();
|
||||
Scriptable scope = ScriptableObject.getTopLevelScope(start);
|
||||
result = cx.newArray(scope, 0);
|
||||
}
|
||||
v.setElementAt(result, index);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a named property.
|
||||
*
|
||||
* We do nothing here, so all properties are effectively read-only.
|
||||
*/
|
||||
public void put(String name, Scriptable start, Object value) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an indexed property.
|
||||
*
|
||||
* We do nothing here, so all properties are effectively read-only.
|
||||
*/
|
||||
public void put(int index, Scriptable start, Object value) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a named property.
|
||||
*
|
||||
* This method shouldn't even be called since we define all properties
|
||||
* as PERMANENT.
|
||||
*/
|
||||
public void delete(String id) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an indexed property.
|
||||
*
|
||||
* This method shouldn't even be called since we define all properties
|
||||
* as PERMANENT.
|
||||
*/
|
||||
public void delete(int index) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prototype.
|
||||
*/
|
||||
public Scriptable getPrototype() {
|
||||
return prototype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set prototype.
|
||||
*/
|
||||
public void setPrototype(Scriptable prototype) {
|
||||
this.prototype = prototype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent.
|
||||
*/
|
||||
public Scriptable getParentScope() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set parent.
|
||||
*/
|
||||
public void setParentScope(Scriptable parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get properties.
|
||||
*
|
||||
* We return an empty array since we define all properties to be DONTENUM.
|
||||
*/
|
||||
public Object[] getIds() {
|
||||
return new Object[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Default value.
|
||||
*
|
||||
* Use the convenience method from Context that takes care of calling
|
||||
* toString, etc.
|
||||
*/
|
||||
public Object getDefaultValue(Class typeHint) {
|
||||
return "[object Matrix]";
|
||||
}
|
||||
|
||||
/**
|
||||
* instanceof operator.
|
||||
*
|
||||
* We mimick the normal JavaScript instanceof semantics, returning
|
||||
* true if <code>this</code> appears in <code>value</code>'s prototype
|
||||
* chain.
|
||||
*/
|
||||
public boolean hasInstance(Scriptable value) {
|
||||
Scriptable proto = value.getPrototype();
|
||||
while (proto != null) {
|
||||
if (proto.equals(this)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Some private data for this class.
|
||||
*/
|
||||
private int dim;
|
||||
private Vector v;
|
||||
private Scriptable prototype, parent;
|
||||
}
|
||||
7
mozilla/js/rhino/examples/NervousText.html
Normal file
7
mozilla/js/rhino/examples/NervousText.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
This is the NervousText applet in javascript:
|
||||
<applet code=NervousText.class width=200 height=50 >
|
||||
</applet>
|
||||
</body>
|
||||
</html>
|
||||
75
mozilla/js/rhino/examples/NervousText.js
Normal file
75
mozilla/js/rhino/examples/NervousText.js
Normal file
@@ -0,0 +1,75 @@
|
||||
// The Java "NervousText" example ported to JavaScript.
|
||||
// Compile using java org.mozilla.tools.jsc.Main -extends java.applet.Applet -implements java.lang.Runnable NervousText.js
|
||||
/*
|
||||
Adapted from Java code by
|
||||
Daniel Wyszynski
|
||||
Center for Applied Large-Scale Computing (CALC)
|
||||
04-12-95
|
||||
|
||||
Test of text animation.
|
||||
|
||||
kwalrath: Changed string; added thread suspension. 5-9-95
|
||||
*/
|
||||
var Font = java.awt.Font;
|
||||
var Thread = java.lang.Thread;
|
||||
var separated;
|
||||
var s = null;
|
||||
var killme = null;
|
||||
var i;
|
||||
var x_coord = 0, y_coord = 0;
|
||||
var num;
|
||||
var speed=35;
|
||||
var counter =0;
|
||||
var threadSuspended = false; //added by kwalrath
|
||||
|
||||
function init() {
|
||||
resize(150,50);
|
||||
setFont(new Font("TimesRoman",Font.BOLD,36));
|
||||
s = getParameter("text");
|
||||
if (s == null) {
|
||||
s = "Rhino";
|
||||
}
|
||||
separated = s.split('');
|
||||
}
|
||||
|
||||
function start() {
|
||||
if(killme == null)
|
||||
{
|
||||
killme = new java.lang.Thread(java.lang.Runnable(this));
|
||||
killme.start();
|
||||
}
|
||||
}
|
||||
|
||||
function stop() {
|
||||
killme = null;
|
||||
}
|
||||
|
||||
function run() {
|
||||
while (killme != null) {
|
||||
try {Thread.sleep(100);} catch (e){}
|
||||
repaint();
|
||||
}
|
||||
killme = null;
|
||||
}
|
||||
|
||||
function paint(g) {
|
||||
for(i=0;i<separated.length;i++)
|
||||
{
|
||||
x_coord = Math.random()*10+15*i;
|
||||
y_coord = Math.random()*10+36;
|
||||
g.drawChars(separated, i,1,x_coord,y_coord);
|
||||
}
|
||||
}
|
||||
|
||||
/* Added by kwalrath. */
|
||||
function mouseDown(evt, x, y) {
|
||||
if (threadSuspended) {
|
||||
killme.resume();
|
||||
}
|
||||
else {
|
||||
killme.suspend();
|
||||
}
|
||||
threadSuspended = !threadSuspended;
|
||||
return true;
|
||||
}
|
||||
|
||||
73
mozilla/js/rhino/examples/RunScript.java
Normal file
73
mozilla/js/rhino/examples/RunScript.java
Normal file
@@ -0,0 +1,73 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
import org.mozilla.javascript.*;
|
||||
|
||||
/**
|
||||
* RunScript: simplest example of controlling execution of Rhino.
|
||||
*
|
||||
* Collects its arguments from the command line, executes the
|
||||
* script, and prints the result.
|
||||
*
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public class RunScript {
|
||||
public static void main(String args[])
|
||||
throws JavaScriptException
|
||||
{
|
||||
// Creates and enters a Context. The Context stores information
|
||||
// about the execution environment of a script.
|
||||
Context cx = Context.enter();
|
||||
|
||||
// Initialize the standard objects (Object, Function, etc.)
|
||||
// This must be done before scripts can be executed. Returns
|
||||
// a scope object that we use in later calls.
|
||||
Scriptable scope = cx.initStandardObjects(null);
|
||||
|
||||
// Collect the arguments into a single string.
|
||||
String s = "";
|
||||
for (int i=0; i < args.length; i++)
|
||||
s += args[i];
|
||||
|
||||
// Now evaluate the string we've colected.
|
||||
Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);
|
||||
|
||||
// Convert the result to a string and print it.
|
||||
System.err.println(cx.toString(result));
|
||||
|
||||
// Exit from the context.
|
||||
Context.exit();
|
||||
}
|
||||
}
|
||||
|
||||
63
mozilla/js/rhino/examples/RunScript2.java
Normal file
63
mozilla/js/rhino/examples/RunScript2.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
import org.mozilla.javascript.*;
|
||||
|
||||
/**
|
||||
* RunScript2: Like RunScript, but reflects the System.out into JavaScript.
|
||||
*
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public class RunScript2 {
|
||||
public static void main(String args[])
|
||||
throws JavaScriptException
|
||||
{
|
||||
Context cx = Context.enter();
|
||||
Scriptable scope = cx.initStandardObjects(null);
|
||||
|
||||
// Add a global variable "out" that is a JavaScript reflection
|
||||
// of System.out
|
||||
Scriptable jsArgs = Context.toObject(System.out, scope);
|
||||
scope.put("out", scope, jsArgs);
|
||||
|
||||
String s = "";
|
||||
for (int i=0; i < args.length; i++)
|
||||
s += args[i];
|
||||
Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);
|
||||
System.err.println(cx.toString(result));
|
||||
Context.exit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
63
mozilla/js/rhino/examples/RunScript3.java
Normal file
63
mozilla/js/rhino/examples/RunScript3.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
import org.mozilla.javascript.*;
|
||||
|
||||
/**
|
||||
* RunScript3: Execute scripts in an environment that includes the
|
||||
* example Counter class.
|
||||
*
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public class RunScript3 {
|
||||
public static void main(String args[])
|
||||
throws Exception
|
||||
{
|
||||
Context cx = Context.enter();
|
||||
Scriptable scope = cx.initStandardObjects(null);
|
||||
|
||||
// Use the Counter class to define a Counter constructor
|
||||
// and prototype in JavaScript.
|
||||
ScriptableObject.defineClass(scope, Counter.class);
|
||||
|
||||
String s = "";
|
||||
for (int i=0; i < args.length; i++)
|
||||
s += args[i];
|
||||
Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);
|
||||
System.err.println(cx.toString(result));
|
||||
Context.exit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
352
mozilla/js/rhino/examples/Shell.java
Normal file
352
mozilla/js/rhino/examples/Shell.java
Normal file
@@ -0,0 +1,352 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
import org.mozilla.javascript.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* The shell program.
|
||||
*
|
||||
* Can execute scripts interactively or in batch mode at the command line.
|
||||
* An example of controlling the JavaScript engine.
|
||||
*
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public class Shell extends ScriptableObject {
|
||||
|
||||
/**
|
||||
* Main entry point.
|
||||
*
|
||||
* Process arguments as would a normal Java program. Also
|
||||
* create a new Context and associate it with the current thread.
|
||||
* Then set up the execution environment and begin to
|
||||
* execute scripts.
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
// Associate a new Context with this thread
|
||||
Context cx = Context.enter();
|
||||
|
||||
// A bit of shorthand: since Shell extends ScriptableObject,
|
||||
// we can make it the global object.
|
||||
global = new Shell();
|
||||
|
||||
// Initialize the standard objects (Object, Function, etc.)
|
||||
// This must be done before scripts can be executed.
|
||||
cx.initStandardObjects(global);
|
||||
|
||||
// Define some global functions particular to the shell. Note
|
||||
// that these functions are not part of ECMA.
|
||||
String[] names = { "print", "quit", "version", "load", "help" };
|
||||
try {
|
||||
global.defineFunctionProperties(names, Shell.class,
|
||||
ScriptableObject.DONTENUM);
|
||||
} catch (PropertyException e) {
|
||||
throw new Error(e.getMessage());
|
||||
}
|
||||
|
||||
args = processOptions(cx, args);
|
||||
|
||||
// Set up "arguments" in the global scope to contain the command
|
||||
// line arguments after the name of the script to execute
|
||||
Object[] array = args;
|
||||
if (args.length > 0) {
|
||||
int length = args.length - 1;
|
||||
array = new Object[length];
|
||||
System.arraycopy(args, 1, array, 0, length);
|
||||
}
|
||||
Scriptable argsObj = cx.newArray(global, array);
|
||||
global.defineProperty("arguments", argsObj,
|
||||
ScriptableObject.DONTENUM);
|
||||
|
||||
processSource(cx, args.length == 0 ? null : args[0]);
|
||||
|
||||
cx.exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse arguments.
|
||||
*/
|
||||
public static String[] processOptions(Context cx, String args[]) {
|
||||
for (int i=0; i < args.length; i++) {
|
||||
String arg = args[i];
|
||||
if (!arg.startsWith("-")) {
|
||||
String[] result = new String[args.length - i];
|
||||
for (int j=i; j < args.length; j++)
|
||||
result[j-i] = args[j];
|
||||
return result;
|
||||
}
|
||||
if (arg.equals("-version")) {
|
||||
if (++i == args.length)
|
||||
usage(arg);
|
||||
double d = cx.toNumber(args[i]);
|
||||
if (d != d)
|
||||
usage(arg);
|
||||
cx.setLanguageVersion((int) d);
|
||||
continue;
|
||||
}
|
||||
usage(arg);
|
||||
}
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return name of this class, the global object.
|
||||
*
|
||||
* This method must be implemented in all concrete classes
|
||||
* extending ScriptableObject.
|
||||
*
|
||||
* @see org.mozilla.javascript.Scriptable#getClassName
|
||||
*/
|
||||
public String getClassName() {
|
||||
return "global";
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a usage message.
|
||||
*/
|
||||
public static void usage(String s) {
|
||||
p("Didn't understand \"" + s + "\".");
|
||||
p("Valid arguments are:");
|
||||
p("-version 100|110|120|130");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a help message.
|
||||
*
|
||||
* This method is defined as a JavaScript function.
|
||||
*/
|
||||
public static void help(String s) {
|
||||
p("");
|
||||
p("Command Description");
|
||||
p("======= ===========");
|
||||
p("help() Display usage and help messages. ");
|
||||
p("defineClass(className) Define an extension using the Java class");
|
||||
p(" named with the string argument. ");
|
||||
p(" Uses ScriptableObject.defineClass(). ");
|
||||
p("load(['foo.js', ...]) Load JavaScript source files named by ");
|
||||
p(" string arguments. ");
|
||||
p("loadClass(className) Load a class named by a string argument.");
|
||||
p(" The class must be a script compiled to a");
|
||||
p(" class file. ");
|
||||
p("print([expr ...]) Evaluate and print expressions. ");
|
||||
p("quit() Quit the shell. ");
|
||||
p("version([number]) Get or set the JavaScript version number.");
|
||||
p("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the string values of its arguments.
|
||||
*
|
||||
* This method is defined as a JavaScript function.
|
||||
* Note that its arguments are of the "varargs" form, which
|
||||
* allows it to handle an arbitrary number of arguments
|
||||
* supplied to the JavaScript function.
|
||||
*
|
||||
*/
|
||||
public static void print(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
for (int i=0; i < args.length; i++) {
|
||||
if (i > 0)
|
||||
System.out.print(" ");
|
||||
|
||||
// Convert the arbitrary JavaScript value into a string form.
|
||||
String s = Context.toString(args[i]);
|
||||
|
||||
System.out.print(s);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Quit the shell.
|
||||
*
|
||||
* This only affects the interactive mode.
|
||||
*
|
||||
* This method is defined as a JavaScript function.
|
||||
*/
|
||||
public static void quit() {
|
||||
quitting = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get and set the language version.
|
||||
*
|
||||
* This method is defined as a JavaScript function.
|
||||
*/
|
||||
public static double version(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
double result = (double) cx.getLanguageVersion();
|
||||
if (args.length > 0) {
|
||||
double d = cx.toNumber(args[0]);
|
||||
cx.setLanguageVersion((int) d);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and execute a set of JavaScript source files.
|
||||
*
|
||||
* This method is defined as a JavaScript function.
|
||||
*
|
||||
*/
|
||||
public static void load(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
for (int i=0; i < args.length; i++) {
|
||||
processSource(cx, cx.toString(args[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate JavaScript source.
|
||||
*
|
||||
* @param cx the current context
|
||||
* @param filename the name of the file to compile, or null
|
||||
* for interactive mode.
|
||||
*/
|
||||
public static void processSource(Context cx, String filename) {
|
||||
if (filename == null) {
|
||||
BufferedReader in = new BufferedReader
|
||||
(new InputStreamReader(System.in));
|
||||
String sourceName = "<stdin>";
|
||||
int lineno = 1;
|
||||
boolean hitEOF = false;
|
||||
do {
|
||||
int startline = lineno;
|
||||
System.err.print("js> ");
|
||||
System.err.flush();
|
||||
try {
|
||||
String source = "";
|
||||
// Collect lines of source to compile.
|
||||
while(true) {
|
||||
String newline;
|
||||
newline = in.readLine();
|
||||
if (newline == null) {
|
||||
hitEOF = true;
|
||||
break;
|
||||
}
|
||||
source = source + newline + "\n";
|
||||
lineno++;
|
||||
// Continue collecting as long as more lines
|
||||
// are needed to complete the current
|
||||
// statement. stringIsCompilableUnit is also
|
||||
// true if the source statement will result in
|
||||
// any error other than one that might be
|
||||
// resolved by appending more source.
|
||||
if (cx.stringIsCompilableUnit(source))
|
||||
break;
|
||||
}
|
||||
Object result = cx.evaluateString(global, source,
|
||||
sourceName, startline,
|
||||
null);
|
||||
if (result != cx.getUndefinedValue()) {
|
||||
System.err.println(cx.toString(result));
|
||||
}
|
||||
}
|
||||
catch (WrappedException we) {
|
||||
// Some form of exception was caught by JavaScript and
|
||||
// propagated up.
|
||||
System.err.println(we.getWrappedException().toString());
|
||||
we.printStackTrace();
|
||||
}
|
||||
catch (EvaluatorException ee) {
|
||||
// Some form of JavaScript error.
|
||||
System.err.println("js: " + ee.getMessage());
|
||||
}
|
||||
catch (JavaScriptException jse) {
|
||||
// Some form of JavaScript error.
|
||||
System.err.println("js: " + jse.getMessage());
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
System.err.println(ioe.toString());
|
||||
}
|
||||
if (quitting) {
|
||||
// The user executed the quit() function.
|
||||
break;
|
||||
}
|
||||
} while (!hitEOF);
|
||||
System.err.println();
|
||||
} else {
|
||||
FileReader in = null;
|
||||
try {
|
||||
in = new FileReader(filename);
|
||||
}
|
||||
catch (FileNotFoundException ex) {
|
||||
Context.reportError("Couldn't open file \"" + filename + "\".");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Here we evalute the entire contents of the file as
|
||||
// a script. Text is printed only if the print() function
|
||||
// is called.
|
||||
cx.evaluateReader(global, in, filename, 1, null);
|
||||
}
|
||||
catch (WrappedException we) {
|
||||
System.err.println(we.getWrappedException().toString());
|
||||
we.printStackTrace();
|
||||
}
|
||||
catch (EvaluatorException ee) {
|
||||
System.err.println("js: " + ee.getMessage());
|
||||
}
|
||||
catch (JavaScriptException jse) {
|
||||
System.err.println("js: " + jse.getMessage());
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
System.err.println(ioe.toString());
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
in.close();
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
System.err.println(ioe.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
private static void p(String s) {
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
static Shell global;
|
||||
static boolean quitting;
|
||||
}
|
||||
|
||||
134
mozilla/js/rhino/examples/checkParam.js
Normal file
134
mozilla/js/rhino/examples/checkParam.js
Normal file
@@ -0,0 +1,134 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
/**
|
||||
* checkParam.js
|
||||
*
|
||||
* The files given as arguments on the command line are assumed to be
|
||||
* Java source code files. This program checks to see that the @param
|
||||
* tags in the documentation comments match with the parameters for
|
||||
* the associated Java methods.
|
||||
* <p>
|
||||
* Any errors found are reported.
|
||||
*
|
||||
*/
|
||||
defineClass("File")
|
||||
|
||||
// Return true if "str" ends with "suffix".
|
||||
function stringEndsWith(str, suffix) {
|
||||
return str.substring(str.length - suffix.length) == suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform processing once the end of a documentation comment is seen.
|
||||
*
|
||||
* Look for a parameter list following the end of the comment and
|
||||
* collect the parameters and compare to the @param entries.
|
||||
* Report any discrepancies.
|
||||
* @param f the current file
|
||||
* @param a an array of parameters from @param comments
|
||||
* @param line the string containing the comment end (in case the
|
||||
* parameters are on the same line)
|
||||
*/
|
||||
function processCommentEnd(f, a, line) {
|
||||
while (line != null && !line.match(/\(/))
|
||||
line = f.readLine();
|
||||
while (line != null && !line.match(/\)/))
|
||||
line += f.readLine();
|
||||
if (line === null)
|
||||
return;
|
||||
var m = line.match(/\(([^\)]+)\)/);
|
||||
var args = m ? m[1].split(",") : [];
|
||||
if (a.length != args.length) {
|
||||
print('"' + f.name +
|
||||
'"; line ' + f.lineNumber +
|
||||
' mismatch: had a different number' +
|
||||
' of @param entries and parameters.');
|
||||
} else {
|
||||
for (var i=0; i < a.length; i++) {
|
||||
if (!stringEndsWith(args[i], a[i])) {
|
||||
print('"' + f.name +
|
||||
'"; line ' + f.lineNumber +
|
||||
' mismatch: had "' + a[i] +
|
||||
'" and "' + args[i] + '".');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the given file, looking for mismatched @param lists and
|
||||
* parameter lists.
|
||||
* @param f the file to process
|
||||
*/
|
||||
function processFile(f) {
|
||||
var line;
|
||||
var m;
|
||||
var i = 0;
|
||||
var a = [];
|
||||
outer:
|
||||
while ((line = f.readLine()) != null) {
|
||||
if (line.match(/@param/)) {
|
||||
while (m = line.match(/@param[ ]+([^ ]+)/)) {
|
||||
a[i++] = m[1];
|
||||
line = f.readLine();
|
||||
if (line == null)
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
if (i != 0 && line.match(/\*\//)) {
|
||||
processCommentEnd(f, a, line);
|
||||
i = 0;
|
||||
a = [];
|
||||
}
|
||||
}
|
||||
if (i != 0) {
|
||||
print('"' + f.name +
|
||||
'"; line ' + f.lineNumber +
|
||||
' missing parameters at end of file.');
|
||||
}
|
||||
}
|
||||
|
||||
// main script: process each file in arguments list
|
||||
|
||||
for (var i=0; i < arguments.length; i++) {
|
||||
var filename = String(arguments[i]);
|
||||
print("Checking " + filename + "...");
|
||||
var f = new File(filename);
|
||||
processFile(f);
|
||||
}
|
||||
print("done.");
|
||||
|
||||
70
mozilla/js/rhino/examples/enum.js
Normal file
70
mozilla/js/rhino/examples/enum.js
Normal file
@@ -0,0 +1,70 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Patrick Beard
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
enum.js
|
||||
|
||||
Implementing the interface java.util.Enumeration using the new syntax.
|
||||
Note that this syntax is experimental only, and hasn't been approved
|
||||
by ECMA.
|
||||
The same functionality can be had without the new syntax using the
|
||||
uglier syntax:
|
||||
|
||||
var elements = new JavaAdapter(java.util.Enumeration, {
|
||||
index: 0, elements: array,
|
||||
hasMoreElements: function ...
|
||||
nextElement: function ...
|
||||
});
|
||||
|
||||
by Patrick C. Beard.
|
||||
*/
|
||||
|
||||
// an array to enumerate.
|
||||
var array = [0, 1, 2];
|
||||
|
||||
// create an array enumeration.
|
||||
var elements = new java.util.Enumeration() {
|
||||
index: 0, elements: array,
|
||||
hasMoreElements: function() {
|
||||
return (this.index < this.elements.length);
|
||||
},
|
||||
nextElement: function() {
|
||||
return this.elements[this.index++];
|
||||
}
|
||||
};
|
||||
|
||||
// now print out the array by enumerating through the Enumeration
|
||||
while (elements.hasMoreElements())
|
||||
print(elements.nextElement());
|
||||
508
mozilla/js/rhino/examples/jsdoc.js
Normal file
508
mozilla/js/rhino/examples/jsdoc.js
Normal file
@@ -0,0 +1,508 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
* Roland Pennings
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Process a JavaScript source file and process special comments
|
||||
* to produce an HTML file of documentation, similar to javadoc.
|
||||
* @author Norris Boyd
|
||||
* @see rhinotip.jar
|
||||
* @lastmodified xx
|
||||
* @version 1.2 Roland Pennings: Allow multiple files for a function.
|
||||
* @version 1.3 Roland Pennings: Removes ../.. from the input directory name
|
||||
*/
|
||||
defineClass("File")
|
||||
|
||||
var functionDocArray = [];
|
||||
var inputDirName = "";
|
||||
var indexFileArray = [];
|
||||
var indexFile = "";
|
||||
var indexFileName = "index_files";
|
||||
var indexFunctionArray = [];
|
||||
var indexFunction = "";
|
||||
var indexFunctionName = "index_functions";
|
||||
var FileList = [];
|
||||
var DirList = [];
|
||||
var outputdir = null;
|
||||
var debug = 0;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Process JavaScript source file <code>f</code>, writing jsdoc to
|
||||
* file <code>out</code>.
|
||||
* @param f input file
|
||||
* @param fname name of the input file (without the path)
|
||||
* @param inputdir directory of the input file
|
||||
* @param out output file
|
||||
*/
|
||||
function processFile(f, fname, inputdir, out) {
|
||||
var s;
|
||||
var firstLine = true;
|
||||
indexFileArray[fname] = "";
|
||||
|
||||
// write the header of the output file
|
||||
out.writeLine('<HTML><HEADER><TITLE>' + fname + '</TITLE><BODY>');
|
||||
if (inputdir != null) {
|
||||
outstr = '<a name=\"_top_\"></a><pre><a href=\"' + indexFile + '\">Index Files</a> ';
|
||||
outstr += '<a href=\"' + indexFunction + '\">Index Functions</a></pre><hr>';
|
||||
out.writeLine(outstr);
|
||||
}
|
||||
|
||||
// process the input file
|
||||
var comment = "";
|
||||
while ((s = f.readLine()) != null) {
|
||||
var m = s.match(/\/\*\*(.*)/);
|
||||
if (m != null) {
|
||||
// Found a comment start.
|
||||
s = "*" + m[1];
|
||||
do {
|
||||
m = s.match(/(.*)\*\//);
|
||||
if (m != null) {
|
||||
// Found end of comment.
|
||||
comment += m[1];
|
||||
break;
|
||||
}
|
||||
// Strip leading whitespace and "*".
|
||||
comment += s.replace(/^\s*\*/, "");
|
||||
s = f.readLine();
|
||||
} while (s != null);
|
||||
|
||||
if (debug)
|
||||
print("Found comment " + comment);
|
||||
|
||||
if (firstLine) {
|
||||
// We have a comment for the whole file.
|
||||
out.writeLine('<H1>File ' + fname + '</H1>');
|
||||
out.writeLine(processComment(comment,firstLine,fname));
|
||||
out.writeLine('<HR>');
|
||||
firstLine = false;
|
||||
comment = "";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// match the beginning of the function
|
||||
// NB we also match functions without a comment!
|
||||
// if we have two comments one after another only the last one will be taken
|
||||
m = s.match(/^\s*function\s+((\w+)|(\w+)(\s+))\(([^)]*)\)/);
|
||||
if (m != null)
|
||||
{
|
||||
// Found a function start
|
||||
var htmlText = processFunction(m[1], m[2], comment);
|
||||
|
||||
// Save the text in a global variable, so we
|
||||
// can write out a table of contents first.
|
||||
functionDocArray[functionDocArray.length] =
|
||||
{name:m[1], text:htmlText};
|
||||
|
||||
// Store the function also in the indexFunctionArray
|
||||
// so we can have a seperate file with the function table of contents
|
||||
if (indexFunctionArray[m[1]]) {
|
||||
// print("ERROR: function: " + m[1] + " is defined more than once!");
|
||||
// Allow multiple files for a function
|
||||
with (indexFunctionArray[m[1]]) {
|
||||
filename = filename + "|" + fname;
|
||||
// print("filename = " + filename);
|
||||
}
|
||||
} else {
|
||||
indexFunctionArray[m[1]] =
|
||||
{filename:fname};
|
||||
}
|
||||
//reset comment
|
||||
comment = "";
|
||||
}
|
||||
firstLine = false;
|
||||
}
|
||||
|
||||
// Write table of contents.
|
||||
for (var i=0; i < functionDocArray.length; i++) {
|
||||
with (functionDocArray[i]) {
|
||||
out.writeLine('function <A HREF=#' + name +
|
||||
'>' + name + '</A><BR>');
|
||||
}
|
||||
}
|
||||
out.writeLine('<HR>');
|
||||
|
||||
// Now write the saved function documentation.
|
||||
for (i=0; i < functionDocArray.length; i++) {
|
||||
with (functionDocArray[i]) {
|
||||
out.writeLine('<A NAME=' + name + '>');
|
||||
out.writeLine(text);
|
||||
}
|
||||
}
|
||||
out.writeLine('</BODY></HTML>');
|
||||
|
||||
// Now clean up the doc array
|
||||
functionDocArray = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Process function and associated comment.
|
||||
* @param name the name of the function
|
||||
* @param args the args of the function as a single string
|
||||
* @param comment the text of the comment
|
||||
* @return a string for the HTML text of the documentation
|
||||
*/
|
||||
function processFunction(name, args, comment) {
|
||||
if (debug)
|
||||
print("Processing " + name + " " + args + " " + comment);
|
||||
return "<H2>Function " + name + "</H2>" +
|
||||
"<PRE>" +
|
||||
"function " + name + "(" + args + ")" +
|
||||
"</PRE>" +
|
||||
processComment(comment,0,name) +
|
||||
"<P><BR><BR>";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Process comment.
|
||||
* @param comment the text of the comment
|
||||
* @param firstLine shows if comment is at the beginning of the file
|
||||
* @param fname name of the file (without path)
|
||||
* @return a string for the HTML text of the documentation
|
||||
*/
|
||||
function processComment(comment,firstLine,fname) {
|
||||
var tags = {};
|
||||
// Use the "lambda" form of regular expression replace,
|
||||
// where the replacement object is a function rather
|
||||
// than a string. The function is called with the
|
||||
// matched text and any parenthetical matches as
|
||||
// arguments, and the result of the function used as the
|
||||
// replacement text.
|
||||
// Here we use the function to build up the "tags" object,
|
||||
// which has a property for each "@" tag that is the name
|
||||
// of the tag, and whose value is an array of the
|
||||
// text following that tag.
|
||||
comment = comment.replace(/@(\w+)\s+([^@]*)/g,
|
||||
function (s, name, text) {
|
||||
var a = tags[name] || [];
|
||||
a.push(text);
|
||||
tags[name] = a;
|
||||
return "";
|
||||
});
|
||||
|
||||
// if we have a comment at the beginning of a file
|
||||
// store the comment for the index file
|
||||
if (firstLine) {
|
||||
indexFileArray[fname] = comment;
|
||||
}
|
||||
|
||||
var out = comment + '<P>';
|
||||
if (tags["param"]) {
|
||||
// Create a table of parameters and their descriptions.
|
||||
var array = tags["param"];
|
||||
var params = "";
|
||||
for (var i=0; i < array.length; i++) {
|
||||
var m = array[i].match(/(\w+)\s+(.*)/);
|
||||
params += '<TR><TD><I>'+m[1]+'</I></TD>' +
|
||||
'<TD>'+m[2]+'</TD></TR>';
|
||||
}
|
||||
out += '<TABLE WIDTH="90%" BORDER=1>';
|
||||
out += '<TR BGCOLOR=0xdddddddd>';
|
||||
out += '<TD><B>Parameter</B></TD>';
|
||||
out += '<TD><B>Description</B></TD></TR>';
|
||||
out += params;
|
||||
out += '</TABLE><P>';
|
||||
}
|
||||
if (tags["return"]) {
|
||||
out += "<DT><B>Returns:</B><DD>";
|
||||
out += tags["return"][0] + "</DL><P>";
|
||||
}
|
||||
if (tags["author"]) {
|
||||
// List the authors together, separated by commas.
|
||||
out += '<DT><B>Author:</B><DD>';
|
||||
var array = tags["author"];
|
||||
for (var i=0; i < array.length; i++) {
|
||||
out += array[i];
|
||||
if (i+1 < array.length)
|
||||
out += ", ";
|
||||
}
|
||||
out += '</DL><P>';
|
||||
}
|
||||
if (tags["version"]) {
|
||||
// Show the version.
|
||||
out += '<DT><B>Version:</B><DD>';
|
||||
var array = tags["version"];
|
||||
for (var i=0; i < array.length; i++) {
|
||||
out += array[i];
|
||||
if (i+1 < array.length)
|
||||
out += "<BR><DD>";
|
||||
}
|
||||
out += '</DL><P>';
|
||||
}
|
||||
if (tags["see"]) {
|
||||
// List the see modules together, separated by <BR>.
|
||||
out += '<DT><B>Dependencies:</B><DD>';
|
||||
var array = tags["see"];
|
||||
for (var i=0; i < array.length; i++) {
|
||||
out += array[i];
|
||||
if (i+1 < array.length)
|
||||
out += "<BR><DD>";
|
||||
}
|
||||
out += '</DL><P>';
|
||||
}
|
||||
if (tags["lastmodified"]) {
|
||||
// Shows a last modified description with client-side js.
|
||||
out += '<DT><B>Last modified:</B><DD>';
|
||||
out += '<script><!--\n';
|
||||
out += 'document.writeln(document.lastModified);\n';
|
||||
out += '// ---></script>\n';
|
||||
out += '</DL><P>';
|
||||
}
|
||||
|
||||
// additional tags can be added here (i.e., "if (tags["see"])...")
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an html output file
|
||||
* @param outputdir directory to put the file
|
||||
* @param htmlfile name of the file
|
||||
*/
|
||||
function CreateOutputFile(outputdir,htmlfile)
|
||||
{
|
||||
if (outputdir==null)
|
||||
{
|
||||
var outname = htmlfile;
|
||||
}
|
||||
else
|
||||
{
|
||||
var separator = Packages.java.io.File.separator;
|
||||
var outname = outputdir + separator + htmlfile.substring(htmlfile.lastIndexOf(separator),htmlfile.length);
|
||||
}
|
||||
print("output file: " + outname);
|
||||
return new File(outname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a javascript file. Puts the generated HTML file in the outdir
|
||||
* @param filename name of the javascript file
|
||||
* @inputdir input directory of the file (default null)
|
||||
*/
|
||||
function processJSFile(filename,inputdir)
|
||||
{
|
||||
if (debug) print("filename = " + filename + " inputdir = " + inputdir);
|
||||
|
||||
if (!filename.match(/\.js$/)) {
|
||||
print("Expected filename to end in '.js'; had instead " +
|
||||
filename + ". I don't treat the file.");
|
||||
} else {
|
||||
if (inputdir==null)
|
||||
{
|
||||
var inname = filename;
|
||||
}
|
||||
else
|
||||
{
|
||||
var separator = Packages.java.io.File.separator;
|
||||
var inname = inputdir + separator + filename;
|
||||
}
|
||||
print("Processing file " + inname);
|
||||
|
||||
var f = new File(inname);
|
||||
|
||||
// create the output file
|
||||
var htmlfile = filename.replace(/\.js$/, ".html");
|
||||
|
||||
var out = CreateOutputFile(outputdir,htmlfile);
|
||||
|
||||
processFile(f, filename, inputdir, out);
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate index files containing links to the processed javascript files
|
||||
* and the generated functions
|
||||
*/
|
||||
function GenerateIndex(dirname)
|
||||
{
|
||||
// construct the files index file
|
||||
var out = CreateOutputFile(outputdir,indexFile);
|
||||
|
||||
// write the beginning of the file
|
||||
out.writeLine('<HTML><HEADER><TITLE>File Index - directory: ' + dirname + '</TITLE><BODY>');
|
||||
out.writeLine('<H1>File Index - directory: ' + dirname + '</H1>\n');
|
||||
out.writeLine('<TABLE WIDTH="90%" BORDER=1>');
|
||||
out.writeLine('<TR BGCOLOR=0xdddddddd>');
|
||||
out.writeLine('<TD><B>File</B></TD>');
|
||||
out.writeLine('<TD><B>Description</B></TD></TR>');
|
||||
|
||||
var separator = Packages.java.io.File.separator;
|
||||
|
||||
// sort the index file array
|
||||
var SortedFileArray = [];
|
||||
for (var fname in indexFileArray)
|
||||
SortedFileArray.push(fname);
|
||||
SortedFileArray.sort();
|
||||
|
||||
for (var i=0; i < SortedFileArray.length; i++) {
|
||||
var fname = SortedFileArray[i];
|
||||
var htmlfile = fname.replace(/\.js$/, ".html");
|
||||
out.writeLine('<TR><TD><A HREF=\"' + htmlfile + '\">' + fname + '</A></TD></TD><TD>');
|
||||
if (indexFileArray[fname])
|
||||
out.writeLine(indexFileArray[fname]);
|
||||
else
|
||||
out.writeLine('No comments');
|
||||
out.writeLine('</TD></TR>\n');
|
||||
}
|
||||
out.writeLine('</TABLE></BODY></HTML>');
|
||||
out.close();
|
||||
|
||||
// construct the functions index file
|
||||
var out = CreateOutputFile(outputdir,indexFunction);
|
||||
|
||||
// write the beginning of the file
|
||||
out.writeLine('<HTML><HEADER><TITLE>Function Index - directory: ' + dirname + '</TITLE><BODY>');
|
||||
out.writeLine('<H1>Function Index - directory: ' + dirname + '</H1>\n');
|
||||
out.writeLine('<TABLE WIDTH="90%" BORDER=1>');
|
||||
out.writeLine('<TR BGCOLOR=0xdddddddd>');
|
||||
out.writeLine('<TD><B>Function</B></TD>');
|
||||
out.writeLine('<TD><B>Files</B></TD></TR>');
|
||||
|
||||
// sort the function array
|
||||
var SortedFunctionArray = [];
|
||||
for (var functionname in indexFunctionArray)
|
||||
SortedFunctionArray.push(functionname);
|
||||
SortedFunctionArray.sort();
|
||||
|
||||
for (var j=0; j < SortedFunctionArray.length; j++) {
|
||||
var funcname = SortedFunctionArray[j];
|
||||
with (indexFunctionArray[funcname]) {
|
||||
var outstr = '<TR><TD>' + funcname + '</TD><TD>';
|
||||
var filelst = filename.split("|");
|
||||
for (var i in filelst) {
|
||||
var htmlfile = filelst[i].replace(/\.js$/, ".html");
|
||||
outstr += '<A HREF=\"' + htmlfile + '#' + funcname + '\">' + filelst[i] + '</A> ';
|
||||
}
|
||||
outstr += '</TD></TR>';
|
||||
out.writeLine(outstr);
|
||||
}
|
||||
}
|
||||
out.writeLine('</TABLE></BODY></HTML>');
|
||||
out.close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* prints the options for JSDoc
|
||||
*/
|
||||
function PrintOptions()
|
||||
{
|
||||
print("You can use the following options:\n");
|
||||
print("-d: specify an output directory for the generated html files\n");
|
||||
print("-i: processes all files in an input directory (you can specify several directories)\n");
|
||||
quit();
|
||||
}
|
||||
|
||||
|
||||
// Main Script
|
||||
// first read the arguments
|
||||
if (! arguments)
|
||||
PrintOptions();
|
||||
|
||||
for (var i=0; i < arguments.length; i++) {
|
||||
if (debug) print("argument: + \'" + arguments[i] + "\'");
|
||||
if (arguments[i].match(/^\-/)) {
|
||||
if (String(arguments[i])=="-d"){
|
||||
// output directory for the generated html files
|
||||
|
||||
outputdir = String(arguments[i+1]);
|
||||
if (debug) print("outputdir: + \'" + outputdir + "\'");
|
||||
|
||||
i++;
|
||||
}
|
||||
else if (String(arguments[i])=="-i"){
|
||||
// process all files in an input directory
|
||||
|
||||
DirList.push(String(arguments[i+1]));
|
||||
if (debug) print("inputdir: + \'" + arguments[i+1] + "\'");
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
print("Unknown option: " + arguments[i] + "\n");
|
||||
PrintOptions();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have a single file
|
||||
if (debug) print("file: + \'" + arguments[i] + "\'");
|
||||
|
||||
FileList.push(String(arguments[i]));
|
||||
}
|
||||
}
|
||||
|
||||
// first handle the single files
|
||||
for (var i in FileList)
|
||||
processJSFile(FileList[i],null);
|
||||
|
||||
// then handle the input directories
|
||||
for (var j in DirList) {
|
||||
var inputdir = String(DirList[j]);
|
||||
|
||||
print("Process input directory: " + inputdir);
|
||||
|
||||
// clean up index arrays
|
||||
var indexFileArray = [];
|
||||
var indexFunctionArray = [];
|
||||
|
||||
// for the directory name get rid of ../../ or ..\..\
|
||||
inputDirName = inputdir.replace(/\.\.\/|\.\.\\/g,"");
|
||||
|
||||
indexFile = indexFileName + "_" + inputDirName + ".html";
|
||||
indexFunction = indexFunctionName + "_" + inputDirName + ".html";
|
||||
|
||||
print("indexFile = " + indexFile);
|
||||
print("indexFunction = " + indexFunction);
|
||||
|
||||
// read the files in the directory
|
||||
var DirFile = new java.io.File(inputdir);
|
||||
var lst = DirFile.list();
|
||||
var separator = Packages.java.io.File.separator;
|
||||
|
||||
for (var i=0; i < lst.length; i++)
|
||||
{
|
||||
processJSFile(String(lst[i]),inputdir);
|
||||
}
|
||||
|
||||
// generate the index files for the input directory
|
||||
GenerateIndex(inputDirName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
54
mozilla/js/rhino/examples/liveConnect.js
Normal file
54
mozilla/js/rhino/examples/liveConnect.js
Normal file
@@ -0,0 +1,54 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
/**
|
||||
* liveConnect.js: a simple demonstration of JavaScript-to-Java connectivity
|
||||
*/
|
||||
|
||||
// Create a new StringBuffer. Note that the class name must be fully qualified
|
||||
// by its package. Packages other than "java" must start with "Packages", i.e.,
|
||||
// "Packages.javax.servlet...".
|
||||
var sb = new java.lang.StringBuffer();
|
||||
|
||||
// Now add some stuff to the buffer.
|
||||
sb.append("hi, mom");
|
||||
sb.append(3); // this will add "3.0" to the buffer since all JS numbers
|
||||
// are doubles by default
|
||||
sb.append(true);
|
||||
|
||||
// Now print it out. (The toString() method of sb is automatically called
|
||||
// to convert the buffer to a string.)
|
||||
// Should print "hi, mom3.0true".
|
||||
print(sb);
|
||||
53
mozilla/js/rhino/examples/unique.js
Normal file
53
mozilla/js/rhino/examples/unique.js
Normal file
@@ -0,0 +1,53 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
// unique.js: read the contents of a file and print out the unique lines
|
||||
|
||||
defineClass("File")
|
||||
|
||||
// "arguments[0]" refers to the first argument at the command line to the
|
||||
// script, if present. If not present, "arguments[0]" will be undefined,
|
||||
// which will cause f to read from System.in.
|
||||
var f = new File(arguments[0]);
|
||||
var o = {}
|
||||
var line;
|
||||
while ((line = f.readLine()) != null) {
|
||||
// Use JavaScript objects' inherent nature as an associative
|
||||
// array to provide uniqueness
|
||||
o[line] = true;
|
||||
}
|
||||
for (i in o) {
|
||||
print(i);
|
||||
}
|
||||
BIN
mozilla/js/rhino/macbuild/import
Normal file
BIN
mozilla/js/rhino/macbuild/import
Normal file
Binary file not shown.
BIN
mozilla/js/rhino/macbuild/js.mcp
Normal file
BIN
mozilla/js/rhino/macbuild/js.mcp
Normal file
Binary file not shown.
3388
mozilla/js/rhino/macbuild/js.mcp.xml
Normal file
3388
mozilla/js/rhino/macbuild/js.mcp.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
mozilla/js/rhino/macbuild/jsdebug.mcp
Executable file
BIN
mozilla/js/rhino/macbuild/jsdebug.mcp
Executable file
Binary file not shown.
BIN
mozilla/js/rhino/macbuild/jsopt.mcp
Executable file
BIN
mozilla/js/rhino/macbuild/jsopt.mcp
Executable file
Binary file not shown.
2
mozilla/js/rhino/manifest
Normal file
2
mozilla/js/rhino/manifest
Normal file
@@ -0,0 +1,2 @@
|
||||
Manifest-Version: 1.0
|
||||
Main-Class: org.mozilla.javascript.tools.shell.Main
|
||||
1082
mozilla/js/rhino/org/mozilla/classfile/ByteCode.java
Normal file
1082
mozilla/js/rhino/org/mozilla/classfile/ByteCode.java
Normal file
File diff suppressed because it is too large
Load Diff
1464
mozilla/js/rhino/org/mozilla/classfile/ClassFileWriter.java
Normal file
1464
mozilla/js/rhino/org/mozilla/classfile/ClassFileWriter.java
Normal file
File diff suppressed because it is too large
Load Diff
130
mozilla/js/rhino/org/mozilla/javascript/Arguments.java
Normal file
130
mozilla/js/rhino/org/mozilla/javascript/Arguments.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* This class implements the "arguments" object.
|
||||
*
|
||||
* See ECMA 10.1.8
|
||||
*
|
||||
* @see org.mozilla.javascript.NativeCall
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
class Arguments extends ScriptableObject {
|
||||
|
||||
public Arguments(NativeCall activation) {
|
||||
this.activation = activation;
|
||||
|
||||
Scriptable parent = activation.getParentScope();
|
||||
setParentScope(parent);
|
||||
setPrototype(ScriptableObject.getObjectPrototype(parent));
|
||||
|
||||
args = activation.getOriginalArguments();
|
||||
int length = args.length;
|
||||
Object callee = activation.funObj;
|
||||
|
||||
defineProperty("length", new Integer(length),
|
||||
ScriptableObject.DONTENUM);
|
||||
defineProperty("callee", callee, ScriptableObject.DONTENUM);
|
||||
|
||||
hasCaller = (activation.funObj.version <= Context.VERSION_1_3 &&
|
||||
activation.funObj.version != Context.VERSION_DEFAULT);
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "Arguments";
|
||||
}
|
||||
|
||||
public boolean has(String name, Scriptable start) {
|
||||
return (hasCaller && name.equals("caller")) || super.has(name, start);
|
||||
}
|
||||
|
||||
public boolean has(int index, Scriptable start) {
|
||||
Object[] args = activation.getOriginalArguments();
|
||||
return (0 <= index && index < args.length) || super.has(index, start);
|
||||
}
|
||||
|
||||
public Object get(String name, Scriptable start) {
|
||||
if (hasCaller && name.equals("caller")) {
|
||||
NativeCall caller = activation.caller;
|
||||
if (caller == null || caller.originalArgs == null)
|
||||
return null;
|
||||
return caller.get("arguments", caller);
|
||||
}
|
||||
return super.get(name, start);
|
||||
}
|
||||
|
||||
public Object get(int index, Scriptable start) {
|
||||
if (0 <= index && index < args.length) {
|
||||
NativeFunction f = activation.funObj;
|
||||
if (index < f.argCount)
|
||||
return activation.get(f.names[index+1], activation);
|
||||
return args[index];
|
||||
}
|
||||
return super.get(index, start);
|
||||
}
|
||||
|
||||
public void put(String name, Scriptable start, Object value) {
|
||||
if (name.equals("caller")) {
|
||||
// Set "hasCaller" to false so that we won't look up a
|
||||
// computed value.
|
||||
hasCaller = false;
|
||||
}
|
||||
super.put(name, start, value);
|
||||
}
|
||||
|
||||
public void put(int index, Scriptable start, Object value) {
|
||||
if (0 <= index && index < args.length) {
|
||||
NativeFunction f = activation.funObj;
|
||||
if (index < f.argCount)
|
||||
activation.put(f.names[index+1], activation, value);
|
||||
else
|
||||
args[index] = value;
|
||||
return;
|
||||
}
|
||||
super.put(index, start, value);
|
||||
}
|
||||
|
||||
public void delete(String name) {
|
||||
if (name.equals("caller"))
|
||||
hasCaller = false;
|
||||
super.delete(name);
|
||||
}
|
||||
|
||||
private NativeCall activation;
|
||||
private Object[] args;
|
||||
private boolean hasCaller;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Waldemar Horwat
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
package org.mozilla.javascript;
|
||||
|
||||
final class BinaryDigitReader {
|
||||
int lgBase; // Logarithm of base of number
|
||||
int digit; // Current digit value in radix given by base
|
||||
int digitPos; // Bit position of last bit extracted from digit
|
||||
String digits; // String containing the digits
|
||||
int start; // Index of the first remaining digit
|
||||
int end; // Index past the last remaining digit
|
||||
|
||||
BinaryDigitReader(int base, String digits, int start, int end) {
|
||||
lgBase = 0;
|
||||
while (base != 1) {
|
||||
lgBase++;
|
||||
base >>= 1;
|
||||
}
|
||||
digitPos = 0;
|
||||
this.digits = digits;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
/* Return the next binary digit from the number or -1 if done */
|
||||
int getNextBinaryDigit()
|
||||
{
|
||||
if (digitPos == 0) {
|
||||
if (start == end)
|
||||
return -1;
|
||||
|
||||
char c = digits.charAt(start++);
|
||||
if ('0' <= c && c <= '9')
|
||||
digit = c - '0';
|
||||
else if ('a' <= c && c <= 'z')
|
||||
digit = c - 'a' + 10;
|
||||
else digit = c - 'A' + 10;
|
||||
digitPos = lgBase;
|
||||
}
|
||||
return digit >> --digitPos & 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* Thrown if errors are detected while attempting to define a host object
|
||||
* from a Java class.
|
||||
*/
|
||||
public class ClassDefinitionException extends Exception {
|
||||
|
||||
public ClassDefinitionException(String detail) {
|
||||
super(detail);
|
||||
}
|
||||
}
|
||||
61
mozilla/js/rhino/org/mozilla/javascript/ClassNameHelper.java
Normal file
61
mozilla/js/rhino/org/mozilla/javascript/ClassNameHelper.java
Normal file
@@ -0,0 +1,61 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
* Roger Lawrence
|
||||
* Andi Vajda
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
public interface ClassNameHelper {
|
||||
|
||||
public String getTargetClassFileName();
|
||||
|
||||
public void setTargetClassFileName(String classFileName);
|
||||
|
||||
public String getTargetPackage();
|
||||
|
||||
public void setTargetPackage(String targetPackage);
|
||||
|
||||
public String getTargetClassFileName(String className);
|
||||
|
||||
public String getGeneratingDirectory();
|
||||
|
||||
public void setTargetExtends(Class extendsClass);
|
||||
|
||||
public void setTargetImplements(Class[] implementsClasses);
|
||||
|
||||
public ClassOutput getClassOutput();
|
||||
|
||||
public void setClassOutput(ClassOutput classOutput);
|
||||
}
|
||||
56
mozilla/js/rhino/org/mozilla/javascript/ClassOutput.java
Normal file
56
mozilla/js/rhino/org/mozilla/javascript/ClassOutput.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Andi Vajda
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
package org.mozilla.javascript;
|
||||
|
||||
// API class
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* This interface is implemented by classes interested in the bytecode
|
||||
* generated by the rhino compiler for script objects.
|
||||
*
|
||||
* @see Context
|
||||
* @author Andi Vajda
|
||||
*/
|
||||
public interface ClassOutput {
|
||||
|
||||
/**
|
||||
* @param className the name of the class for which bytecode is ready.
|
||||
* @return a stream into which to write bytecode.
|
||||
* @since 1.5 Release 2
|
||||
*/
|
||||
public OutputStream getOutputStream(String className)
|
||||
throws IOException;
|
||||
1819
mozilla/js/rhino/org/mozilla/javascript/Context.java
Normal file
1819
mozilla/js/rhino/org/mozilla/javascript/Context.java
Normal file
File diff suppressed because it is too large
Load Diff
1197
mozilla/js/rhino/org/mozilla/javascript/DToA.java
Normal file
1197
mozilla/js/rhino/org/mozilla/javascript/DToA.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,63 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* This is the default error reporter for JavaScript.
|
||||
*
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
class DefaultErrorReporter implements ErrorReporter {
|
||||
|
||||
public void warning(String message, String sourceName, int line,
|
||||
String lineSource, int lineOffset)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public void error(String message, String sourceName, int line,
|
||||
String lineSource, int lineOffset)
|
||||
{
|
||||
throw new EvaluatorException(message);
|
||||
}
|
||||
|
||||
public EvaluatorException runtimeError(String message, String sourceName,
|
||||
int line, String lineSource,
|
||||
int lineOffset)
|
||||
{
|
||||
return new EvaluatorException(message);
|
||||
}
|
||||
}
|
||||
152
mozilla/js/rhino/org/mozilla/javascript/EcmaError.java
Normal file
152
mozilla/js/rhino/org/mozilla/javascript/EcmaError.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Roger Lawrence
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* The class of exceptions raised by the engine as described in
|
||||
* ECMA edition 3. See section 15.11.6 in particular.
|
||||
*/
|
||||
public class EcmaError extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Create an exception with the specified detail message.
|
||||
*
|
||||
* Errors internal to the JavaScript engine will simply throw a
|
||||
* RuntimeException.
|
||||
*
|
||||
* @param nativeError the NativeError object constructed for this error
|
||||
* @param sourceName the name of the source reponsible for the error
|
||||
* @param lineNumber the line number of the source
|
||||
* @param columnNumber the columnNumber of the source (may be zero if
|
||||
* unknown)
|
||||
* @param lineSource the source of the line containing the error (may be
|
||||
* null if unknown)
|
||||
*/
|
||||
public EcmaError(NativeError nativeError, String sourceName,
|
||||
int lineNumber, int columnNumber, String lineSource)
|
||||
{
|
||||
super("EcmaError");
|
||||
errorObject = nativeError;
|
||||
this.sourceName = sourceName;
|
||||
this.lineNumber = lineNumber;
|
||||
this.columnNumber = columnNumber;
|
||||
this.lineSource = lineSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string representation of the error, which currently consists
|
||||
* of the name of the error together with the message.
|
||||
*/
|
||||
public String toString() {
|
||||
if (sourceName != null && lineNumber > 0)
|
||||
return errorObject.toString() + " (" + sourceName +
|
||||
"; line " + lineNumber + ")";
|
||||
else
|
||||
return errorObject.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the error.
|
||||
*
|
||||
* ECMA edition 3 defines the following
|
||||
* errors: EvalError, RangeError, ReferenceError,
|
||||
* SyntaxError, TypeError, and URIError. Additional error names
|
||||
* may be added in the future.
|
||||
*
|
||||
* See ECMA edition 3, 15.11.7.9.
|
||||
*
|
||||
* @return the name of the error.
|
||||
*/
|
||||
public String getName() {
|
||||
return errorObject.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message corresponding to the error.
|
||||
*
|
||||
* See ECMA edition 3, 15.11.7.10.
|
||||
*
|
||||
* @return an implemenation-defined string describing the error.
|
||||
*/
|
||||
public String getMessage() {
|
||||
return errorObject.getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the source containing the error, or null
|
||||
* if that information is not available.
|
||||
*/
|
||||
public String getSourceName() {
|
||||
return sourceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the line number of the statement causing the error,
|
||||
* or zero if not available.
|
||||
*/
|
||||
public int getLineNumber() {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error object corresponding to this exception.
|
||||
*/
|
||||
public Scriptable getErrorObject() {
|
||||
return errorObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* The column number of the location of the error, or zero if unknown.
|
||||
*/
|
||||
public int getColumnNumber() {
|
||||
return columnNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* The source of the line causing the error, or zero if unknown.
|
||||
*/
|
||||
public String getLineSource() {
|
||||
return lineSource;
|
||||
}
|
||||
|
||||
private NativeError errorObject;
|
||||
private String sourceName;
|
||||
private int lineNumber;
|
||||
private int columnNumber;
|
||||
private String lineSource;
|
||||
}
|
||||
103
mozilla/js/rhino/org/mozilla/javascript/ErrorReporter.java
Normal file
103
mozilla/js/rhino/org/mozilla/javascript/ErrorReporter.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* This is interface defines a protocol for the reporting of
|
||||
* errors during JavaScript translation or execution.
|
||||
*
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
|
||||
public interface ErrorReporter {
|
||||
|
||||
/**
|
||||
* Report a warning.
|
||||
*
|
||||
* The implementing class may choose to ignore the warning
|
||||
* if it desires.
|
||||
*
|
||||
* @param message a String describing the warning
|
||||
* @param sourceName a String describing the JavaScript source
|
||||
* where the warning occured; typically a filename or URL
|
||||
* @param line the line number associated with the warning
|
||||
* @param lineSource the text of the line (may be null)
|
||||
* @param lineOffset the offset into lineSource where problem was detected
|
||||
*/
|
||||
void warning(String message, String sourceName, int line,
|
||||
String lineSource, int lineOffset);
|
||||
|
||||
/**
|
||||
* Report an error.
|
||||
*
|
||||
* The implementing class is free to throw an exception if
|
||||
* it desires.
|
||||
*
|
||||
* If execution has not yet begun, the JavaScript engine is
|
||||
* free to find additional errors rather than terminating
|
||||
* the translation. It will not execute a script that had
|
||||
* errors, however.
|
||||
*
|
||||
* @param message a String describing the error
|
||||
* @param sourceName a String describing the JavaScript source
|
||||
* where the error occured; typically a filename or URL
|
||||
* @param line the line number associated with the error
|
||||
* @param lineSource the text of the line (may be null)
|
||||
* @param lineOffset the offset into lineSource where problem was detected
|
||||
*/
|
||||
void error(String message, String sourceName, int line,
|
||||
String lineSource, int lineOffset);
|
||||
|
||||
/**
|
||||
* Creates an EvaluatorException that may be thrown.
|
||||
*
|
||||
* runtimeErrors, unlike errors, will always terminate the
|
||||
* current script.
|
||||
*
|
||||
* @param message a String describing the error
|
||||
* @param sourceName a String describing the JavaScript source
|
||||
* where the error occured; typically a filename or URL
|
||||
* @param line the line number associated with the error
|
||||
* @param lineSource the text of the line (may be null)
|
||||
* @param lineOffset the offset into lineSource where problem was detected
|
||||
* @return an EvaluatorException that will be thrown.
|
||||
*/
|
||||
EvaluatorException runtimeError(String message, String sourceName,
|
||||
int line, String lineSource,
|
||||
int lineOffset);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* The class of exceptions thrown by the JavaScript engine.
|
||||
*/
|
||||
public class EvaluatorException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Create an exception with the specified detail message.
|
||||
*
|
||||
* Errors internal to the JavaScript engine will simply throw a
|
||||
* RuntimeException.
|
||||
*
|
||||
* @param detail a message with detail about the exception
|
||||
*/
|
||||
public EvaluatorException(String detail) {
|
||||
super(detail);
|
||||
}
|
||||
|
||||
}
|
||||
342
mozilla/js/rhino/org/mozilla/javascript/FlattenedObject.java
Normal file
342
mozilla/js/rhino/org/mozilla/javascript/FlattenedObject.java
Normal file
@@ -0,0 +1,342 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
* Roger Lawrence
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
* Manipulate a Scriptable object as if its prototype chain were flattened.
|
||||
* <p>
|
||||
* This class has been deprecated in favor of the static methods
|
||||
* <code>getProperty</code>, <code>putProperty</code>, and
|
||||
* <code>deleteProperty</code>. Those methods provide the
|
||||
* same functionality without the confusing and inefficient need to construct
|
||||
* a new object instance.
|
||||
*
|
||||
* @see org.mozilla.javascript.ScriptableObject
|
||||
*
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
|
||||
public class FlattenedObject {
|
||||
|
||||
/**
|
||||
* Construct a new FlattenedObject.
|
||||
*
|
||||
* @param object the object to be viewed with flattened properties
|
||||
* @deprecated
|
||||
*/
|
||||
public FlattenedObject(Scriptable object) {
|
||||
this.obj = object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated Scriptable object.
|
||||
* @deprecated
|
||||
*/
|
||||
public Scriptable getObject() {
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a property exists in an object.
|
||||
*
|
||||
* This is a more convenient (and less efficient) form than
|
||||
* <code>Scriptable.has()</code>.
|
||||
* It returns true if and only if the property
|
||||
* exists in this object or any of the objects in its prototype
|
||||
* chain.
|
||||
*
|
||||
* @param id the property index, which may be either a String or a
|
||||
* Number
|
||||
* @return true if and only if the property exists in the prototype
|
||||
* chain
|
||||
* @see org.mozilla.javascript.Scriptable#has
|
||||
* @deprecated As of 1.5R2, replaced by ScriptableObject.getProperty
|
||||
*/
|
||||
public boolean hasProperty(Object id) {
|
||||
String stringId = ScriptRuntime.toString(id);
|
||||
String s = ScriptRuntime.getStringId(stringId);
|
||||
if (s == null)
|
||||
return getBase(obj, ScriptRuntime.getIntId(stringId)) != null;
|
||||
return getBase(obj, s) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a property of an object.
|
||||
* <p>
|
||||
* This is a more convenient (and less efficient) form than
|
||||
* <code>Scriptable.get()</code>. It corresponds exactly to the
|
||||
* expression <code>obj[id]</code> in JavaScript. This method
|
||||
* will traverse the prototype chain of an object to find the
|
||||
* property.<p>
|
||||
*
|
||||
* If the property does not exist in the object or its prototype
|
||||
* chain, the undefined value will be returned.
|
||||
*
|
||||
* @param id the property index; can be a String or a Number; the
|
||||
* String may contain characters representing a number
|
||||
* @return the value of the property or the undefined value
|
||||
* @see org.mozilla.javascript.Scriptable#get
|
||||
* @see org.mozilla.javascript.Context#getUndefinedValue
|
||||
* @deprecated As of 1.5R2, replaced by ScriptableObject.getProperty
|
||||
*/
|
||||
public Object getProperty(Object id) {
|
||||
String s = ScriptRuntime.getStringId(id);
|
||||
int index = s == null ? ScriptRuntime.getIntId(id) : 0;
|
||||
Scriptable m = obj;
|
||||
Object result;
|
||||
for(;;) {
|
||||
result = s == null ? m.get(index, obj) : m.get(s, obj);
|
||||
if (result != Scriptable.NOT_FOUND)
|
||||
break;
|
||||
m = m.getPrototype();
|
||||
if (m == null)
|
||||
return Undefined.instance;
|
||||
}
|
||||
if (result instanceof Scriptable)
|
||||
return new FlattenedObject((Scriptable) result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a property of an object.
|
||||
*
|
||||
* This is a more convenient (and less efficient) form than that
|
||||
* provided in Scriptable. It corresponds exactly to the
|
||||
* expression <code>obj[id] = val</code> in JavaScript.<p>
|
||||
*
|
||||
* @param id the property index, which may be either a String or
|
||||
* a Number
|
||||
* @param value the value of the property
|
||||
* @see org.mozilla.javascript.Scriptable#put
|
||||
* @deprecated As of 1.5R2, replaced by ScriptableObject.putProperty
|
||||
*/
|
||||
public void putProperty(Object id, Object value) {
|
||||
String s = ScriptRuntime.getStringId(id);
|
||||
if (value instanceof FlattenedObject)
|
||||
value = ((FlattenedObject) value).getObject();
|
||||
Scriptable x;
|
||||
if (s == null) {
|
||||
int index = ScriptRuntime.getIntId(id);
|
||||
x = getBase(obj, index);
|
||||
if (x == null)
|
||||
x = obj;
|
||||
x.put(index, obj, value);
|
||||
return;
|
||||
}
|
||||
x = getBase(obj, s);
|
||||
if (x == null)
|
||||
x = obj;
|
||||
x.put(s, obj, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a property.
|
||||
*
|
||||
* This method provides the functionality of the <code>delete</code>
|
||||
* operator in JavaScript.
|
||||
*
|
||||
* @param id the property index, which may be either a String or
|
||||
* a Number
|
||||
* @return true if the property didn't exist, or existed and was removed
|
||||
* @see org.mozilla.javascript.Scriptable#delete
|
||||
* @deprecated as of 1.5R2, replaced by ScriptableObject.deleteProperty
|
||||
*/
|
||||
public boolean deleteProperty(Object id) {
|
||||
String s = ScriptRuntime.getStringId(id);
|
||||
if (s == null) {
|
||||
int index = ScriptRuntime.getIntId(id);
|
||||
Scriptable base = getBase(obj, index);
|
||||
if (base == null)
|
||||
return true;
|
||||
base.delete(index);
|
||||
return !base.has(index, base);
|
||||
}
|
||||
Scriptable base = getBase(obj, s);
|
||||
if (base == null)
|
||||
return true;
|
||||
base.delete(s);
|
||||
return !base.has(s, base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array that contains the ids of the properties.
|
||||
*
|
||||
* <p>This method will walk the prototype chain and collect the
|
||||
* ids of all objects in the prototype chain.<p>
|
||||
*
|
||||
* If an id appears in more than one object in the prototype chain,
|
||||
* it will only be in the array once. (So all the entries in the
|
||||
* array will be unique respective to equals().)
|
||||
*
|
||||
* @see org.mozilla.javascript.Scriptable#getIds
|
||||
* @deprecated
|
||||
*/
|
||||
public Object[] getIds() {
|
||||
Hashtable h = new Hashtable(11);
|
||||
Scriptable m = obj;
|
||||
while (m != null) {
|
||||
Object[] e = m.getIds();
|
||||
for (int i=0; i < e.length; i++) {
|
||||
h.put(e[i], Boolean.TRUE);
|
||||
}
|
||||
m = m.getPrototype();
|
||||
}
|
||||
Enumeration keys = h.keys();
|
||||
Object elem;
|
||||
Object[] result = new Object[h.size()];
|
||||
int index = 0;
|
||||
while (keys.hasMoreElements()) {
|
||||
elem = keys.nextElement();
|
||||
result[index++] = elem;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consider this object to be a function, and call it.
|
||||
*
|
||||
* @param cx the current Context for this thread
|
||||
* @param thisObj the JavaScript 'this' for the call
|
||||
* @param args the arguments for the call
|
||||
* @return the result of the JavaScript function call
|
||||
* @exception NotAFunctionException if this object is not a function
|
||||
* @exception JavaScriptException if an uncaught JavaScript exception
|
||||
* occurred while executing the function
|
||||
* @see org.mozilla.javascript.Function#call
|
||||
* @deprecated
|
||||
*/
|
||||
public Object call(Context cx, Scriptable thisObj, Object[] args)
|
||||
throws NotAFunctionException,
|
||||
JavaScriptException
|
||||
{
|
||||
if (!(obj instanceof Function)) {
|
||||
throw new NotAFunctionException();
|
||||
}
|
||||
return ScriptRuntime.call(cx, obj, thisObj, args, (Function) obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Consider this object to be a function, and invoke it as a
|
||||
* constructor call.
|
||||
*
|
||||
* @param cx the current Context for this thread
|
||||
* @param args the arguments for the constructor call
|
||||
* @return the allocated object
|
||||
* @exception NotAFunctionException if this object is not a function
|
||||
* @exception JavaScriptException if an uncaught JavaScript exception
|
||||
* occurred while executing the constructor
|
||||
* @see org.mozilla.javascript.Function#construct
|
||||
* @deprecated
|
||||
*/
|
||||
public Scriptable construct(Context cx, Object[] args)
|
||||
throws NotAFunctionException,
|
||||
JavaScriptException
|
||||
{
|
||||
if (!(obj instanceof Function)) {
|
||||
throw new NotAFunctionException();
|
||||
}
|
||||
return ScriptRuntime.newObject(cx, obj, args, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the property indicated by the id, and invoke it with the
|
||||
* specified arguments.
|
||||
* <p>
|
||||
* For example, for a FlattenedObject <code>obj</code>,
|
||||
* and a Java array <code>a</code> consisting of a single string
|
||||
* <code>"hi"</code>, the call <pre>
|
||||
* obj.callMethod("m", a)</pre>
|
||||
* is equivalent to the JavaScript code <code>obj.m("hi")</code>.<p>
|
||||
*
|
||||
* If the property is not found or is not a function, an
|
||||
* exception will be thrown.
|
||||
*
|
||||
* @param id the Number or String to use to find the function property
|
||||
* to call
|
||||
* @param args the arguments for the constructor call
|
||||
* @return the result of the call
|
||||
* @exception PropertyException if the designated property
|
||||
* was not found
|
||||
* @exception NotAFunctionException if this object is not a function
|
||||
* @exception JavaScriptException if an uncaught JavaScript exception
|
||||
* occurred while executing the method
|
||||
* @see org.mozilla.javascript.Function#call
|
||||
* @deprecated
|
||||
*/
|
||||
public Object callMethod(Object id, Object[] args)
|
||||
throws PropertyException,
|
||||
NotAFunctionException,
|
||||
JavaScriptException
|
||||
{
|
||||
if (!hasProperty(id)) {
|
||||
throw new PropertyException(
|
||||
Context.getMessage("msg.prop.not.found", null));
|
||||
}
|
||||
Object o = getProperty(id);
|
||||
if (o instanceof FlattenedObject)
|
||||
return ((FlattenedObject) o).call(Context.getContext(), obj, args);
|
||||
throw new NotAFunctionException();
|
||||
}
|
||||
|
||||
/****** End of API *******/
|
||||
|
||||
private static Scriptable getBase(Scriptable obj, String s) {
|
||||
Scriptable m = obj;
|
||||
while (m != null) {
|
||||
if (m.has(s, obj))
|
||||
return m;
|
||||
m = m.getPrototype();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Scriptable getBase(Scriptable obj, int index) {
|
||||
Scriptable m = obj;
|
||||
while (m != null) {
|
||||
if (m.has(index, obj))
|
||||
return m;
|
||||
m = m.getPrototype();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Scriptable obj;
|
||||
}
|
||||
|
||||
86
mozilla/js/rhino/org/mozilla/javascript/Function.java
Normal file
86
mozilla/js/rhino/org/mozilla/javascript/Function.java
Normal file
@@ -0,0 +1,86 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* This is interface that all functions in JavaScript must implement.
|
||||
* The interface provides for calling functions and constructors.
|
||||
*
|
||||
* @see org.mozilla.javascript.Scriptable
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
|
||||
public interface Function extends Scriptable {
|
||||
/**
|
||||
* Call the function.
|
||||
*
|
||||
* Note that the array of arguments is not guaranteed to have
|
||||
* length greater than 0.
|
||||
*
|
||||
* @param cx the current Context for this thread
|
||||
* @param scope the scope to execute the function relative to. This is
|
||||
* set to the value returned by getParentScope() except
|
||||
* when the function is called from a closure.
|
||||
* @param thisObj the JavaScript <code>this</code> object
|
||||
* @param args the array of arguments
|
||||
* @return the result of the call
|
||||
* @exception JavaScriptException if an uncaught exception
|
||||
* occurred while executing the function
|
||||
*/
|
||||
public Object call(Context cx, Scriptable scope, Scriptable thisObj,
|
||||
Object[] args)
|
||||
throws JavaScriptException;
|
||||
|
||||
/**
|
||||
* Call the function as a constructor.
|
||||
*
|
||||
* This method is invoked by the runtime in order to satisfy a use
|
||||
* of the JavaScript <code>new</code> operator. This method is
|
||||
* expected to create a new object and return it.
|
||||
*
|
||||
* @param cx the current Context for this thread
|
||||
* @param scope an enclosing scope of the caller except
|
||||
* when the function is called from a closure.
|
||||
* @param args the array of arguments
|
||||
* @return the allocated object
|
||||
* @exception JavaScriptException if an uncaught exception
|
||||
* occurred while executing the constructor
|
||||
*/
|
||||
public Scriptable construct(Context cx, Scriptable scope, Object[] args)
|
||||
throws JavaScriptException;
|
||||
}
|
||||
94
mozilla/js/rhino/org/mozilla/javascript/FunctionNode.java
Normal file
94
mozilla/js/rhino/org/mozilla/javascript/FunctionNode.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
* Roger Lawrence
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class FunctionNode extends Node {
|
||||
|
||||
public FunctionNode(String name, Node left, Node right) {
|
||||
super(TokenStream.FUNCTION, left, right, name);
|
||||
itsVariableTable = new VariableTable();
|
||||
}
|
||||
|
||||
public String getFunctionName() {
|
||||
return getString();
|
||||
}
|
||||
|
||||
public VariableTable getVariableTable() {
|
||||
return itsVariableTable;
|
||||
}
|
||||
|
||||
public boolean requiresActivation() {
|
||||
return itsNeedsActivation;
|
||||
}
|
||||
|
||||
public boolean setRequiresActivation(boolean b) {
|
||||
return itsNeedsActivation = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* There are three types of functions that can be defined. The first
|
||||
* is a function statement. This is a function appearing as a top-level
|
||||
* statement (i.e., not nested inside some other statement) in either a
|
||||
* script or a function.
|
||||
*
|
||||
* The second is a function expression, which is a function appearing in
|
||||
* an expression except for the third type, which is...
|
||||
*
|
||||
* The third type is a function expression where the expression is the
|
||||
* top-level expression in an expression statement.
|
||||
*
|
||||
* The three types of functions have different treatment and must be
|
||||
* distinquished.
|
||||
*/
|
||||
public static final byte FUNCTION_STATEMENT = 1;
|
||||
public static final byte FUNCTION_EXPRESSION = 2;
|
||||
public static final byte FUNCTION_EXPRESSION_STATEMENT = 3;
|
||||
|
||||
public byte getFunctionType() {
|
||||
return itsFunctionType;
|
||||
}
|
||||
|
||||
public void setFunctionType(byte functionType) {
|
||||
itsFunctionType = functionType;
|
||||
}
|
||||
|
||||
protected VariableTable itsVariableTable;
|
||||
protected boolean itsNeedsActivation;
|
||||
protected byte itsFunctionType;
|
||||
}
|
||||
636
mozilla/js/rhino/org/mozilla/javascript/FunctionObject.java
Normal file
636
mozilla/js/rhino/org/mozilla/javascript/FunctionObject.java
Normal file
@@ -0,0 +1,636 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
* Ted Neward
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
public class FunctionObject extends NativeFunction {
|
||||
|
||||
/**
|
||||
* Create a JavaScript function object from a Java method.
|
||||
*
|
||||
* <p>The <code>member</code> argument must be either a java.lang.reflect.Method
|
||||
* or a java.lang.reflect.Constructor and must match one of two forms.<p>
|
||||
*
|
||||
* The first form is a member with zero or more parameters
|
||||
* of the following types: Object, String, boolean, Scriptable,
|
||||
* byte, short, int, float, or double. The Long type is not supported
|
||||
* because the double representation of a long (which is the
|
||||
* EMCA-mandated storage type for Numbers) may lose precision.
|
||||
* If the member is a Method, the return value must be void or one
|
||||
* of the types allowed for parameters.<p>
|
||||
*
|
||||
* The runtime will perform appropriate conversions based
|
||||
* upon the type of the parameter. A parameter type of
|
||||
* Object specifies that no conversions are to be done. A parameter
|
||||
* of type String will use Context.toString to convert arguments.
|
||||
* Similarly, parameters of type double, boolean, and Scriptable
|
||||
* will cause Context.toNumber, Context.toBoolean, and
|
||||
* Context.toObject, respectively, to be called.<p>
|
||||
*
|
||||
* If the method is not static, the Java 'this' value will
|
||||
* correspond to the JavaScript 'this' value. Any attempt
|
||||
* to call the function with a 'this' value that is not
|
||||
* of the right Java type will result in an error.<p>
|
||||
*
|
||||
* The second form is the variable arguments (or "varargs")
|
||||
* form. If the FunctionObject will be used as a constructor,
|
||||
* the member must have the following parameters
|
||||
* <pre>
|
||||
* (Context cx, Object[] args, Function ctorObj,
|
||||
* boolean inNewExpr)</pre>
|
||||
* and if it is a Method, be static and return an Object result.<p>
|
||||
*
|
||||
* Otherwise, if the FunctionObject will <i>not</i> be used to define a
|
||||
* constructor, the member must be a static Method with parameters
|
||||
* (Context cx, Scriptable thisObj, Object[] args,
|
||||
* Function funObj) </pre>
|
||||
* <pre>
|
||||
* and an Object result.<p>
|
||||
*
|
||||
* When the function varargs form is called as part of a function call,
|
||||
* the <code>args</code> parameter contains the
|
||||
* arguments, with <code>thisObj</code>
|
||||
* set to the JavaScript 'this' value. <code>funObj</code>
|
||||
* is the function object for the invoked function.<p>
|
||||
*
|
||||
* When the constructor varargs form is called or invoked while evaluating
|
||||
* a <code>new</code> expression, <code>args</code> contains the
|
||||
* arguments, <code>ctorObj</code> refers to this FunctionObject, and
|
||||
* <code>inNewExpr</code> is true if and only if a <code>new</code>
|
||||
* expression caused the call. This supports defining a function that
|
||||
* has different behavior when called as a constructor than when
|
||||
* invoked as a normal function call. (For example, the Boolean
|
||||
* constructor, when called as a function,
|
||||
* will convert to boolean rather than creating a new object.)<p>
|
||||
*
|
||||
* @param name the name of the function
|
||||
* @param methodOrConstructor a java.lang.reflect.Method or a java.lang.reflect.Constructor
|
||||
* that defines the object
|
||||
* @param scope enclosing scope of function
|
||||
* @see org.mozilla.javascript.Scriptable
|
||||
*/
|
||||
public FunctionObject(String name, Member methodOrConstructor,
|
||||
Scriptable scope)
|
||||
{
|
||||
String methodName;
|
||||
if (methodOrConstructor instanceof Constructor) {
|
||||
ctor = (Constructor) methodOrConstructor;
|
||||
isStatic = true; // well, doesn't take a 'this'
|
||||
types = ctor.getParameterTypes();
|
||||
methodName = ctor.getName();
|
||||
} else {
|
||||
method = (Method) methodOrConstructor;
|
||||
isStatic = Modifier.isStatic(method.getModifiers());
|
||||
types = method.getParameterTypes();
|
||||
methodName = method.getName();
|
||||
}
|
||||
String myNames[] = { name };
|
||||
super.names = myNames;
|
||||
int length;
|
||||
if (types.length == 4 && (types[1].isArray() || types[2].isArray())) {
|
||||
// Either variable args or an error.
|
||||
if (types[1].isArray()) {
|
||||
if (!isStatic ||
|
||||
types[0] != Context.class ||
|
||||
types[1].getComponentType() != ScriptRuntime.ObjectClass ||
|
||||
types[2] != ScriptRuntime.FunctionClass ||
|
||||
types[3] != Boolean.TYPE)
|
||||
{
|
||||
String[] args = { methodName };
|
||||
String message = Context.getMessage("msg.varargs.ctor",
|
||||
args);
|
||||
throw Context.reportRuntimeError(message);
|
||||
}
|
||||
parmsLength = VARARGS_CTOR;
|
||||
} else {
|
||||
if (!isStatic ||
|
||||
types[0] != Context.class ||
|
||||
types[1] != ScriptRuntime.ScriptableClass ||
|
||||
types[2].getComponentType() != ScriptRuntime.ObjectClass ||
|
||||
types[3] != ScriptRuntime.FunctionClass)
|
||||
{
|
||||
String[] args = { methodName };
|
||||
String message = Context.getMessage("msg.varargs.fun",
|
||||
args);
|
||||
throw Context.reportRuntimeError(message);
|
||||
}
|
||||
parmsLength = VARARGS_METHOD;
|
||||
}
|
||||
// XXX check return type
|
||||
length = 1;
|
||||
} else {
|
||||
parmsLength = (short) types.length;
|
||||
boolean hasConversions = false;
|
||||
for (int i=0; i < parmsLength; i++) {
|
||||
Class type = types[i];
|
||||
if (type == ScriptRuntime.ObjectClass) {
|
||||
// may not need conversions
|
||||
} else if (type == ScriptRuntime.StringClass ||
|
||||
type == ScriptRuntime.BooleanClass ||
|
||||
ScriptRuntime.NumberClass.isAssignableFrom(type) ||
|
||||
Scriptable.class.isAssignableFrom(type))
|
||||
{
|
||||
hasConversions = true;
|
||||
} else if (type == Boolean.TYPE) {
|
||||
hasConversions = true;
|
||||
types[i] = ScriptRuntime.BooleanClass;
|
||||
} else if (type == Byte.TYPE) {
|
||||
hasConversions = true;
|
||||
types[i] = ScriptRuntime.ByteClass;
|
||||
} else if (type == Short.TYPE) {
|
||||
hasConversions = true;
|
||||
types[i] = ScriptRuntime.ShortClass;
|
||||
} else if (type == Integer.TYPE) {
|
||||
hasConversions = true;
|
||||
types[i] = ScriptRuntime.IntegerClass;
|
||||
} else if (type == Float.TYPE) {
|
||||
hasConversions = true;
|
||||
types[i] = ScriptRuntime.FloatClass;
|
||||
} else if (type == Double.TYPE) {
|
||||
hasConversions = true;
|
||||
types[i] = ScriptRuntime.DoubleClass;
|
||||
}
|
||||
// Note that long is not supported; see comments above
|
||||
else {
|
||||
Object[] errArgs = { methodName };
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.bad.parms", errArgs));
|
||||
}
|
||||
}
|
||||
if (!hasConversions)
|
||||
types = null;
|
||||
length = parmsLength;
|
||||
}
|
||||
|
||||
// Initialize length property
|
||||
lengthPropertyValue = (short) length;
|
||||
|
||||
hasVoidReturn = method != null && method.getReturnType() == Void.TYPE;
|
||||
this.argCount = (short) length;
|
||||
|
||||
setParentScope(scope);
|
||||
setPrototype(getFunctionPrototype(scope));
|
||||
Context cx = Context.getCurrentContext();
|
||||
useDynamicScope = cx != null &&
|
||||
cx.hasCompileFunctionsWithDynamicScope();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override ScriptableObject's has, get, and set in order to define
|
||||
* the "length" property of the function. <p>
|
||||
*
|
||||
* We could also have defined the property using ScriptableObject's
|
||||
* defineProperty method, but that would have consumed a slot in every
|
||||
* FunctionObject. Most FunctionObjects typically don't have any
|
||||
* properties anyway, so having the "length" property would cause us
|
||||
* to allocate an array of slots. <p>
|
||||
*
|
||||
* In particular, this method will return true for
|
||||
* <code>name.equals("length")</code>
|
||||
* and will delegate to the superclass for all other
|
||||
* values of <code>name</code>.
|
||||
*/
|
||||
public boolean has(String name, Scriptable start) {
|
||||
return name.equals("length") || super.has(name, start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override ScriptableObject's has, get, and set in order to define
|
||||
* the "length" property of the function. <p>
|
||||
*
|
||||
* In particular, this method will return the value defined by
|
||||
* the method used to construct the object (number of parameters
|
||||
* of the method, or 1 if the method is a "varargs" form), unless
|
||||
* setLength has been called with a new value.
|
||||
*
|
||||
* @see org.mozilla.javascript.FunctionObject#setLength
|
||||
*/
|
||||
public Object get(String name, Scriptable start) {
|
||||
if (name.equals("length"))
|
||||
return new Integer(lengthPropertyValue);
|
||||
return super.get(name, start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override ScriptableObject's has, get, and set in order to define
|
||||
* the "length" property of the function. <p>
|
||||
*
|
||||
* In particular, this method will ignore all attempts to set the
|
||||
* "length" property and forward all other requests to ScriptableObject.
|
||||
*
|
||||
* @see org.mozilla.javascript.FunctionObject#setLength
|
||||
*/
|
||||
public void put(String name, Scriptable start, Object value) {
|
||||
if (!name.equals("length"))
|
||||
super.put(name, start, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the "length" property.
|
||||
*
|
||||
* <p>Changing the value of the "length" property of a FunctionObject only
|
||||
* affects the value retrieved from get() and does not affect the way
|
||||
* the method itself is called. <p>
|
||||
*
|
||||
* The "length" property will be defined by default as the number
|
||||
* of parameters of the method used to construct the FunctionObject,
|
||||
* unless the method is a "varargs" form, in which case the "length"
|
||||
* property will be defined to 1.
|
||||
*
|
||||
* @param length the new length
|
||||
*/
|
||||
public void setLength(short length) {
|
||||
lengthPropertyValue = length;
|
||||
}
|
||||
|
||||
// TODO: Make not public
|
||||
/**
|
||||
* Finds methods of a given name in a given class.
|
||||
*
|
||||
* <p>Searches <code>clazz</code> for methods with name
|
||||
* <code>name</code>. Maintains a cache so that multiple
|
||||
* lookups on the same class are cheap.
|
||||
*
|
||||
* @param clazz the class to search
|
||||
* @param name the name of the methods to find
|
||||
* @return an array of the found methods, or null if no methods
|
||||
* by that name were found.
|
||||
* @see java.lang.Class#getMethods
|
||||
*/
|
||||
public static Method[] findMethods(Class clazz, String name) {
|
||||
return findMethods(getMethodList(clazz), name);
|
||||
}
|
||||
|
||||
static Method[] findMethods(Method[] methods, String name) {
|
||||
// Usually we're just looking for a single method, so optimize
|
||||
// for that case.
|
||||
Vector v = null;
|
||||
Method first = null;
|
||||
for (int i=0; i < methods.length; i++) {
|
||||
if (methods[i] == null)
|
||||
continue;
|
||||
if (methods[i].getName().equals(name)) {
|
||||
if (first == null) {
|
||||
first = methods[i];
|
||||
} else {
|
||||
if (v == null) {
|
||||
v = new Vector(5);
|
||||
v.addElement(first);
|
||||
}
|
||||
v.addElement(methods[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (v == null) {
|
||||
if (first == null)
|
||||
return null;
|
||||
Method[] single = { first };
|
||||
return single;
|
||||
}
|
||||
Method[] result = new Method[v.size()];
|
||||
v.copyInto(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static Method[] getMethodList(Class clazz) {
|
||||
Method[] cached = methodsCache; // get once to avoid synchronization
|
||||
if (cached != null && cached[0].getDeclaringClass() == clazz)
|
||||
return cached;
|
||||
Method[] methods = null;
|
||||
try {
|
||||
// getDeclaredMethods may be rejected by the security manager
|
||||
// but getMethods is more expensive
|
||||
if (!sawSecurityException)
|
||||
methods = clazz.getDeclaredMethods();
|
||||
} catch (SecurityException e) {
|
||||
// If we get an exception once, give up on getDeclaredMethods
|
||||
sawSecurityException = true;
|
||||
}
|
||||
if (methods == null) {
|
||||
methods = clazz.getMethods();
|
||||
}
|
||||
int count = 0;
|
||||
for (int i=0; i < methods.length; i++) {
|
||||
if (sawSecurityException
|
||||
? methods[i].getDeclaringClass() != clazz
|
||||
: !Modifier.isPublic(methods[i].getModifiers()))
|
||||
{
|
||||
methods[i] = null;
|
||||
} else {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
Method[] result = new Method[count];
|
||||
int j=0;
|
||||
for (int i=0; i < methods.length; i++) {
|
||||
if (methods[i] != null)
|
||||
result[j++] = methods[i];
|
||||
}
|
||||
if (result.length > 0 && Context.isCachingEnabled)
|
||||
methodsCache = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define this function as a JavaScript constructor.
|
||||
* <p>
|
||||
* Sets up the "prototype" and "constructor" properties. Also
|
||||
* calls setParent and setPrototype with appropriate values.
|
||||
* Then adds the function object as a property of the given scope, using
|
||||
* <code>prototype.getClassName()</code>
|
||||
* as the name of the property.
|
||||
*
|
||||
* @param scope the scope in which to define the constructor (typically
|
||||
* the global object)
|
||||
* @param prototype the prototype object
|
||||
* @see org.mozilla.javascript.Scriptable#setParentScope
|
||||
* @see org.mozilla.javascript.Scriptable#setPrototype
|
||||
* @see org.mozilla.javascript.Scriptable#getClassName
|
||||
*/
|
||||
public void addAsConstructor(Scriptable scope, Scriptable prototype) {
|
||||
setParentScope(scope);
|
||||
setPrototype(getFunctionPrototype(scope));
|
||||
prototype.setParentScope(this);
|
||||
final int attr = ScriptableObject.DONTENUM |
|
||||
ScriptableObject.PERMANENT |
|
||||
ScriptableObject.READONLY;
|
||||
defineProperty("prototype", prototype, attr);
|
||||
String name = prototype.getClassName();
|
||||
if (!name.equals("With")) {
|
||||
// A "With" object would delegate these calls to the prototype:
|
||||
// not the right thing to do here!
|
||||
if (prototype instanceof ScriptableObject) {
|
||||
((ScriptableObject) prototype).defineProperty("constructor",
|
||||
this, attr);
|
||||
} else {
|
||||
prototype.put("constructor", prototype, this);
|
||||
}
|
||||
}
|
||||
if (scope instanceof ScriptableObject) {
|
||||
((ScriptableObject) scope).defineProperty(name, this,
|
||||
ScriptableObject.DONTENUM);
|
||||
} else {
|
||||
scope.put(name, scope, this);
|
||||
}
|
||||
setParentScope(scope);
|
||||
}
|
||||
|
||||
static public Object convertArg(Scriptable scope,
|
||||
Object arg, Class desired)
|
||||
{
|
||||
if (desired == ScriptRuntime.BooleanClass
|
||||
|| desired == Boolean.TYPE)
|
||||
return ScriptRuntime.toBoolean(arg) ? Boolean.TRUE
|
||||
: Boolean.FALSE;
|
||||
else if (desired == ScriptRuntime.StringClass)
|
||||
return ScriptRuntime.toString(arg);
|
||||
else if (desired == ScriptRuntime.IntegerClass
|
||||
|| desired == Integer.TYPE)
|
||||
return new Integer(ScriptRuntime.toInt32(arg));
|
||||
else if (desired == ScriptRuntime.DoubleClass
|
||||
|| desired == Double.TYPE)
|
||||
return new Double(ScriptRuntime.toNumber(arg));
|
||||
else if (desired == ScriptRuntime.ScriptableClass)
|
||||
return ScriptRuntime.toObject(scope, arg);
|
||||
else if (desired == ScriptRuntime.ObjectClass)
|
||||
return arg;
|
||||
// Note that the long type is not supported; see the javadoc for
|
||||
// the constructor for this class
|
||||
else {
|
||||
Object[] errArgs = { desired.getName() };
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.cant.convert", errArgs));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs conversions on argument types if needed and
|
||||
* invokes the underlying Java method or constructor.
|
||||
* <p>
|
||||
* Implements Function.call.
|
||||
*
|
||||
* @see org.mozilla.javascript.Function#call
|
||||
* @exception JavaScriptException if the underlying Java method or
|
||||
* constructor threw an exception
|
||||
*/
|
||||
public Object call(Context cx, Scriptable scope, Scriptable thisObj,
|
||||
Object[] args)
|
||||
throws JavaScriptException
|
||||
{
|
||||
if (parmsLength < 0)
|
||||
return callVarargs(cx, thisObj, args, false);
|
||||
|
||||
if (!isStatic) {
|
||||
// OPT: cache "clazz"?
|
||||
Class clazz = method != null ? method.getDeclaringClass()
|
||||
: ctor.getDeclaringClass();
|
||||
while (!clazz.isInstance(thisObj)) {
|
||||
thisObj = thisObj.getPrototype();
|
||||
if (thisObj == null || !useDynamicScope) {
|
||||
// Couldn't find an object to call this on.
|
||||
Object[] errArgs = { names[0] };
|
||||
String msg = Context.getMessage("msg.incompat.call", errArgs);
|
||||
throw NativeGlobal.constructError(cx, "TypeError", msg, scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
Object[] invokeArgs;
|
||||
int i;
|
||||
if (parmsLength == args.length) {
|
||||
invokeArgs = args;
|
||||
// avoid copy loop if no conversions needed
|
||||
i = (types == null) ? parmsLength : 0;
|
||||
} else {
|
||||
invokeArgs = new Object[parmsLength];
|
||||
i = 0;
|
||||
}
|
||||
for (; i < parmsLength; i++) {
|
||||
Object arg = (i < args.length)
|
||||
? args[i]
|
||||
: Undefined.instance;
|
||||
if (types != null) {
|
||||
arg = convertArg(this, arg, types[i]);
|
||||
}
|
||||
invokeArgs[i] = arg;
|
||||
}
|
||||
try {
|
||||
Object result = (method != null)
|
||||
? method.invoke(thisObj, invokeArgs)
|
||||
: ctor.newInstance(invokeArgs);
|
||||
return hasVoidReturn ? Undefined.instance : result;
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw JavaScriptException.wrapException(scope, e);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw WrappedException.wrapException(e);
|
||||
}
|
||||
catch (InstantiationException e) {
|
||||
throw WrappedException.wrapException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs conversions on argument types if needed and
|
||||
* invokes the underlying Java method or constructor
|
||||
* to create a new Scriptable object.
|
||||
* <p>
|
||||
* Implements Function.construct.
|
||||
*
|
||||
* @param cx the current Context for this thread
|
||||
* @param scope the scope to execute the function relative to. This
|
||||
* set to the value returned by getParentScope() except
|
||||
* when the function is called from a closure.
|
||||
* @param args arguments to the constructor
|
||||
* @see org.mozilla.javascript.Function#construct
|
||||
* @exception JavaScriptException if the underlying Java method or constructor
|
||||
* threw an exception
|
||||
*/
|
||||
public Scriptable construct(Context cx, Scriptable scope, Object[] args)
|
||||
throws JavaScriptException
|
||||
{
|
||||
if (method == null || parmsLength == VARARGS_CTOR) {
|
||||
Scriptable result;
|
||||
if (method != null) {
|
||||
// Ugly: allow variable-arg constructors that need access to the
|
||||
// scope to get it from the Context. Cleanest solution would be
|
||||
// to modify the varargs form, but that would require users with
|
||||
// the old form to change their code.
|
||||
cx.ctorScope = scope;
|
||||
result = (Scriptable) callVarargs(cx, null, args, true);
|
||||
cx.ctorScope = null;
|
||||
} else {
|
||||
result = (Scriptable) call(cx, scope, null, args);
|
||||
}
|
||||
|
||||
if (result.getPrototype() == null)
|
||||
result.setPrototype(getClassPrototype());
|
||||
if (result.getParentScope() == null) {
|
||||
Scriptable parent = getParentScope();
|
||||
if (result != parent)
|
||||
result.setParentScope(parent);
|
||||
}
|
||||
|
||||
return result;
|
||||
} else if (method != null && !isStatic) {
|
||||
Scriptable result;
|
||||
try {
|
||||
result = (Scriptable) method.getDeclaringClass().newInstance();
|
||||
} catch (IllegalAccessException e) {
|
||||
throw WrappedException.wrapException(e);
|
||||
} catch (InstantiationException e) {
|
||||
throw WrappedException.wrapException(e);
|
||||
}
|
||||
|
||||
result.setPrototype(getClassPrototype());
|
||||
result.setParentScope(getParentScope());
|
||||
|
||||
Object val = call(cx, scope, result, args);
|
||||
if (val != null && val != Undefined.instance &&
|
||||
val instanceof Scriptable)
|
||||
{
|
||||
return (Scriptable) val;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return super.construct(cx, scope, args);
|
||||
}
|
||||
|
||||
private Object callVarargs(Context cx, Scriptable thisObj, Object[] args,
|
||||
boolean inNewExpr)
|
||||
throws JavaScriptException
|
||||
{
|
||||
try {
|
||||
if (parmsLength == VARARGS_METHOD) {
|
||||
Object[] invokeArgs = { cx, thisObj, args, this };
|
||||
Object result = method.invoke(null, invokeArgs);
|
||||
return hasVoidReturn ? Undefined.instance : result;
|
||||
} else {
|
||||
Boolean b = inNewExpr ? Boolean.TRUE : Boolean.FALSE;
|
||||
Object[] invokeArgs = { cx, args, this, b };
|
||||
return (method == null)
|
||||
? ctor.newInstance(invokeArgs)
|
||||
: method.invoke(null, invokeArgs);
|
||||
}
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
Throwable target = e.getTargetException();
|
||||
if (target instanceof EvaluatorException)
|
||||
throw (EvaluatorException) target;
|
||||
if (target instanceof EcmaError)
|
||||
throw (EcmaError) target;
|
||||
Scriptable scope = thisObj == null ? this : thisObj;
|
||||
throw JavaScriptException.wrapException(scope, target);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw WrappedException.wrapException(e);
|
||||
}
|
||||
catch (InstantiationException e) {
|
||||
throw WrappedException.wrapException(e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isVarArgsMethod() {
|
||||
return parmsLength == VARARGS_METHOD;
|
||||
}
|
||||
|
||||
boolean isVarArgsConstructor() {
|
||||
return parmsLength == VARARGS_CTOR;
|
||||
}
|
||||
|
||||
private static final short VARARGS_METHOD = -1;
|
||||
private static final short VARARGS_CTOR = -2;
|
||||
|
||||
private static boolean sawSecurityException;
|
||||
|
||||
static Method[] methodsCache;
|
||||
|
||||
Method method;
|
||||
Constructor ctor;
|
||||
private Class[] types;
|
||||
private short parmsLength;
|
||||
private short lengthPropertyValue;
|
||||
private boolean hasVoidReturn;
|
||||
private boolean isStatic;
|
||||
private boolean useDynamicScope;
|
||||
}
|
||||
1056
mozilla/js/rhino/org/mozilla/javascript/IRFactory.java
Normal file
1056
mozilla/js/rhino/org/mozilla/javascript/IRFactory.java
Normal file
File diff suppressed because it is too large
Load Diff
144
mozilla/js/rhino/org/mozilla/javascript/ImporterTopLevel.java
Normal file
144
mozilla/js/rhino/org/mozilla/javascript/ImporterTopLevel.java
Normal file
@@ -0,0 +1,144 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Class ImporterTopLevel
|
||||
*
|
||||
* This class defines a ScriptableObject that can be instantiated
|
||||
* as a top-level ("global") object to provide functionality similar
|
||||
* to Java's "import" statement.
|
||||
* <p>
|
||||
* This class can be used to create a top-level scope using the following code:
|
||||
* <pre>
|
||||
* Scriptable scope = cx.initStandardObjects(new ImporterTopLevel());
|
||||
* </pre>
|
||||
* Then JavaScript code will have access to the following methods:
|
||||
* <ul>
|
||||
* <li>importClass - will "import" a class by making its unqualified name
|
||||
* available as a property of the top-level scope
|
||||
* <li>importPackage - will "import" all the classes of the package by
|
||||
* searching for unqualified names as classes qualified
|
||||
* by the given package.
|
||||
* </ul>
|
||||
* The following code from the shell illustrates this use:
|
||||
* <pre>
|
||||
* js> importClass(java.io.File)
|
||||
* js> f = new File('help.txt')
|
||||
* help.txt
|
||||
* js> importPackage(java.util)
|
||||
* js> v = new Vector()
|
||||
* []
|
||||
*
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public class ImporterTopLevel extends ScriptableObject {
|
||||
|
||||
public ImporterTopLevel() {
|
||||
String[] names = { "importClass", "importPackage" };
|
||||
|
||||
try {
|
||||
this.defineFunctionProperties(names, ImporterTopLevel.class,
|
||||
ScriptableObject.DONTENUM);
|
||||
} catch (PropertyException e) {
|
||||
throw new Error(); // should never happen
|
||||
}
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "global";
|
||||
}
|
||||
|
||||
public Object get(String name, Scriptable start) {
|
||||
Object result = super.get(name, start);
|
||||
if (result == NOT_FOUND && importedPackages != null) {
|
||||
for (int i=0; i < importedPackages.size(); i++) {
|
||||
Object o = importedPackages.elementAt(i);
|
||||
NativeJavaPackage p = (NativeJavaPackage) o;
|
||||
Object v = p.getPkgProperty(name, start, false);
|
||||
if (v != null && !(v instanceof NativeJavaPackage)) {
|
||||
if (result == NOT_FOUND) {
|
||||
result = v;
|
||||
} else {
|
||||
String[] args = { result.toString(), v.toString() };
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.ambig.import",
|
||||
args));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void importClass(Object cl) {
|
||||
if (!(cl instanceof NativeJavaClass)) {
|
||||
String[] args = { Context.toString(cl) };
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.not.class", args));
|
||||
}
|
||||
String s = ((NativeJavaClass) cl).getClassObject().getName();
|
||||
String n = s.substring(s.lastIndexOf('.')+1);
|
||||
Object val = this.get(n, this);
|
||||
if (val != NOT_FOUND && val != cl) {
|
||||
String[] args = { n };
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.prop.defined", args));
|
||||
}
|
||||
this.defineProperty(n, cl, DONTENUM);
|
||||
}
|
||||
|
||||
public void importPackage(Object pkg) {
|
||||
if (importedPackages == null)
|
||||
importedPackages = new Vector();
|
||||
if (!(pkg instanceof NativeJavaPackage)) {
|
||||
String[] args = { Context.toString(pkg) };
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.not.pkg", args));
|
||||
}
|
||||
for (int i=0; i < importedPackages.size(); i++) {
|
||||
if (pkg == importedPackages.elementAt(i))
|
||||
return; // allready in list
|
||||
}
|
||||
importedPackages.addElement(pkg);
|
||||
}
|
||||
|
||||
private Vector importedPackages;
|
||||
}
|
||||
113
mozilla/js/rhino/org/mozilla/javascript/InterpretedFunction.java
Normal file
113
mozilla/js/rhino/org/mozilla/javascript/InterpretedFunction.java
Normal file
@@ -0,0 +1,113 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Roger Lawrence
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.util.*;
|
||||
import org.mozilla.javascript.debug.DebuggableScript;
|
||||
|
||||
class InterpretedFunction extends NativeFunction implements DebuggableScript {
|
||||
|
||||
InterpretedFunction(InterpreterData theData, Context cx)
|
||||
{
|
||||
itsData = theData;
|
||||
init(cx);
|
||||
}
|
||||
|
||||
void init(Context cx)
|
||||
{
|
||||
// probably too much copying going on from theData to the InterpretedFunction object
|
||||
// should pass them as parameters - unless we need them in the data block anyway?
|
||||
|
||||
names = new String[itsData.itsVariableTable.size() + 1];
|
||||
names[0] = itsData.itsName;
|
||||
for (int i = 0; i < itsData.itsVariableTable.size(); i++)
|
||||
names[i + 1] = itsData.itsVariableTable.getName(i);
|
||||
argCount = (short)itsData.itsVariableTable.getParameterCount();
|
||||
source = itsData.itsSource;
|
||||
nestedFunctions = itsData.itsNestedFunctions;
|
||||
if (cx != null)
|
||||
version = (short)cx.getLanguageVersion();
|
||||
}
|
||||
|
||||
InterpretedFunction(InterpretedFunction theOther,
|
||||
Scriptable theScope, Context cx)
|
||||
{
|
||||
itsData = theOther.itsData;
|
||||
itsClosure = theScope;
|
||||
init(cx);
|
||||
}
|
||||
|
||||
public Object call(Context cx, Scriptable scope, Scriptable thisObj,
|
||||
Object[] args)
|
||||
throws JavaScriptException
|
||||
{
|
||||
itsData.itsCX = cx;
|
||||
if (itsClosure != null)
|
||||
scope = itsClosure;
|
||||
else if (!itsData.itsUseDynamicScope)
|
||||
scope = getParentScope();
|
||||
if (itsData.itsNeedsActivation)
|
||||
scope = ScriptRuntime.initVarObj(cx, scope, this, thisObj, args);
|
||||
itsData.itsScope = scope;
|
||||
itsData.itsThisObj = thisObj;
|
||||
itsData.itsInArgs = args;
|
||||
return Interpreter.interpret(itsData, this);
|
||||
}
|
||||
|
||||
public Scriptable getScriptable() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getSourceName() {
|
||||
return itsData.itsSourceFile;
|
||||
}
|
||||
|
||||
public Enumeration getLineNumbers() {
|
||||
return itsData.itsLineNumberTable.keys();
|
||||
}
|
||||
|
||||
public boolean placeBreakpoint(int line) { // XXX throw exn?
|
||||
return itsData.placeBreakpoint(line);
|
||||
}
|
||||
|
||||
public boolean removeBreakpoint(int line) {
|
||||
return itsData.removeBreakpoint(line);
|
||||
}
|
||||
|
||||
InterpreterData itsData;
|
||||
Scriptable itsClosure;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Roger Lawrence
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import org.mozilla.javascript.debug.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class InterpretedScript extends NativeScript implements DebuggableScript {
|
||||
|
||||
InterpretedScript(InterpreterData theData, Context cx)
|
||||
{
|
||||
itsData = theData;
|
||||
names = new String[itsData.itsVariableTable.size() + 1];
|
||||
names[0] = "";
|
||||
for (int i = 0; i < itsData.itsVariableTable.size(); i++)
|
||||
names[i + 1] = itsData.itsVariableTable.getName(i);
|
||||
nestedFunctions = itsData.itsNestedFunctions;
|
||||
version = (short)cx.getLanguageVersion();
|
||||
}
|
||||
|
||||
public Object exec(Context cx, Scriptable scope)
|
||||
throws JavaScriptException
|
||||
{
|
||||
return call(cx, scope, scope, null);
|
||||
}
|
||||
|
||||
public Object call(Context cx, Scriptable scope,
|
||||
Scriptable thisObj, Object[] args)
|
||||
throws JavaScriptException
|
||||
{
|
||||
scope = ScriptRuntime.initScript(cx, scope, this, thisObj,
|
||||
itsData.itsFromEvalCode);
|
||||
itsData.itsCX = cx;
|
||||
itsData.itsScope = scope;
|
||||
itsData.itsThisObj = thisObj;
|
||||
itsData.itsInArgs = args;
|
||||
return Interpreter.interpret(itsData, this);
|
||||
}
|
||||
|
||||
public Scriptable getScriptable() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getSourceName() {
|
||||
return itsData.itsSourceFile;
|
||||
}
|
||||
|
||||
public Enumeration getLineNumbers() {
|
||||
return itsData.itsLineNumberTable.keys();
|
||||
}
|
||||
|
||||
public boolean placeBreakpoint(int line) { // XXX throw exn?
|
||||
return itsData.placeBreakpoint(line);
|
||||
}
|
||||
|
||||
public boolean removeBreakpoint(int line) {
|
||||
return itsData.removeBreakpoint(line);
|
||||
}
|
||||
|
||||
InterpreterData itsData;
|
||||
}
|
||||
|
||||
1993
mozilla/js/rhino/org/mozilla/javascript/Interpreter.java
Normal file
1993
mozilla/js/rhino/org/mozilla/javascript/Interpreter.java
Normal file
File diff suppressed because it is too large
Load Diff
138
mozilla/js/rhino/org/mozilla/javascript/InterpreterData.java
Normal file
138
mozilla/js/rhino/org/mozilla/javascript/InterpreterData.java
Normal file
@@ -0,0 +1,138 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Roger Lawrence
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
class InterpreterData {
|
||||
|
||||
static final int INITIAL_MAX_ICODE_LENGTH = 1024;
|
||||
static final int INITIAL_STRINGTABLE_SIZE = 64;
|
||||
static final int INITIAL_NUMBERTABLE_SIZE = 64;
|
||||
|
||||
InterpreterData(int lastICodeTop, int lastStringTableIndex,
|
||||
int lastNumberTableIndex, Object securityDomain,
|
||||
boolean useDynamicScope)
|
||||
{
|
||||
itsICodeTop = lastICodeTop == 0
|
||||
? INITIAL_MAX_ICODE_LENGTH
|
||||
: lastICodeTop * 2;
|
||||
itsICode = new byte[itsICodeTop];
|
||||
|
||||
itsStringTable = new String[lastStringTableIndex == 0
|
||||
? INITIAL_STRINGTABLE_SIZE
|
||||
: lastStringTableIndex * 2];
|
||||
|
||||
itsNumberTable = new Number[lastNumberTableIndex == 0
|
||||
? INITIAL_NUMBERTABLE_SIZE
|
||||
: lastNumberTableIndex * 2];
|
||||
|
||||
itsUseDynamicScope = useDynamicScope;
|
||||
if (securityDomain == null && Context.isSecurityDomainRequired())
|
||||
throw new SecurityException("Required security context missing");
|
||||
this.securityDomain = securityDomain;
|
||||
}
|
||||
|
||||
public boolean placeBreakpoint(int line) { // XXX throw exn?
|
||||
int offset = getOffset(line);
|
||||
if (offset != -1 && (itsICode[offset] == TokenStream.LINE ||
|
||||
itsICode[offset] == TokenStream.BREAKPOINT))
|
||||
{
|
||||
itsICode[offset] = (byte) TokenStream.BREAKPOINT;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean removeBreakpoint(int line) {
|
||||
int offset = getOffset(line);
|
||||
if (offset != -1 && itsICode[offset] == TokenStream.BREAKPOINT)
|
||||
{
|
||||
itsICode[offset] = (byte) TokenStream.LINE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int getOffset(int line) {
|
||||
Object offset = itsLineNumberTable.get(new Integer(line));
|
||||
if (offset != null && offset instanceof Integer) {
|
||||
int i = ((Integer)offset).intValue();
|
||||
if (i >= 0 && i < itsICode.length)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
VariableTable itsVariableTable;
|
||||
|
||||
String itsName;
|
||||
String itsSource;
|
||||
String itsSourceFile;
|
||||
boolean itsNeedsActivation;
|
||||
boolean itsFromEvalCode;
|
||||
boolean itsUseDynamicScope;
|
||||
byte itsFunctionType;
|
||||
|
||||
String[] itsStringTable;
|
||||
int itsStringTableIndex;
|
||||
|
||||
Number[] itsNumberTable;
|
||||
int itsNumberTableIndex;
|
||||
|
||||
InterpretedFunction[] itsNestedFunctions;
|
||||
|
||||
Object[] itsRegExpLiterals;
|
||||
|
||||
byte[] itsICode;
|
||||
int itsICodeTop;
|
||||
|
||||
int itsMaxLocals;
|
||||
int itsMaxArgs;
|
||||
int itsMaxStack;
|
||||
int itsMaxTryDepth;
|
||||
|
||||
java.util.Hashtable itsLineNumberTable;
|
||||
|
||||
Object securityDomain;
|
||||
|
||||
Context itsCX;
|
||||
Scriptable itsScope;
|
||||
Scriptable itsThisObj;
|
||||
Object[] itsInArgs;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import org.mozilla.javascript.debug.*;
|
||||
|
||||
class InterpreterFrame implements Frame {
|
||||
|
||||
InterpreterFrame(Scriptable scope, InterpreterData data, Scriptable obj) {
|
||||
this.scope = scope;
|
||||
this.data = data;
|
||||
this.lineNumber = -1;
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
public Scriptable getVariableObject() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public String getSourceName() {
|
||||
return data.itsSourceFile;
|
||||
}
|
||||
|
||||
public void setLineNumber(int lineNumber) {
|
||||
this.lineNumber = lineNumber;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
public DebuggableScript getScript() {
|
||||
if (obj instanceof DebuggableScript)
|
||||
return (DebuggableScript) obj;
|
||||
return null;
|
||||
}
|
||||
|
||||
private Scriptable scope;
|
||||
private InterpreterData data;
|
||||
private Scriptable obj;
|
||||
private int lineNumber;
|
||||
}
|
||||
849
mozilla/js/rhino/org/mozilla/javascript/JavaAdapter.java
Normal file
849
mozilla/js/rhino/org/mozilla/javascript/JavaAdapter.java
Normal file
@@ -0,0 +1,849 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Patrick Beard
|
||||
* Norris Boyd
|
||||
* Mike McCabe
|
||||
* Matthias Radestock
|
||||
* Andi Vajda
|
||||
* Andrew Wason
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import org.mozilla.classfile.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class JavaAdapter extends ScriptableObject {
|
||||
public boolean equals(Object obj) {
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "JavaAdapter";
|
||||
}
|
||||
|
||||
public static Object convertResult(Object result, String classname)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
Class c = ScriptRuntime.loadClassName(classname);
|
||||
if (result == Undefined.instance &&
|
||||
(c != ScriptRuntime.ObjectClass &&
|
||||
c != ScriptRuntime.StringClass))
|
||||
{
|
||||
// Avoid an error for an undefined value; return null instead.
|
||||
return null;
|
||||
}
|
||||
return NativeJavaObject.coerceType(c, result);
|
||||
}
|
||||
|
||||
public static Object js_JavaAdapter(Context cx, Object[] args,
|
||||
Function ctorObj, boolean inNewExpr)
|
||||
throws InstantiationException, NoSuchMethodException,
|
||||
IllegalAccessException, InvocationTargetException,
|
||||
ClassNotFoundException
|
||||
{
|
||||
Class superClass = Object.class;
|
||||
Class[] intfs = new Class[args.length-1];
|
||||
int interfaceCount = 0;
|
||||
for (int i=0; i < args.length-1; i++) {
|
||||
if (!(args[i] instanceof NativeJavaClass)) {
|
||||
// TODO: report error
|
||||
throw new RuntimeException("expected java class object");
|
||||
}
|
||||
Class c = ((NativeJavaClass) args[i]).getClassObject();
|
||||
if (!c.isInterface()) {
|
||||
superClass = c;
|
||||
break;
|
||||
}
|
||||
intfs[interfaceCount++] = c;
|
||||
}
|
||||
|
||||
Class[] interfaces = new Class[interfaceCount];
|
||||
System.arraycopy(intfs, 0, interfaces, 0, interfaceCount);
|
||||
Scriptable obj = (Scriptable) args[args.length - 1];
|
||||
|
||||
ClassSignature sig = new ClassSignature(superClass, interfaces, obj);
|
||||
Class adapterClass = (Class) generatedClasses.get(sig);
|
||||
if (adapterClass == null) {
|
||||
String adapterName = "adapter" + serial++;
|
||||
adapterClass = createAdapterClass(cx, obj, adapterName,
|
||||
superClass, interfaces,
|
||||
null, null);
|
||||
generatedClasses.put(sig, adapterClass);
|
||||
}
|
||||
|
||||
Class[] ctorParms = { Scriptable.class };
|
||||
Object[] ctorArgs = { obj };
|
||||
Object v = adapterClass.getConstructor(ctorParms).newInstance(ctorArgs);
|
||||
return cx.toObject(v, ScriptableObject.getTopLevelScope(ctorObj));
|
||||
}
|
||||
|
||||
public static Class createAdapterClass(Context cx, Scriptable jsObj,
|
||||
String adapterName, Class superClass,
|
||||
Class[] interfaces,
|
||||
String scriptClassName,
|
||||
ClassNameHelper nameHelper)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
ClassFileWriter cfw = new ClassFileWriter(adapterName,
|
||||
superClass.getName(),
|
||||
"<adapter>");
|
||||
cfw.addField("self", "Lorg/mozilla/javascript/Scriptable;",
|
||||
(short) (ClassFileWriter.ACC_PUBLIC |
|
||||
ClassFileWriter.ACC_FINAL));
|
||||
int interfacesCount = interfaces == null ? 0 : interfaces.length;
|
||||
for (int i=0; i < interfacesCount; i++) {
|
||||
if (interfaces[i] != null)
|
||||
cfw.addInterface(interfaces[i].getName());
|
||||
}
|
||||
|
||||
String superName = superClass.getName().replace('.', '/');
|
||||
generateCtor(cfw, adapterName, superName);
|
||||
if (scriptClassName != null)
|
||||
generateEmptyCtor(cfw, adapterName, superName, scriptClassName);
|
||||
|
||||
Hashtable generatedOverrides = new Hashtable();
|
||||
Hashtable generatedMethods = new Hashtable();
|
||||
|
||||
// generate methods to satisfy all specified interfaces.
|
||||
for (int i = 0; i < interfacesCount; i++) {
|
||||
Method[] methods = interfaces[i].getMethods();
|
||||
for (int j = 0; j < methods.length; j++) {
|
||||
Method method = methods[j];
|
||||
int mods = method.getModifiers();
|
||||
if (Modifier.isStatic(mods) || Modifier.isFinal(mods))
|
||||
continue;
|
||||
// make sure to generate only one instance of a particular
|
||||
// method/signature.
|
||||
String methodName = method.getName();
|
||||
String methodKey = methodName + getMethodSignature(method);
|
||||
if (! generatedOverrides.containsKey(methodKey)) {
|
||||
generateMethod(cfw, adapterName, methodName,
|
||||
method.getParameterTypes(),
|
||||
method.getReturnType());
|
||||
generatedOverrides.put(methodKey, Boolean.TRUE);
|
||||
generatedMethods.put(methodName, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now, go through the superclasses methods, checking for abstract
|
||||
// methods or additional methods to override.
|
||||
|
||||
// generate any additional overrides that the object might contain.
|
||||
Method[] methods = superClass.getMethods();
|
||||
for (int j = 0; j < methods.length; j++) {
|
||||
Method method = methods[j];
|
||||
int mods = method.getModifiers();
|
||||
if (Modifier.isStatic(mods) || Modifier.isFinal(mods))
|
||||
continue;
|
||||
// if a method is marked abstract, must implement it or the
|
||||
// resulting class won't be instantiable. otherwise, if the object
|
||||
// has a property of the same name, then an override is intended.
|
||||
boolean isAbstractMethod = Modifier.isAbstract(mods);
|
||||
if (isAbstractMethod ||
|
||||
(jsObj != null && jsObj.has(method.getName(), jsObj)))
|
||||
{
|
||||
// make sure to generate only one instance of a particular
|
||||
// method/signature.
|
||||
String methodName = method.getName();
|
||||
String methodSignature = getMethodSignature(method);
|
||||
String methodKey = methodName + methodSignature;
|
||||
if (! generatedOverrides.containsKey(methodKey)) {
|
||||
generateMethod(cfw, adapterName, methodName,
|
||||
method.getParameterTypes(),
|
||||
method.getReturnType());
|
||||
generatedOverrides.put(methodKey, Boolean.TRUE);
|
||||
generatedMethods.put(methodName, Boolean.TRUE);
|
||||
}
|
||||
// if a method was overridden, generate a "super$method"
|
||||
// which lets the delegate call the superclass' version.
|
||||
if (!isAbstractMethod) {
|
||||
generateSuper(cfw, adapterName, superName,
|
||||
methodName, methodSignature,
|
||||
method.getParameterTypes(),
|
||||
method.getReturnType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate Java methods, fields for remaining properties that
|
||||
// are not overrides.
|
||||
Object[] ids = jsObj.getIds();
|
||||
for (int j=0; j < ids.length; j++) {
|
||||
if (!(ids[j] instanceof String))
|
||||
continue;
|
||||
String id = (String) ids[j];
|
||||
if (generatedMethods.containsKey(id))
|
||||
continue;
|
||||
Object f = jsObj.get(id, jsObj);
|
||||
int length;
|
||||
if (f instanceof Scriptable) {
|
||||
Scriptable p = (Scriptable) f;
|
||||
if (!(p instanceof Function))
|
||||
continue;
|
||||
length = (int) Context.toNumber(
|
||||
ScriptableObject.getProperty(p, "length"));
|
||||
} else if (f instanceof FunctionNode) {
|
||||
length = ((FunctionNode) f).getVariableTable().getParameterCount();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
Class[] parms = new Class[length];
|
||||
for (int k=0; k < length; k++)
|
||||
parms[k] = Object.class;
|
||||
generateMethod(cfw, adapterName, id, parms, Object.class);
|
||||
}
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(512);
|
||||
try {
|
||||
cfw.write(out);
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
throw new RuntimeException("unexpected IOException");
|
||||
}
|
||||
byte[] bytes = out.toByteArray();
|
||||
|
||||
if (nameHelper != null)
|
||||
{
|
||||
if (nameHelper.getGeneratingDirectory() != null) {
|
||||
try {
|
||||
int lastDot = adapterName.lastIndexOf('.');
|
||||
if (lastDot != -1)
|
||||
adapterName = adapterName.substring(lastDot+1);
|
||||
String filename = nameHelper.getTargetClassFileName(adapterName);
|
||||
FileOutputStream file = new FileOutputStream(filename);
|
||||
file.write(bytes);
|
||||
file.close();
|
||||
}
|
||||
catch (IOException iox) {
|
||||
throw WrappedException.wrapException(iox);
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
ClassOutput classOutput = nameHelper.getClassOutput();
|
||||
|
||||
if (classOutput != null) {
|
||||
OutputStream cOut =
|
||||
classOutput.getOutputStream(adapterName);
|
||||
|
||||
cOut.write(bytes);
|
||||
cOut.close();
|
||||
}
|
||||
} catch (IOException iox) {
|
||||
throw WrappedException.wrapException(iox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SecuritySupport ss = cx.getSecuritySupport();
|
||||
if (ss != null) {
|
||||
Object securityDomain = cx.getSecurityDomainForStackDepth(-1);
|
||||
return ss.defineClass(adapterName, bytes, securityDomain);
|
||||
} else {
|
||||
if (classLoader == null)
|
||||
classLoader = new MyClassLoader();
|
||||
classLoader.defineClass(adapterName, bytes);
|
||||
return classLoader.loadClass(adapterName, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method, which dynamically binds a Context to the current thread,
|
||||
* if none already exists.
|
||||
*/
|
||||
public static Object callMethod(Scriptable object, String methodId,
|
||||
Object[] args)
|
||||
{
|
||||
if (object.has(methodId, object)) {
|
||||
try {
|
||||
Context cx = Context.enter();
|
||||
Object fun = object.get(methodId, object);
|
||||
return ScriptRuntime.call(cx, fun, object, args, object);
|
||||
} catch (JavaScriptException ex) {
|
||||
// TODO: could occur
|
||||
} finally {
|
||||
Context.exit();
|
||||
}
|
||||
}
|
||||
return Context.getUndefinedValue();
|
||||
}
|
||||
|
||||
public static Scriptable toObject(Object value, Scriptable scope,
|
||||
Class staticType)
|
||||
{
|
||||
Context.enter();
|
||||
try {
|
||||
return Context.toObject(value, scope, staticType);
|
||||
} finally {
|
||||
Context.exit();
|
||||
}
|
||||
}
|
||||
|
||||
private static void generateCtor(ClassFileWriter cfw, String adapterName,
|
||||
String superName)
|
||||
{
|
||||
cfw.startMethod("<init>",
|
||||
"(Lorg/mozilla/javascript/Scriptable;)V",
|
||||
ClassFileWriter.ACC_PUBLIC);
|
||||
|
||||
// Invoke base class constructor
|
||||
cfw.add(ByteCode.ALOAD_0); // this
|
||||
cfw.add(ByteCode.INVOKESPECIAL, superName, "<init>", "()", "V");
|
||||
|
||||
// Save parameter in instance variable "self"
|
||||
cfw.add(ByteCode.ALOAD_0); // this
|
||||
cfw.add(ByteCode.ALOAD_1); // first arg
|
||||
cfw.add(ByteCode.PUTFIELD, adapterName, "self",
|
||||
"Lorg/mozilla/javascript/Scriptable;");
|
||||
|
||||
// Set the prototype of the js object to be a LiveConnect
|
||||
// wrapper of the generated class's object
|
||||
cfw.add(ByteCode.ALOAD_1); // first arg
|
||||
cfw.add(ByteCode.ALOAD_0); // this
|
||||
cfw.add(ByteCode.INVOKESTATIC,
|
||||
"org/mozilla/javascript/ScriptRuntime",
|
||||
"setAdapterProto",
|
||||
"(Lorg/mozilla/javascript/Scriptable;" +
|
||||
"Ljava/lang/Object;)",
|
||||
"V");
|
||||
|
||||
cfw.add(ByteCode.RETURN);
|
||||
cfw.stopMethod((short)20, null); // TODO: magic number "20"
|
||||
}
|
||||
|
||||
private static void generateEmptyCtor(ClassFileWriter cfw, String adapterName,
|
||||
String superName, String scriptClassName)
|
||||
{
|
||||
cfw.startMethod("<init>", "()V", ClassFileWriter.ACC_PUBLIC);
|
||||
|
||||
// Invoke base class constructor
|
||||
cfw.add(ByteCode.ALOAD_0); // this
|
||||
cfw.add(ByteCode.INVOKESPECIAL, superName, "<init>", "()", "V");
|
||||
|
||||
// Load script class
|
||||
cfw.add(ByteCode.NEW, scriptClassName);
|
||||
cfw.add(ByteCode.DUP);
|
||||
cfw.add(ByteCode.INVOKESPECIAL, scriptClassName, "<init>", "()", "V");
|
||||
|
||||
// Run script and save resulting scope
|
||||
cfw.add(ByteCode.INVOKESTATIC,
|
||||
"org/mozilla/javascript/ScriptRuntime",
|
||||
"runScript",
|
||||
"(Lorg/mozilla/javascript/Script;)",
|
||||
"Lorg/mozilla/javascript/Scriptable;");
|
||||
cfw.add(ByteCode.ASTORE_1);
|
||||
|
||||
// Save the Scriptable in instance variable "self"
|
||||
cfw.add(ByteCode.ALOAD_0); // this
|
||||
cfw.add(ByteCode.ALOAD_1); // the Scriptable
|
||||
cfw.add(ByteCode.PUTFIELD, adapterName, "self",
|
||||
"Lorg/mozilla/javascript/Scriptable;");
|
||||
|
||||
// Set the prototype of the js object to be a LiveConnect
|
||||
// wrapper of the generated class's object
|
||||
cfw.add(ByteCode.ALOAD_1); // the Scriptable
|
||||
cfw.add(ByteCode.ALOAD_0); // this
|
||||
cfw.add(ByteCode.INVOKESTATIC,
|
||||
"org/mozilla/javascript/ScriptRuntime",
|
||||
"setAdapterProto",
|
||||
"(Lorg/mozilla/javascript/Scriptable;" +
|
||||
"Ljava/lang/Object;)",
|
||||
"V");
|
||||
|
||||
cfw.add(ByteCode.RETURN);
|
||||
cfw.stopMethod((short)20, null); // TODO: magic number "20"
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates code to create a java.lang.Boolean, java.lang.Character or a
|
||||
* java.lang.Double to wrap the specified primitive parameter. Leaves the
|
||||
* wrapper object on the top of the stack.
|
||||
*/
|
||||
private static int generateWrapParam(ClassFileWriter cfw, int paramOffset,
|
||||
Class paramType)
|
||||
{
|
||||
if (paramType.equals(Boolean.TYPE)) {
|
||||
// wrap boolean values with java.lang.Boolean.
|
||||
cfw.add(ByteCode.NEW, "java/lang/Boolean");
|
||||
cfw.add(ByteCode.DUP);
|
||||
cfw.add(ByteCode.ILOAD, paramOffset++);
|
||||
cfw.add(ByteCode.INVOKESPECIAL, "java/lang/Boolean",
|
||||
"<init>", "(Z)", "V");
|
||||
} else
|
||||
if (paramType.equals(Character.TYPE)) {
|
||||
// Create a string of length 1 using the character parameter.
|
||||
cfw.add(ByteCode.NEW, "java/lang/String");
|
||||
cfw.add(ByteCode.DUP);
|
||||
cfw.add(ByteCode.ICONST_1);
|
||||
cfw.add(ByteCode.NEWARRAY, ByteCode.T_CHAR);
|
||||
cfw.add(ByteCode.DUP);
|
||||
cfw.add(ByteCode.ICONST_0);
|
||||
cfw.add(ByteCode.ILOAD, paramOffset++);
|
||||
cfw.add(ByteCode.CASTORE);
|
||||
cfw.add(ByteCode.INVOKESPECIAL, "java/lang/String",
|
||||
"<init>", "([C)", "V");
|
||||
} else {
|
||||
// convert all numeric values to java.lang.Double.
|
||||
cfw.add(ByteCode.NEW, "java/lang/Double");
|
||||
cfw.add(ByteCode.DUP);
|
||||
String typeName = paramType.getName();
|
||||
switch (typeName.charAt(0)) {
|
||||
case 'b':
|
||||
case 's':
|
||||
case 'i':
|
||||
// load an int value, convert to double.
|
||||
cfw.add(ByteCode.ILOAD, paramOffset++);
|
||||
cfw.add(ByteCode.I2D);
|
||||
break;
|
||||
case 'l':
|
||||
// load a long, convert to double.
|
||||
cfw.add(ByteCode.LLOAD, paramOffset);
|
||||
cfw.add(ByteCode.L2D);
|
||||
paramOffset += 2;
|
||||
break;
|
||||
case 'f':
|
||||
// load a float, convert to double.
|
||||
cfw.add(ByteCode.FLOAD, paramOffset++);
|
||||
cfw.add(ByteCode.F2D);
|
||||
break;
|
||||
case 'd':
|
||||
cfw.add(ByteCode.DLOAD, paramOffset);
|
||||
paramOffset += 2;
|
||||
break;
|
||||
}
|
||||
cfw.add(ByteCode.INVOKESPECIAL, "java/lang/Double",
|
||||
"<init>", "(D)", "V");
|
||||
}
|
||||
return paramOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates code to convert a wrapped value type to a primitive type.
|
||||
* Handles unwrapping java.lang.Boolean, and java.lang.Number types.
|
||||
* May need to map between char and java.lang.String as well.
|
||||
* Generates the appropriate RETURN bytecode.
|
||||
*/
|
||||
private static void generateReturnResult(ClassFileWriter cfw,
|
||||
Class retType)
|
||||
{
|
||||
// wrap boolean values with java.lang.Boolean, convert all other
|
||||
// primitive values to java.lang.Double.
|
||||
if (retType.equals(Boolean.TYPE)) {
|
||||
cfw.add(ByteCode.INVOKESTATIC,
|
||||
"org/mozilla/javascript/Context",
|
||||
"toBoolean", "(Ljava/lang/Object;)",
|
||||
"Z");
|
||||
cfw.add(ByteCode.IRETURN);
|
||||
} else if (retType.equals(Character.TYPE)) {
|
||||
// characters are represented as strings in JavaScript.
|
||||
// return the first character.
|
||||
// first convert the value to a string if possible.
|
||||
cfw.add(ByteCode.INVOKESTATIC,
|
||||
"org/mozilla/javascript/Context",
|
||||
"toString", "(Ljava/lang/Object;)",
|
||||
"Ljava/lang/String;");
|
||||
cfw.add(ByteCode.ICONST_0);
|
||||
cfw.add(ByteCode.INVOKEVIRTUAL, "java/lang/String", "charAt",
|
||||
"(I)", "C");
|
||||
cfw.add(ByteCode.IRETURN);
|
||||
} else if (retType.isPrimitive()) {
|
||||
cfw.add(ByteCode.INVOKESTATIC,
|
||||
"org/mozilla/javascript/Context",
|
||||
"toNumber", "(Ljava/lang/Object;)",
|
||||
"D");
|
||||
String typeName = retType.getName();
|
||||
switch (typeName.charAt(0)) {
|
||||
case 'b':
|
||||
case 's':
|
||||
case 'i':
|
||||
cfw.add(ByteCode.D2I);
|
||||
cfw.add(ByteCode.IRETURN);
|
||||
break;
|
||||
case 'l':
|
||||
cfw.add(ByteCode.D2L);
|
||||
cfw.add(ByteCode.LRETURN);
|
||||
break;
|
||||
case 'f':
|
||||
cfw.add(ByteCode.D2F);
|
||||
cfw.add(ByteCode.FRETURN);
|
||||
break;
|
||||
case 'd':
|
||||
cfw.add(ByteCode.DRETURN);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unexpected return type " +
|
||||
retType.toString());
|
||||
}
|
||||
} else {
|
||||
String retTypeStr = retType.getName();
|
||||
cfw.addLoadConstant(retTypeStr);
|
||||
cfw.add(ByteCode.INVOKESTATIC,
|
||||
"org/mozilla/javascript/JavaAdapter",
|
||||
"convertResult",
|
||||
"(Ljava/lang/Object;" +
|
||||
"Ljava/lang/String;)",
|
||||
"Ljava/lang/Object;");
|
||||
// Now cast to return type
|
||||
cfw.add(ByteCode.CHECKCAST, retTypeStr.replace('.', '/'));
|
||||
cfw.add(ByteCode.ARETURN);
|
||||
}
|
||||
}
|
||||
|
||||
private static void generateMethod(ClassFileWriter cfw, String genName,
|
||||
String methodName, Class[] parms,
|
||||
Class returnType)
|
||||
{
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append('(');
|
||||
short arrayLocal = 1; // includes this.
|
||||
for (int i = 0; i < parms.length; i++) {
|
||||
Class type = parms[i];
|
||||
appendTypeString(sb, type);
|
||||
if (type.equals(Long.TYPE) || type.equals(Double.TYPE))
|
||||
arrayLocal += 2;
|
||||
else
|
||||
arrayLocal += 1;
|
||||
}
|
||||
sb.append(')');
|
||||
appendTypeString(sb, returnType);
|
||||
String methodSignature = sb.toString();
|
||||
// System.out.println("generating " + m.getName() + methodSignature);
|
||||
// System.out.flush();
|
||||
cfw.startMethod(methodName, methodSignature,
|
||||
ClassFileWriter.ACC_PUBLIC);
|
||||
cfw.add(ByteCode.BIPUSH, (byte) parms.length); // > 255 parms?
|
||||
cfw.add(ByteCode.ANEWARRAY, "java/lang/Object");
|
||||
cfw.add(ByteCode.ASTORE, arrayLocal);
|
||||
|
||||
// allocate a local variable to store the scope used to wrap native objects.
|
||||
short scopeLocal = (short) (arrayLocal + 1);
|
||||
boolean loadedScope = false;
|
||||
|
||||
int paramOffset = 1;
|
||||
for (int i = 0; i < parms.length; i++) {
|
||||
cfw.add(ByteCode.ALOAD, arrayLocal);
|
||||
cfw.add(ByteCode.BIPUSH, i);
|
||||
if (parms[i].isPrimitive()) {
|
||||
paramOffset = generateWrapParam(cfw, paramOffset, parms[i]);
|
||||
} else {
|
||||
// An arbitary Java object; call Context.toObject to wrap in
|
||||
// a Scriptable object
|
||||
cfw.add(ByteCode.ALOAD, paramOffset++);
|
||||
if (! loadedScope) {
|
||||
// load this.self into a local the first time it's needed.
|
||||
// it will provide the scope needed by Context.toObject().
|
||||
cfw.add(ByteCode.ALOAD_0);
|
||||
cfw.add(ByteCode.GETFIELD, genName, "self",
|
||||
"Lorg/mozilla/javascript/Scriptable;");
|
||||
cfw.add(ByteCode.ASTORE, scopeLocal);
|
||||
loadedScope = true;
|
||||
}
|
||||
cfw.add(ByteCode.ALOAD, scopeLocal);
|
||||
|
||||
// Get argument Class
|
||||
cfw.addLoadConstant(parms[i].getName());
|
||||
cfw.add(ByteCode.INVOKESTATIC,
|
||||
"org/mozilla/javascript/ScriptRuntime",
|
||||
"loadClassName",
|
||||
"(Ljava/lang/String;)",
|
||||
"Ljava/lang/Class;");
|
||||
|
||||
cfw.add(ByteCode.INVOKESTATIC,
|
||||
"org/mozilla/javascript/JavaAdapter",
|
||||
"toObject",
|
||||
"(Ljava/lang/Object;" +
|
||||
"Lorg/mozilla/javascript/Scriptable;" +
|
||||
"Ljava/lang/Class;)",
|
||||
"Lorg/mozilla/javascript/Scriptable;");
|
||||
}
|
||||
cfw.add(ByteCode.AASTORE);
|
||||
}
|
||||
|
||||
cfw.add(ByteCode.ALOAD_0); // this
|
||||
cfw.add(ByteCode.GETFIELD, genName, "self",
|
||||
"Lorg/mozilla/javascript/Scriptable;");
|
||||
|
||||
cfw.addLoadConstant(methodName);
|
||||
cfw.add(ByteCode.ALOAD, arrayLocal);
|
||||
|
||||
// go through utility method, which creates a Context to run the
|
||||
// method in.
|
||||
cfw.add(ByteCode.INVOKESTATIC,
|
||||
"org/mozilla/javascript/JavaAdapter",
|
||||
"callMethod",
|
||||
"(Lorg/mozilla/javascript/Scriptable;" +
|
||||
"Ljava/lang/String;[Ljava/lang/Object;)",
|
||||
"Ljava/lang/Object;");
|
||||
|
||||
Class retType = returnType;
|
||||
if (retType.equals(Void.TYPE)) {
|
||||
cfw.add(ByteCode.POP);
|
||||
cfw.add(ByteCode.RETURN);
|
||||
} else {
|
||||
generateReturnResult(cfw, retType);
|
||||
}
|
||||
cfw.stopMethod((short)(scopeLocal + 1), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates code to push typed parameters onto the operand stack
|
||||
* prior to a direct Java method call.
|
||||
*/
|
||||
private static int generatePushParam(ClassFileWriter cfw, int paramOffset,
|
||||
Class paramType)
|
||||
{
|
||||
String typeName = paramType.getName();
|
||||
switch (typeName.charAt(0)) {
|
||||
case 'z':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 's':
|
||||
case 'i':
|
||||
// load an int value, convert to double.
|
||||
cfw.add(ByteCode.ILOAD, paramOffset++);
|
||||
break;
|
||||
case 'l':
|
||||
// load a long, convert to double.
|
||||
cfw.add(ByteCode.LLOAD, paramOffset);
|
||||
paramOffset += 2;
|
||||
break;
|
||||
case 'f':
|
||||
// load a float, convert to double.
|
||||
cfw.add(ByteCode.FLOAD, paramOffset++);
|
||||
break;
|
||||
case 'd':
|
||||
cfw.add(ByteCode.DLOAD, paramOffset);
|
||||
paramOffset += 2;
|
||||
break;
|
||||
}
|
||||
return paramOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates code to return a Java type, after calling a Java method
|
||||
* that returns the same type.
|
||||
* Generates the appropriate RETURN bytecode.
|
||||
*/
|
||||
private static void generatePopResult(ClassFileWriter cfw,
|
||||
Class retType)
|
||||
{
|
||||
if (retType.isPrimitive()) {
|
||||
String typeName = retType.getName();
|
||||
switch (typeName.charAt(0)) {
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 's':
|
||||
case 'i':
|
||||
case 'z':
|
||||
cfw.add(ByteCode.IRETURN);
|
||||
break;
|
||||
case 'l':
|
||||
cfw.add(ByteCode.LRETURN);
|
||||
break;
|
||||
case 'f':
|
||||
cfw.add(ByteCode.FRETURN);
|
||||
break;
|
||||
case 'd':
|
||||
cfw.add(ByteCode.DRETURN);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
cfw.add(ByteCode.ARETURN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a method called "super$methodName()" which can be called
|
||||
* from JavaScript that is equivalent to calling "super.methodName()"
|
||||
* from Java. Eventually, this may be supported directly in JavaScript.
|
||||
*/
|
||||
private static void generateSuper(ClassFileWriter cfw,
|
||||
String genName, String superName,
|
||||
String methodName, String methodSignature,
|
||||
Class[] parms, Class returnType)
|
||||
{
|
||||
cfw.startMethod("super$" + methodName, methodSignature,
|
||||
ClassFileWriter.ACC_PUBLIC);
|
||||
|
||||
// push "this"
|
||||
cfw.add(ByteCode.ALOAD, 0);
|
||||
|
||||
// push the rest of the parameters.
|
||||
int paramOffset = 1;
|
||||
for (int i = 0; i < parms.length; i++) {
|
||||
if (parms[i].isPrimitive()) {
|
||||
paramOffset = generatePushParam(cfw, paramOffset, parms[i]);
|
||||
} else {
|
||||
cfw.add(ByteCode.ALOAD, paramOffset++);
|
||||
}
|
||||
}
|
||||
|
||||
// split the method signature at the right parentheses.
|
||||
int rightParen = methodSignature.indexOf(')');
|
||||
|
||||
// call the superclass implementation of the method.
|
||||
cfw.add(ByteCode.INVOKESPECIAL,
|
||||
superName,
|
||||
methodName,
|
||||
methodSignature.substring(0, rightParen + 1),
|
||||
methodSignature.substring(rightParen + 1));
|
||||
|
||||
// now, handle the return type appropriately.
|
||||
Class retType = returnType;
|
||||
if (!retType.equals(Void.TYPE)) {
|
||||
generatePopResult(cfw, retType);
|
||||
} else {
|
||||
cfw.add(ByteCode.RETURN);
|
||||
}
|
||||
cfw.stopMethod((short)(paramOffset + 1), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fully qualified method name concatenated with its signature.
|
||||
*/
|
||||
private static String getMethodSignature(Method method) {
|
||||
Class[] parms = method.getParameterTypes();
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append('(');
|
||||
for (int i = 0; i < parms.length; i++) {
|
||||
Class type = parms[i];
|
||||
appendTypeString(sb, type);
|
||||
}
|
||||
sb.append(')');
|
||||
appendTypeString(sb, method.getReturnType());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static StringBuffer appendTypeString(StringBuffer sb, Class type)
|
||||
{
|
||||
while (type.isArray()) {
|
||||
sb.append('[');
|
||||
type = type.getComponentType();
|
||||
}
|
||||
if (type.isPrimitive()) {
|
||||
if (type.equals(Boolean.TYPE)) {
|
||||
sb.append('Z');
|
||||
} else
|
||||
if (type.equals(Long.TYPE)) {
|
||||
sb.append('J');
|
||||
} else {
|
||||
String typeName = type.getName();
|
||||
sb.append(Character.toUpperCase(typeName.charAt(0)));
|
||||
}
|
||||
} else {
|
||||
sb.append('L');
|
||||
sb.append(type.getName().replace('.', '/'));
|
||||
sb.append(';');
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
static final class MyClassLoader extends ClassLoader {
|
||||
public Class defineClass(String name, byte data[]) {
|
||||
return super.defineClass(name, data, 0, data.length);
|
||||
}
|
||||
|
||||
protected Class loadClass(String name, boolean resolve)
|
||||
throws ClassNotFoundException
|
||||
{
|
||||
Class clazz = findLoadedClass(name);
|
||||
if (clazz == null) {
|
||||
ClassLoader loader = getClass().getClassLoader();
|
||||
try {
|
||||
if (loader != null)
|
||||
return loader.loadClass(name);
|
||||
clazz = findSystemClass(name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
return ScriptRuntime.loadClassName(name);
|
||||
}
|
||||
}
|
||||
if (resolve)
|
||||
resolveClass(clazz);
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a key with which to distinguish previously generated
|
||||
* adapter classes stored in a hash table.
|
||||
*/
|
||||
static class ClassSignature {
|
||||
Class mSuperClass;
|
||||
Class[] mInterfaces;
|
||||
Object[] mProperties;
|
||||
|
||||
ClassSignature(Class superClass, Class[] interfaces, Scriptable jsObj) {
|
||||
mSuperClass = superClass;
|
||||
mInterfaces = interfaces;
|
||||
mProperties = jsObj.getIds();
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ClassSignature) {
|
||||
ClassSignature sig = (ClassSignature) obj;
|
||||
if (mSuperClass == sig.mSuperClass) {
|
||||
Class[] interfaces = sig.mInterfaces;
|
||||
if (mInterfaces != interfaces) {
|
||||
if (mInterfaces == null || interfaces == null)
|
||||
return false;
|
||||
if (mInterfaces.length != interfaces.length)
|
||||
return false;
|
||||
for (int i = 0; i < interfaces.length; i++)
|
||||
if (mInterfaces[i] != interfaces[i])
|
||||
return false;
|
||||
}
|
||||
Object[] properties = sig.mProperties;
|
||||
if (mProperties.length != properties.length)
|
||||
return false;
|
||||
for (int i = 0; i < properties.length; i++)
|
||||
if (!mProperties[i].equals(properties[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return mSuperClass.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
private static int serial;
|
||||
private static MyClassLoader classLoader;
|
||||
private static Hashtable generatedClasses = new Hashtable(7);
|
||||
}
|
||||
595
mozilla/js/rhino/org/mozilla/javascript/JavaMembers.java
Normal file
595
mozilla/js/rhino/org/mozilla/javascript/JavaMembers.java
Normal file
@@ -0,0 +1,595 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
* Frank Mitchell
|
||||
* Mike Shaver
|
||||
* Kurt Westerfeld
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Mike Shaver
|
||||
* @author Norris Boyd
|
||||
* @see NativeJavaObject
|
||||
* @see NativeJavaClass
|
||||
*/
|
||||
class JavaMembers {
|
||||
|
||||
JavaMembers(Scriptable scope, Class cl) {
|
||||
this.members = new Hashtable(23);
|
||||
this.staticMembers = new Hashtable(7);
|
||||
this.cl = cl;
|
||||
reflect(scope, cl);
|
||||
}
|
||||
|
||||
boolean has(String name, boolean isStatic) {
|
||||
Hashtable ht = isStatic ? staticMembers : members;
|
||||
Object obj = ht.get(name);
|
||||
if (obj != null) {
|
||||
return true;
|
||||
} else {
|
||||
Member member = this.findExplicitFunction(name, isStatic);
|
||||
return member != null;
|
||||
}
|
||||
}
|
||||
|
||||
Object get(Scriptable scope, String name, Object javaObject,
|
||||
boolean isStatic)
|
||||
{
|
||||
Hashtable ht = isStatic ? staticMembers : members;
|
||||
Object member = ht.get(name);
|
||||
if (!isStatic && member == null) {
|
||||
// Try to get static member from instance (LC3)
|
||||
member = staticMembers.get(name);
|
||||
}
|
||||
if (member == null) {
|
||||
member = this.getExplicitFunction(scope, name,
|
||||
javaObject, isStatic);
|
||||
if (member == null)
|
||||
return Scriptable.NOT_FOUND;
|
||||
}
|
||||
if (member instanceof Scriptable)
|
||||
return member; // why is this here?
|
||||
Object rval;
|
||||
Class type;
|
||||
try {
|
||||
if (member instanceof BeanProperty) {
|
||||
BeanProperty bp = (BeanProperty) member;
|
||||
rval = bp.getter.invoke(javaObject, ScriptRuntime.emptyArgs);
|
||||
type = bp.getter.getReturnType();
|
||||
} else {
|
||||
Field field = (Field) member;
|
||||
rval = field.get(isStatic ? null : javaObject);
|
||||
type = field.getType();
|
||||
}
|
||||
} catch (IllegalAccessException accEx) {
|
||||
throw new RuntimeException("unexpected IllegalAccessException "+
|
||||
"accessing Java field");
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new WrappedException(e.getTargetException());
|
||||
}
|
||||
// Need to wrap the object before we return it.
|
||||
scope = ScriptableObject.getTopLevelScope(scope);
|
||||
return NativeJavaObject.wrap(scope, rval, type);
|
||||
}
|
||||
|
||||
Member findExplicitFunction(String name, boolean isStatic) {
|
||||
Hashtable ht = isStatic ? staticMembers : members;
|
||||
int sigStart = name.indexOf('(');
|
||||
Member[] methodsOrCtors = null;
|
||||
NativeJavaMethod method = null;
|
||||
boolean isCtor = (isStatic && sigStart == 0);
|
||||
|
||||
if (isCtor) {
|
||||
// Explicit request for an overloaded constructor
|
||||
methodsOrCtors = ctors;
|
||||
}
|
||||
else if (sigStart > 0) {
|
||||
// Explicit request for an overloaded method
|
||||
String trueName = name.substring(0,sigStart);
|
||||
Object obj = ht.get(trueName);
|
||||
if (!isStatic && obj == null) {
|
||||
// Try to get static member from instance (LC3)
|
||||
obj = staticMembers.get(trueName);
|
||||
}
|
||||
if (obj != null && obj instanceof NativeJavaMethod) {
|
||||
method = (NativeJavaMethod)obj;
|
||||
methodsOrCtors = method.getMethods();
|
||||
}
|
||||
}
|
||||
|
||||
if (methodsOrCtors != null) {
|
||||
for (int i = 0; i < methodsOrCtors.length; i++) {
|
||||
String nameWithSig =
|
||||
NativeJavaMethod.signature(methodsOrCtors[i]);
|
||||
if (name.equals(nameWithSig)) {
|
||||
return methodsOrCtors[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Object getExplicitFunction(Scriptable scope, String name,
|
||||
Object javaObject, boolean isStatic)
|
||||
{
|
||||
Hashtable ht = isStatic ? staticMembers : members;
|
||||
Object member = null;
|
||||
Member methodOrCtor = this.findExplicitFunction(name, isStatic);
|
||||
|
||||
if (methodOrCtor != null) {
|
||||
Scriptable prototype =
|
||||
ScriptableObject.getFunctionPrototype(scope);
|
||||
|
||||
if (methodOrCtor instanceof Constructor) {
|
||||
NativeJavaConstructor fun =
|
||||
new NativeJavaConstructor((Constructor)methodOrCtor);
|
||||
fun.setPrototype(prototype);
|
||||
member = fun;
|
||||
ht.put(name, fun);
|
||||
} else {
|
||||
String trueName = methodOrCtor.getName();
|
||||
member = ht.get(trueName);
|
||||
|
||||
if (member instanceof NativeJavaMethod &&
|
||||
((NativeJavaMethod)member).getMethods().length > 1 ) {
|
||||
NativeJavaMethod fun =
|
||||
new NativeJavaMethod((Method)methodOrCtor, name);
|
||||
fun.setPrototype(prototype);
|
||||
ht.put(name, fun);
|
||||
member = fun;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return member;
|
||||
}
|
||||
|
||||
|
||||
public void put(String name, Object javaObject, Object value,
|
||||
boolean isStatic)
|
||||
{
|
||||
Hashtable ht = isStatic ? staticMembers : members;
|
||||
Object member = ht.get(name);
|
||||
if (!isStatic && member == null) {
|
||||
// Try to get static member from instance (LC3)
|
||||
member = staticMembers.get(name);
|
||||
}
|
||||
if (member == null)
|
||||
throw reportMemberNotFound(name);
|
||||
if (member instanceof FieldAndMethods) {
|
||||
FieldAndMethods fam = (FieldAndMethods) ht.get(name);
|
||||
member = fam.getField();
|
||||
}
|
||||
|
||||
// Is this a bean property "set"?
|
||||
if (member instanceof BeanProperty) {
|
||||
try {
|
||||
Method method = ((BeanProperty) member).setter;
|
||||
if (method == null)
|
||||
throw reportMemberNotFound(name);
|
||||
Class[] types = method.getParameterTypes();
|
||||
Object[] params = { NativeJavaObject.coerceType(types[0], value) };
|
||||
method.invoke(javaObject, params);
|
||||
} catch (IllegalAccessException accessEx) {
|
||||
throw new RuntimeException("unexpected IllegalAccessException " +
|
||||
"accessing Java field");
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new WrappedException(e.getTargetException());
|
||||
}
|
||||
}
|
||||
else {
|
||||
Field field = null;
|
||||
try {
|
||||
field = (Field) member;
|
||||
if (field == null) {
|
||||
Object[] args = {name};
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.java.internal.private", args));
|
||||
}
|
||||
field.set(javaObject, NativeJavaObject.coerceType(field.getType(),
|
||||
value));
|
||||
} catch (ClassCastException e) {
|
||||
Object errArgs[] = { name };
|
||||
throw Context.reportRuntimeError(Context.getMessage
|
||||
("msg.java.method.assign",
|
||||
errArgs));
|
||||
} catch (IllegalAccessException accessEx) {
|
||||
throw new RuntimeException("unexpected IllegalAccessException "+
|
||||
"accessing Java field");
|
||||
} catch (IllegalArgumentException argEx) {
|
||||
Object errArgs[] = { value.getClass().getName(), field,
|
||||
javaObject.getClass().getName() };
|
||||
throw Context.reportRuntimeError(Context.getMessage(
|
||||
"msg.java.internal.field.type", errArgs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object[] getIds(boolean isStatic) {
|
||||
Hashtable ht = isStatic ? staticMembers : members;
|
||||
int len = ht.size();
|
||||
Object[] result = new Object[len];
|
||||
Enumeration keys = ht.keys();
|
||||
for (int i=0; i < len; i++)
|
||||
result[i] = keys.nextElement();
|
||||
return result;
|
||||
}
|
||||
|
||||
Class getReflectedClass() {
|
||||
return cl;
|
||||
}
|
||||
|
||||
void reflectField(Scriptable scope, Field field) {
|
||||
int mods = field.getModifiers();
|
||||
if (!Modifier.isPublic(mods))
|
||||
return;
|
||||
boolean isStatic = Modifier.isStatic(mods);
|
||||
Hashtable ht = isStatic ? staticMembers : members;
|
||||
String name = field.getName();
|
||||
Object member = ht.get(name);
|
||||
if (member != null) {
|
||||
if (member instanceof NativeJavaMethod) {
|
||||
NativeJavaMethod method = (NativeJavaMethod) member;
|
||||
FieldAndMethods fam = new FieldAndMethods(method.getMethods(),
|
||||
field,
|
||||
null);
|
||||
fam.setPrototype(ScriptableObject.getFunctionPrototype(scope));
|
||||
getFieldAndMethodsTable(isStatic).put(name, fam);
|
||||
ht.put(name, fam);
|
||||
return;
|
||||
}
|
||||
if (member instanceof Field) {
|
||||
Field oldField = (Field) member;
|
||||
// If this newly reflected field shadows an inherited field,
|
||||
// then replace it. Otherwise, since access to the field
|
||||
// would be ambiguous from Java, no field should be reflected.
|
||||
// For now, the first field found wins, unless another field
|
||||
// explicitly shadows it.
|
||||
if (oldField.getDeclaringClass().isAssignableFrom(field.getDeclaringClass()))
|
||||
ht.put(name, field);
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException("unknown member type");
|
||||
}
|
||||
ht.put(name, field);
|
||||
}
|
||||
|
||||
void reflectMethod(Scriptable scope, Method method) {
|
||||
int mods = method.getModifiers();
|
||||
if (!Modifier.isPublic(mods))
|
||||
return;
|
||||
boolean isStatic = Modifier.isStatic(mods);
|
||||
Hashtable ht = isStatic ? staticMembers : members;
|
||||
String name = method.getName();
|
||||
NativeJavaMethod fun = (NativeJavaMethod) ht.get(name);
|
||||
if (fun == null) {
|
||||
fun = new NativeJavaMethod();
|
||||
if (scope != null)
|
||||
fun.setPrototype(ScriptableObject.getFunctionPrototype(scope));
|
||||
ht.put(name, fun);
|
||||
fun.add(method);
|
||||
} else {
|
||||
fun.add(method);
|
||||
}
|
||||
}
|
||||
|
||||
void reflect(Scriptable scope, Class cl) {
|
||||
// We reflect methods first, because we want overloaded field/method
|
||||
// names to be allocated to the NativeJavaMethod before the field
|
||||
// gets in the way.
|
||||
Method[] methods = cl.getMethods();
|
||||
for (int i = 0; i < methods.length; i++)
|
||||
reflectMethod(scope, methods[i]);
|
||||
|
||||
Field[] fields = cl.getFields();
|
||||
for (int i = 0; i < fields.length; i++)
|
||||
reflectField(scope, fields[i]);
|
||||
|
||||
makeBeanProperties(scope, false);
|
||||
makeBeanProperties(scope, true);
|
||||
|
||||
ctors = cl.getConstructors();
|
||||
}
|
||||
|
||||
Hashtable getFieldAndMethodsTable(boolean isStatic) {
|
||||
Hashtable fmht = isStatic ? staticFieldAndMethods
|
||||
: fieldAndMethods;
|
||||
if (fmht == null) {
|
||||
fmht = new Hashtable(11);
|
||||
if (isStatic)
|
||||
staticFieldAndMethods = fmht;
|
||||
else
|
||||
fieldAndMethods = fmht;
|
||||
}
|
||||
|
||||
return fmht;
|
||||
}
|
||||
|
||||
void makeBeanProperties(Scriptable scope, boolean isStatic) {
|
||||
Hashtable ht = isStatic ? staticMembers : members;
|
||||
Hashtable toAdd = new Hashtable();
|
||||
|
||||
// Now, For each member, make "bean" properties.
|
||||
for (Enumeration e = ht.keys(); e.hasMoreElements(); ) {
|
||||
|
||||
// Is this a getter?
|
||||
String name = (String) e.nextElement();
|
||||
boolean memberIsGetMethod = name.startsWith("get");
|
||||
boolean memberIsIsMethod = name.startsWith("is");
|
||||
if (memberIsGetMethod || memberIsIsMethod) {
|
||||
// Double check name component.
|
||||
String nameComponent = name.substring(memberIsGetMethod ? 3 : 2);
|
||||
if (nameComponent.length() == 0)
|
||||
continue;
|
||||
|
||||
// Make the bean property name.
|
||||
String beanPropertyName = nameComponent;
|
||||
if (nameComponent.length() > 1 &&
|
||||
Character.isUpperCase(nameComponent.charAt(0)) &&
|
||||
!Character.isUpperCase(nameComponent.charAt(1)))
|
||||
{
|
||||
beanPropertyName = Character.toLowerCase(nameComponent.charAt(0)) +
|
||||
nameComponent.substring(1);
|
||||
}
|
||||
|
||||
// If we already have a member by this name, don't do this
|
||||
// property.
|
||||
if (ht.containsKey(beanPropertyName))
|
||||
continue;
|
||||
|
||||
// Get the method by this name.
|
||||
Object method = ht.get(name);
|
||||
if (!(method instanceof NativeJavaMethod))
|
||||
continue;
|
||||
NativeJavaMethod getJavaMethod = (NativeJavaMethod) method;
|
||||
|
||||
// Grab and inspect the getter method; does it have an empty parameter list,
|
||||
// with a return value (eg. a getSomething() or isSomething())?
|
||||
Class[] params;
|
||||
Method[] getMethods = getJavaMethod.getMethods();
|
||||
Class type;
|
||||
if (getMethods != null &&
|
||||
getMethods.length == 1 &&
|
||||
(type = getMethods[0].getReturnType()) != null &&
|
||||
(params = getMethods[0].getParameterTypes()) != null &&
|
||||
params.length == 0)
|
||||
{
|
||||
|
||||
// Make sure the method static-ness is preserved for this property.
|
||||
if (isStatic && !Modifier.isStatic(getMethods[0].getModifiers()))
|
||||
continue;
|
||||
|
||||
// We have a getter. Now, do we have a setter?
|
||||
Method setMethod = null;
|
||||
String setter = "set" + nameComponent;
|
||||
if (ht.containsKey(setter)) {
|
||||
|
||||
// Is this value a method?
|
||||
method = ht.get(setter);
|
||||
if (method instanceof NativeJavaMethod) {
|
||||
|
||||
//
|
||||
// Note: it may be preferable to allow NativeJavaMethod.findFunction()
|
||||
// to find the appropriate setter; unfortunately, it requires an
|
||||
// instance of the target arg to determine that.
|
||||
//
|
||||
|
||||
// Make two passes: one to find a method with direct type assignment,
|
||||
// and one to find a widening conversion.
|
||||
NativeJavaMethod setJavaMethod = (NativeJavaMethod) method;
|
||||
Method[] setMethods = setJavaMethod.getMethods();
|
||||
for (int pass = 1; pass <= 2 && setMethod == null; ++pass) {
|
||||
for (int i = 0; i < setMethods.length; ++i) {
|
||||
if (setMethods[i].getReturnType() == void.class &&
|
||||
(!isStatic || Modifier.isStatic(setMethods[i].getModifiers())) &&
|
||||
(params = setMethods[i].getParameterTypes()) != null &&
|
||||
params.length == 1 ) {
|
||||
|
||||
if ((pass == 1 && params[0] == type) ||
|
||||
(pass == 2 && params[0].isAssignableFrom(type))) {
|
||||
setMethod = setMethods[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make the property.
|
||||
BeanProperty bp = new BeanProperty(getMethods[0], setMethod);
|
||||
toAdd.put(beanPropertyName, bp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the new bean properties.
|
||||
for (Enumeration e = toAdd.keys(); e.hasMoreElements();) {
|
||||
String key = (String) e.nextElement();
|
||||
Object value = toAdd.get(key);
|
||||
ht.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
Hashtable getFieldAndMethodsObjects(Scriptable scope, Object javaObject,
|
||||
boolean isStatic)
|
||||
{
|
||||
Hashtable ht = isStatic ? staticFieldAndMethods : fieldAndMethods;
|
||||
if (ht == null)
|
||||
return null;
|
||||
int len = ht.size();
|
||||
Hashtable result = new Hashtable(Math.max(len,1));
|
||||
Enumeration e = ht.elements();
|
||||
while (len-- > 0) {
|
||||
FieldAndMethods fam = (FieldAndMethods) e.nextElement();
|
||||
fam = (FieldAndMethods) fam.clone();
|
||||
fam.setJavaObject(javaObject);
|
||||
result.put(fam.getName(), fam);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Constructor[] getConstructors() {
|
||||
return ctors;
|
||||
}
|
||||
|
||||
static JavaMembers lookupClass(Scriptable scope, Class dynamicType,
|
||||
Class staticType)
|
||||
{
|
||||
Class cl = dynamicType;
|
||||
Hashtable ct = classTable; // use local reference to avoid synchronize
|
||||
JavaMembers members = (JavaMembers) ct.get(cl);
|
||||
if (members != null)
|
||||
return members;
|
||||
if (staticType != null && staticType != dynamicType &&
|
||||
!Modifier.isPublic(dynamicType.getModifiers()) &&
|
||||
Modifier.isPublic(staticType.getModifiers()))
|
||||
{
|
||||
cl = staticType;
|
||||
|
||||
// We can use the static type, and that is OK, but we'll trace
|
||||
// back the java class chain here to look for something more suitable.
|
||||
for (Class parentType = dynamicType;
|
||||
parentType != null && parentType != ScriptRuntime.ObjectClass;
|
||||
parentType = parentType.getSuperclass())
|
||||
{
|
||||
if (Modifier.isPublic(parentType.getModifiers())) {
|
||||
cl = parentType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
members = new JavaMembers(scope, cl);
|
||||
} catch (SecurityException e) {
|
||||
// Reflection may fail for objects that are in a restricted
|
||||
// access package (e.g. sun.*). If we get a security
|
||||
// exception, try again with the static type. Otherwise,
|
||||
// rethrow the exception.
|
||||
if (cl != staticType)
|
||||
members = new JavaMembers(scope, staticType);
|
||||
else
|
||||
throw e;
|
||||
}
|
||||
if (Context.isCachingEnabled)
|
||||
ct.put(cl, members);
|
||||
return members;
|
||||
}
|
||||
|
||||
RuntimeException reportMemberNotFound(String memberName) {
|
||||
Object errArgs[] = { cl.getName(),
|
||||
memberName };
|
||||
return Context.reportRuntimeError(
|
||||
Context.getMessage("msg.java.member.not.found",
|
||||
errArgs));
|
||||
}
|
||||
|
||||
static Hashtable classTable = new Hashtable();
|
||||
|
||||
private Class cl;
|
||||
private Hashtable members;
|
||||
private Hashtable fieldAndMethods;
|
||||
private Hashtable staticMembers;
|
||||
private Hashtable staticFieldAndMethods;
|
||||
private Constructor[] ctors;
|
||||
}
|
||||
|
||||
class BeanProperty {
|
||||
BeanProperty(Method getter, Method setter) {
|
||||
this.getter = getter;
|
||||
this.setter = setter;
|
||||
}
|
||||
Method getter;
|
||||
Method setter;
|
||||
}
|
||||
|
||||
class FieldAndMethods extends NativeJavaMethod {
|
||||
|
||||
FieldAndMethods(Method[] methods, Field field, String name) {
|
||||
super(methods);
|
||||
this.field = field;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
void setJavaObject(Object javaObject) {
|
||||
this.javaObject = javaObject;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
if (field == null)
|
||||
return name;
|
||||
return field.getName();
|
||||
}
|
||||
|
||||
Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public Object getDefaultValue(Class hint) {
|
||||
if (hint == ScriptRuntime.FunctionClass)
|
||||
return this;
|
||||
Object rval;
|
||||
Class type;
|
||||
try {
|
||||
rval = field.get(javaObject);
|
||||
type = field.getType();
|
||||
} catch (IllegalAccessException accEx) {
|
||||
Object[] args = {getName()};
|
||||
throw Context.reportRuntimeError(Context.getMessage
|
||||
("msg.java.internal.private", args));
|
||||
}
|
||||
rval = NativeJavaObject.wrap(this, rval, type);
|
||||
if (rval instanceof Scriptable) {
|
||||
rval = ((Scriptable) rval).getDefaultValue(hint);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
FieldAndMethods result = new FieldAndMethods(methods, field, name);
|
||||
result.javaObject = javaObject;
|
||||
return result;
|
||||
}
|
||||
|
||||
private Field field;
|
||||
private Object javaObject;
|
||||
private String name;
|
||||
}
|
||||
109
mozilla/js/rhino/org/mozilla/javascript/JavaScriptException.java
Normal file
109
mozilla/js/rhino/org/mozilla/javascript/JavaScriptException.java
Normal file
@@ -0,0 +1,109 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
// API class
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
/**
|
||||
* Java reflection of JavaScript exceptions. (Possibly wrapping a Java exception.)
|
||||
*
|
||||
* @author Mike McCabe
|
||||
*/
|
||||
public class JavaScriptException extends Exception {
|
||||
|
||||
/**
|
||||
* Create a JavaScript exception wrapping the given JavaScript value.
|
||||
*
|
||||
* Instances of this class are thrown by the JavaScript 'throw' keyword.
|
||||
*
|
||||
* @param value the JavaScript value thrown.
|
||||
*/
|
||||
public JavaScriptException(Object value) {
|
||||
super(ScriptRuntime.toString(value));
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the exception message.
|
||||
*
|
||||
* <p>Will just convert the wrapped exception to a string.
|
||||
*/
|
||||
public String getMessage() {
|
||||
return ScriptRuntime.toString(value);
|
||||
}
|
||||
|
||||
static JavaScriptException wrapException(Scriptable scope,
|
||||
Throwable exn)
|
||||
{
|
||||
if (exn instanceof InvocationTargetException)
|
||||
exn = ((InvocationTargetException)exn).getTargetException();
|
||||
if (exn instanceof JavaScriptException)
|
||||
return (JavaScriptException)exn;
|
||||
Object wrapper = NativeJavaObject.wrap(scope, exn, Throwable.class);
|
||||
return new JavaScriptException(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the exception value originally thrown. This may be a
|
||||
* JavaScript value (null, undefined, Boolean, Number, String,
|
||||
* Scriptable or Function) or a Java exception value thrown from a
|
||||
* host object or from Java called through LiveConnect.
|
||||
*
|
||||
* @return the value wrapped by this exception
|
||||
*/
|
||||
public Object getValue() {
|
||||
if (value != null && value instanceof Wrapper)
|
||||
// this will also catch NativeStrings...
|
||||
return ((Wrapper)value).unwrap();
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The JavaScript exception value. This value is not
|
||||
* intended for general use; if the JavaScriptException wraps a
|
||||
* Java exception, getScriptableValue may return a Scriptable
|
||||
* wrapping the original Java exception object.
|
||||
*
|
||||
* We would prefer to go through a getter to encapsulate the value,
|
||||
* however that causes the bizarre error "nanosecond timeout value
|
||||
* out of range" on the MS JVM.
|
||||
* @serial
|
||||
*/
|
||||
Object value;
|
||||
}
|
||||
104
mozilla/js/rhino/org/mozilla/javascript/Label.java
Normal file
104
mozilla/js/rhino/org/mozilla/javascript/Label.java
Normal file
@@ -0,0 +1,104 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Roger Lawrence
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
public class Label {
|
||||
|
||||
private static final int FIXUPTABLE_SIZE = 8;
|
||||
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
public Label()
|
||||
{
|
||||
itsPC = -1;
|
||||
}
|
||||
|
||||
public short getPC()
|
||||
{
|
||||
return itsPC;
|
||||
}
|
||||
|
||||
public void fixGotos(byte theCodeBuffer[])
|
||||
{
|
||||
if (DEBUG) {
|
||||
if ((itsPC == -1) && (itsFixupTable != null))
|
||||
throw new RuntimeException("Unlocated label");
|
||||
}
|
||||
if (itsFixupTable != null) {
|
||||
for (int i = 0; i < itsFixupTableTop; i++) {
|
||||
int fixupSite = itsFixupTable[i];
|
||||
// -1 to get delta from instruction start
|
||||
short offset = (short)(itsPC - (fixupSite - 1));
|
||||
theCodeBuffer[fixupSite++] = (byte)(offset >> 8);
|
||||
theCodeBuffer[fixupSite] = (byte)offset;
|
||||
}
|
||||
}
|
||||
itsFixupTable = null;
|
||||
}
|
||||
|
||||
public void setPC(short thePC)
|
||||
{
|
||||
if (DEBUG) {
|
||||
if ((itsPC != -1) && (itsPC != thePC))
|
||||
throw new RuntimeException("Duplicate label");
|
||||
}
|
||||
itsPC = thePC;
|
||||
}
|
||||
|
||||
public void addFixup(int fixupSite)
|
||||
{
|
||||
if (itsFixupTable == null) {
|
||||
itsFixupTableTop = 1;
|
||||
itsFixupTable = new int[FIXUPTABLE_SIZE];
|
||||
itsFixupTable[0] = fixupSite;
|
||||
}
|
||||
else {
|
||||
if (itsFixupTableTop == itsFixupTable.length) {
|
||||
int oldLength = itsFixupTable.length;
|
||||
int newTable[] = new int[oldLength + FIXUPTABLE_SIZE];
|
||||
System.arraycopy(itsFixupTable, 0, newTable, 0, oldLength);
|
||||
itsFixupTable = newTable;
|
||||
}
|
||||
itsFixupTable[itsFixupTableTop++] = fixupSite;
|
||||
}
|
||||
}
|
||||
|
||||
private short itsPC;
|
||||
private int itsFixupTable[];
|
||||
private int itsFixupTableTop;
|
||||
|
||||
}
|
||||
|
||||
80
mozilla/js/rhino/org/mozilla/javascript/LabelTable.java
Normal file
80
mozilla/js/rhino/org/mozilla/javascript/LabelTable.java
Normal file
@@ -0,0 +1,80 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Roger Lawrence
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
public class LabelTable {
|
||||
|
||||
private static final boolean DEBUGLABELS = false;
|
||||
|
||||
private static final int LabelTableSize = 32;
|
||||
protected Label itsLabelTable[];
|
||||
protected int itsLabelTableTop;
|
||||
|
||||
public int acquireLabel()
|
||||
{
|
||||
if (itsLabelTable == null) {
|
||||
itsLabelTable = new Label[LabelTableSize];
|
||||
itsLabelTable[0] = new Label();
|
||||
itsLabelTableTop = 1;
|
||||
return 0x80000000;
|
||||
}
|
||||
else {
|
||||
if (itsLabelTableTop == itsLabelTable.length) {
|
||||
Label oldTable[] = itsLabelTable;
|
||||
itsLabelTable = new Label[itsLabelTableTop * 2];
|
||||
System.arraycopy(oldTable, 0, itsLabelTable, 0, itsLabelTableTop);
|
||||
}
|
||||
itsLabelTable[itsLabelTableTop] = new Label();
|
||||
int result = itsLabelTableTop++;
|
||||
return result | 0x80000000;
|
||||
}
|
||||
}
|
||||
|
||||
public int markLabel(int theLabel, int pc)
|
||||
{
|
||||
if (DEBUGLABELS) {
|
||||
if ((theLabel & 0x80000000) != 0x80000000)
|
||||
throw new RuntimeException("Bad label, no biscuit");
|
||||
}
|
||||
theLabel &= 0x7FFFFFFF;
|
||||
if (DEBUGLABELS) {
|
||||
System.out.println("Marking label " + theLabel + " at " + pc);
|
||||
}
|
||||
itsLabelTable[theLabel].setPC((short)pc);
|
||||
return theLabel | 0x80000000;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
|
||||
/**
|
||||
* Avoid loading classes unless they are used.
|
||||
*
|
||||
* <p> This improves startup time and average memory usage.
|
||||
*/
|
||||
class LazilyLoadedCtor {
|
||||
|
||||
LazilyLoadedCtor(ScriptableObject scope, String ctorName,
|
||||
String className, int attributes)
|
||||
throws PropertyException
|
||||
{
|
||||
this.className = className;
|
||||
this.ctorName = ctorName;
|
||||
Class cl = getClass();
|
||||
Method[] getter = FunctionObject.findMethods(cl, "getProperty");
|
||||
Method[] setter = FunctionObject.findMethods(cl, "setProperty");
|
||||
scope.defineProperty(this.ctorName, this, getter[0], setter[0],
|
||||
attributes);
|
||||
}
|
||||
|
||||
public Object getProperty(ScriptableObject obj) {
|
||||
try {
|
||||
synchronized (obj) {
|
||||
if (!isReplaced)
|
||||
ScriptableObject.defineClass(obj, Class.forName(className));
|
||||
isReplaced = true;
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw WrappedException.wrapException(e);
|
||||
}
|
||||
catch (InstantiationException e) {
|
||||
throw WrappedException.wrapException(e);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw WrappedException.wrapException(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw WrappedException.wrapException(e);
|
||||
}
|
||||
catch (ClassDefinitionException e) {
|
||||
throw WrappedException.wrapException(e);
|
||||
}
|
||||
catch (PropertyException e) {
|
||||
throw WrappedException.wrapException(e);
|
||||
}
|
||||
return obj.get(ctorName, obj);
|
||||
}
|
||||
|
||||
public Object setProperty(ScriptableObject obj, Object val) {
|
||||
synchronized (obj) {
|
||||
isReplaced = true;
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
private String ctorName;
|
||||
private String className;
|
||||
private boolean isReplaced;
|
||||
}
|
||||
412
mozilla/js/rhino/org/mozilla/javascript/LineBuffer.java
Normal file
412
mozilla/js/rhino/org/mozilla/javascript/LineBuffer.java
Normal file
@@ -0,0 +1,412 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike McCabe
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An input buffer that combines fast character-based access with
|
||||
* (slower) support for retrieving the text of the current line. It
|
||||
* also supports building strings directly out of the internal buffer
|
||||
* to support fast scanning with minimal object creation.
|
||||
*
|
||||
* Note that it is customized in several ways to support the
|
||||
* TokenStream class, and should not be considered general.
|
||||
*
|
||||
* Credits to Kipp Hickman and John Bandhauer.
|
||||
*
|
||||
* @author Mike McCabe
|
||||
*/
|
||||
final class LineBuffer {
|
||||
/*
|
||||
* for smooth operation of getLine(), this should be greater than
|
||||
* the length of any expected line. Currently, 256 is 3% slower
|
||||
* than 4096 for large compiles, but seems safer given evaluateString.
|
||||
* Strings for the scanner are are built with StringBuffers
|
||||
* instead of directly out of the buffer whenever a string crosses
|
||||
* a buffer boundary, so small buffer sizes will mean that more
|
||||
* objects are created.
|
||||
*/
|
||||
static final int BUFLEN = 256;
|
||||
|
||||
LineBuffer(Reader in, int lineno) {
|
||||
this.in = in;
|
||||
this.lineno = lineno;
|
||||
}
|
||||
|
||||
int read() throws IOException {
|
||||
for(;;) {
|
||||
if (end == offset && !fill())
|
||||
return -1;
|
||||
|
||||
// Do only a bitmask + branch per character, at the cost of
|
||||
// three branches per low-bits-only (or 2028/9) character.
|
||||
if ((buffer[offset] & '\udfd0') == 0) {
|
||||
if (buffer[offset] == '\r') {
|
||||
// if the next character is a newline, skip past it.
|
||||
if ((offset + 1) < end) {
|
||||
if (buffer[offset + 1] == '\n')
|
||||
offset++;
|
||||
} else {
|
||||
// set a flag for fill(), in case the first char of the
|
||||
// next fill is a newline.
|
||||
lastWasCR = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((buffer[offset] != '\n')
|
||||
&& (buffer[offset] != '\u2028')
|
||||
&& (buffer[offset] != '\u2029'))
|
||||
{
|
||||
if (Character.getType(buffer[offset])
|
||||
== Character.FORMAT) {
|
||||
hadCFSinceStringStart = true;
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
return (int) buffer[offset++];
|
||||
}
|
||||
offset++;
|
||||
prevStart = lineStart;
|
||||
lineStart = offset;
|
||||
lineno++;
|
||||
return '\n';
|
||||
}
|
||||
if ((buffer[offset] >= 128)
|
||||
&& (Character.getType(buffer[offset]) == Character.FORMAT)) {
|
||||
hadCFSinceStringStart = true;
|
||||
offset++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return (int) buffer[offset++];
|
||||
}
|
||||
|
||||
void unread() {
|
||||
if (offset == 0)
|
||||
// We can get here when we're asked to unread() an
|
||||
// implicit EOF_CHAR.
|
||||
|
||||
// This would also be wrong behavior in the general case,
|
||||
// because a peek() could map a buffer.length offset to 0
|
||||
// in the process of a fill(), and leave it there. But
|
||||
// the scanner never calls peek() or a failed match()
|
||||
// followed by unread()... this would violate 1-character
|
||||
// lookahead. So we're OK.
|
||||
return;
|
||||
offset--;
|
||||
if ((buffer[offset] & '\ufff0') == 0
|
||||
&& (buffer[offset] == '\r' || buffer[offset] == '\n')) {
|
||||
// back off from the line start we presumably just registered...
|
||||
lineStart = prevStart;
|
||||
lineno--;
|
||||
}
|
||||
}
|
||||
|
||||
int peek() throws IOException {
|
||||
if (end == offset && !fill())
|
||||
return -1;
|
||||
|
||||
if (buffer[offset] == '\r')
|
||||
return '\n';
|
||||
|
||||
return buffer[offset];
|
||||
}
|
||||
|
||||
boolean match(char c) throws IOException {
|
||||
if (end == offset && !fill())
|
||||
return false;
|
||||
|
||||
// This'd be a place where we'd need to map '\r' to '\n' and
|
||||
// do other updates, but TokenStream never looks ahead for
|
||||
// '\n', so we don't bother.
|
||||
if (buffer[offset] == c) {
|
||||
offset++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reconstruct a source line from the buffers. This can be slow...
|
||||
String getLine() {
|
||||
StringBuffer result = new StringBuffer();
|
||||
|
||||
int start = lineStart;
|
||||
if (start >= offset) {
|
||||
// the line begins somewhere in the other buffer; get that first.
|
||||
if (otherStart < otherEnd)
|
||||
// if a line ending was seen in the other buffer... otherwise
|
||||
// just ignore this strange case.
|
||||
result.append(otherBuffer, otherStart,
|
||||
otherEnd - otherStart);
|
||||
start = 0;
|
||||
}
|
||||
|
||||
// get the part of the line in the current buffer.
|
||||
result.append(buffer, start, offset - start);
|
||||
|
||||
// Get the remainder of the line.
|
||||
int i = offset;
|
||||
while(true) {
|
||||
if (i == buffer.length) {
|
||||
// we're out of buffer, let's just expand it. We do
|
||||
// this instead of reading into a StringBuffer to
|
||||
// preserve the stream for later reads.
|
||||
char[] newBuffer = new char[buffer.length * 2];
|
||||
System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
|
||||
buffer = newBuffer;
|
||||
int charsRead = 0;
|
||||
try {
|
||||
charsRead = in.read(buffer, end, buffer.length - end);
|
||||
} catch (IOException ioe) {
|
||||
// ignore it, we're already displaying an error...
|
||||
}
|
||||
if (charsRead < 0)
|
||||
break;
|
||||
end += charsRead;
|
||||
}
|
||||
if (buffer[i] == '\r' || buffer[i] == '\n')
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
|
||||
result.append(buffer, offset, i - offset);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
// Get the offset of the current character, relative to
|
||||
// the line that getLine() returns.
|
||||
int getOffset() {
|
||||
if (lineStart >= offset)
|
||||
// The line begins somewhere in the other buffer.
|
||||
return offset + (otherEnd - otherStart);
|
||||
else
|
||||
return offset - lineStart;
|
||||
}
|
||||
|
||||
// Set a mark to indicate that the reader should begin
|
||||
// accumulating characters for getString(). The string begins
|
||||
// with the last character read.
|
||||
void startString() {
|
||||
if (offset == 0) {
|
||||
// We can get here if startString is called after a peek()
|
||||
// or failed match() with offset past the end of the
|
||||
// buffer.
|
||||
|
||||
// We're at the beginning of the buffer, and the previous character
|
||||
// (which we want to include) is at the end of the last one, so
|
||||
// we just go to StringBuffer mode.
|
||||
stringSoFar = new StringBuffer();
|
||||
|
||||
stringSoFar.append(otherBuffer, otherEnd - 1, 1);
|
||||
|
||||
stringStart = -1; // Set sentinel value.
|
||||
hadCFSinceStringStart = ((otherBuffer[otherEnd - 1] >= 128)
|
||||
&& Character.getType(otherBuffer[otherEnd - 1])
|
||||
== Character.FORMAT);
|
||||
} else {
|
||||
// Support restarting strings
|
||||
stringSoFar = null;
|
||||
stringStart = offset - 1;
|
||||
hadCFSinceStringStart = ((buffer[stringStart] >= 128)
|
||||
&& Character.getType(buffer[stringStart]) == Character.FORMAT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Get a string consisting of the characters seen since the last
|
||||
// startString.
|
||||
String getString() {
|
||||
String result;
|
||||
|
||||
/*
|
||||
* There's one strange case here: If the character offset currently
|
||||
* points to (which we never want to include in the string) is
|
||||
* a newline, then if the previous character is a carriage return,
|
||||
* we probably want to exclude that as well. If the offset is 0,
|
||||
* then we hope that fill() handled excluding it from stringSoFar.
|
||||
*/
|
||||
int loseCR = (offset > 0 &&
|
||||
buffer[offset] == '\n' && buffer[offset - 1] == '\r') ?
|
||||
1 : 0;
|
||||
|
||||
if (stringStart != -1) {
|
||||
// String mark is valid, and in this buffer.
|
||||
|
||||
result = new String(buffer, stringStart,
|
||||
offset - stringStart - loseCR);
|
||||
} else {
|
||||
if (stringSoFar == null)
|
||||
stringSoFar = new StringBuffer();
|
||||
// Exclude cr as well as nl of newline. If offset is 0, then
|
||||
// hopefully fill() did the right thing.
|
||||
result = (stringSoFar.append(buffer, 0, offset - loseCR)).toString();
|
||||
}
|
||||
|
||||
stringStart = -1;
|
||||
stringSoFar = null;
|
||||
|
||||
if (hadCFSinceStringStart) {
|
||||
char c[] = result.toCharArray();
|
||||
StringBuffer x = null;
|
||||
for (int i = 0; i < c.length; i++) {
|
||||
if (Character.getType(c[i]) == Character.FORMAT) {
|
||||
if (x == null) {
|
||||
x = new StringBuffer();
|
||||
x.append(c, 0, i);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (x != null) x.append(c[i]);
|
||||
}
|
||||
if (x != null) result = x.toString();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean fill() throws IOException {
|
||||
// not sure I care...
|
||||
if (end - offset != 0)
|
||||
throw new IOException("fill of non-empty buffer");
|
||||
|
||||
// If there's a string currently being accumulated, save
|
||||
// off the progress.
|
||||
|
||||
/*
|
||||
* Exclude an end-of-buffer carriage return. NOTE this is not
|
||||
* fully correct in the general case, because we really only
|
||||
* want to exclude the carriage return if it's followed by a
|
||||
* linefeed at the beginning of the next buffer. But we fudge
|
||||
* because the scanner doesn't do this.
|
||||
*/
|
||||
int loseCR = (offset > 0 && lastWasCR) ? 1 : 0;
|
||||
|
||||
if (stringStart != -1) {
|
||||
// The mark is in the current buffer, save off from the mark to the
|
||||
// end.
|
||||
stringSoFar = new StringBuffer();
|
||||
|
||||
stringSoFar.append(buffer, stringStart, end - stringStart - loseCR);
|
||||
stringStart = -1;
|
||||
} else if (stringSoFar != null) {
|
||||
// the string began prior to the current buffer, so save the
|
||||
// whole current buffer.
|
||||
stringSoFar.append(buffer, 0, end - loseCR);
|
||||
}
|
||||
|
||||
// swap buffers
|
||||
char[] tempBuffer = buffer;
|
||||
buffer = otherBuffer;
|
||||
otherBuffer = tempBuffer;
|
||||
|
||||
// allocate the buffers lazily, in case we're handed a short string.
|
||||
if (buffer == null) {
|
||||
buffer = new char[BUFLEN];
|
||||
}
|
||||
|
||||
// buffers have switched, so move the newline marker.
|
||||
otherStart = lineStart;
|
||||
otherEnd = end;
|
||||
|
||||
// set lineStart to a sentinel value, unless this is the first
|
||||
// time around.
|
||||
prevStart = lineStart = (otherBuffer == null) ? 0 : buffer.length + 1;
|
||||
|
||||
offset = 0;
|
||||
end = in.read(buffer, 0, buffer.length);
|
||||
if (end < 0) {
|
||||
end = 0;
|
||||
|
||||
// can't null buffers here, because a string might be retrieved
|
||||
// out of the other buffer, and a 0-length string might be
|
||||
// retrieved out of this one.
|
||||
|
||||
hitEOF = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the last character of the previous fill was a carriage return,
|
||||
// then ignore a newline.
|
||||
|
||||
// There's another bizzare special case here. If lastWasCR is
|
||||
// true, and we see a newline, and the buffer length is
|
||||
// 1... then we probably just read the last character of the
|
||||
// file, and returning after advancing offset is not the right
|
||||
// thing to do. Instead, we try to ignore the newline (and
|
||||
// likely get to EOF for real) by doing yet another fill().
|
||||
if (lastWasCR) {
|
||||
if (buffer[0] == '\n') {
|
||||
offset++;
|
||||
if (end == 1)
|
||||
return fill();
|
||||
}
|
||||
lineStart = offset;
|
||||
lastWasCR = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int getLineno() { return lineno; }
|
||||
boolean eof() { return hitEOF; }
|
||||
|
||||
private Reader in;
|
||||
private char[] otherBuffer = null;
|
||||
private char[] buffer = null;
|
||||
|
||||
// Yes, there are too too many of these.
|
||||
private int offset = 0;
|
||||
private int end = 0;
|
||||
private int otherEnd;
|
||||
private int lineno;
|
||||
|
||||
private int lineStart = 0;
|
||||
private int otherStart = 0;
|
||||
private int prevStart = 0;
|
||||
|
||||
private boolean lastWasCR = false;
|
||||
private boolean hitEOF = false;
|
||||
|
||||
private int stringStart = -1;
|
||||
private StringBuffer stringSoFar = null;
|
||||
private boolean hadCFSinceStringStart = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
114
mozilla/js/rhino/org/mozilla/javascript/ListenerCollection.java
Normal file
114
mozilla/js/rhino/org/mozilla/javascript/ListenerCollection.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is ListenerCollection, released
|
||||
* May 15, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Ian D. Stewart.
|
||||
* Portions created by Ian D. Stewart are Copyright (C) 1998, 1999
|
||||
* Ian D. Stewart.
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ian D. Stewart
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
|
||||
/* This class provides a series of methods for accessing event listeners. */
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* This class acts as central storage location for miscelanious
|
||||
* event listeners. It provides methods for adding, removing
|
||||
* and accessing listeners, both individually and collectively,
|
||||
* by the listener interface implemented
|
||||
*
|
||||
* Note: This class performs the same functions as
|
||||
* javax.swing.event.EventListenerList, and is provided
|
||||
* primarily for implementations lacking the Swing packages
|
||||
*
|
||||
* @author Ian D. Stewart
|
||||
* @since JavaScript-Java 1.4 rel 3
|
||||
*/
|
||||
public class ListenerCollection extends Vector {
|
||||
/**
|
||||
* Create a new ListenerCollection
|
||||
*/
|
||||
public ListenerCollection() {
|
||||
super();
|
||||
} // Constructor
|
||||
|
||||
/**
|
||||
* Add a new listener to the collection
|
||||
* @param listener the listener
|
||||
*/
|
||||
public void addListener(Object listener) {
|
||||
this.addElement(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a listener from the collection
|
||||
* @param listener the listener
|
||||
*/
|
||||
public void removeListener(Object listener) {
|
||||
this.removeElement(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Enumeration of all the listeners
|
||||
* being stored in this collection
|
||||
* @return an Enumeration of all listeners
|
||||
*/
|
||||
public Enumeration getAllListeners() {
|
||||
return this.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the listeners in this collection which
|
||||
* implement the specified interface
|
||||
*
|
||||
* @param iface the interface
|
||||
* @return an array of listeners which implement the given
|
||||
* interface
|
||||
*/
|
||||
public Object[] getListeners(Class iface) {
|
||||
Vector array = new Vector();
|
||||
|
||||
for(Enumeration enum = getAllListeners();enum.hasMoreElements();) {
|
||||
Object listener = enum.nextElement();
|
||||
if(iface.isInstance(listener)) {
|
||||
array.addElement(listener);
|
||||
}
|
||||
}
|
||||
Object[] result = new Object[array.size()];
|
||||
array.copyInto(result);
|
||||
return result;
|
||||
}
|
||||
} // ListenerCollection
|
||||
|
||||
// end of ListenerCollection.java ...
|
||||
|
||||
79
mozilla/js/rhino/org/mozilla/javascript/LocalVariable.java
Normal file
79
mozilla/js/rhino/org/mozilla/javascript/LocalVariable.java
Normal file
@@ -0,0 +1,79 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Roger Lawrence
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
public class LocalVariable {
|
||||
|
||||
public LocalVariable(String name, boolean isParameter) {
|
||||
itsName = name;
|
||||
itsIsParameter = isParameter;
|
||||
}
|
||||
|
||||
public void setIndex(int index){ itsIndex = index; }
|
||||
public int getIndex() { return itsIndex; }
|
||||
|
||||
public void setIsParameter() { itsIsParameter = true; }
|
||||
public boolean isParameter() { return itsIsParameter; }
|
||||
|
||||
public String getName() { return itsName; }
|
||||
|
||||
/**
|
||||
* Return the starting PC where this variable is live, or -1
|
||||
* if it is not a Java register.
|
||||
*/
|
||||
public int getStartPC() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Java register number or -1 if it is not a Java register.
|
||||
*/
|
||||
public short getJRegister() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the local variable is a Java register with double type.
|
||||
*/
|
||||
public boolean isNumber() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private String itsName;
|
||||
private int itsIndex = -1;
|
||||
|
||||
private boolean itsIsParameter;
|
||||
}
|
||||
244
mozilla/js/rhino/org/mozilla/javascript/Makefile
Normal file
244
mozilla/js/rhino/org/mozilla/javascript/Makefile
Normal file
@@ -0,0 +1,244 @@
|
||||
#! gmake
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
# the License at http://www.mozilla.org/NPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS
|
||||
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
# implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code is Rhino code, released
|
||||
# May 6, 1998.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Netscape
|
||||
# Communications Corporation. Portions created by Netscape are
|
||||
# Copyright (C) 1999 Netscape Communications Corporation. All
|
||||
# Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the
|
||||
# terms of the GNU Public License (the "GPL"), in which case the
|
||||
# provisions of the GPL are applicable instead of those above.
|
||||
# If you wish to allow use of your version of this file only
|
||||
# under the terms of the GPL and not to allow others to use your
|
||||
# version of this file under the NPL, indicate your decision by
|
||||
# deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this
|
||||
# file under either the NPL or the GPL.
|
||||
|
||||
#
|
||||
# Makefile the core javascript classes.
|
||||
#
|
||||
# This Makefile is intended to be called from the toplevel Makefile.
|
||||
#
|
||||
|
||||
# List files explicitly to exclude .java files in this dir we don't want
|
||||
# to compile. Also hack in classfile stuff...
|
||||
SOURCES = \
|
||||
$(PATH_PREFIX)/Arguments.java \
|
||||
$(PATH_PREFIX)/BinaryDigitReader.java \
|
||||
$(PATH_PREFIX)/ClassDefinitionException.java \
|
||||
$(PATH_PREFIX)/ClassNameHelper.java \
|
||||
$(PATH_PREFIX)/Context.java \
|
||||
$(PATH_PREFIX)/DeepBytecodeHook.java \
|
||||
$(PATH_PREFIX)/DeepCallHook.java \
|
||||
$(PATH_PREFIX)/DeepErrorReporterHook.java \
|
||||
$(PATH_PREFIX)/DeepExecuteHook.java \
|
||||
$(PATH_PREFIX)/DeepNewObjectHook.java \
|
||||
$(PATH_PREFIX)/DeepScriptHook.java \
|
||||
$(PATH_PREFIX)/DefaultErrorReporter.java \
|
||||
$(PATH_PREFIX)/EcmaError.java \
|
||||
$(PATH_PREFIX)/ErrorReporter.java \
|
||||
$(PATH_PREFIX)/EvaluatorException.java \
|
||||
$(PATH_PREFIX)/FlattenedObject.java \
|
||||
$(PATH_PREFIX)/Function.java \
|
||||
$(PATH_PREFIX)/FunctionNode.java \
|
||||
$(PATH_PREFIX)/FunctionObject.java \
|
||||
$(PATH_PREFIX)/IRFactory.java \
|
||||
$(PATH_PREFIX)/ImporterTopLevel.java \
|
||||
$(PATH_PREFIX)/InterpretedFunction.java \
|
||||
$(PATH_PREFIX)/InterpretedScript.java \
|
||||
$(PATH_PREFIX)/Interpreter.java \
|
||||
$(PATH_PREFIX)/InterpreterData.java \
|
||||
$(PATH_PREFIX)/JavaAdapter.java \
|
||||
$(PATH_PREFIX)/JavaMembers.java \
|
||||
$(PATH_PREFIX)/JavaScriptException.java \
|
||||
$(PATH_PREFIX)/Label.java \
|
||||
$(PATH_PREFIX)/LabelTable.java \
|
||||
$(PATH_PREFIX)/LazilyLoadedCtor.java \
|
||||
$(PATH_PREFIX)/LineBuffer.java \
|
||||
$(PATH_PREFIX)/ListenerCollection.java \
|
||||
$(PATH_PREFIX)/LocalVariable.java \
|
||||
$(PATH_PREFIX)/NativeArray.java \
|
||||
$(PATH_PREFIX)/NativeBoolean.java \
|
||||
$(PATH_PREFIX)/NativeCall.java \
|
||||
$(PATH_PREFIX)/NativeDate.java \
|
||||
$(PATH_PREFIX)/NativeError.java \
|
||||
$(PATH_PREFIX)/NativeFunction.java \
|
||||
$(PATH_PREFIX)/NativeGlobal.java \
|
||||
$(PATH_PREFIX)/NativeJavaArray.java \
|
||||
$(PATH_PREFIX)/NativeJavaClass.java \
|
||||
$(PATH_PREFIX)/NativeJavaConstructor.java \
|
||||
$(PATH_PREFIX)/NativeJavaMethod.java \
|
||||
$(PATH_PREFIX)/NativeJavaObject.java \
|
||||
$(PATH_PREFIX)/NativeJavaPackage.java \
|
||||
$(PATH_PREFIX)/NativeMath.java \
|
||||
$(PATH_PREFIX)/NativeNumber.java \
|
||||
$(PATH_PREFIX)/NativeObject.java \
|
||||
$(PATH_PREFIX)/NativeScript.java \
|
||||
$(PATH_PREFIX)/NativeString.java \
|
||||
$(PATH_PREFIX)/NativeWith.java \
|
||||
$(PATH_PREFIX)/Node.java \
|
||||
$(PATH_PREFIX)/NodeTransformer.java \
|
||||
$(PATH_PREFIX)/NotAFunctionException.java \
|
||||
$(PATH_PREFIX)/Parser.java \
|
||||
$(PATH_PREFIX)/PreorderNodeIterator.java \
|
||||
$(PATH_PREFIX)/PropertyException.java \
|
||||
$(PATH_PREFIX)/RegExpProxy.java \
|
||||
$(PATH_PREFIX)/Script.java \
|
||||
$(PATH_PREFIX)/ScriptRuntime.java \
|
||||
$(PATH_PREFIX)/Scriptable.java \
|
||||
$(PATH_PREFIX)/ScriptableObject.java \
|
||||
$(PATH_PREFIX)/SecuritySupport.java \
|
||||
$(PATH_PREFIX)/ShallowNodeIterator.java \
|
||||
$(PATH_PREFIX)/SourceTextItem.java \
|
||||
$(PATH_PREFIX)/SourceTextManager.java \
|
||||
$(PATH_PREFIX)/TokenStream.java \
|
||||
$(PATH_PREFIX)/Undefined.java \
|
||||
$(PATH_PREFIX)/VariableTable.java \
|
||||
$(PATH_PREFIX)/WrappedException.java \
|
||||
$(PATH_PREFIX)/Wrapper.java \
|
||||
$(PATH_PREFIX)/regexp/NativeRegExp.java \
|
||||
$(PATH_PREFIX)/regexp/NativeRegExpCtor.java \
|
||||
$(PATH_PREFIX)/regexp/RegExpImpl.java \
|
||||
$(PATH_PREFIX)/regexp/SubString.java \
|
||||
$(PATH_PREFIX)/optimizer/Block.java \
|
||||
$(PATH_PREFIX)/optimizer/Codegen.java \
|
||||
$(PATH_PREFIX)/optimizer/DataFlowBitSet.java \
|
||||
$(PATH_PREFIX)/optimizer/FatBlock.java \
|
||||
$(PATH_PREFIX)/optimizer/JavaScriptClassLoader.java\
|
||||
$(PATH_PREFIX)/optimizer/OptClassNameHelper.java\
|
||||
$(PATH_PREFIX)/optimizer/OptFunctionNode.java \
|
||||
$(PATH_PREFIX)/optimizer/OptIRFactory.java \
|
||||
$(PATH_PREFIX)/optimizer/OptLocalVariable.java \
|
||||
$(PATH_PREFIX)/optimizer/OptRuntime.java \
|
||||
$(PATH_PREFIX)/optimizer/OptTransformer.java \
|
||||
$(PATH_PREFIX)/optimizer/OptVariableTable.java \
|
||||
$(PATH_PREFIX)/optimizer/Optimizer.java \
|
||||
$(PATH_PREFIX)/optimizer/StmtNodeIterator.java \
|
||||
$(PATH_PREFIX)/optimizer/TypeEvent.java \
|
||||
$(PATH_PREFIX)/../classfile/ByteCode.java \
|
||||
$(PATH_PREFIX)/../classfile/ClassFileWriter.java\
|
||||
$(NULL)
|
||||
|
||||
RESOURCEDIR = $(PATH_PREFIX)/resources
|
||||
RESOURCES = $(RESOURCEDIR)/*.properties
|
||||
|
||||
# This must be evaluated in some context where the classes can be
|
||||
# found; we can't use a simple translation from sources, because a
|
||||
# .java file may produce more than one .class file.
|
||||
# (use org/mozilla/classfile explicitly for now; should be replaced
|
||||
# with something parameterized, but jar doesn't understand ..)
|
||||
CLASSES = $(PATH_PREFIX)/*.class $(PATH_PREFIX)/regexp/*.class \
|
||||
$(PATH_PREFIX)/optimizer/*.class org/mozilla/classfile/*.class
|
||||
|
||||
# A class or set of classes as visible from the top level. For want
|
||||
# of ${subst ,,}. This variable is only used to trigger dependency
|
||||
# analysis, and multiple words confuse gmake, so it can be smaller
|
||||
# than the full set of sources. (We assume we'll never need to do the
|
||||
# same thing with RESOURCES.)
|
||||
TLCLASS = $(CLASSDIR)/$(PATH_PREFIX)/*.class
|
||||
|
||||
# An empty file, used mainly for timestamp/dependency purposes by
|
||||
# "fast" builds
|
||||
FASTTARGET=$(CLASSDIR)/.lastbuild
|
||||
|
||||
|
||||
$(JAR) : $(TLCLASS) $(CLASSDIR)/$(RESOURCES)
|
||||
cd $(CLASSDIR) ; \
|
||||
jar cf ../$(JAR) $(CLASSES) $(RESOURCES)
|
||||
|
||||
$(TLCLASS) : $(SOURCES)
|
||||
- mkdir -p $(CLASSDIR)
|
||||
echo "" > $(FASTTARGET)
|
||||
$(JAVAC) $(JFLAGS) -d $(CLASSDIR) $(SOURCES)
|
||||
|
||||
$(CLASSDIR)/$(RESOURCES) : $(RESOURCES)
|
||||
- mkdir -p $(CLASSDIR)/$(RESOURCEDIR)
|
||||
cp $(RESOURCES) $(CLASSDIR)/$(RESOURCEDIR)
|
||||
|
||||
# Since the jar file is a target for regular builds, "fast" builds use a
|
||||
# dummy file, updated before each compilation to provide a timestamp.
|
||||
# Even so, using a dummy file is far from foolproof, so we still need
|
||||
# the regular build.
|
||||
|
||||
fast: $(FASTTARGET)
|
||||
|
||||
# So that we recompile only the files that have changed, we pretend
|
||||
# the only real dependencies are the source files, and recopy the
|
||||
# resources every time. Right now (14 Jun 99), the only resource is
|
||||
# Messages.properties, so it's a small price to pay.
|
||||
$(FASTTARGET) : $(SOURCES)
|
||||
- mkdir -p $(CLASSDIR)/$(RESOURCEDIR)
|
||||
cp $(RESOURCES) $(CLASSDIR)/$(RESOURCEDIR)
|
||||
echo "" > $(FASTTARGET)
|
||||
$(JAVAC) $(JFLAGS) -d $(CLASSDIR) $(?)
|
||||
cd $(CLASSDIR) ; \
|
||||
jar cf ../$(JAR) $(CLASSES) $(RESOURCES)
|
||||
|
||||
clean :
|
||||
- cd $(CLASSDIR)
|
||||
- rm $(CLASSES)
|
||||
- rm $(PATH_PREFIX)/message.ids \
|
||||
$(PATH_PREFIX)/property.ids \
|
||||
$(PATH_PREFIX)/MANIFEST
|
||||
|
||||
clobber : clean
|
||||
-rm $(JAR)
|
||||
|
||||
$(PATH_PREFIX)/MANIFEST : $(SOURCES) $(RESOURCES) $(PATH_PREFIX)/Makefile
|
||||
ls $(SOURCES) $(RESOURCES) $(PATH_PREFIX)/Makefile \
|
||||
> $(@)
|
||||
|
||||
# A sed/grep regular expression.
|
||||
MESSAGE_PREFIX = msg\.
|
||||
|
||||
|
||||
# Find all the msg.* strings in the source, and condense them to a sorted list,
|
||||
# excluding duplicates.
|
||||
|
||||
$(PATH_PREFIX)/message.ids : $(SOURCES)
|
||||
grep '$(MESSAGE_PREFIX)' $(SOURCES) |\
|
||||
sed -e 's/.*\"\($(MESSAGE_PREFIX)\)\([^\"]*\).*/\1\2/' | \
|
||||
sort | uniq > $(PATH_PREFIX)/message.ids
|
||||
|
||||
|
||||
# Find all the msg.* strings in the resource files, and condense them to a
|
||||
# sorted list, not excluding duplicates.
|
||||
$(PATH_PREFIX)/property.ids : $(RESOURCES)
|
||||
grep '^$(MESSAGE_PREFIX)' $(RESOURCES) |\
|
||||
sed -e 's/.*\($(MESSAGE_PREFIX)\)\([^ =]*\).*/\1\2/' |\
|
||||
sort > $(PATH_PREFIX)/property.ids
|
||||
|
||||
|
||||
# Compare the resulting message.ids and property.ids files and confirm
|
||||
# that they do not differ. This means that every message string used
|
||||
# in the source is defined somewhere in the resource file, every
|
||||
# resource in the resource file is used somewhere in the source, and
|
||||
# no resource is defined more than once.
|
||||
check : $(PATH_PREFIX)/message.ids $(PATH_PREFIX)/property.ids FORCE
|
||||
- diff $(PATH_PREFIX)/message.ids $(PATH_PREFIX)/property.ids
|
||||
|
||||
# look for unmatched single quotes ... seems to fail when none!
|
||||
# - sed -e s/\'\'//g $($RESOURCES) | grep \'
|
||||
|
||||
# Emulate .PHONY
|
||||
FORCE :
|
||||
|
||||
|
||||
|
||||
|
||||
954
mozilla/js/rhino/org/mozilla/javascript/NativeArray.java
Normal file
954
mozilla/js/rhino/org/mozilla/javascript/NativeArray.java
Normal file
@@ -0,0 +1,954 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
* Mike McCabe
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* This class implements the Array native object.
|
||||
* @author Norris Boyd
|
||||
* @author Mike McCabe
|
||||
*/
|
||||
public class NativeArray extends ScriptableObject {
|
||||
|
||||
/*
|
||||
* Optimization possibilities and open issues:
|
||||
* - Long vs. double schizophrenia. I suspect it might be better
|
||||
* to use double throughout.
|
||||
|
||||
* - Most array operations go through getElem or setElem (defined
|
||||
* in this file) to handle the full 2^32 range; it might be faster
|
||||
* to have versions of most of the loops in this file for the
|
||||
* (infinitely more common) case of indices < 2^31.
|
||||
|
||||
* - Functions that need a new Array call "new Array" in the
|
||||
* current scope rather than using a hardwired constructor;
|
||||
* "Array" could be redefined. It turns out that js calls the
|
||||
* equivalent of "new Array" in the current scope, except that it
|
||||
* always gets at least an object back, even when Array == null.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Zero-parameter constructor: just used to create Array.prototype
|
||||
*/
|
||||
public NativeArray() {
|
||||
dense = null;
|
||||
this.length = 0;
|
||||
}
|
||||
|
||||
public NativeArray(long length) {
|
||||
int intLength = (int) length;
|
||||
if (intLength == length && intLength > 0) {
|
||||
if (intLength > maximumDenseLength)
|
||||
intLength = maximumDenseLength;
|
||||
dense = new Object[intLength];
|
||||
for (int i=0; i < intLength; i++)
|
||||
dense[i] = NOT_FOUND;
|
||||
}
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public NativeArray(Object[] array) {
|
||||
dense = array;
|
||||
this.length = array.length;
|
||||
}
|
||||
|
||||
public static void finishInit(Scriptable scope, FunctionObject ctor,
|
||||
Scriptable proto)
|
||||
{
|
||||
// Set some method length values.
|
||||
// See comment for NativeString.finishInit()
|
||||
|
||||
String[] specialLengthNames = { "reverse",
|
||||
"toString",
|
||||
};
|
||||
|
||||
short[] specialLengthValues = { 0,
|
||||
0,
|
||||
};
|
||||
|
||||
for (int i=0; i < specialLengthNames.length; i++) {
|
||||
Object obj = proto.get(specialLengthNames[i], proto);
|
||||
((FunctionObject) obj).setLength(specialLengthValues[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "Array";
|
||||
}
|
||||
|
||||
public Object get(int index, Scriptable start) {
|
||||
if (dense != null && 0 <= index && index < dense.length)
|
||||
return dense[index];
|
||||
return super.get(index, start);
|
||||
}
|
||||
|
||||
public boolean has(int index, Scriptable start) {
|
||||
if (dense != null && 0 <= index && index < dense.length)
|
||||
return dense[index] != NOT_FOUND;
|
||||
return super.has(index, start);
|
||||
}
|
||||
|
||||
public void put(String id, Scriptable start, Object value) {
|
||||
// only set the array length if given an array index (ECMA 15.4.0)
|
||||
|
||||
// try to get an array index from id
|
||||
double d = ScriptRuntime.toNumber(id);
|
||||
|
||||
if (ScriptRuntime.toUint32(d) == d &&
|
||||
ScriptRuntime.numberToString(d, 10).equals(id) &&
|
||||
this.length <= d && d != 4294967295.0)
|
||||
{
|
||||
this.length = (long)d + 1;
|
||||
}
|
||||
|
||||
super.put(id, start, value);
|
||||
}
|
||||
|
||||
public void put(int index, Scriptable start, Object value) {
|
||||
// only set the array length if given an array index (ECMA 15.4.0)
|
||||
|
||||
if (this.length <= index) {
|
||||
// avoid overflowing index!
|
||||
this.length = (long)index + 1;
|
||||
}
|
||||
|
||||
if (dense != null && 0 <= index && index < dense.length) {
|
||||
dense[index] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
super.put(index, start, value);
|
||||
}
|
||||
|
||||
public void delete(int index) {
|
||||
if (dense != null && 0 <= index && index < dense.length) {
|
||||
dense[index] = NOT_FOUND;
|
||||
return;
|
||||
}
|
||||
super.delete(index);
|
||||
}
|
||||
|
||||
public Object[] getIds() {
|
||||
Object[] superIds = super.getIds();
|
||||
if (dense == null)
|
||||
return superIds;
|
||||
int count = 0;
|
||||
int last = dense.length;
|
||||
if (last > length)
|
||||
last = (int) length;
|
||||
for (int i=last-1; i >= 0; i--) {
|
||||
if (dense[i] != NOT_FOUND)
|
||||
count++;
|
||||
}
|
||||
count += superIds.length;
|
||||
Object[] result = new Object[count];
|
||||
System.arraycopy(superIds, 0, result, 0, superIds.length);
|
||||
for (int i=last-1; i >= 0; i--) {
|
||||
if (dense[i] != NOT_FOUND)
|
||||
result[--count] = new Integer(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Object getDefaultValue(Class hint) {
|
||||
if (hint == ScriptRuntime.NumberClass) {
|
||||
Context cx = Context.getContext();
|
||||
if (cx.getLanguageVersion() == Context.VERSION_1_2)
|
||||
return new Long(length);
|
||||
}
|
||||
return super.getDefaultValue(hint);
|
||||
}
|
||||
|
||||
/**
|
||||
* See ECMA 15.4.1,2
|
||||
*/
|
||||
public static Object jsConstructor(Context cx, Object[] args,
|
||||
Function ctorObj, boolean inNewExpr)
|
||||
throws JavaScriptException
|
||||
{
|
||||
if (!inNewExpr) {
|
||||
// FunctionObject.construct will set up parent, proto
|
||||
return ctorObj.construct(cx, ctorObj.getParentScope(), args);
|
||||
}
|
||||
if (args.length == 0)
|
||||
return new NativeArray();
|
||||
|
||||
// Only use 1 arg as first element for version 1.2; for
|
||||
// any other version (including 1.3) follow ECMA and use it as
|
||||
// a length.
|
||||
if (cx.getLanguageVersion() == cx.VERSION_1_2) {
|
||||
return new NativeArray(args);
|
||||
}
|
||||
else {
|
||||
if ((args.length > 1) || (!(args[0] instanceof Number)))
|
||||
return new NativeArray(args);
|
||||
else {
|
||||
long len = ScriptRuntime.toUint32(args[0]);
|
||||
if (len != (((Number)(args[0])).doubleValue()))
|
||||
throw Context.reportRuntimeError(Context.getMessage
|
||||
("msg.arraylength.bad", null));
|
||||
return new NativeArray(len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final int lengthAttr = ScriptableObject.DONTENUM |
|
||||
ScriptableObject.PERMANENT;
|
||||
|
||||
public long jsGet_length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public void jsSet_length(Object val) {
|
||||
/* XXX do we satisfy this?
|
||||
* 15.4.5.1 [[Put]](P, V):
|
||||
* 1. Call the [[CanPut]] method of A with name P.
|
||||
* 2. If Result(1) is false, return.
|
||||
* ?
|
||||
*/
|
||||
|
||||
if (!(val instanceof Number))
|
||||
throw Context.reportRuntimeError(Context.getMessage
|
||||
("msg.arraylength.bad", null));
|
||||
|
||||
long longVal = ScriptRuntime.toUint32(val);
|
||||
if (longVal != (((Number)val).doubleValue()))
|
||||
throw Context.reportRuntimeError(Context.getMessage
|
||||
("msg.arraylength.bad", null));
|
||||
|
||||
if (longVal < length) {
|
||||
// remove all properties between longVal and length
|
||||
if (length - longVal > 0x1000) {
|
||||
// assume that the representation is sparse
|
||||
Object[] e = getIds(); // will only find in object itself
|
||||
for (int i=0; i < e.length; i++) {
|
||||
if (e[i] instanceof String) {
|
||||
// > MAXINT will appear as string
|
||||
String id = (String) e[i];
|
||||
double d = ScriptRuntime.toNumber(id);
|
||||
if (d == d && d < length)
|
||||
delete(id);
|
||||
continue;
|
||||
}
|
||||
int index = ((Number) e[i]).intValue();
|
||||
if (index >= longVal)
|
||||
delete(index);
|
||||
}
|
||||
} else {
|
||||
// assume a dense representation
|
||||
for (long i=longVal; i < length; i++) {
|
||||
// only delete if defined in the object itself
|
||||
if (hasElem(this, i))
|
||||
ScriptRuntime.delete(this, new Long(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
length = longVal;
|
||||
}
|
||||
|
||||
/* Support for generic Array-ish objects. Most of the Array
|
||||
* functions try to be generic; anything that has a length
|
||||
* property is assumed to be an array. hasLengthProperty is
|
||||
* needed in addition to getLengthProperty, because
|
||||
* getLengthProperty always succeeds - tries to convert strings, etc.
|
||||
*/
|
||||
static double getLengthProperty(Scriptable obj) {
|
||||
// These will both give numeric lengths within Uint32 range.
|
||||
if (obj instanceof NativeString)
|
||||
return (double)((NativeString)obj).jsGet_length();
|
||||
if (obj instanceof NativeArray)
|
||||
return (double)((NativeArray)obj).jsGet_length();
|
||||
return ScriptRuntime.toUint32(ScriptRuntime
|
||||
.getProp(obj, "length", obj));
|
||||
}
|
||||
|
||||
static boolean hasLengthProperty(Object obj) {
|
||||
if (!(obj instanceof Scriptable) || obj == Context.getUndefinedValue())
|
||||
return false;
|
||||
if (obj instanceof NativeString || obj instanceof NativeArray)
|
||||
return true;
|
||||
Scriptable sobj = (Scriptable)obj;
|
||||
|
||||
// XXX some confusion as to whether or not to walk to get the length
|
||||
// property. Pending review of js/[new ecma submission] treatment
|
||||
// of 'arrayness'.
|
||||
|
||||
Object property = ScriptRuntime.getProp(sobj, "length", sobj);
|
||||
return property instanceof Number;
|
||||
}
|
||||
|
||||
/* Utility functions to encapsulate index > Integer.MAX_VALUE
|
||||
* handling. Also avoids unnecessary object creation that would
|
||||
* be necessary to use the general ScriptRuntime.get/setElem
|
||||
* functions... though this is probably premature optimization.
|
||||
*/
|
||||
private static boolean hasElem(Scriptable target, long index) {
|
||||
return index > Integer.MAX_VALUE
|
||||
? target.has(Long.toString(index), target)
|
||||
: target.has((int)index, target);
|
||||
}
|
||||
|
||||
private static Object getElem(Scriptable target, long index) {
|
||||
if (index > Integer.MAX_VALUE) {
|
||||
String id = Long.toString(index);
|
||||
return ScriptRuntime.getElem(target, id, target);
|
||||
} else {
|
||||
return ScriptRuntime.getElem(target, (int)index);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setElem(Scriptable target, long index, Object value) {
|
||||
if (index > Integer.MAX_VALUE) {
|
||||
String id = Long.toString(index);
|
||||
ScriptRuntime.setElem(target, id, value, target);
|
||||
} else {
|
||||
ScriptRuntime.setElem(target, (int)index, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static String jsFunction_toString(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
return toStringHelper(cx, thisObj,
|
||||
cx.getLanguageVersion() == cx.VERSION_1_2);
|
||||
}
|
||||
|
||||
private static String toStringHelper(Context cx, Scriptable thisObj,
|
||||
boolean toSource)
|
||||
{
|
||||
/* It's probably redundant to handle long lengths in this
|
||||
* function; StringBuffers are limited to 2^31 in java.
|
||||
*/
|
||||
|
||||
long length = (long)getLengthProperty(thisObj);
|
||||
|
||||
StringBuffer result = new StringBuffer();
|
||||
|
||||
if (cx.iterating == null)
|
||||
cx.iterating = new Hashtable(31);
|
||||
boolean iterating = cx.iterating.get(thisObj) == Boolean.TRUE;
|
||||
|
||||
// whether to return '4,unquoted,5' or '[4, "quoted", 5]'
|
||||
String separator;
|
||||
|
||||
if (toSource) {
|
||||
result.append("[");
|
||||
separator = ", ";
|
||||
} else {
|
||||
separator = ",";
|
||||
}
|
||||
|
||||
boolean haslast = false;
|
||||
long i = 0;
|
||||
|
||||
if (!iterating) {
|
||||
for (i = 0; i < length; i++) {
|
||||
if (i > 0)
|
||||
result.append(separator);
|
||||
Object elem = getElem(thisObj, i);
|
||||
if (elem == null || elem == Undefined.instance) {
|
||||
haslast = false;
|
||||
continue;
|
||||
}
|
||||
haslast = true;
|
||||
|
||||
if (elem instanceof String) {
|
||||
if (toSource) {
|
||||
result.append("\"");
|
||||
result.append(ScriptRuntime.escapeString
|
||||
(ScriptRuntime.toString(elem)));
|
||||
result.append("\"");
|
||||
} else {
|
||||
result.append(ScriptRuntime.toString(elem));
|
||||
}
|
||||
} else {
|
||||
/* wrap changes to cx.iterating in a try/finally
|
||||
* so that the reference always gets removed, and
|
||||
* we don't leak memory. Good place for weak
|
||||
* references, if we had them. */
|
||||
try {
|
||||
// stop recursion.
|
||||
cx.iterating.put(thisObj, Boolean.TRUE);
|
||||
result.append(ScriptRuntime.toString(elem));
|
||||
} finally {
|
||||
cx.iterating.remove(thisObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (toSource) {
|
||||
//for [,,].length behavior; we want toString to be symmetric.
|
||||
if (!haslast && i > 0)
|
||||
result.append(", ]");
|
||||
else
|
||||
result.append("]");
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* See ECMA 15.4.4.3
|
||||
*/
|
||||
public static String jsFunction_join(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
StringBuffer result = new StringBuffer();
|
||||
String separator;
|
||||
|
||||
double length = getLengthProperty(thisObj);
|
||||
|
||||
// if no args, use "," as separator
|
||||
if (args.length < 1) {
|
||||
separator = ",";
|
||||
} else {
|
||||
separator = ScriptRuntime.toString(args[0]);
|
||||
}
|
||||
for (long i=0; i < length; i++) {
|
||||
if (i > 0)
|
||||
result.append(separator);
|
||||
Object temp = getElem(thisObj, i);
|
||||
if (temp == null || temp == Undefined.instance)
|
||||
continue;
|
||||
result.append(ScriptRuntime.toString(temp));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* See ECMA 15.4.4.4
|
||||
*/
|
||||
public static Scriptable jsFunction_reverse(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
long len = (long)getLengthProperty(thisObj);
|
||||
|
||||
long half = len / 2;
|
||||
for(long i=0; i < half; i++) {
|
||||
long j = len - i - 1;
|
||||
Object temp1 = getElem(thisObj, i);
|
||||
Object temp2 = getElem(thisObj, j);
|
||||
setElem(thisObj, i, temp2);
|
||||
setElem(thisObj, j, temp1);
|
||||
}
|
||||
return thisObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* See ECMA 15.4.4.5
|
||||
*/
|
||||
public static Scriptable jsFunction_sort(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
throws JavaScriptException
|
||||
{
|
||||
long length = (long)getLengthProperty(thisObj);
|
||||
|
||||
Object compare;
|
||||
if (args.length > 0 && Undefined.instance != args[0])
|
||||
// sort with given compare function
|
||||
compare = args[0];
|
||||
else
|
||||
// sort with default compare
|
||||
compare = null;
|
||||
|
||||
|
||||
// OPT: Would it make sense to use the extended sort for very small
|
||||
// arrays?
|
||||
|
||||
// Should we use the extended sort function, or the faster one?
|
||||
if (length >= Integer.MAX_VALUE) {
|
||||
qsort_extended(cx, compare, thisObj, 0, length - 1);
|
||||
} else {
|
||||
// copy the JS array into a working array, so it can be
|
||||
// sorted cheaply.
|
||||
Object[] working = new Object[(int)length];
|
||||
for (int i=0; i<length; i++) {
|
||||
working[i] = getElem(thisObj, i);
|
||||
}
|
||||
|
||||
qsort(cx, compare, working, 0, (int)length - 1, funObj);
|
||||
|
||||
// copy the working array back into thisObj
|
||||
for (int i=0; i<length; i++) {
|
||||
setElem(thisObj, i, working[i]);
|
||||
}
|
||||
}
|
||||
return thisObj;
|
||||
}
|
||||
|
||||
private static double qsortCompare(Context cx, Object jsCompare, Object x,
|
||||
Object y, Scriptable scope)
|
||||
throws JavaScriptException
|
||||
{
|
||||
Object undef = Undefined.instance;
|
||||
|
||||
// sort undefined to end
|
||||
if (undef == x || undef == y) {
|
||||
if (undef != x)
|
||||
return -1;
|
||||
if (undef != y)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (jsCompare == null) {
|
||||
// if no compare function supplied, sort lexicographically
|
||||
String a = ScriptRuntime.toString(x);
|
||||
String b = ScriptRuntime.toString(y);
|
||||
|
||||
return a.compareTo(b);
|
||||
} else {
|
||||
// assemble args and call supplied JS compare function
|
||||
// OPT: put this argument creation in the caller and reuse it.
|
||||
// XXX what to do when compare function returns NaN? ECMA states
|
||||
// that it's then not a 'consistent compararison function'... but
|
||||
// then what do we do? Back out and start over with the generic
|
||||
// compare function when we see a NaN? Throw an error?
|
||||
Object[] args = {x, y};
|
||||
// return ScriptRuntime.toNumber(ScriptRuntime.call(jsCompare, null,
|
||||
// args));
|
||||
// for now, just ignore it:
|
||||
double d = ScriptRuntime.
|
||||
toNumber(ScriptRuntime.call(cx, jsCompare, null, args, scope));
|
||||
|
||||
return (d == d) ? d : 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static void qsort(Context cx, Object jsCompare, Object[] working,
|
||||
int lo, int hi, Scriptable scope)
|
||||
throws JavaScriptException
|
||||
{
|
||||
Object pivot;
|
||||
int i, j;
|
||||
int a, b;
|
||||
|
||||
while (lo < hi) {
|
||||
i = lo;
|
||||
j = hi;
|
||||
a = i;
|
||||
pivot = working[a];
|
||||
while (i < j) {
|
||||
for(;;) {
|
||||
b = j;
|
||||
if (qsortCompare(cx, jsCompare, working[j], pivot,
|
||||
scope) <= 0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
working[a] = working[b];
|
||||
while (i < j && qsortCompare(cx, jsCompare, working[a],
|
||||
pivot, scope) <= 0)
|
||||
{
|
||||
i++;
|
||||
a = i;
|
||||
}
|
||||
working[b] = working[a];
|
||||
}
|
||||
working[a] = pivot;
|
||||
if (i - lo < hi - i) {
|
||||
qsort(cx, jsCompare, working, lo, i - 1, scope);
|
||||
lo = i + 1;
|
||||
} else {
|
||||
qsort(cx, jsCompare, working, i + 1, hi, scope);
|
||||
hi = i - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A version that knows about long indices and doesn't use
|
||||
// a working array. Probably will never be used.
|
||||
private static void qsort_extended(Context cx, Object jsCompare,
|
||||
Scriptable target, long lo, long hi)
|
||||
throws JavaScriptException
|
||||
{
|
||||
Object pivot;
|
||||
long i, j;
|
||||
long a, b;
|
||||
|
||||
while (lo < hi) {
|
||||
i = lo;
|
||||
j = hi;
|
||||
a = i;
|
||||
pivot = getElem(target, a);
|
||||
while (i < j) {
|
||||
for(;;) {
|
||||
b = j;
|
||||
if (qsortCompare(cx, jsCompare, getElem(target, j),
|
||||
pivot, target) <= 0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
setElem(target, a, getElem(target, b));
|
||||
while (i < j && qsortCompare(cx, jsCompare,
|
||||
getElem(target, a),
|
||||
pivot, target) <= 0)
|
||||
{
|
||||
i++;
|
||||
a = i;
|
||||
}
|
||||
setElem(target, b, getElem(target, a));
|
||||
}
|
||||
setElem(target, a, pivot);
|
||||
if (i - lo < hi - i) {
|
||||
qsort_extended(cx, jsCompare, target, lo, i - 1);
|
||||
lo = i + 1;
|
||||
} else {
|
||||
qsort_extended(cx, jsCompare, target, i + 1, hi);
|
||||
hi = i - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-ECMA methods.
|
||||
*/
|
||||
|
||||
public static Object jsFunction_push(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
double length = getLengthProperty(thisObj);
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
setElem(thisObj, (long)length + i, args[i]);
|
||||
}
|
||||
|
||||
length += args.length;
|
||||
ScriptRuntime.setProp(thisObj, "length", new Double(length), thisObj);
|
||||
|
||||
/*
|
||||
* If JS1.2, follow Perl4 by returning the last thing pushed.
|
||||
* Otherwise, return the new array length.
|
||||
*/
|
||||
if (cx.getLanguageVersion() == Context.VERSION_1_2)
|
||||
// if JS1.2 && no arguments, return undefined.
|
||||
return args.length == 0
|
||||
? Context.getUndefinedValue()
|
||||
: args[args.length - 1];
|
||||
|
||||
else
|
||||
return new Long((long)length);
|
||||
}
|
||||
|
||||
public static Object jsFunction_pop(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
Object result;
|
||||
double length = getLengthProperty(thisObj);
|
||||
if (length > 0) {
|
||||
length--;
|
||||
|
||||
// Get the to-be-deleted property's value.
|
||||
result = getElem(thisObj, (long)length);
|
||||
|
||||
// We don't need to delete the last property, because
|
||||
// setLength does that for us.
|
||||
} else {
|
||||
result = Context.getUndefinedValue();
|
||||
}
|
||||
// necessary to match js even when length < 0; js pop will give a
|
||||
// length property to any target it is called on.
|
||||
ScriptRuntime.setProp(thisObj, "length", new Double(length), thisObj);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Object jsFunction_shift(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funOjb)
|
||||
{
|
||||
Object result;
|
||||
double length = getLengthProperty(thisObj);
|
||||
if (length > 0) {
|
||||
long i = 0;
|
||||
length--;
|
||||
|
||||
// Get the to-be-deleted property's value.
|
||||
result = getElem(thisObj, i);
|
||||
|
||||
/*
|
||||
* Slide down the array above the first element. Leave i
|
||||
* set to point to the last element.
|
||||
*/
|
||||
if (length > 0) {
|
||||
for (i = 1; i <= length; i++) {
|
||||
Object temp = getElem(thisObj, i);
|
||||
setElem(thisObj, i - 1, temp);
|
||||
}
|
||||
}
|
||||
// We don't need to delete the last property, because
|
||||
// setLength does that for us.
|
||||
} else {
|
||||
result = Context.getUndefinedValue();
|
||||
}
|
||||
ScriptRuntime.setProp(thisObj, "length", new Double(length), thisObj);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Object jsFunction_unshift(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funOjb)
|
||||
{
|
||||
Object result;
|
||||
double length = (double)getLengthProperty(thisObj);
|
||||
int argc = args.length;
|
||||
|
||||
if (args.length > 0) {
|
||||
/* Slide up the array to make room for args at the bottom */
|
||||
if (length > 0) {
|
||||
for (long last = (long)length - 1; last >= 0; last--) {
|
||||
Object temp = getElem(thisObj, last);
|
||||
setElem(thisObj, last + argc, temp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy from argv to the bottom of the array. */
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
setElem(thisObj, i, args[i]);
|
||||
}
|
||||
|
||||
/* Follow Perl by returning the new array length. */
|
||||
length += args.length;
|
||||
ScriptRuntime.setProp(thisObj, "length",
|
||||
new Double(length), thisObj);
|
||||
}
|
||||
return new Long((long)length);
|
||||
}
|
||||
|
||||
public static Object jsFunction_splice(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
/* create an empty Array to return. */
|
||||
Scriptable scope = getTopLevelScope(funObj);
|
||||
Object result = ScriptRuntime.newObject(cx, scope, "Array", null);
|
||||
int argc = args.length;
|
||||
if (argc == 0)
|
||||
return result;
|
||||
double length = getLengthProperty(thisObj);
|
||||
|
||||
/* Convert the first argument into a starting index. */
|
||||
double begin = ScriptRuntime.toInteger(args[0]);
|
||||
double end;
|
||||
double delta;
|
||||
double count;
|
||||
|
||||
if (begin < 0) {
|
||||
begin += length;
|
||||
if (begin < 0)
|
||||
begin = 0;
|
||||
} else if (begin > length) {
|
||||
begin = length;
|
||||
}
|
||||
argc--;
|
||||
|
||||
/* Convert the second argument from a count into a fencepost index. */
|
||||
delta = length - begin;
|
||||
|
||||
if (args.length == 1) {
|
||||
count = delta;
|
||||
end = length;
|
||||
} else {
|
||||
count = ScriptRuntime.toInteger(args[1]);
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
else if (count > delta)
|
||||
count = delta;
|
||||
end = begin + count;
|
||||
|
||||
argc--;
|
||||
}
|
||||
|
||||
long lbegin = (long)begin;
|
||||
long lend = (long)end;
|
||||
|
||||
/* If there are elements to remove, put them into the return value. */
|
||||
if (count > 0) {
|
||||
if (count == 1
|
||||
&& (cx.getLanguageVersion() == Context.VERSION_1_2))
|
||||
{
|
||||
/*
|
||||
* JS lacks "list context", whereby in Perl one turns the
|
||||
* single scalar that's spliced out into an array just by
|
||||
* assigning it to @single instead of $single, or by using it
|
||||
* as Perl push's first argument, for instance.
|
||||
*
|
||||
* JS1.2 emulated Perl too closely and returned a non-Array for
|
||||
* the single-splice-out case, requiring callers to test and
|
||||
* wrap in [] if necessary. So JS1.3, default, and other
|
||||
* versions all return an array of length 1 for uniformity.
|
||||
*/
|
||||
result = getElem(thisObj, lbegin);
|
||||
} else {
|
||||
for (long last = lbegin; last < lend; last++) {
|
||||
Scriptable resultArray = (Scriptable)result;
|
||||
Object temp = getElem(thisObj, last);
|
||||
setElem(resultArray, last - lbegin, temp);
|
||||
}
|
||||
}
|
||||
} else if (count == 0
|
||||
&& cx.getLanguageVersion() == Context.VERSION_1_2)
|
||||
{
|
||||
/* Emulate C JS1.2; if no elements are removed, return undefined. */
|
||||
result = Context.getUndefinedValue();
|
||||
}
|
||||
|
||||
/* Find the direction (up or down) to copy and make way for argv. */
|
||||
delta = argc - count;
|
||||
|
||||
if (delta > 0) {
|
||||
for (long last = (long)length - 1; last >= lend; last--) {
|
||||
Object temp = getElem(thisObj, last);
|
||||
setElem(thisObj, last + (long)delta, temp);
|
||||
}
|
||||
} else if (delta < 0) {
|
||||
for (long last = lend; last < length; last++) {
|
||||
Object temp = getElem(thisObj, last);
|
||||
setElem(thisObj, last + (long)delta, temp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy from argv into the hole to complete the splice. */
|
||||
int argoffset = args.length - argc;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
setElem(thisObj, lbegin + i, args[i + argoffset]);
|
||||
}
|
||||
|
||||
/* Update length in case we deleted elements from the end. */
|
||||
ScriptRuntime.setProp(thisObj, "length",
|
||||
new Double(length + delta), thisObj);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Python-esque sequence operations.
|
||||
*/
|
||||
public static Scriptable jsFunction_concat(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
/* Concat tries to keep the definition of an array as general
|
||||
* as possible; if it finds that an object has a numeric
|
||||
* 'length' property, then it treats that object as an array.
|
||||
* This treats string atoms and string objects differently; as
|
||||
* string objects have a length property and are accessible by
|
||||
* index, they get exploded into arrays when added, while
|
||||
* atomic strings are just added as strings.
|
||||
*/
|
||||
|
||||
// create an empty Array to return.
|
||||
Scriptable scope = getTopLevelScope(funObj);
|
||||
Scriptable result = ScriptRuntime.newObject(cx, scope, "Array", null);
|
||||
double length;
|
||||
long slot = 0;
|
||||
|
||||
/* Put the target in the result array; only add it as an array
|
||||
* if it looks like one.
|
||||
*/
|
||||
if (hasLengthProperty(thisObj)) {
|
||||
length = getLengthProperty(thisObj);
|
||||
|
||||
// Copy from the target object into the result
|
||||
for (slot = 0; slot < length; slot++) {
|
||||
Object temp = getElem(thisObj, slot);
|
||||
setElem(result, slot, temp);
|
||||
}
|
||||
} else {
|
||||
setElem(result, slot++, thisObj);
|
||||
}
|
||||
|
||||
/* Copy from the arguments into the result. If any argument
|
||||
* has a numeric length property, treat it as an array and add
|
||||
* elements separately; otherwise, just copy the argument.
|
||||
*/
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (hasLengthProperty(args[i])) {
|
||||
// hasLengthProperty => instanceOf Scriptable.
|
||||
Scriptable arg = (Scriptable)args[i];
|
||||
length = getLengthProperty(arg);
|
||||
for (long j = 0; j < length; j++, slot++) {
|
||||
Object temp = getElem(arg, j);
|
||||
setElem(result, slot, temp);
|
||||
}
|
||||
} else {
|
||||
setElem(result, slot++, args[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Scriptable jsFunction_slice(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
Scriptable scope = getTopLevelScope(funObj);
|
||||
Scriptable result = ScriptRuntime.newObject(cx, scope, "Array", null);
|
||||
double length = getLengthProperty(thisObj);
|
||||
|
||||
double begin = 0;
|
||||
double end = length;
|
||||
|
||||
if (args.length > 0) {
|
||||
begin = ScriptRuntime.toInteger(args[0]);
|
||||
if (begin < 0) {
|
||||
begin += length;
|
||||
if (begin < 0)
|
||||
begin = 0;
|
||||
} else if (begin > length) {
|
||||
begin = length;
|
||||
}
|
||||
|
||||
if (args.length > 1) {
|
||||
end = ScriptRuntime.toInteger(args[1]);
|
||||
if (end < 0) {
|
||||
end += length;
|
||||
if (end < 0)
|
||||
end = 0;
|
||||
} else if (end > length) {
|
||||
end = length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long lbegin = (long)begin;
|
||||
long lend = (long)end;
|
||||
for (long slot = lbegin; slot < lend; slot++) {
|
||||
Object temp = getElem(thisObj, slot);
|
||||
setElem(result, slot - lbegin, temp);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private long length;
|
||||
private Object[] dense;
|
||||
private static final int maximumDenseLength = 10000;
|
||||
}
|
||||
92
mozilla/js/rhino/org/mozilla/javascript/NativeBoolean.java
Normal file
92
mozilla/js/rhino/org/mozilla/javascript/NativeBoolean.java
Normal file
@@ -0,0 +1,92 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
* Mike McCabe
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* This class implements the Boolean native object.
|
||||
* See ECMA 15.6.
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public class NativeBoolean extends ScriptableObject {
|
||||
|
||||
/**
|
||||
* Zero-parameter constructor: just used to create Boolean.prototype
|
||||
*/
|
||||
public NativeBoolean() {
|
||||
}
|
||||
|
||||
public NativeBoolean(boolean b) {
|
||||
booleanValue = b;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "Boolean";
|
||||
}
|
||||
|
||||
public Object getDefaultValue(Class typeHint) {
|
||||
// This is actually non-ECMA, but will be proposed
|
||||
// as a change in round 2.
|
||||
if (typeHint == ScriptRuntime.BooleanClass)
|
||||
return booleanValue ? Boolean.TRUE : Boolean.FALSE;
|
||||
return super.getDefaultValue(typeHint);
|
||||
}
|
||||
|
||||
public static Object jsConstructor(Context cx, Object[] args,
|
||||
Function ctorObj, boolean inNewExpr)
|
||||
{
|
||||
boolean b = args.length >= 1
|
||||
? ScriptRuntime.toBoolean(args[0])
|
||||
: false;
|
||||
if (inNewExpr) {
|
||||
// new Boolean(val) creates a new boolean object.
|
||||
return new NativeBoolean(b);
|
||||
}
|
||||
|
||||
// Boolean(val) converts val to a boolean.
|
||||
return b ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
|
||||
public String jsFunction_toString() {
|
||||
return booleanValue ? "true" : "false";
|
||||
}
|
||||
|
||||
public boolean jsFunction_valueOf() {
|
||||
return booleanValue;
|
||||
}
|
||||
|
||||
private boolean booleanValue;
|
||||
}
|
||||
135
mozilla/js/rhino/org/mozilla/javascript/NativeCall.java
Normal file
135
mozilla/js/rhino/org/mozilla/javascript/NativeCall.java
Normal file
@@ -0,0 +1,135 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* This class implements the activation object.
|
||||
*
|
||||
* See ECMA 10.1.6
|
||||
*
|
||||
* @see org.mozilla.javascript.Arguments
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public final class NativeCall extends ScriptableObject {
|
||||
|
||||
NativeCall(Context cx, Scriptable scope, NativeFunction funObj,
|
||||
Scriptable thisObj, Object[] args)
|
||||
{
|
||||
this(cx, scope, funObj, thisObj);
|
||||
this.originalArgs = args;
|
||||
|
||||
// initialize values of arguments
|
||||
String[] names = funObj.names;
|
||||
if (names != null) {
|
||||
for (int i=0; i < funObj.argCount; i++) {
|
||||
Object val = i < args.length ? args[i]
|
||||
: Undefined.instance;
|
||||
super.put(names[i+1], this, val);
|
||||
}
|
||||
}
|
||||
|
||||
// initialize "arguments" property
|
||||
super.put("arguments", this, new Arguments(this));
|
||||
}
|
||||
|
||||
NativeCall(Context cx, Scriptable scope, NativeFunction funObj,
|
||||
Scriptable thisObj)
|
||||
{
|
||||
this.funObj = funObj;
|
||||
this.thisObj = thisObj;
|
||||
|
||||
setParentScope(scope);
|
||||
// leave prototype null
|
||||
|
||||
// save current activation
|
||||
this.caller = cx.currentActivation;
|
||||
cx.currentActivation = this;
|
||||
}
|
||||
|
||||
// Needed in order to use this class with ScriptableObject.defineClass
|
||||
public NativeCall() {
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "Call";
|
||||
}
|
||||
|
||||
public static Object jsConstructor(Context cx, Object[] args,
|
||||
Function ctorObj, boolean inNewExpr)
|
||||
{
|
||||
if (!inNewExpr) {
|
||||
Object[] errArgs = { "Call" };
|
||||
throw Context.reportRuntimeError(Context.getMessage
|
||||
("msg.only.from.new", errArgs));
|
||||
}
|
||||
ScriptRuntime.checkDeprecated(cx, "Call");
|
||||
NativeCall result = new NativeCall();
|
||||
result.setPrototype(getObjectPrototype(ctorObj));
|
||||
return result;
|
||||
}
|
||||
|
||||
NativeCall getActivation(NativeFunction f) {
|
||||
NativeCall x = this;
|
||||
do {
|
||||
if (x.funObj == f)
|
||||
return x;
|
||||
x = x.caller;
|
||||
} while (x != null);
|
||||
return null;
|
||||
}
|
||||
|
||||
public NativeFunction getFunctionObject() {
|
||||
return funObj;
|
||||
}
|
||||
|
||||
public Object[] getOriginalArguments() {
|
||||
return originalArgs;
|
||||
}
|
||||
|
||||
public NativeCall getCaller() {
|
||||
return caller;
|
||||
}
|
||||
|
||||
public Scriptable getThisObj() {
|
||||
return thisObj;
|
||||
}
|
||||
|
||||
NativeCall caller;
|
||||
NativeFunction funObj;
|
||||
Scriptable thisObj;
|
||||
Object[] originalArgs;
|
||||
public int debugPC;
|
||||
}
|
||||
1441
mozilla/js/rhino/org/mozilla/javascript/NativeDate.java
Normal file
1441
mozilla/js/rhino/org/mozilla/javascript/NativeDate.java
Normal file
File diff suppressed because it is too large
Load Diff
82
mozilla/js/rhino/org/mozilla/javascript/NativeError.java
Normal file
82
mozilla/js/rhino/org/mozilla/javascript/NativeError.java
Normal file
@@ -0,0 +1,82 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Roger Lawrence
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
*
|
||||
* The class of error objects
|
||||
*
|
||||
* ECMA 15.11
|
||||
*/
|
||||
public class NativeError extends ScriptableObject {
|
||||
|
||||
public NativeError() {
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "Error";
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName() + ": " + getMessage();
|
||||
}
|
||||
|
||||
public String jsFunction_toString() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return ScriptRuntime.toString(
|
||||
ScriptRuntime.getProp(this, "name", this));
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return ScriptRuntime.toString(
|
||||
ScriptRuntime.getProp(this, "message", this));
|
||||
}
|
||||
|
||||
public static void finishInit(Scriptable scope, FunctionObject ctor,
|
||||
Scriptable proto)
|
||||
throws PropertyException
|
||||
{
|
||||
((ScriptableObject) proto).defineProperty("message", "",
|
||||
ScriptableObject.EMPTY);
|
||||
((ScriptableObject) proto).defineProperty("name", "Error",
|
||||
ScriptableObject.EMPTY);
|
||||
}
|
||||
|
||||
}
|
||||
1037
mozilla/js/rhino/org/mozilla/javascript/NativeFunction.java
Normal file
1037
mozilla/js/rhino/org/mozilla/javascript/NativeFunction.java
Normal file
File diff suppressed because it is too large
Load Diff
758
mozilla/js/rhino/org/mozilla/javascript/NativeGlobal.java
Normal file
758
mozilla/js/rhino/org/mozilla/javascript/NativeGlobal.java
Normal file
@@ -0,0 +1,758 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
* Mike McCabe
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* This class implements the global native object (function and value
|
||||
* properties only).
|
||||
*
|
||||
* See ECMA 15.1.[12].
|
||||
*
|
||||
* @author Mike Shaver
|
||||
*/
|
||||
|
||||
public class NativeGlobal {
|
||||
|
||||
public static void init(Scriptable scope)
|
||||
throws PropertyException,
|
||||
NotAFunctionException,
|
||||
JavaScriptException
|
||||
{
|
||||
|
||||
String names[] = { "eval",
|
||||
"parseInt",
|
||||
"parseFloat",
|
||||
"escape",
|
||||
"unescape",
|
||||
"isNaN",
|
||||
"isFinite",
|
||||
"decodeURI",
|
||||
"decodeURIComponent",
|
||||
"encodeURI",
|
||||
"encodeURIComponent"
|
||||
};
|
||||
|
||||
// We can downcast here because Context.initStandardObjects
|
||||
// takes a ScriptableObject scope.
|
||||
ScriptableObject global = (ScriptableObject) scope;
|
||||
global.defineFunctionProperties(names, NativeGlobal.class,
|
||||
ScriptableObject.DONTENUM);
|
||||
|
||||
global.defineProperty("NaN", ScriptRuntime.NaNobj,
|
||||
ScriptableObject.DONTENUM);
|
||||
global.defineProperty("Infinity", new Double(Double.POSITIVE_INFINITY),
|
||||
ScriptableObject.DONTENUM);
|
||||
global.defineProperty("undefined", Undefined.instance,
|
||||
ScriptableObject.DONTENUM);
|
||||
|
||||
String[] errorMethods = { "ConversionError",
|
||||
"EvalError",
|
||||
"RangeError",
|
||||
"ReferenceError",
|
||||
"SyntaxError",
|
||||
"TypeError",
|
||||
"URIError"
|
||||
};
|
||||
Method[] m = FunctionObject.findMethods(NativeGlobal.class,
|
||||
"CommonError");
|
||||
Context cx = Context.getContext();
|
||||
/*
|
||||
Each error constructor gets its own Error object as a prototype,
|
||||
with the 'name' property set to the name of the error.
|
||||
*/
|
||||
for (int i = 0; i < errorMethods.length; i++) {
|
||||
String name = errorMethods[i];
|
||||
FunctionObject ctor = new FunctionObject(name, m[0], global);
|
||||
global.defineProperty(name, ctor, ScriptableObject.DONTENUM);
|
||||
Scriptable errorProto = cx.newObject(scope, "Error");
|
||||
errorProto.put("name", errorProto, name);
|
||||
ctor.put("prototype", ctor, errorProto);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The global method parseInt, as per ECMA-262 15.1.2.2.
|
||||
*/
|
||||
public static Object parseInt(String s, int radix) {
|
||||
int len = s.length();
|
||||
if (len == 0)
|
||||
return ScriptRuntime.NaNobj;
|
||||
|
||||
boolean negative = false;
|
||||
int start = 0;
|
||||
char c;
|
||||
do {
|
||||
c = s.charAt(start);
|
||||
if (!Character.isWhitespace(c))
|
||||
break;
|
||||
start++;
|
||||
} while (start < len);
|
||||
|
||||
if (c == '+' || (negative = (c == '-')))
|
||||
start++;
|
||||
|
||||
final int NO_RADIX = -1;
|
||||
if (radix == 0) {
|
||||
radix = NO_RADIX;
|
||||
} else if (radix < 2 || radix > 36) {
|
||||
return ScriptRuntime.NaNobj;
|
||||
} else if (radix == 16 && len - start > 1 &&
|
||||
s.charAt(start) == '0')
|
||||
{
|
||||
c = s.charAt(start+1);
|
||||
if (c == 'x' || c == 'X')
|
||||
start += 2;
|
||||
}
|
||||
|
||||
if (radix == NO_RADIX) {
|
||||
radix = 10;
|
||||
if (len - start > 1 && s.charAt(start) == '0') {
|
||||
c = s.charAt(start+1);
|
||||
if (c == 'x' || c == 'X') {
|
||||
radix = 16;
|
||||
start += 2;
|
||||
} else if (c != '.') {
|
||||
radix = 8;
|
||||
start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double d = ScriptRuntime.stringToNumber(s, start, radix);
|
||||
return new Double(negative ? -d : d);
|
||||
}
|
||||
|
||||
/**
|
||||
* The global method parseFloat, as per ECMA-262 15.1.2.3.
|
||||
*
|
||||
* @param cx unused
|
||||
* @param thisObj unused
|
||||
* @param args the arguments to parseFloat, ignoring args[>=1]
|
||||
* @param funObj unused
|
||||
*/
|
||||
public static Object parseFloat(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
if (args.length < 1)
|
||||
return ScriptRuntime.NaNobj;
|
||||
String s = ScriptRuntime.toString(args[0]);
|
||||
int len = s.length();
|
||||
if (len == 0)
|
||||
return ScriptRuntime.NaNobj;
|
||||
|
||||
int i;
|
||||
char c;
|
||||
// Scan forward to the first digit or .
|
||||
for (i=0; TokenStream.isJSSpace(c = s.charAt(i)) && i+1 < len; i++)
|
||||
/* empty */
|
||||
;
|
||||
|
||||
int start = i;
|
||||
|
||||
if (c == '+' || c == '-')
|
||||
c = s.charAt(++i);
|
||||
|
||||
if (c == 'I') {
|
||||
// check for "Infinity"
|
||||
double d;
|
||||
if (i+8 <= len && s.substring(i, i+8).equals("Infinity"))
|
||||
d = s.charAt(start) == '-' ? Double.NEGATIVE_INFINITY
|
||||
: Double.POSITIVE_INFINITY;
|
||||
else
|
||||
return ScriptRuntime.NaNobj;
|
||||
return new Double(d);
|
||||
}
|
||||
|
||||
// Find the end of the legal bit
|
||||
int decimal = -1;
|
||||
int exponent = -1;
|
||||
for (; i < len; i++) {
|
||||
switch (s.charAt(i)) {
|
||||
case '.':
|
||||
if (decimal != -1) // Only allow a single decimal point.
|
||||
break;
|
||||
decimal = i;
|
||||
continue;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
if (exponent != -1)
|
||||
break;
|
||||
exponent = i;
|
||||
continue;
|
||||
|
||||
case '+':
|
||||
case '-':
|
||||
// Only allow '+' or '-' after 'e' or 'E'
|
||||
if (exponent != i-1)
|
||||
break;
|
||||
continue;
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
s = s.substring(start, i);
|
||||
try {
|
||||
return Double.valueOf(s);
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
return ScriptRuntime.NaNobj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The global method escape, as per ECMA-262 15.1.2.4.
|
||||
|
||||
* Includes code for the 'mask' argument supported by the C escape
|
||||
* method, which used to be part of the browser imbedding. Blame
|
||||
* for the strange constant names should be directed there.
|
||||
*/
|
||||
private static int
|
||||
URL_XALPHAS = 1,
|
||||
URL_XPALPHAS = 2,
|
||||
URL_PATH = 4;
|
||||
|
||||
public static Object escape(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
char digits[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
if (args.length < 1)
|
||||
args = ScriptRuntime.padArguments(args, 1);
|
||||
|
||||
String s = ScriptRuntime.toString(args[0]);
|
||||
|
||||
int mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;
|
||||
if (args.length > 1) { // the 'mask' argument. Non-ECMA.
|
||||
double d = ScriptRuntime.toNumber(args[1]);
|
||||
if (d != d || ((mask = (int) d) != d) ||
|
||||
0 != (mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH)))
|
||||
{
|
||||
String message = Context.getMessage
|
||||
("msg.bad.esc.mask", null);
|
||||
cx.reportError(message);
|
||||
// do the ecma thing, in case reportError returns.
|
||||
mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;
|
||||
}
|
||||
}
|
||||
|
||||
StringBuffer R = new StringBuffer();
|
||||
for (int k = 0; k < s.length(); k++) {
|
||||
char c = s.charAt(k);
|
||||
if (mask != 0 &&
|
||||
((c >= '0' && c <= '9') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
c == '@' || c == '*' || c == '_' ||
|
||||
c == '-' || c == '.' ||
|
||||
((c == '/' || c == '+') && mask > 3)))
|
||||
R.append(c);
|
||||
else if (c < 256) {
|
||||
if (c == ' ' && mask == URL_XPALPHAS) {
|
||||
R.append('+');
|
||||
} else {
|
||||
R.append('%');
|
||||
R.append(digits[c >> 4]);
|
||||
R.append(digits[c & 0xF]);
|
||||
}
|
||||
} else {
|
||||
R.append('%');
|
||||
R.append('u');
|
||||
R.append(digits[c >> 12]);
|
||||
R.append(digits[(c & 0xF00) >> 8]);
|
||||
R.append(digits[(c & 0xF0) >> 4]);
|
||||
R.append(digits[c & 0xF]);
|
||||
}
|
||||
}
|
||||
return R.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* The global unescape method, as per ECMA-262 15.1.2.5.
|
||||
*/
|
||||
|
||||
public static Object unescape(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
if (args.length < 1)
|
||||
args = ScriptRuntime.padArguments(args, 1);
|
||||
|
||||
String s = ScriptRuntime.toString(args[0]);
|
||||
StringBuffer R = new StringBuffer();
|
||||
stringIter: for (int k = 0; k < s.length(); k++) {
|
||||
char c = s.charAt(k);
|
||||
if (c != '%' || k == s.length() -1) {
|
||||
R.append(c);
|
||||
continue;
|
||||
}
|
||||
String hex;
|
||||
int end, start;
|
||||
if (s.charAt(k+1) == 'u') {
|
||||
start = k+2;
|
||||
end = k+6;
|
||||
} else {
|
||||
start = k+1;
|
||||
end = k+3;
|
||||
}
|
||||
if (end > s.length()) {
|
||||
R.append('%');
|
||||
continue;
|
||||
}
|
||||
hex = s.substring(start, end);
|
||||
for (int i = 0; i < hex.length(); i++)
|
||||
if (!TokenStream.isXDigit(hex.charAt(i))) {
|
||||
R.append('%');
|
||||
continue stringIter;
|
||||
}
|
||||
k = end - 1;
|
||||
R.append((new Character((char) Integer.valueOf(hex, 16).intValue())));
|
||||
}
|
||||
|
||||
return R.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* The global method isNaN, as per ECMA-262 15.1.2.6.
|
||||
*/
|
||||
|
||||
public static Object isNaN(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
if (args.length < 1)
|
||||
return Boolean.TRUE;
|
||||
double d = ScriptRuntime.toNumber(args[0]);
|
||||
return (d != d) ? Boolean.TRUE : Boolean.FALSE;
|
||||
}
|
||||
|
||||
public static Object isFinite(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
if (args.length < 1)
|
||||
return Boolean.FALSE;
|
||||
double d = ScriptRuntime.toNumber(args[0]);
|
||||
return (d != d || d == Double.POSITIVE_INFINITY ||
|
||||
d == Double.NEGATIVE_INFINITY)
|
||||
? Boolean.FALSE
|
||||
: Boolean.TRUE;
|
||||
}
|
||||
|
||||
public static Object eval(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
throws JavaScriptException
|
||||
{
|
||||
Object[] a = { "eval" };
|
||||
String m = ScriptRuntime.getMessage("msg.cant.call.indirect", a);
|
||||
throw NativeGlobal.constructError(cx, "EvalError", m, funObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* The eval function property of the global object.
|
||||
*
|
||||
* See ECMA 15.1.2.1
|
||||
*/
|
||||
public static Object evalSpecial(Context cx, Scriptable scope,
|
||||
Object thisArg, Object[] args,
|
||||
String filename, int lineNumber)
|
||||
throws JavaScriptException
|
||||
{
|
||||
if (args.length < 1)
|
||||
return Undefined.instance;
|
||||
Object x = args[0];
|
||||
if (!(x instanceof String)) {
|
||||
String message = Context.getMessage("msg.eval.nonstring", null);
|
||||
Context.reportWarning(message);
|
||||
return x;
|
||||
}
|
||||
int[] linep = { lineNumber };
|
||||
if (filename == null) {
|
||||
filename = Context.getSourcePositionFromStack(linep);
|
||||
if (filename == null) {
|
||||
filename = "<eval'ed string>";
|
||||
linep[0] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
StringReader in = new StringReader((String) x);
|
||||
Object securityDomain = cx.getSecurityDomainForStackDepth(3);
|
||||
|
||||
// Compile the reader with opt level of -1 to force interpreter
|
||||
// mode.
|
||||
int oldOptLevel = cx.getOptimizationLevel();
|
||||
cx.setOptimizationLevel(-1);
|
||||
Script script = cx.compileReader(scope, in, filename, linep[0],
|
||||
securityDomain);
|
||||
cx.setOptimizationLevel(oldOptLevel);
|
||||
|
||||
// if the compile fails, an error has been reported by the
|
||||
// compiler, but we need to stop execution to avoid
|
||||
// infinite looping on while(true) { eval('foo bar') } -
|
||||
// so we throw an EvaluatorException.
|
||||
if (script == null) {
|
||||
String message = Context.getMessage("msg.syntax", null);
|
||||
throw new EvaluatorException(message);
|
||||
}
|
||||
|
||||
InterpretedScript is = (InterpretedScript) script;
|
||||
is.itsData.itsFromEvalCode = true;
|
||||
Object result = is.call(cx, scope, (Scriptable) thisArg, null);
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
// should never happen since we just made the Reader from a String
|
||||
throw new RuntimeException("unexpected io exception");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The NativeError functions
|
||||
*
|
||||
* See ECMA 15.11.6
|
||||
*/
|
||||
public static EcmaError constructError(Context cx,
|
||||
String error,
|
||||
String message,
|
||||
Object scope)
|
||||
{
|
||||
int[] linep = { 0 };
|
||||
String filename = cx.getSourcePositionFromStack(linep);
|
||||
return constructError(cx, error, message, scope,
|
||||
filename, linep[0], 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* The NativeError functions
|
||||
*
|
||||
* See ECMA 15.11.6
|
||||
*/
|
||||
public static EcmaError constructError(Context cx,
|
||||
String error,
|
||||
String message,
|
||||
Object scope,
|
||||
String sourceName,
|
||||
int lineNumber,
|
||||
int columnNumber,
|
||||
String lineSource)
|
||||
{
|
||||
Scriptable scopeObject;
|
||||
try {
|
||||
scopeObject = (Scriptable) scope;
|
||||
}
|
||||
catch (ClassCastException x) {
|
||||
throw new RuntimeException(x.toString());
|
||||
}
|
||||
|
||||
Object args[] = { message };
|
||||
try {
|
||||
Object errorObject = cx.newObject(scopeObject, error, args);
|
||||
return new EcmaError((NativeError)errorObject, sourceName,
|
||||
lineNumber, columnNumber, lineSource);
|
||||
}
|
||||
catch (PropertyException x) {
|
||||
throw new RuntimeException(x.toString());
|
||||
}
|
||||
catch (JavaScriptException x) {
|
||||
throw new RuntimeException(x.toString());
|
||||
}
|
||||
catch (NotAFunctionException x) {
|
||||
throw new RuntimeException(x.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The implementation of all the ECMA error constructors (SyntaxError,
|
||||
* TypeError, etc.)
|
||||
*/
|
||||
public static Object CommonError(Context cx, Object[] args,
|
||||
Function ctorObj, boolean inNewExpr)
|
||||
{
|
||||
Scriptable newInstance = new NativeError();
|
||||
newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
|
||||
newInstance.setParentScope(cx.ctorScope);
|
||||
if (args.length > 0)
|
||||
newInstance.put("message", newInstance, args[0]);
|
||||
return newInstance;
|
||||
}
|
||||
|
||||
/*
|
||||
* ECMA 3, 15.1.3 URI Handling Function Properties
|
||||
*
|
||||
* The following are implementations of the algorithms
|
||||
* given in the ECMA specification for the hidden functions
|
||||
* 'Encode' and 'Decode'.
|
||||
*/
|
||||
private static String encode(Context cx, String str, String unescapedSet)
|
||||
{
|
||||
int j, k = 0, L;
|
||||
char C, C2;
|
||||
int V;
|
||||
char utf8buf[] = new char[6];
|
||||
StringBuffer R;
|
||||
|
||||
R = new StringBuffer();
|
||||
|
||||
while (k < str.length()) {
|
||||
C = str.charAt(k);
|
||||
if (unescapedSet.indexOf(C) != -1) {
|
||||
R.append(C);
|
||||
} else {
|
||||
if ((C >= 0xDC00) && (C <= 0xDFFF)) {
|
||||
throw cx.reportRuntimeError(
|
||||
cx.getMessage("msg.bad.uri", null));
|
||||
}
|
||||
if ((C < 0xD800) || (C > 0xDBFF))
|
||||
V = C;
|
||||
else {
|
||||
k++;
|
||||
if (k == str.length()) {
|
||||
throw cx.reportRuntimeError(
|
||||
cx.getMessage("msg.bad.uri", null));
|
||||
}
|
||||
C2 = str.charAt(k);
|
||||
if ((C2 < 0xDC00) || (C2 > 0xDFFF)) {
|
||||
throw cx.reportRuntimeError(
|
||||
cx.getMessage("msg.bad.uri", null));
|
||||
}
|
||||
V = ((C - 0xD800) << 10) + (C2 - 0xDC00) + 0x10000;
|
||||
}
|
||||
L = oneUcs4ToUtf8Char(utf8buf, V);
|
||||
for (j = 0; j < L; j++) {
|
||||
R.append('%');
|
||||
if (utf8buf[j] < 16)
|
||||
R.append('0');
|
||||
R.append(Integer.toHexString(utf8buf[j]));
|
||||
}
|
||||
}
|
||||
k++;
|
||||
}
|
||||
return R.toString();
|
||||
}
|
||||
|
||||
private static boolean isHex(char c) {
|
||||
return ((c >= '0' && c <= '9')
|
||||
|| (c >= 'a' && c <= 'f')
|
||||
|| (c >= 'A' && c <= 'F'));
|
||||
}
|
||||
|
||||
private static int unHex(char c) {
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
else
|
||||
if (c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
else
|
||||
return c - 'A' +10;
|
||||
}
|
||||
|
||||
private static String decode(Context cx, String str, String reservedSet)
|
||||
{
|
||||
int start, k = 0;
|
||||
char C, H;
|
||||
int V;
|
||||
int B;
|
||||
char[] octets = new char[6];
|
||||
StringBuffer R;
|
||||
int j, n;
|
||||
|
||||
R = new StringBuffer();
|
||||
|
||||
while (k < str.length()) {
|
||||
C = str.charAt(k);
|
||||
if (C == '%') {
|
||||
start = k;
|
||||
if ((k + 2) >= str.length())
|
||||
throw cx.reportRuntimeError(
|
||||
cx.getMessage("msg.bad.uri", null));
|
||||
if (!isHex(str.charAt(k + 1)) || !isHex(str.charAt(k + 2)))
|
||||
throw cx.reportRuntimeError(
|
||||
cx.getMessage("msg.bad.uri", null));
|
||||
B = unHex(str.charAt(k + 1)) * 16 + unHex(str.charAt(k + 2));
|
||||
k += 2;
|
||||
if ((B & 0x80) == 0)
|
||||
C = (char)B;
|
||||
else {
|
||||
n = 1;
|
||||
while ((B & (0x80 >>> n)) != 0) n++;
|
||||
if ((n == 1) || (n > 6))
|
||||
throw cx.reportRuntimeError(
|
||||
cx.getMessage("msg.bad.uri", null));
|
||||
octets[0] = (char)B;
|
||||
if ((k + 3 * (n - 1)) >= str.length())
|
||||
throw cx.reportRuntimeError(
|
||||
cx.getMessage("msg.bad.uri", null));
|
||||
for (j = 1; j < n; j++) {
|
||||
k++;
|
||||
if (str.charAt(k) != '%')
|
||||
throw cx.reportRuntimeError(
|
||||
cx.getMessage("msg.bad.uri", null));
|
||||
if (!isHex(str.charAt(k + 1))
|
||||
|| !isHex(str.charAt(k + 2)))
|
||||
throw cx.reportRuntimeError(
|
||||
cx.getMessage("msg.bad.uri", null));
|
||||
B = unHex(str.charAt(k + 1)) * 16
|
||||
+ unHex(str.charAt(k + 2));
|
||||
if ((B & 0xC0) != 0x80)
|
||||
throw cx.reportRuntimeError(
|
||||
cx.getMessage("msg.bad.uri", null));
|
||||
k += 2;
|
||||
octets[j] = (char)B;
|
||||
}
|
||||
V = utf8ToOneUcs4Char(octets, n);
|
||||
if (V >= 0x10000) {
|
||||
V -= 0x10000;
|
||||
if (V > 0xFFFFF)
|
||||
throw cx.reportRuntimeError(
|
||||
cx.getMessage("msg.bad.uri", null));
|
||||
C = (char)((V & 0x3FF) + 0xDC00);
|
||||
H = (char)((V >>> 10) + 0xD800);
|
||||
R.append(H);
|
||||
}
|
||||
else
|
||||
C = (char)V;
|
||||
}
|
||||
if (reservedSet.indexOf(C) != -1) {
|
||||
for (int x = 0; x < (k - start + 1); x++)
|
||||
R.append(str.charAt(start + x));
|
||||
}
|
||||
else
|
||||
R.append(C);
|
||||
}
|
||||
else
|
||||
R.append(C);
|
||||
k++;
|
||||
}
|
||||
return R.toString();
|
||||
}
|
||||
|
||||
private static String uriReservedPlusPound = ";/?:@&=+$,#";
|
||||
private static String uriUnescaped =
|
||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.!~*'()";
|
||||
|
||||
public static String decodeURI(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
String str = ScriptRuntime.toString(args[0]);
|
||||
return decode(cx, str, uriReservedPlusPound);
|
||||
}
|
||||
|
||||
public static String decodeURIComponent(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
String str = ScriptRuntime.toString(args[0]);
|
||||
return decode(cx, str, "");
|
||||
}
|
||||
|
||||
public static Object encodeURI(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
String str = ScriptRuntime.toString(args[0]);
|
||||
return encode(cx, str, uriReservedPlusPound + uriUnescaped);
|
||||
}
|
||||
|
||||
public static String encodeURIComponent(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
String str = ScriptRuntime.toString(args[0]);
|
||||
return encode(cx, str, uriUnescaped);
|
||||
}
|
||||
|
||||
/* Convert one UCS-4 char and write it into a UTF-8 buffer, which must be
|
||||
* at least 6 bytes long. Return the number of UTF-8 bytes of data written.
|
||||
*/
|
||||
private static int oneUcs4ToUtf8Char(char[] utf8Buffer, int ucs4Char)
|
||||
{
|
||||
int utf8Length = 1;
|
||||
|
||||
// JS_ASSERT(ucs4Char <= 0x7FFFFFFF);
|
||||
if ((ucs4Char < 0x80) && (ucs4Char >= 0))
|
||||
utf8Buffer[0] = (char)ucs4Char;
|
||||
else {
|
||||
int i;
|
||||
int a = ucs4Char >>> 11;
|
||||
utf8Length = 2;
|
||||
while (a != 0) {
|
||||
a >>>= 5;
|
||||
utf8Length++;
|
||||
}
|
||||
i = utf8Length;
|
||||
while (--i > 0) {
|
||||
utf8Buffer[i] = (char)((ucs4Char & 0x3F) | 0x80);
|
||||
ucs4Char >>>= 6;
|
||||
}
|
||||
utf8Buffer[0] = (char)(0x100 - (1 << (8-utf8Length)) + ucs4Char);
|
||||
}
|
||||
return utf8Length;
|
||||
}
|
||||
|
||||
|
||||
/* Convert a utf8 character sequence into a UCS-4 character and return that
|
||||
* character. It is assumed that the caller already checked that the sequence is valid.
|
||||
*/
|
||||
private static int utf8ToOneUcs4Char(char[] utf8Buffer, int utf8Length)
|
||||
{
|
||||
int ucs4Char;
|
||||
int k = 0;
|
||||
// JS_ASSERT(utf8Length >= 1 && utf8Length <= 6);
|
||||
if (utf8Length == 1) {
|
||||
ucs4Char = utf8Buffer[0];
|
||||
// JS_ASSERT(!(ucs4Char & 0x80));
|
||||
} else {
|
||||
// JS_ASSERT((*utf8Buffer & (0x100 - (1 << (7-utf8Length)))) == (0x100 - (1 << (8-utf8Length))));
|
||||
ucs4Char = utf8Buffer[k++] & ((1<<(7-utf8Length))-1);
|
||||
while (--utf8Length > 0) {
|
||||
// JS_ASSERT((*utf8Buffer & 0xC0) == 0x80);
|
||||
ucs4Char = ucs4Char<<6 | (utf8Buffer[k++] & 0x3F);
|
||||
}
|
||||
}
|
||||
return ucs4Char;
|
||||
}
|
||||
|
||||
}
|
||||
158
mozilla/js/rhino/org/mozilla/javascript/NativeJavaArray.java
Normal file
158
mozilla/js/rhino/org/mozilla/javascript/NativeJavaArray.java
Normal file
@@ -0,0 +1,158 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is Rhino code, released
|
||||
* May 6, 1999.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1997-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Norris Boyd
|
||||
* Frank Mitchell
|
||||
* Mike Shaver
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
/**
|
||||
* This class reflects Java arrays into the JavaScript environment.
|
||||
*
|
||||
* @author Mike Shaver
|
||||
* @see NativeJavaClass
|
||||
* @see NativeJavaObject
|
||||
* @see NativeJavaPackage
|
||||
*/
|
||||
|
||||
public class NativeJavaArray extends NativeJavaObject {
|
||||
|
||||
public String getClassName() {
|
||||
return "JavaArray";
|
||||
}
|
||||
|
||||
public static NativeJavaArray wrap(Scriptable scope, Object array) {
|
||||
return new NativeJavaArray(scope, array);
|
||||
}
|
||||
|
||||
public Object unwrap() {
|
||||
return array;
|
||||
}
|
||||
|
||||
public NativeJavaArray(Scriptable scope, Object array) {
|
||||
super(scope, null, ScriptRuntime.ObjectClass);
|
||||
Class cl = array.getClass();
|
||||
if (!cl.isArray()) {
|
||||
throw new RuntimeException("Array expected");
|
||||
}
|
||||
this.array = array;
|
||||
this.length = Array.getLength(array);
|
||||
this.cls = cl.getComponentType();
|
||||
}
|
||||
|
||||
public boolean has(String id, Scriptable start) {
|
||||
return id.equals("length") || super.has(id, start);
|
||||
}
|
||||
|
||||
public boolean has(int index, Scriptable start) {
|
||||
return 0 <= index && index < length;
|
||||
}
|
||||
|
||||
public Object get(String id, Scriptable start) {
|
||||
if (id.equals("length"))
|
||||
return new Integer(length);
|
||||
Object result = super.get(id, start);
|
||||
if (result == NOT_FOUND &&
|
||||
!ScriptRuntime.hasProp(getPrototype(), id))
|
||||
{
|
||||
Object errArgs[] = { array.getClass().getName(),
|
||||
id };
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.java.member.not.found",
|
||||
errArgs));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Object get(int index, Scriptable start) {
|
||||
if (0 <= index && index < length)
|
||||
return NativeJavaObject.wrap(this, Array.get(array, index), cls);
|
||||
return Undefined.instance;
|
||||
}
|
||||
|
||||
public void put(String id, Scriptable start, Object value) {
|
||||
// Ignore assignments to "length"--it's readonly.
|
||||
if (!id.equals("length"))
|
||||
super.put(id, start, value);
|
||||
}
|
||||
|
||||
public void put(int index, Scriptable start, Object value) {
|
||||
if (0 <= index && index < length) {
|
||||
Array.set(array, index, NativeJavaObject.coerceType(cls, value));
|
||||
return;
|
||||
}
|
||||
super.put(index, start, value);
|
||||
}
|
||||
|
||||
public Object getDefaultValue(Class hint) {
|
||||
if (hint == null || hint == ScriptRuntime.StringClass)
|
||||
return array.toString();
|
||||
if (hint == ScriptRuntime.BooleanClass)
|
||||
return Boolean.TRUE;
|
||||
if (hint == ScriptRuntime.NumberClass)
|
||||
return ScriptRuntime.NaNobj;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object[] getIds() {
|
||||
Object[] result = new Object[length];
|
||||
int i = length;
|
||||
while (--i >= 0)
|
||||
result[i] = new Integer(i);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean hasInstance(Scriptable value) {
|
||||
if (!(value instanceof NativeJavaObject))
|
||||
return false;
|
||||
Object instance = ((NativeJavaObject)value).unwrap();
|
||||
return cls.isInstance(instance);
|
||||
}
|
||||
|
||||
public Scriptable getPrototype() {
|
||||
if (prototype == null) {
|
||||
prototype =
|
||||
ScriptableObject.getClassPrototype(this.getParentScope(),
|
||||
"Array");
|
||||
}
|
||||
return prototype;
|
||||
}
|
||||
|
||||
Object array;
|
||||
int length;
|
||||
Class cls;
|
||||
Scriptable prototype;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user