Compare commits
10 Commits
NETSCAPE_7
...
EXP_DEBUGG
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4ffa41ca0 | ||
|
|
71eac19bd9 | ||
|
|
c91ef3e25d | ||
|
|
d912f6c544 | ||
|
|
f066ed34eb | ||
|
|
75c0a6d536 | ||
|
|
6374a47cb5 | ||
|
|
87a77bdb54 | ||
|
|
01bdc9a81a | ||
|
|
cf3aa1ee61 |
@@ -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,573 +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;
|
||||
|
||||
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_0_RTM
|
||||
mozilla/security/nss, NETSCAPE_7_0_RTM
|
||||
mozilla/security/manager, NETSCAPE_7_0_RTM
|
||||
mozilla/accessible, NETSCAPE_7_0_RTM
|
||||
mozilla/directory/c-sdk, NETSCAPE_7_0_RTM
|
||||
mozilla/lib/mac/Instrumentation, NETSCAPE_7_0_RTM
|
||||
mozilla/gfx2, NETSCAPE_7_0_RTM
|
||||
mozilla/modules/libpr0n, NETSCAPE_7_0_RTM
|
||||
SeaMonkeyAll, NETSCAPE_7_0_RTM
|
||||
|
||||
## 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,511 +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):
|
||||
|
||||
DEPTH=.
|
||||
|
||||
!if !defined(MOZ_TOP)
|
||||
#enable builds from changed top level directories
|
||||
MOZ_TOP=mozilla
|
||||
!endif
|
||||
|
||||
MOZ_SRC_FLIPPED = $(MOZ_SRC:\=/)
|
||||
MOZ_DIST_FLIPPED = $(MOZ_SRC_FLIPPED)/mozilla/dist
|
||||
!ifdef MOZ_DEBUG
|
||||
MOZ_OBJDIR = WIN32_D.OBJ
|
||||
!else
|
||||
MOZ_OBJDIR = WIN32_O.OBJ
|
||||
!endif
|
||||
|
||||
#
|
||||
# Command macro defines
|
||||
#
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to do the pull.
|
||||
#//------------------------------------------------------------------------
|
||||
# uncomment these, modify branch tag, and check in to branch for milestones
|
||||
MOZ_BRANCH=NETSCAPE_7_0_RTM
|
||||
NSPR_CO_TAG=NETSCAPE_7_0_RTM
|
||||
PSM_CO_TAG=NETSCAPE_7_0_RTM
|
||||
NSS_CO_TAG=NETSCAPE_7_0_RTM
|
||||
LDAPCSDK_CO_TAG=NETSCAPE_7_0_RTM
|
||||
ACCESSIBLE_CO_TAG=NETSCAPE_7_0_RTM
|
||||
IMGLIB2_CO_TAG=NETSCAPE_7_0_RTM
|
||||
GFX2_CO_TAG=NETSCAPE_7_0_RTM
|
||||
|
||||
|
||||
!ifdef MOZ_BRANCH
|
||||
CVS_BRANCH=-r $(MOZ_BRANCH)
|
||||
!endif
|
||||
|
||||
!ifdef MOZ_DATE
|
||||
CVS_BRANCH=$(CVS_BRANCH) -D "$(MOZ_DATE)"
|
||||
!endif
|
||||
|
||||
# default pull is "quiet" but it can be overridden with MOZ_CVS_VERBOSE
|
||||
!ifndef MOZ_CVS_VERBOSE
|
||||
CVS_FLAGS=-q
|
||||
!endif
|
||||
|
||||
# honor any user-defined CVS flags
|
||||
!ifdef MOZ_CVS_FLAGS
|
||||
CVS_FLAGS=$(CVS_FLAGS) $(MOZ_CVS_FLAGS)
|
||||
!endif
|
||||
|
||||
# let's be explicit about CVSROOT... some windows cvs clients
|
||||
# are too stupid to correctly work without the -d option
|
||||
#
|
||||
# if they are too stupid, they should fail. I am
|
||||
# commenting this out because this does not work
|
||||
# under 4nt. (%'s are evaluted differently)
|
||||
#
|
||||
# If it breaks you, mail dougt@netscape.com
|
||||
# and leaf@mozilla.org
|
||||
#
|
||||
!if 0
|
||||
!if defined(CVSROOT)
|
||||
CVS_FLAGS=$(CVS_FLAGS) -d "$(CVSROOT)"
|
||||
!endif
|
||||
!endif
|
||||
|
||||
!ifndef MOZ_CO_FLAGS
|
||||
MOZ_CO_FLAGS = -P
|
||||
!endif
|
||||
|
||||
CVSCO = cvs $(CVS_FLAGS) co $(MOZ_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull NSPR.
|
||||
#// If no NSPR_CO_TAG is specified, use the default static tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!ifndef NSPR_CO_FLAGS
|
||||
NSPR_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
NSPR_CO_FLAGS=$(NSPR_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
|
||||
CVSCO_NSPR = cvs $(CVS_FLAGS) co $(NSPR_CO_FLAGS)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull NSS and PSM libs.
|
||||
#// If no NSS_CO_TAG or PSM_CO_TAG is specified, use the default static tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!ifndef NSS_CO_FLAGS
|
||||
NSS_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
NSS_CO_FLAGS=$(NSS_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
CVSCO_NSS = cvs $(CVS_FLAGS) co $(NSS_CO_FLAGS)
|
||||
|
||||
!ifndef PSM_CO_FLAGS
|
||||
PSM_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
PSM_CO_FLAGS=$(PSM_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
CVSCO_PSM = cvs $(CVS_FLAGS) co $(PSM_CO_FLAGS)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull LDAP C SDK client libs.
|
||||
#// If no LDAPCSDK_CO_TAG is specified, use the default tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
|
||||
!ifndef LDAPCSDK_CO_FLAGS
|
||||
LDAPCSDK_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
LDAPCSDK_CO_FLAGS=$(LDAPCSDK_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
CVSCO_LDAPCSDK = cvs $(CVS_FLAGS) co $(LDAPCSDK_CO_FLAGS)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull accessibility libs.
|
||||
#// If no ACCESSIBLE_CO_TAG is specified, use the default tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!ifndef ACCESSIBLE_CO_FLAGS
|
||||
ACCESSIBLE_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
ACCESSIBLE_CO_FLAGS=$(ACCESSIBLE_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
CVSCO_ACCESSIBLE = cvs $(CVS_FLAGS) co $(ACCESSIBLE_CO_FLAGS)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull new image library.
|
||||
#// If no IMGLIB2_CO_TAG is specified, use the default tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!ifndef IMGLIB2_CO_FLAGS
|
||||
IMGLIB2_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
IMGLIB2_CO_FLAGS=$(IMGLIB2_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
CVSCO_IMGLIB2 = cvs $(CVS_FLAGS) co $(IMGLIB2_CO_FLAGS)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull new image library.
|
||||
#// If no GFX2_CO_TAG is specified, use the default tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!ifndef GFX2_CO_FLAGS
|
||||
GFX2_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
GFX2_CO_FLAGS=$(GFX2_CO_FLAGS) $(CVS_BRANCH)
|
||||
|
||||
CVSCO_GFX2 = cvs $(CVS_FLAGS) co $(GFX2_CO_FLAGS)
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Figure out how to pull the internal libart
|
||||
#// (only pulled and built if MOZ_INTERNAL_LIBART_LGPL is set)
|
||||
#// If no MOZ_INTERNAL_LIBART_CO_TAG is specified, use the default tag
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!if defined(MOZ_SVG) && !defined(MOZ_INTERNAL_LIBART_LGPL)
|
||||
ERR_MESSAGE = ^
|
||||
You are trying to build Mozilla with SVG support (MOZ_SVG=1), but you ^
|
||||
haven not specified that mozilla/other-licenses/libart_lgpl should be ^
|
||||
pulled and built. At the moment Mozilla SVG builds need this patched ^
|
||||
version of libart. You either need to disable SVG support (unset MOZ_SVG) ^
|
||||
or enable pulling and building by setting MOZ_INTERNAL_LIBART_LGPL=1.^
|
||||
^
|
||||
If you choose to pull and build libart, note that it is only licensed^
|
||||
under the terms of the LGPL, not the MPL. (Which is why you have to opt^
|
||||
in explicitly.)
|
||||
!endif
|
||||
|
||||
!if defined(MOZ_INTERNAL_LIBART_LGPL)
|
||||
|
||||
!ifndef MOZ_INTERNAL_LIBART_CO_FLAGS
|
||||
MOZ_INTERNAL_LIBART_CO_FLAGS=$(MOZ_CO_FLAGS)
|
||||
!endif
|
||||
|
||||
!if "$(MOZ_INTERNAL_LIBART_CO_TAG)" != ""
|
||||
MOZ_INTERNAL_LIBART_CO_FLAGS=$(MOZ_INTERNAL_LIBART_CO_FLAGS) -r $(MOZ_INTERNAL_LIBART_CO_TAG)
|
||||
!else
|
||||
MOZ_INTERNAL_LIBART_CO_FLAGS=$(MOZ_INTERNAL_LIBART_CO_FLAGS) $(CVS_BRANCH)
|
||||
!endif
|
||||
|
||||
CVSCO_MOZ_INTERNAL_LIBART = cvs $(CVS_FLAGS) co $(MOZ_INTERNAL_LIBART_CO_FLAGS)
|
||||
|
||||
!endif
|
||||
|
||||
## The master target
|
||||
############################################################
|
||||
|
||||
pull_and_build_all: pull_all build_all_dep
|
||||
|
||||
|
||||
## Rules for pulling the source from the cvs repository
|
||||
############################################################
|
||||
|
||||
pull_clobber_and_build_all: pull_all clobber_all build_all
|
||||
|
||||
!if !defined(MOZ_INTERNAL_LIBART_LGPL)
|
||||
pull_all: pull_nspr pull_psm pull_ldapcsdk pull_accessible pull_gfx2 pull_imglib2 pull_seamonkey
|
||||
!else
|
||||
pull_all: pull_nspr pull_psm pull_ldapcsdk pull_accessible pull_gfx2 pull_imglib2 pull_moz_internal_libart pull_seamonkey
|
||||
!endif
|
||||
|
||||
pull_nspr: pull_clientmak
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_NSPR) mozilla/nsprpub
|
||||
|
||||
pull_nss:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_NSS) mozilla/security/coreconf
|
||||
$(CVSCO_NSS) mozilla/security/nss
|
||||
|
||||
pull_psm: pull_nss
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_PSM) mozilla/security/manager
|
||||
$(CVSCO_PSM) mozilla/security/makefile.win
|
||||
|
||||
pull_ldapcsdk:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_LDAPCSDK) mozilla/directory/c-sdk
|
||||
|
||||
pull_accessible:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_ACCESSIBLE) mozilla/accessible
|
||||
|
||||
pull_gfx2:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_GFX2) mozilla/gfx2
|
||||
|
||||
pull_imglib2:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_IMGLIB2) mozilla/modules/libpr0n
|
||||
|
||||
!if defined(MOZ_INTERNAL_LIBART_LGPL)
|
||||
pull_moz_internal_libart:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO_MOZ_INTERNAL_LIBART) mozilla/other-licenses/libart_lgpl
|
||||
!endif
|
||||
|
||||
pull_xpconnect: pull_nspr
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO) mozilla/include
|
||||
$(CVSCO) mozilla/config
|
||||
$(CVSCO) -l mozilla/js
|
||||
$(CVSCO) -l mozilla/js/src
|
||||
$(CVSCO) mozilla/js/src/fdlibm
|
||||
$(CVSCO) mozilla/js/src/xpconnect
|
||||
$(CVSCO) mozilla/modules/libreg
|
||||
$(CVSCO) mozilla/xpcom
|
||||
$(CVSCO) mozilla/string
|
||||
|
||||
# pull either layout only or seamonkey the browser
|
||||
pull_layout:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO) RaptorWin
|
||||
|
||||
pull_seamonkey: pull_clientmak
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO) SeaMonkeyAll
|
||||
|
||||
pull_clientmak:
|
||||
cd $(MOZ_SRC)\.
|
||||
$(CVSCO) mozilla/client.mak
|
||||
|
||||
############################################################
|
||||
|
||||
# nmake has to be hardcoded, or we have to depend on mozilla/config
|
||||
# being pulled already to figure out what $(NMAKE) should be.
|
||||
|
||||
clobber_all: clobber_nspr clobber_ldapcsdk clobber_psm clobber_seamonkey
|
||||
|
||||
build_all: build_nspr build_ldapcsdk build_seamonkey
|
||||
|
||||
build_all_dep: depend libs
|
||||
|
||||
distclean:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\directory\c-sdk
|
||||
gmake -f gmakefile.win distclean MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\nsprpub
|
||||
gmake -f gmakefile.win distclean MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)
|
||||
nmake /f client.mak clobber_psm
|
||||
nmake /f client.mak clobber_seamonkey
|
||||
|
||||
clobber_ldapcsdk:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\directory\c-sdk
|
||||
gmake -f gmakefile.win clobber_all MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED) \
|
||||
SHELL=sh
|
||||
|
||||
clobber_nspr:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\nsprpub
|
||||
gmake -f gmakefile.win clobber_all MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
|
||||
|
||||
clobber_psm:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\security
|
||||
nmake -f makefile.win clobber_all
|
||||
|
||||
clobber_xpconnect:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
|
||||
-rd /s /q dist
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\nsprpub
|
||||
gmake -f gmakefile.win clobber_all MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\include
|
||||
nmake -f makefile.win clobber_all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\modules\libreg
|
||||
nmake -f makefile.win clobber_all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\string
|
||||
nmake -f makefile.win clobber_all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\xpcom
|
||||
nmake -f makefile.win clobber_all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\js
|
||||
nmake -f makefile.win clobber_all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src\xpconnect
|
||||
nmake -f makefile.win clobber_all
|
||||
|
||||
clobber_seamonkey:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
|
||||
-rd /s /q dist
|
||||
nmake -f makefile.win clobber_all
|
||||
|
||||
depend: export
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
|
||||
nmake -f makefile.win depend
|
||||
|
||||
depend_xpconnect:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\include
|
||||
nmake -f makefile.win depend
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\modules\libreg
|
||||
nmake -f makefile.win depend
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\string
|
||||
nmake -f makefile.win depend
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\xpcom
|
||||
nmake -f makefile.win depend
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src
|
||||
nmake -f makefile.win depend
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src\xpconnect
|
||||
nmake -f makefile.win depend
|
||||
|
||||
build_nspr:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\nsprpub
|
||||
gmake -f gmakefile.win MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED)
|
||||
|
||||
build_ldapcsdk:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\directory\c-sdk
|
||||
gmake -f gmakefile.win MOZ_SRC_FLIPPED=$(MOZ_SRC_FLIPPED) SHELL=sh
|
||||
|
||||
build_psm:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\security
|
||||
nmake -f makefile.win
|
||||
|
||||
build_xpconnect: build_nspr
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\include
|
||||
nmake -f makefile.win all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\modules\libreg
|
||||
nmake -f makefile.win all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\xpcom
|
||||
nmake -f makefile.win export
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\string
|
||||
nmake -f makefile.win all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\xpcom
|
||||
nmake -f makefile.win libs
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src
|
||||
nmake -f makefile.win all
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\js\src\xpconnect
|
||||
nmake -f makefile.win all
|
||||
|
||||
build_seamonkey:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
|
||||
nmake -f makefile.win all
|
||||
|
||||
build_client:
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake -f makefile.win all
|
||||
|
||||
build_layout:
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake -f makefile.win all
|
||||
|
||||
build_dist:
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake -f makefile.win all
|
||||
|
||||
libs:
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
|
||||
nmake -f makefile.win libs
|
||||
|
||||
export: build_nspr build_ldapcsdk
|
||||
@cd $(MOZ_SRC)\$(MOZ_TOP)\.
|
||||
nmake -f makefile.win export
|
||||
|
||||
clobber_dist:
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake -f makefile.win clobber_all
|
||||
|
||||
clobber_client:
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake -f makefile.win clobber_all
|
||||
|
||||
clobber_layout:
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake -f makefile.win clobber_all
|
||||
|
||||
browse_info::
|
||||
cd $(MOZ_SRC)\$(MOZ_TOP)
|
||||
-dir /s /b *.sbr > sbrlist.tmp
|
||||
-bscmake /Es /o mozilla.bsc @sbrlist.tmp
|
||||
-rm sbrlist.tmp
|
||||
|
||||
regchrome::
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake /f makefile.win regchrome
|
||||
|
||||
deliver::
|
||||
@cd $(MOZ_SRC)\mozilla\.
|
||||
nmake /f makefile.win splitsymbols
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Utility stuff...
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
# Verify that MOZ_SRC is set correctly
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
# Check to see if it is set at all
|
||||
!if "$(MOZ_SRC)"==""
|
||||
MOZ_SRC = $(MAKEDIR)\..
|
||||
!endif
|
||||
|
||||
#
|
||||
# create a temp file at the root and make sure it is visible from MOZ_SRC
|
||||
#
|
||||
!if [copy $(MAKEDIR)\client.mak $(MAKEDIR)\xyzzy.tmp > NUL] == 0
|
||||
!endif
|
||||
|
||||
!if !EXIST( $(MOZ_SRC)\mozilla\xyzzy.tmp )
|
||||
ERR_MESSAGE=$(ERR_MESSAGE)^
|
||||
MOZ_SRC isn't set correctly: [$(MOZ_SRC)\mozilla]!=[$(MAKEDIR)]
|
||||
!endif
|
||||
|
||||
!if [del $(MAKEDIR)\xyzzy.tmp]
|
||||
!endif
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
# Verify that MOZ_BITS is set
|
||||
#//------------------------------------------------------------------------
|
||||
!if !defined(MOZ_BITS)
|
||||
ERR_MESSAGE=$(ERR_MESSAGE)^
|
||||
Environment variable MOZ_BITS isn't set.
|
||||
!endif
|
||||
|
||||
!if !defined(MOZ_TOOLS)
|
||||
ERR_MESSAGE=$(ERR_MESSAGE)^
|
||||
Environment variable MOZ_TOOLS isn't set.
|
||||
!endif
|
||||
|
||||
|
||||
#//------------------------------------------------------------------------
|
||||
#// Display error
|
||||
#//------------------------------------------------------------------------
|
||||
|
||||
!if "$(ERR_MESSAGE)" != ""
|
||||
ERR_MESSAGE = ^
|
||||
client.mak: ^
|
||||
$(ERR_MESSAGE) ^
|
||||
^
|
||||
client.mak: usage^
|
||||
^
|
||||
nmake -f client.mak [MOZ_BRANCH=<cvs_branch_name>] ^
|
||||
[MOZ_DATE=<cvs_date>]^
|
||||
[pull_and_build_all]^
|
||||
[pull_all]^
|
||||
[build_all]^
|
||||
^
|
||||
Environment variables:^
|
||||
^
|
||||
MOZ_BITS set to 32^
|
||||
MOZ_TOOLS set to the directory containing the needed tools ^
|
||||
|
||||
!ERROR $(ERR_MESSAGE)
|
||||
|
||||
!endif
|
||||
@@ -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_0_RTM
|
||||
NSPR_CO_TAG = NETSCAPE_7_0_RTM
|
||||
PSM_CO_TAG = NETSCAPE_7_0_RTM
|
||||
NSS_CO_TAG = NETSCAPE_7_0_RTM
|
||||
LDAPCSDK_CO_TAG = NETSCAPE_7_0_RTM
|
||||
ACCESSIBLE_CO_TAG = NETSCAPE_7_0_RTM
|
||||
GFX2_CO_TAG = NETSCAPE_7_0_RTM
|
||||
IMGLIB2_CO_TAG = NETSCAPE_7_0_RTM
|
||||
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;
|
||||
}
|
||||
283
mozilla/js/rhino/org/mozilla/javascript/NativeJavaClass.java
Normal file
283
mozilla/js/rhino/org/mozilla/javascript/NativeJavaClass.java
Normal file
@@ -0,0 +1,283 @@
|
||||
/* -*- 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
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* This class reflects Java classes into the JavaScript environment, mainly
|
||||
* for constructors and static members. We lazily reflect properties,
|
||||
* and currently do not guarantee that a single j.l.Class is only
|
||||
* reflected once into the JS environment, although we should.
|
||||
* The only known case where multiple reflections
|
||||
* are possible occurs when a j.l.Class is wrapped as part of a
|
||||
* method return or property access, rather than by walking the
|
||||
* Packages/java tree.
|
||||
*
|
||||
* @author Mike Shaver
|
||||
* @see NativeJavaArray
|
||||
* @see NativeJavaObject
|
||||
* @see NativeJavaPackage
|
||||
*/
|
||||
|
||||
public class NativeJavaClass extends NativeJavaObject implements Function {
|
||||
|
||||
public NativeJavaClass(Scriptable scope, Class cl) {
|
||||
super(scope, cl, JavaMembers.lookupClass(scope, cl, cl));
|
||||
fieldAndMethods = members.getFieldAndMethodsObjects(this, javaObject,
|
||||
true);
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "JavaClass";
|
||||
}
|
||||
|
||||
public boolean has(String name, Scriptable start) {
|
||||
return members.has(name, true);
|
||||
}
|
||||
|
||||
public Object get(String name, Scriptable start) {
|
||||
// When used as a constructor, ScriptRuntime.newObject() asks
|
||||
// for our prototype to create an object of the correct type.
|
||||
// We don't really care what the object is, since we're returning
|
||||
// one constructed out of whole cloth, so we return null.
|
||||
|
||||
if (name.equals("prototype"))
|
||||
return null;
|
||||
|
||||
Object result = Scriptable.NOT_FOUND;
|
||||
|
||||
if (fieldAndMethods != null) {
|
||||
result = fieldAndMethods.get(name);
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (members.has(name, true)) {
|
||||
result = members.get(this, name, javaObject, true);
|
||||
} else {
|
||||
// experimental: look for nested classes by appending $name to current class' name.
|
||||
try {
|
||||
String nestedName = getClassObject().getName() + '$' + name;
|
||||
Class nestedClass = ScriptRuntime.loadClassName(nestedName);
|
||||
Scriptable nestedValue = wrap(ScriptableObject.getTopLevelScope(this), nestedClass);
|
||||
nestedValue.setParentScope(this);
|
||||
result = nestedValue;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
throw members.reportMemberNotFound(name);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw members.reportMemberNotFound(name);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void put(String name, Scriptable start, Object value) {
|
||||
members.put(name, javaObject, value, true);
|
||||
}
|
||||
|
||||
public Object[] getIds() {
|
||||
return members.getIds(true);
|
||||
}
|
||||
|
||||
public Class getClassObject() {
|
||||
return (Class) super.unwrap();
|
||||
}
|
||||
|
||||
// XXX ??
|
||||
public static NativeJavaClass wrap(Scriptable scope, Class cls) {
|
||||
return new NativeJavaClass(scope, cls);
|
||||
}
|
||||
|
||||
public Object getDefaultValue(Class hint) {
|
||||
if (hint == null || hint == ScriptRuntime.StringClass)
|
||||
return this.toString();
|
||||
if (hint == ScriptRuntime.BooleanClass)
|
||||
return Boolean.TRUE;
|
||||
if (hint == ScriptRuntime.NumberClass)
|
||||
return ScriptRuntime.NaNobj;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object call(Context cx, Scriptable scope, Scriptable thisObj,
|
||||
Object[] args)
|
||||
throws JavaScriptException
|
||||
{
|
||||
// If it looks like a "cast" of an object to this class type,
|
||||
// walk the prototype chain to see if there's a wrapper of a
|
||||
// object that's an instanceof this class.
|
||||
if (args.length == 1 && args[0] instanceof Scriptable) {
|
||||
Class c = getClassObject();
|
||||
Scriptable p = (Scriptable) args[0];
|
||||
do {
|
||||
if (p instanceof Wrapper) {
|
||||
Object o = ((Wrapper) p).unwrap();
|
||||
if (c.isInstance(o))
|
||||
return p;
|
||||
}
|
||||
p = p.getPrototype();
|
||||
} while (p != null);
|
||||
}
|
||||
return construct(cx, scope, args);
|
||||
}
|
||||
|
||||
public Scriptable construct(Context cx, Scriptable scope, Object[] args)
|
||||
throws JavaScriptException
|
||||
{
|
||||
Class classObject = getClassObject();
|
||||
int modifiers = classObject.getModifiers();
|
||||
if (! (Modifier.isInterface(modifiers) ||
|
||||
Modifier.isAbstract(modifiers)))
|
||||
{
|
||||
Constructor[] ctors = members.getConstructors();
|
||||
Member member = NativeJavaMethod.findFunction(ctors, args);
|
||||
Constructor ctor = (Constructor) member;
|
||||
if (ctor == null) {
|
||||
String sig = NativeJavaMethod.scriptSignature(args);
|
||||
Object errArgs[] = { classObject.getName(), sig };
|
||||
throw Context.reportRuntimeError(Context.getMessage(
|
||||
"msg.no.java.ctor", errArgs));
|
||||
}
|
||||
|
||||
// Found the constructor, so try invoking it.
|
||||
return NativeJavaClass.constructSpecific(cx, scope,
|
||||
this, ctor, args);
|
||||
} else {
|
||||
Scriptable topLevel = ScriptableObject.getTopLevelScope(this);
|
||||
String msg = "";
|
||||
try {
|
||||
// trying to construct an interface; use JavaAdapter to
|
||||
// construct a new class on the fly that implements this
|
||||
// interface.
|
||||
Object v = topLevel.get("JavaAdapter", topLevel);
|
||||
if (v != NOT_FOUND) {
|
||||
Function f = (Function) v;
|
||||
Object[] adapterArgs = { this, args[0] };
|
||||
return (Scriptable) f.construct(cx, topLevel,
|
||||
adapterArgs);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// fall through to error
|
||||
String m = ex.getMessage();
|
||||
if (m != null)
|
||||
msg = m;
|
||||
}
|
||||
Object[] errArgs = { msg, classObject.getName() };
|
||||
throw Context.reportRuntimeError(Context.getMessage
|
||||
("msg.cant.instantiate",
|
||||
errArgs));
|
||||
}
|
||||
}
|
||||
|
||||
public static Scriptable constructSpecific(Context cx,
|
||||
Scriptable scope,
|
||||
Scriptable thisObj,
|
||||
Constructor ctor,
|
||||
Object[] args)
|
||||
throws JavaScriptException
|
||||
{
|
||||
Scriptable topLevel = ScriptableObject.getTopLevelScope(thisObj);
|
||||
Class classObject = ctor.getDeclaringClass();
|
||||
|
||||
Class[] paramTypes = ctor.getParameterTypes();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
args[i] = NativeJavaObject.coerceType(paramTypes[i], args[i]);
|
||||
}
|
||||
try {
|
||||
// we need to force this to be wrapped, because construct _has_
|
||||
// to return a scriptable
|
||||
return
|
||||
(Scriptable) NativeJavaObject.wrap(topLevel,
|
||||
ctor.newInstance(args),
|
||||
classObject);
|
||||
|
||||
} catch (InstantiationException instEx) {
|
||||
Object[] errArgs = { instEx.getMessage(),
|
||||
classObject.getName() };
|
||||
throw Context.reportRuntimeError(Context.getMessage
|
||||
("msg.cant.instantiate",
|
||||
errArgs));
|
||||
} catch (IllegalArgumentException argEx) {
|
||||
String signature = NativeJavaMethod.scriptSignature(args);
|
||||
String ctorString = ctor.toString();
|
||||
Object[] errArgs = { argEx.getMessage(),ctorString,signature };
|
||||
throw Context.reportRuntimeError(Context.getMessage
|
||||
("msg.bad.ctor.sig",
|
||||
errArgs));
|
||||
} catch (InvocationTargetException e) {
|
||||
throw JavaScriptException.wrapException(scope, e);
|
||||
} catch (IllegalAccessException accessEx) {
|
||||
Object[] errArgs = { accessEx.getMessage() };
|
||||
throw Context.reportRuntimeError(Context.getMessage
|
||||
("msg.java.internal.private", errArgs));
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "[JavaClass " + getClassObject().getName() + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if prototype is a wrapped Java object and performs
|
||||
* a Java "instanceof".
|
||||
* Exception: if value is an instance of NativeJavaClass, it isn't
|
||||
* considered an instance of the Java class; this forestalls any
|
||||
* name conflicts between java.lang.Class's methods and the
|
||||
* static methods exposed by a JavaNativeClass.
|
||||
*/
|
||||
public boolean hasInstance(Scriptable value) {
|
||||
|
||||
if (value instanceof NativeJavaObject &&
|
||||
!(value instanceof NativeJavaClass)) {
|
||||
Object instance = ((NativeJavaObject)value).unwrap();
|
||||
|
||||
return getClassObject().isInstance(instance);
|
||||
}
|
||||
|
||||
// value wasn't something we understand
|
||||
return false;
|
||||
}
|
||||
|
||||
private Hashtable fieldAndMethods;
|
||||
|
||||
// beard: need a scope for finding top-level prototypes.
|
||||
private Scriptable parent;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/* -*- 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.*;
|
||||
|
||||
/**
|
||||
* This class reflects a single Java constructor into the JavaScript
|
||||
* environment. It satisfies a request for an overloaded constructor,
|
||||
* as introduced in LiveConnect 3.
|
||||
* All NativeJavaConstructors behave as JSRef `bound' methods, in that they
|
||||
* always construct the same NativeJavaClass regardless of any reparenting
|
||||
* that may occur.
|
||||
*
|
||||
* @author Frank Mitchell
|
||||
* @see NativeJavaMethod
|
||||
* @see NativeJavaPackage
|
||||
* @see NativeJavaClass
|
||||
*/
|
||||
|
||||
public class NativeJavaConstructor extends NativeFunction implements Function {
|
||||
|
||||
public NativeJavaConstructor(Constructor ctor) {
|
||||
this.constructor = ctor;
|
||||
names = new String[1];
|
||||
names[0] = "<init>" + NativeJavaMethod.signature(ctor);
|
||||
}
|
||||
|
||||
public Object call(Context cx, Scriptable scope, Scriptable thisObj,
|
||||
Object[] args)
|
||||
throws JavaScriptException
|
||||
{
|
||||
// Find a method that matches the types given.
|
||||
if (constructor == null) {
|
||||
throw new RuntimeException("No constructor defined for call");
|
||||
}
|
||||
|
||||
// Eliminate useless args[0] and unwrap if required
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (args[i] instanceof Wrapper) {
|
||||
args[i] = ((Wrapper)args[i]).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
return NativeJavaClass.constructSpecific(cx, scope,
|
||||
this, constructor, args);
|
||||
}
|
||||
|
||||
/*
|
||||
public Object getDefaultValue(Class hint) {
|
||||
return this;
|
||||
}
|
||||
*/
|
||||
|
||||
public String toString() {
|
||||
return "[JavaConstructor " + constructor.getName() + "]";
|
||||
}
|
||||
|
||||
Constructor getConstructor() {
|
||||
return constructor;
|
||||
}
|
||||
|
||||
Constructor constructor;
|
||||
}
|
||||
|
||||
505
mozilla/js/rhino/org/mozilla/javascript/NativeJavaMethod.java
Normal file
505
mozilla/js/rhino/org/mozilla/javascript/NativeJavaMethod.java
Normal file
@@ -0,0 +1,505 @@
|
||||
/* -*- 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.*;
|
||||
|
||||
/**
|
||||
* This class reflects Java methods into the JavaScript environment. It
|
||||
* handles overloading of methods, and method/field name conflicts.
|
||||
* All NativeJavaMethods behave as JSRef `bound' methods, in that they
|
||||
* always operate on the object underlying the original NativeJavaObject
|
||||
* parent regardless of any reparenting that may occur.
|
||||
*
|
||||
* @author Mike Shaver
|
||||
* @see NativeJavaArray
|
||||
* @see NativeJavaPackage
|
||||
* @see NativeJavaClass
|
||||
*/
|
||||
|
||||
public class NativeJavaMethod extends NativeFunction implements Function {
|
||||
|
||||
public NativeJavaMethod() {
|
||||
names = new String[1];
|
||||
}
|
||||
|
||||
public NativeJavaMethod(Method[] methods) {
|
||||
this.methods = methods;
|
||||
names = new String[1];
|
||||
names[0] = methods[0].getName();
|
||||
}
|
||||
|
||||
public NativeJavaMethod(Method method, String name) {
|
||||
this.methods = new Method[1];
|
||||
this.methods[0] = method;
|
||||
names = new String[1];
|
||||
names[0] = name;
|
||||
}
|
||||
|
||||
public void add(Method method) {
|
||||
if (names[0] == null) {
|
||||
names[0] = method.getName();
|
||||
} else if (!names[0].equals(method.getName())) {
|
||||
throw new RuntimeException("internal method name mismatch");
|
||||
}
|
||||
// XXX a more intelligent growth algorithm would be nice
|
||||
int len = methods == null ? 0 : methods.length;
|
||||
Method[] newMeths = new Method[len + 1];
|
||||
for (int i = 0; i < len; i++)
|
||||
newMeths[i] = methods[i];
|
||||
newMeths[len] = method;
|
||||
methods = newMeths;
|
||||
}
|
||||
|
||||
static String scriptSignature(Object value) {
|
||||
if (value == null) {
|
||||
return "null";
|
||||
}
|
||||
else {
|
||||
Class type = value.getClass();
|
||||
if (type == ScriptRuntime.UndefinedClass)
|
||||
return "undefined";
|
||||
if (type == ScriptRuntime.BooleanClass)
|
||||
return "boolean";
|
||||
if (type == ScriptRuntime.StringClass)
|
||||
return "string";
|
||||
if (ScriptRuntime.NumberClass.isAssignableFrom(type))
|
||||
return "number";
|
||||
if (value instanceof NativeJavaObject) {
|
||||
return ((NativeJavaObject)value).unwrap().getClass().getName();
|
||||
}
|
||||
if (value instanceof Scriptable) {
|
||||
if (value instanceof Function)
|
||||
return "function";
|
||||
return "object";
|
||||
}
|
||||
return javaSignature(type);
|
||||
}
|
||||
}
|
||||
|
||||
static String scriptSignature(Object[] values) {
|
||||
StringBuffer sig = new StringBuffer();
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (i != 0)
|
||||
sig.append(',');
|
||||
sig.append(scriptSignature(values[i]));
|
||||
}
|
||||
return sig.toString();
|
||||
}
|
||||
|
||||
static String javaSignature(Class type) {
|
||||
if (type == null) {
|
||||
return "null";
|
||||
}
|
||||
else if (type.isArray()) {
|
||||
return javaSignature(type.getComponentType()) + "[]";
|
||||
}
|
||||
return type.getName();
|
||||
}
|
||||
|
||||
static String javaSignature(Class[] types) {
|
||||
StringBuffer sig = new StringBuffer();
|
||||
for (int i = 0; i < types.length; i++) {
|
||||
if (i != 0)
|
||||
sig.append(',');
|
||||
sig.append(javaSignature(types[i]));
|
||||
}
|
||||
return sig.toString();
|
||||
}
|
||||
|
||||
static String signature(Member member) {
|
||||
Class paramTypes[];
|
||||
|
||||
if (member instanceof Method) {
|
||||
paramTypes = ((Method) member).getParameterTypes();
|
||||
return member.getName() + "(" + javaSignature(paramTypes) + ")";
|
||||
}
|
||||
else {
|
||||
paramTypes = ((Constructor) member).getParameterTypes();
|
||||
return "(" + javaSignature(paramTypes) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (int i=0; i < methods.length; i++) {
|
||||
sb.append(javaSignature(methods[i].getReturnType()));
|
||||
sb.append(' ');
|
||||
sb.append(signature(methods[i]));
|
||||
sb.append('\n');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Object call(Context cx, Scriptable scope, Scriptable thisObj,
|
||||
Object[] args)
|
||||
throws JavaScriptException
|
||||
{
|
||||
// Find a method that matches the types given.
|
||||
if (methods.length == 0) {
|
||||
throw new RuntimeException("No methods defined for call");
|
||||
}
|
||||
|
||||
Method meth = (Method) findFunction(methods, args);
|
||||
if (meth == null) {
|
||||
Class c = methods[0].getDeclaringClass();
|
||||
String sig = c.getName() + "." + names[0] + "(" +
|
||||
scriptSignature(args) + ")";
|
||||
Object errArgs[] = { sig };
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.java.no_such_method", errArgs));
|
||||
}
|
||||
|
||||
// OPT: already retrieved in findFunction, so we should inline that
|
||||
// OPT: or pass it back somehow
|
||||
Class paramTypes[] = meth.getParameterTypes();
|
||||
|
||||
// First, we marshall the args.
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
args[i] = NativeJavaObject.coerceType(paramTypes[i], args[i]);
|
||||
}
|
||||
Object javaObject;
|
||||
if (Modifier.isStatic(meth.getModifiers())) {
|
||||
javaObject = null; // don't need an object
|
||||
} else {
|
||||
Scriptable o = thisObj;
|
||||
while (!(o instanceof NativeJavaObject)) {
|
||||
o = o.getPrototype();
|
||||
if (o == null) {
|
||||
Object errArgs[] = { names[0] };
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.nonjava.method", errArgs));
|
||||
}
|
||||
}
|
||||
javaObject = ((NativeJavaObject) o).unwrap();
|
||||
}
|
||||
try {
|
||||
if (debug) {
|
||||
printDebug("Calling ", meth, args);
|
||||
}
|
||||
|
||||
Object retval = meth.invoke(javaObject, args);
|
||||
Class staticType = meth.getReturnType();
|
||||
|
||||
if (debug) {
|
||||
Class actualType = (retval == null) ? null : retval.getClass();
|
||||
System.err.println(" ----- Returned " + retval +
|
||||
" actual = " + actualType +
|
||||
" expect = " + staticType);
|
||||
}
|
||||
|
||||
Object wrapped = NativeJavaObject.wrap(scope, retval, staticType);
|
||||
|
||||
if (debug) {
|
||||
Class actualType = (wrapped == null) ? null : wrapped.getClass();
|
||||
System.err.println(" ----- Wrapped as " + wrapped +
|
||||
" class = " + actualType);
|
||||
}
|
||||
|
||||
if (wrapped == Undefined.instance)
|
||||
return wrapped;
|
||||
if (wrapped == null && staticType == Void.TYPE)
|
||||
return Undefined.instance;
|
||||
return wrapped;
|
||||
} catch (IllegalAccessException accessEx) {
|
||||
throw Context.reportRuntimeError(accessEx.getMessage());
|
||||
} catch (InvocationTargetException e) {
|
||||
throw JavaScriptException.wrapException(scope, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the correct function to call given the set of methods
|
||||
* or constructors and the arguments.
|
||||
* If no function can be found to call, return null.
|
||||
*/
|
||||
static Member findFunction(Member[] methodsOrCtors, Object[] args) {
|
||||
if (methodsOrCtors.length == 0)
|
||||
return null;
|
||||
boolean hasMethods = methodsOrCtors[0] instanceof Method;
|
||||
if (Context.useJSObject &&
|
||||
NativeJavaObject.jsObjectClass != null)
|
||||
{
|
||||
try {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (NativeJavaObject.jsObjectClass.isInstance(args[i]))
|
||||
args[i] = NativeJavaObject.jsObjectGetScriptable.invoke(
|
||||
args[i], ScriptRuntime.emptyArgs);
|
||||
}
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
// Just abandon conversion from JSObject
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
// Just abandon conversion from JSObject
|
||||
}
|
||||
}
|
||||
|
||||
Member bestFit = null;
|
||||
Class[] bestFitTypes = null;
|
||||
|
||||
java.util.Vector ambiguousMethods = null;
|
||||
|
||||
for (int i = 0; i < methodsOrCtors.length; i++) {
|
||||
Member member = methodsOrCtors[i];
|
||||
Class paramTypes[] = hasMethods
|
||||
? ((Method) member).getParameterTypes()
|
||||
: ((Constructor) member).getParameterTypes();
|
||||
if (paramTypes.length != args.length) {
|
||||
continue;
|
||||
}
|
||||
if (bestFitTypes == null) {
|
||||
int j;
|
||||
for (j = 0; j < paramTypes.length; j++) {
|
||||
if (!NativeJavaObject.canConvert(args[j], paramTypes[j])) {
|
||||
if (debug) printDebug("Rejecting (args can't convert) ",
|
||||
member, args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == paramTypes.length) {
|
||||
if (debug) printDebug("Found ", member, args);
|
||||
bestFit = member;
|
||||
bestFitTypes = paramTypes;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int preference =
|
||||
NativeJavaMethod.preferSignature(args,
|
||||
paramTypes,
|
||||
bestFitTypes);
|
||||
if (preference == PREFERENCE_AMBIGUOUS) {
|
||||
if (debug) printDebug("Deferring ", member, args);
|
||||
// add to "ambiguity list"
|
||||
if (ambiguousMethods == null)
|
||||
ambiguousMethods = new java.util.Vector();
|
||||
ambiguousMethods.addElement(member);
|
||||
}
|
||||
else if (preference == PREFERENCE_FIRST_ARG) {
|
||||
if (debug) printDebug("Substituting ", member, args);
|
||||
bestFit = member;
|
||||
bestFitTypes = paramTypes;
|
||||
}
|
||||
else {
|
||||
if (preference == PREFERENCE_EQUAL &&
|
||||
Modifier.isStatic(bestFit.getModifiers()) &&
|
||||
bestFit.getDeclaringClass().isAssignableFrom(
|
||||
member.getDeclaringClass()))
|
||||
{
|
||||
// On some JVMs, Class.getMethods will return all
|
||||
// static methods of the class heirarchy, even if
|
||||
// a derived class's parameters match exactly.
|
||||
// We want to call the dervied class's method.
|
||||
if (debug) printDebug("Rejecting (overridden static)",
|
||||
member, args);
|
||||
bestFit = member;
|
||||
bestFitTypes = paramTypes;
|
||||
} else {
|
||||
if (debug) printDebug("Rejecting ", member, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ambiguousMethods == null)
|
||||
return bestFit;
|
||||
|
||||
// Compare ambiguous methods with best fit, in case
|
||||
// the current best fit removes the ambiguities.
|
||||
for (int i = ambiguousMethods.size() - 1; i >= 0 ; i--) {
|
||||
Member member = (Member)ambiguousMethods.elementAt(i);
|
||||
Class paramTypes[] = hasMethods
|
||||
? ((Method) member).getParameterTypes()
|
||||
: ((Constructor) member).getParameterTypes();
|
||||
int preference =
|
||||
NativeJavaMethod.preferSignature(args,
|
||||
paramTypes,
|
||||
bestFitTypes);
|
||||
|
||||
if (preference == PREFERENCE_FIRST_ARG) {
|
||||
if (debug) printDebug("Substituting ", member, args);
|
||||
bestFit = member;
|
||||
bestFitTypes = paramTypes;
|
||||
ambiguousMethods.removeElementAt(i);
|
||||
}
|
||||
else if (preference == PREFERENCE_SECOND_ARG) {
|
||||
if (debug) printDebug("Rejecting ", member, args);
|
||||
ambiguousMethods.removeElementAt(i);
|
||||
}
|
||||
else {
|
||||
if (debug) printDebug("UNRESOLVED: ", member, args);
|
||||
}
|
||||
}
|
||||
|
||||
if (ambiguousMethods.size() > 0) {
|
||||
// PENDING: report remaining ambiguity
|
||||
StringBuffer buf = new StringBuffer();
|
||||
boolean isCtor = (bestFit instanceof Constructor);
|
||||
|
||||
ambiguousMethods.addElement(bestFit);
|
||||
|
||||
for (int i = 0; i < ambiguousMethods.size(); i++) {
|
||||
if (i != 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
Member member = (Member)ambiguousMethods.elementAt(i);
|
||||
if (!isCtor) {
|
||||
Class rtnType = ((Method)member).getReturnType();
|
||||
buf.append(rtnType);
|
||||
buf.append(' ');
|
||||
}
|
||||
buf.append(NativeJavaMethod.signature(member));
|
||||
}
|
||||
|
||||
String errMsg;
|
||||
if (isCtor) {
|
||||
Object errArgs[] = {
|
||||
bestFit.getName(),
|
||||
NativeJavaMethod.scriptSignature(args),
|
||||
buf.toString()
|
||||
};
|
||||
errMsg =
|
||||
Context.getMessage("msg.constructor.ambiguous", errArgs);
|
||||
}
|
||||
else {
|
||||
Object errArgs[] = {
|
||||
bestFit.getDeclaringClass().getName(),
|
||||
bestFit.getName(),
|
||||
NativeJavaMethod.scriptSignature(args),
|
||||
buf.toString()
|
||||
};
|
||||
errMsg = Context.getMessage("msg.method.ambiguous", errArgs);
|
||||
}
|
||||
|
||||
throw
|
||||
Context.reportRuntimeError(errMsg);
|
||||
}
|
||||
|
||||
return bestFit;
|
||||
}
|
||||
|
||||
/** Types are equal */
|
||||
static final int PREFERENCE_EQUAL = 0;
|
||||
static final int PREFERENCE_FIRST_ARG = 1;
|
||||
static final int PREFERENCE_SECOND_ARG = 2;
|
||||
/** No clear "easy" conversion */
|
||||
static final int PREFERENCE_AMBIGUOUS = 3;
|
||||
|
||||
/**
|
||||
* Determine which of two signatures is the closer fit.
|
||||
* Returns one of PREFERENCE_EQUAL, PREFERENCE_FIRST_ARG,
|
||||
* PREFERENCE_SECOND_ARG, or PREFERENCE_AMBIGUOUS.
|
||||
*/
|
||||
public static int preferSignature(Object[] args,
|
||||
Class[] sig1, Class[] sig2)
|
||||
{
|
||||
int preference = 0;
|
||||
|
||||
for (int j = 0; j < args.length; j++) {
|
||||
Class type1 = sig1[j];
|
||||
Class type2 = sig2[j];
|
||||
|
||||
if (type1 == type2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
preference |=
|
||||
NativeJavaMethod.preferConversion(args[j],
|
||||
type1,
|
||||
type2);
|
||||
|
||||
if (preference == PREFERENCE_AMBIGUOUS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return preference;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine which of two types is the easier conversion.
|
||||
* Returns one of PREFERENCE_EQUAL, PREFERENCE_FIRST_ARG,
|
||||
* PREFERENCE_SECOND_ARG, or PREFERENCE_AMBIGUOUS.
|
||||
*/
|
||||
public static int preferConversion(Object fromObj,
|
||||
Class toClass1, Class toClass2) {
|
||||
|
||||
int rank1 =
|
||||
NativeJavaObject.getConversionWeight(fromObj, toClass1);
|
||||
int rank2 =
|
||||
NativeJavaObject.getConversionWeight(fromObj, toClass2);
|
||||
|
||||
if (rank1 == NativeJavaObject.CONVERSION_NONTRIVIAL &&
|
||||
rank2 == NativeJavaObject.CONVERSION_NONTRIVIAL) {
|
||||
|
||||
if (toClass1.isAssignableFrom(toClass2)) {
|
||||
return PREFERENCE_SECOND_ARG;
|
||||
}
|
||||
else if (toClass2.isAssignableFrom(toClass1)) {
|
||||
return PREFERENCE_FIRST_ARG;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (rank1 < rank2) {
|
||||
return PREFERENCE_FIRST_ARG;
|
||||
}
|
||||
else if (rank1 > rank2) {
|
||||
return PREFERENCE_SECOND_ARG;
|
||||
}
|
||||
}
|
||||
return PREFERENCE_AMBIGUOUS;
|
||||
}
|
||||
|
||||
Method[] getMethods() {
|
||||
return methods;
|
||||
}
|
||||
|
||||
private static final boolean debug = false;
|
||||
|
||||
private static void printDebug(String msg, Member member, Object[] args) {
|
||||
if (debug) {
|
||||
System.err.println(" ----- " + msg +
|
||||
member.getDeclaringClass().getName() +
|
||||
"." + signature(member) +
|
||||
" for arguments (" + scriptSignature(args) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
Method methods[];
|
||||
}
|
||||
|
||||
921
mozilla/js/rhino/org/mozilla/javascript/NativeJavaObject.java
Normal file
921
mozilla/js/rhino/org/mozilla/javascript/NativeJavaObject.java
Normal file
@@ -0,0 +1,921 @@
|
||||
/* -*- 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
|
||||
*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* This class reflects non-Array Java objects into the JavaScript environment. It
|
||||
* reflect fields directly, and uses NativeJavaMethod objects to reflect (possibly
|
||||
* overloaded) methods.<p>
|
||||
*
|
||||
* @author Mike Shaver
|
||||
* @see NativeJavaArray
|
||||
* @see NativeJavaPackage
|
||||
* @see NativeJavaClass
|
||||
*/
|
||||
|
||||
public class NativeJavaObject implements Scriptable, Wrapper {
|
||||
|
||||
public NativeJavaObject(Scriptable scope, Object javaObject,
|
||||
JavaMembers members)
|
||||
{
|
||||
this.parent = scope;
|
||||
this.javaObject = javaObject;
|
||||
this.members = members;
|
||||
}
|
||||
|
||||
public NativeJavaObject(Scriptable scope, Object javaObject,
|
||||
Class staticType)
|
||||
{
|
||||
this.parent = scope;
|
||||
this.javaObject = javaObject;
|
||||
Class dynamicType = javaObject != null ? javaObject.getClass()
|
||||
: staticType;
|
||||
members = JavaMembers.lookupClass(scope, dynamicType, staticType);
|
||||
fieldAndMethods = members.getFieldAndMethodsObjects(this, javaObject, false);
|
||||
}
|
||||
|
||||
public boolean has(String name, Scriptable start) {
|
||||
return members.has(name, false);
|
||||
}
|
||||
|
||||
public boolean has(int index, Scriptable start) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object get(String name, Scriptable start) {
|
||||
if (fieldAndMethods != null) {
|
||||
Object result = fieldAndMethods.get(name);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// TODO: passing 'this' as the scope is bogus since it has
|
||||
// no parent scope
|
||||
return members.get(this, name, javaObject, false);
|
||||
}
|
||||
|
||||
public Object get(int index, Scriptable start) {
|
||||
throw members.reportMemberNotFound(Integer.toString(index));
|
||||
}
|
||||
|
||||
public void put(String name, Scriptable start, Object value) {
|
||||
members.put(name, javaObject, value, false);
|
||||
}
|
||||
|
||||
public void put(int index, Scriptable start, Object value) {
|
||||
throw members.reportMemberNotFound(Integer.toString(index));
|
||||
}
|
||||
|
||||
public boolean hasInstance(Scriptable value) {
|
||||
// This is an instance of a Java class, so always return false
|
||||
return false;
|
||||
}
|
||||
|
||||
public void delete(String name) {
|
||||
}
|
||||
|
||||
public void delete(int index) {
|
||||
}
|
||||
|
||||
public Scriptable getPrototype() {
|
||||
if (prototype == null && javaObject.getClass() == ScriptRuntime.StringClass) {
|
||||
return ScriptableObject.getClassPrototype(parent, "String");
|
||||
}
|
||||
return prototype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the prototype of the object.
|
||||
*/
|
||||
public void setPrototype(Scriptable m) {
|
||||
prototype = m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent (enclosing) scope of the object.
|
||||
*/
|
||||
public Scriptable getParentScope() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parent (enclosing) scope of the object.
|
||||
*/
|
||||
public void setParentScope(Scriptable m) {
|
||||
parent = m;
|
||||
}
|
||||
|
||||
public Object[] getIds() {
|
||||
return members.getIds(false);
|
||||
}
|
||||
|
||||
public static Object wrap(Scriptable scope, Object obj, Class staticType)
|
||||
{
|
||||
if (obj == null)
|
||||
return obj;
|
||||
Context cx = Context.getCurrentContext();
|
||||
if (cx != null && cx.wrapHandler != null) {
|
||||
Object result = cx.wrapHandler.wrap(scope, obj, staticType);
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
Class cls = obj.getClass();
|
||||
if (staticType != null && staticType.isPrimitive()) {
|
||||
if (staticType == Void.TYPE)
|
||||
return Undefined.instance;
|
||||
if (staticType == Character.TYPE)
|
||||
return new Integer((int) ((Character) obj).charValue());
|
||||
return obj;
|
||||
}
|
||||
if (cls.isArray())
|
||||
return NativeJavaArray.wrap(scope, obj);
|
||||
if (obj instanceof Scriptable)
|
||||
return obj;
|
||||
if (Context.useJSObject && jsObjectClass != null &&
|
||||
staticType != jsObjectClass && jsObjectClass.isInstance(obj))
|
||||
{
|
||||
try {
|
||||
return jsObjectGetScriptable.invoke(obj, ScriptRuntime.emptyArgs);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
// Just abandon conversion from JSObject
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
// Just abandon conversion from JSObject
|
||||
}
|
||||
}
|
||||
return new NativeJavaObject(scope, obj, staticType);
|
||||
}
|
||||
|
||||
public Object unwrap() {
|
||||
return javaObject;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "JavaObject";
|
||||
}
|
||||
|
||||
Function getConverter(String converterName) {
|
||||
Object converterFunction = get(converterName, this);
|
||||
if (converterFunction instanceof Function) {
|
||||
return (Function) converterFunction;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Object callConverter(Function converterFunction)
|
||||
throws JavaScriptException
|
||||
{
|
||||
Function f = (Function) converterFunction;
|
||||
return f.call(Context.getContext(), f.getParentScope(),
|
||||
this, new Object[0]);
|
||||
}
|
||||
|
||||
Object callConverter(String converterName)
|
||||
throws JavaScriptException
|
||||
{
|
||||
Function converter = getConverter(converterName);
|
||||
if (converter == null) {
|
||||
Object[] errArgs = { converterName, javaObject.getClass().getName() };
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.java.conversion.implicit_method",
|
||||
errArgs));
|
||||
}
|
||||
return callConverter(converter);
|
||||
}
|
||||
|
||||
public Object getDefaultValue(Class hint) {
|
||||
if (hint == null || hint == ScriptRuntime.StringClass)
|
||||
return javaObject.toString();
|
||||
try {
|
||||
if (hint == ScriptRuntime.BooleanClass)
|
||||
return callConverter("booleanValue");
|
||||
if (hint == ScriptRuntime.NumberClass) {
|
||||
return callConverter("doubleValue");
|
||||
}
|
||||
// fall through to error message
|
||||
} catch (JavaScriptException jse) {
|
||||
// fall through to error message
|
||||
}
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.default.value", null));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether we can/should convert between the given type and the
|
||||
* desired one. This should be superceded by a conversion-cost calculation
|
||||
* function, but for now I'll hide behind precedent.
|
||||
*/
|
||||
public static boolean canConvert(Object fromObj, Class to) {
|
||||
int weight = NativeJavaObject.getConversionWeight(fromObj, to);
|
||||
|
||||
return (weight < CONVERSION_NONE);
|
||||
}
|
||||
|
||||
static final int JSTYPE_UNDEFINED = 0; // undefined type
|
||||
static final int JSTYPE_NULL = 1; // null
|
||||
static final int JSTYPE_BOOLEAN = 2; // boolean
|
||||
static final int JSTYPE_NUMBER = 3; // number
|
||||
static final int JSTYPE_STRING = 4; // string
|
||||
static final int JSTYPE_JAVA_CLASS = 5; // JavaClass
|
||||
static final int JSTYPE_JAVA_OBJECT = 6; // JavaObject
|
||||
static final int JSTYPE_JAVA_ARRAY = 7; // JavaArray
|
||||
static final int JSTYPE_OBJECT = 8; // Scriptable
|
||||
|
||||
public static final byte CONVERSION_TRIVIAL = 1;
|
||||
public static final byte CONVERSION_NONTRIVIAL = 0;
|
||||
public static final byte CONVERSION_NONE = 99;
|
||||
|
||||
/**
|
||||
* Derive a ranking based on how "natural" the conversion is.
|
||||
* The special value CONVERSION_NONE means no conversion is possible,
|
||||
* and CONVERSION_NONTRIVIAL signals that more type conformance testing
|
||||
* is required.
|
||||
* Based on
|
||||
* <a href="http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html">
|
||||
* "preferred method conversions" from Live Connect 3</a>
|
||||
*/
|
||||
public static int getConversionWeight(Object fromObj, Class to) {
|
||||
int fromCode = NativeJavaObject.getJSTypeCode(fromObj);
|
||||
|
||||
int result = CONVERSION_NONE;
|
||||
|
||||
switch (fromCode) {
|
||||
|
||||
case JSTYPE_UNDEFINED:
|
||||
if (to == ScriptRuntime.StringClass ||
|
||||
to == ScriptRuntime.ObjectClass) {
|
||||
result = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case JSTYPE_NULL:
|
||||
if (!to.isPrimitive()) {
|
||||
result = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case JSTYPE_BOOLEAN:
|
||||
// "boolean" is #1
|
||||
if (to == Boolean.TYPE) {
|
||||
result = 1;
|
||||
}
|
||||
else if (to == ScriptRuntime.BooleanClass) {
|
||||
result = 2;
|
||||
}
|
||||
else if (to == ScriptRuntime.ObjectClass) {
|
||||
result = 3;
|
||||
}
|
||||
else if (to == ScriptRuntime.StringClass) {
|
||||
result = 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case JSTYPE_NUMBER:
|
||||
if (to.isPrimitive()) {
|
||||
if (to == Double.TYPE) {
|
||||
result = 1;
|
||||
}
|
||||
else if (to != Boolean.TYPE) {
|
||||
result = 1 + NativeJavaObject.getSizeRank(to);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (to == ScriptRuntime.StringClass) {
|
||||
// native numbers are #1-8
|
||||
result = 9;
|
||||
}
|
||||
else if (to == ScriptRuntime.ObjectClass) {
|
||||
result = 10;
|
||||
}
|
||||
else if (ScriptRuntime.NumberClass.isAssignableFrom(to)) {
|
||||
// "double" is #1
|
||||
result = 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case JSTYPE_STRING:
|
||||
if (to == ScriptRuntime.StringClass) {
|
||||
result = 1;
|
||||
}
|
||||
else if (to == ScriptRuntime.ObjectClass) {
|
||||
result = 2;
|
||||
}
|
||||
else if (to.isPrimitive() && to != Boolean.TYPE) {
|
||||
if (to == Character.TYPE) {
|
||||
result = 3;
|
||||
}
|
||||
else {
|
||||
result = 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case JSTYPE_JAVA_CLASS:
|
||||
if (to == ScriptRuntime.ClassClass) {
|
||||
result = 1;
|
||||
}
|
||||
else if (Context.useJSObject && jsObjectClass != null &&
|
||||
jsObjectClass.isAssignableFrom(to)) {
|
||||
result = 2;
|
||||
}
|
||||
else if (to == ScriptRuntime.ObjectClass) {
|
||||
result = 3;
|
||||
}
|
||||
else if (to == ScriptRuntime.StringClass) {
|
||||
result = 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case JSTYPE_JAVA_OBJECT:
|
||||
case JSTYPE_JAVA_ARRAY:
|
||||
if (to == ScriptRuntime.StringClass) {
|
||||
result = 2;
|
||||
}
|
||||
else if (to.isPrimitive() && to != Boolean.TYPE) {
|
||||
result =
|
||||
(fromCode == JSTYPE_JAVA_ARRAY) ?
|
||||
CONVERSION_NONTRIVIAL :
|
||||
2 + NativeJavaObject.getSizeRank(to);
|
||||
}
|
||||
else {
|
||||
Object javaObj = fromObj;
|
||||
if (javaObj instanceof NativeJavaObject) {
|
||||
javaObj = ((NativeJavaObject)javaObj).unwrap();
|
||||
}
|
||||
if (to.isInstance(javaObj)) {
|
||||
result = CONVERSION_NONTRIVIAL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case JSTYPE_OBJECT:
|
||||
// Other objects takes #1-#3 spots
|
||||
if (Context.useJSObject && jsObjectClass != null &&
|
||||
jsObjectClass.isAssignableFrom(to)) {
|
||||
result = 1;
|
||||
}
|
||||
else if (fromObj instanceof NativeArray && to.isArray()) {
|
||||
// This is a native array conversion to a java array
|
||||
// Array conversions are all equal, and preferable to object
|
||||
// and string conversion, per LC3.
|
||||
result = 1;
|
||||
}
|
||||
else if (to == ScriptRuntime.ObjectClass) {
|
||||
result = 2;
|
||||
}
|
||||
else if (to == ScriptRuntime.StringClass) {
|
||||
result = 3;
|
||||
}
|
||||
else if (to.isPrimitive() || to != Boolean.TYPE) {
|
||||
result = 3 + NativeJavaObject.getSizeRank(to);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
static int getSizeRank(Class aType) {
|
||||
if (aType == Double.TYPE) {
|
||||
return 1;
|
||||
}
|
||||
else if (aType == Float.TYPE) {
|
||||
return 2;
|
||||
}
|
||||
else if (aType == Long.TYPE) {
|
||||
return 3;
|
||||
}
|
||||
else if (aType == Integer.TYPE) {
|
||||
return 4;
|
||||
}
|
||||
else if (aType == Short.TYPE) {
|
||||
return 5;
|
||||
}
|
||||
else if (aType == Character.TYPE) {
|
||||
return 6;
|
||||
}
|
||||
else if (aType == Byte.TYPE) {
|
||||
return 7;
|
||||
}
|
||||
else if (aType == Boolean.TYPE) {
|
||||
return CONVERSION_NONE;
|
||||
}
|
||||
else {
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
static int getJSTypeCode(Object value) {
|
||||
if (value == null) {
|
||||
return JSTYPE_NULL;
|
||||
}
|
||||
else if (value == Undefined.instance) {
|
||||
return JSTYPE_UNDEFINED;
|
||||
}
|
||||
else if (value instanceof Scriptable) {
|
||||
if (value instanceof NativeJavaClass) {
|
||||
return JSTYPE_JAVA_CLASS;
|
||||
}
|
||||
else if (value instanceof NativeJavaArray) {
|
||||
return JSTYPE_JAVA_ARRAY;
|
||||
}
|
||||
else if (value instanceof NativeJavaObject) {
|
||||
return JSTYPE_JAVA_OBJECT;
|
||||
}
|
||||
else {
|
||||
return JSTYPE_OBJECT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Class valueClass = value.getClass();
|
||||
|
||||
if (valueClass == ScriptRuntime.StringClass) {
|
||||
return JSTYPE_STRING;
|
||||
}
|
||||
else if (valueClass == ScriptRuntime.BooleanClass) {
|
||||
return JSTYPE_BOOLEAN;
|
||||
}
|
||||
else if (value instanceof Number) {
|
||||
return JSTYPE_NUMBER;
|
||||
}
|
||||
else if (valueClass == ScriptRuntime.ClassClass) {
|
||||
return JSTYPE_JAVA_CLASS;
|
||||
}
|
||||
else if (valueClass.isArray()) {
|
||||
return JSTYPE_JAVA_ARRAY;
|
||||
}
|
||||
else {
|
||||
return JSTYPE_JAVA_OBJECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type-munging for field setting and method invocation.
|
||||
* Conforms to LC3 specification
|
||||
*/
|
||||
public static Object coerceType(Class type, Object value) {
|
||||
if (value != null && value.getClass() == type) {
|
||||
return value;
|
||||
}
|
||||
|
||||
switch (NativeJavaObject.getJSTypeCode(value)) {
|
||||
|
||||
case JSTYPE_NULL:
|
||||
// raise error if type.isPrimitive()
|
||||
if (type.isPrimitive()) {
|
||||
reportConversionError(value, type);
|
||||
}
|
||||
return null;
|
||||
|
||||
case JSTYPE_UNDEFINED:
|
||||
if (type == ScriptRuntime.StringClass ||
|
||||
type == ScriptRuntime.ObjectClass) {
|
||||
return "undefined";
|
||||
}
|
||||
else {
|
||||
reportConversionError("undefined", type);
|
||||
}
|
||||
break;
|
||||
|
||||
case JSTYPE_BOOLEAN:
|
||||
// Under LC3, only JS Booleans can be coerced into a Boolean value
|
||||
if (type == Boolean.TYPE ||
|
||||
type == ScriptRuntime.BooleanClass ||
|
||||
type == ScriptRuntime.ObjectClass) {
|
||||
return value;
|
||||
}
|
||||
else if (type == ScriptRuntime.StringClass) {
|
||||
return value.toString();
|
||||
}
|
||||
else {
|
||||
reportConversionError(value, type);
|
||||
}
|
||||
break;
|
||||
|
||||
case JSTYPE_NUMBER:
|
||||
if (type == ScriptRuntime.StringClass) {
|
||||
return ScriptRuntime.toString(value);
|
||||
}
|
||||
else if (type == ScriptRuntime.ObjectClass) {
|
||||
return coerceToNumber(Double.TYPE, value);
|
||||
}
|
||||
else if ((type.isPrimitive() && type != Boolean.TYPE) ||
|
||||
ScriptRuntime.NumberClass.isAssignableFrom(type)) {
|
||||
return coerceToNumber(type, value);
|
||||
}
|
||||
else {
|
||||
reportConversionError(value, type);
|
||||
}
|
||||
break;
|
||||
|
||||
case JSTYPE_STRING:
|
||||
if (type == ScriptRuntime.StringClass ||
|
||||
type == ScriptRuntime.ObjectClass) {
|
||||
return value;
|
||||
}
|
||||
else if (type == Character.TYPE ||
|
||||
type == ScriptRuntime.CharacterClass) {
|
||||
// Special case for converting a single char string to a
|
||||
// character
|
||||
// Placed here because it applies *only* to JS strings,
|
||||
// not other JS objects converted to strings
|
||||
if (((String)value).length() == 1) {
|
||||
return new Character(((String)value).charAt(0));
|
||||
}
|
||||
else {
|
||||
return coerceToNumber(type, value);
|
||||
}
|
||||
}
|
||||
else if ((type.isPrimitive() && type != Boolean.TYPE) ||
|
||||
ScriptRuntime.NumberClass.isAssignableFrom(type)) {
|
||||
return coerceToNumber(type, value);
|
||||
}
|
||||
else {
|
||||
reportConversionError(value, type);
|
||||
}
|
||||
break;
|
||||
|
||||
case JSTYPE_JAVA_CLASS:
|
||||
if (Context.useJSObject && jsObjectClass != null &&
|
||||
(type == ScriptRuntime.ObjectClass ||
|
||||
jsObjectClass.isAssignableFrom(type))) {
|
||||
return coerceToJSObject(type, (Scriptable)value);
|
||||
}
|
||||
else {
|
||||
if (value instanceof Wrapper) {
|
||||
value = ((Wrapper)value).unwrap();
|
||||
}
|
||||
|
||||
if (type == ScriptRuntime.ClassClass ||
|
||||
type == ScriptRuntime.ObjectClass) {
|
||||
return value;
|
||||
}
|
||||
else if (type == ScriptRuntime.StringClass) {
|
||||
return value.toString();
|
||||
}
|
||||
else {
|
||||
reportConversionError(value, type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case JSTYPE_JAVA_OBJECT:
|
||||
case JSTYPE_JAVA_ARRAY:
|
||||
if (type.isPrimitive()) {
|
||||
if (type == Boolean.TYPE) {
|
||||
reportConversionError(value, type);
|
||||
}
|
||||
return coerceToNumber(type, value);
|
||||
}
|
||||
else {
|
||||
if (value instanceof Wrapper) {
|
||||
value = ((Wrapper)value).unwrap();
|
||||
}
|
||||
if (type == ScriptRuntime.StringClass) {
|
||||
return value.toString();
|
||||
}
|
||||
else {
|
||||
if (type.isInstance(value)) {
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
reportConversionError(value, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case JSTYPE_OBJECT:
|
||||
if (Context.useJSObject && jsObjectClass != null &&
|
||||
(type == ScriptRuntime.ObjectClass ||
|
||||
jsObjectClass.isAssignableFrom(type))) {
|
||||
return coerceToJSObject(type, (Scriptable)value);
|
||||
}
|
||||
else if (type == ScriptRuntime.StringClass) {
|
||||
return ScriptRuntime.toString(value);
|
||||
}
|
||||
else if (type.isPrimitive()) {
|
||||
if (type == Boolean.TYPE) {
|
||||
reportConversionError(value, type);
|
||||
}
|
||||
return coerceToNumber(type, value);
|
||||
}
|
||||
else if (type.isInstance(value)) {
|
||||
return value;
|
||||
}
|
||||
else if (type.isArray() && value instanceof NativeArray) {
|
||||
// Make a new java array, and coerce the JS array components
|
||||
// to the target (component) type.
|
||||
NativeArray array = (NativeArray) value;
|
||||
long length = array.jsGet_length();
|
||||
Class arrayType = type.getComponentType();
|
||||
Object Result = Array.newInstance(arrayType, (int)length);
|
||||
for (int i = 0 ; i < length ; ++i) {
|
||||
try {
|
||||
Array.set(Result, i, coerceType(arrayType,
|
||||
array.get(i, array)));
|
||||
}
|
||||
catch (EvaluatorException ee) {
|
||||
reportConversionError(value, type);
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
else {
|
||||
reportConversionError(value, type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static Object coerceToJSObject(Class type, Scriptable value) {
|
||||
// If JSObject compatibility is enabled, and the method wants it,
|
||||
// wrap the Scriptable value in a JSObject.
|
||||
|
||||
if (ScriptRuntime.ScriptableClass.isAssignableFrom(type))
|
||||
return value;
|
||||
|
||||
try {
|
||||
Object ctorArgs[] = { value };
|
||||
return jsObjectCtor.newInstance(ctorArgs);
|
||||
} catch (InstantiationException instEx) {
|
||||
throw new EvaluatorException("error generating JSObject wrapper for " +
|
||||
value);
|
||||
} catch (IllegalArgumentException argEx) {
|
||||
throw new EvaluatorException("JSObject constructor doesn't want [Scriptable]!");
|
||||
} catch (InvocationTargetException e) {
|
||||
throw WrappedException.wrapException(e.getTargetException());
|
||||
} catch (IllegalAccessException accessEx) {
|
||||
throw new EvaluatorException("JSObject constructor is protected/private!");
|
||||
}
|
||||
}
|
||||
|
||||
static Object coerceToNumber(Class type, Object value) {
|
||||
Class valueClass = value.getClass();
|
||||
|
||||
// Character
|
||||
if (type == Character.TYPE || type == ScriptRuntime.CharacterClass) {
|
||||
if (valueClass == ScriptRuntime.CharacterClass) {
|
||||
return value;
|
||||
}
|
||||
return new Character((char)toInteger(value,
|
||||
ScriptRuntime.CharacterClass,
|
||||
(double)Character.MIN_VALUE,
|
||||
(double)Character.MAX_VALUE));
|
||||
}
|
||||
|
||||
// Double, Float
|
||||
if (type == ScriptRuntime.ObjectClass ||
|
||||
type == ScriptRuntime.DoubleClass || type == Double.TYPE) {
|
||||
return valueClass == ScriptRuntime.DoubleClass
|
||||
? value
|
||||
: new Double(toDouble(value));
|
||||
}
|
||||
|
||||
if (type == ScriptRuntime.FloatClass || type == Float.TYPE) {
|
||||
if (valueClass == ScriptRuntime.FloatClass) {
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
double number = toDouble(value);
|
||||
if (Double.isInfinite(number) || Double.isNaN(number)
|
||||
|| number == 0.0) {
|
||||
return new Float((float)number);
|
||||
}
|
||||
else {
|
||||
double absNumber = Math.abs(number);
|
||||
if (absNumber < (double)Float.MIN_VALUE) {
|
||||
return new Float((number > 0.0) ? +0.0 : -0.0);
|
||||
}
|
||||
else if (absNumber > (double)Float.MAX_VALUE) {
|
||||
return new Float((number > 0.0) ?
|
||||
Float.POSITIVE_INFINITY :
|
||||
Float.NEGATIVE_INFINITY);
|
||||
}
|
||||
else {
|
||||
return new Float((float)number);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Integer, Long, Short, Byte
|
||||
if (type == ScriptRuntime.IntegerClass || type == Integer.TYPE) {
|
||||
if (valueClass == ScriptRuntime.IntegerClass) {
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
return new Integer((int)toInteger(value,
|
||||
ScriptRuntime.IntegerClass,
|
||||
(double)Integer.MIN_VALUE,
|
||||
(double)Integer.MAX_VALUE));
|
||||
}
|
||||
}
|
||||
|
||||
if (type == ScriptRuntime.LongClass || type == Long.TYPE) {
|
||||
if (valueClass == ScriptRuntime.LongClass) {
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
/* Long values cannot be expressed exactly in doubles.
|
||||
* We thus use the largest and smallest double value that
|
||||
* has a value expressible as a long value. We build these
|
||||
* numerical values from their hexidecimal representations
|
||||
* to avoid any problems caused by attempting to parse a
|
||||
* decimal representation.
|
||||
*/
|
||||
final double max = Double.longBitsToDouble(0x43dfffffffffffffL);
|
||||
final double min = Double.longBitsToDouble(0xc3e0000000000000L);
|
||||
return new Long(toInteger(value,
|
||||
ScriptRuntime.LongClass,
|
||||
min,
|
||||
max));
|
||||
}
|
||||
}
|
||||
|
||||
if (type == ScriptRuntime.ShortClass || type == Short.TYPE) {
|
||||
if (valueClass == ScriptRuntime.ShortClass) {
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
return new Short((short)toInteger(value,
|
||||
ScriptRuntime.ShortClass,
|
||||
(double)Short.MIN_VALUE,
|
||||
(double)Short.MAX_VALUE));
|
||||
}
|
||||
}
|
||||
|
||||
if (type == ScriptRuntime.ByteClass || type == Byte.TYPE) {
|
||||
if (valueClass == ScriptRuntime.ByteClass) {
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
return new Byte((byte)toInteger(value,
|
||||
ScriptRuntime.ByteClass,
|
||||
(double)Byte.MIN_VALUE,
|
||||
(double)Byte.MAX_VALUE));
|
||||
}
|
||||
}
|
||||
|
||||
return new Double(toDouble(value));
|
||||
}
|
||||
|
||||
|
||||
static double toDouble(Object value) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number)value).doubleValue();
|
||||
}
|
||||
else if (value instanceof String) {
|
||||
return ScriptRuntime.toNumber((String)value);
|
||||
}
|
||||
else if (value instanceof Scriptable) {
|
||||
if (value instanceof Wrapper) {
|
||||
// XXX: optimize tail-recursion?
|
||||
return toDouble(((Wrapper)value).unwrap());
|
||||
}
|
||||
else {
|
||||
return ScriptRuntime.toNumber(value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Method meth;
|
||||
try {
|
||||
meth = value.getClass().getMethod("doubleValue", null);
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
meth = null;
|
||||
}
|
||||
catch (SecurityException e) {
|
||||
meth = null;
|
||||
}
|
||||
if (meth != null) {
|
||||
try {
|
||||
return ((Number)meth.invoke(value, null)).doubleValue();
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
// XXX: ignore, or error message?
|
||||
reportConversionError(value, Double.TYPE);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
// XXX: ignore, or error message?
|
||||
reportConversionError(value, Double.TYPE);
|
||||
}
|
||||
}
|
||||
return ScriptRuntime.toNumber(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
static long toInteger(Object value, Class type, double min, double max) {
|
||||
double d = toDouble(value);
|
||||
|
||||
if (Double.isInfinite(d) || Double.isNaN(d)) {
|
||||
// Convert to string first, for more readable message
|
||||
reportConversionError(ScriptRuntime.toString(value), type);
|
||||
}
|
||||
|
||||
if (d > 0.0) {
|
||||
d = Math.floor(d);
|
||||
}
|
||||
else {
|
||||
d = Math.ceil(d);
|
||||
}
|
||||
|
||||
if (d < min || d > max) {
|
||||
// Convert to string first, for more readable message
|
||||
reportConversionError(ScriptRuntime.toString(value), type);
|
||||
}
|
||||
return (long)d;
|
||||
}
|
||||
|
||||
static void reportConversionError(Object value, Class type) {
|
||||
Object[] args = { value.toString(),
|
||||
NativeJavaMethod.javaSignature(type)
|
||||
};
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.conversion.not.allowed", args));
|
||||
}
|
||||
|
||||
public static void initJSObject() {
|
||||
if (!Context.useJSObject)
|
||||
return;
|
||||
// if netscape.javascript.JSObject is in the CLASSPATH, enable JSObject
|
||||
// compatability wrappers
|
||||
jsObjectClass = null;
|
||||
try {
|
||||
jsObjectClass = Class.forName("netscape.javascript.JSObject");
|
||||
Class ctorParms[] = { ScriptRuntime.ScriptableClass };
|
||||
jsObjectCtor = jsObjectClass.getConstructor(ctorParms);
|
||||
jsObjectGetScriptable = jsObjectClass.getMethod("getScriptable",
|
||||
new Class[0]);
|
||||
} catch (ClassNotFoundException classEx) {
|
||||
// jsObjectClass already null
|
||||
} catch (NoSuchMethodException methEx) {
|
||||
// jsObjectClass already null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The prototype of this object.
|
||||
*/
|
||||
protected Scriptable prototype;
|
||||
|
||||
/**
|
||||
* The parent scope of this object.
|
||||
*/
|
||||
protected Scriptable parent;
|
||||
|
||||
protected Object javaObject;
|
||||
protected JavaMembers members;
|
||||
private Hashtable fieldAndMethods;
|
||||
static Class jsObjectClass;
|
||||
static Constructor jsObjectCtor;
|
||||
static Method jsObjectGetScriptable;
|
||||
}
|
||||
|
||||
237
mozilla/js/rhino/org/mozilla/javascript/NativeJavaPackage.java
Normal file
237
mozilla/js/rhino/org/mozilla/javascript/NativeJavaPackage.java
Normal file
@@ -0,0 +1,237 @@
|
||||
/* -*- 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.*;
|
||||
|
||||
/**
|
||||
* This class reflects Java packages into the JavaScript environment. We
|
||||
* lazily reflect classes and subpackages, and use a caching/sharing
|
||||
* system to ensure that members reflected into one JavaPackage appear
|
||||
* in all other references to the same package (as with Packages.java.lang
|
||||
* and java.lang).
|
||||
*
|
||||
* @author Mike Shaver
|
||||
* @see NativeJavaArray
|
||||
* @see NativeJavaObject
|
||||
* @see NativeJavaClass
|
||||
*/
|
||||
|
||||
public class NativeJavaPackage extends ScriptableObject {
|
||||
|
||||
// we know these are packages so we can skip the class check
|
||||
// note that this is ok even if the package isn't present.
|
||||
static final String[] commonPackages = {
|
||||
"java.lang",
|
||||
"java.lang.reflect",
|
||||
"java.io",
|
||||
"java.math",
|
||||
"java.util",
|
||||
"java.util.zip",
|
||||
"java.text",
|
||||
"java.text.resources",
|
||||
"java.applet",
|
||||
};
|
||||
|
||||
public static Scriptable init(Scriptable scope)
|
||||
throws PropertyException
|
||||
{
|
||||
NativeJavaPackage packages = new NativeJavaPackage("");
|
||||
packages.setPrototype(getObjectPrototype(scope));
|
||||
packages.setParentScope(scope);
|
||||
|
||||
// We want to get a real alias, and not a distinct JavaPackage
|
||||
// with the same packageName, so that we share classes and packages
|
||||
// that are underneath.
|
||||
NativeJavaPackage javaAlias = (NativeJavaPackage)packages.get("java",
|
||||
packages);
|
||||
|
||||
// It's safe to downcast here since initStandardObjects takes
|
||||
// a ScriptableObject.
|
||||
ScriptableObject global = (ScriptableObject) scope;
|
||||
|
||||
global.defineProperty("Packages", packages, ScriptableObject.DONTENUM);
|
||||
global.defineProperty("java", javaAlias, ScriptableObject.DONTENUM);
|
||||
|
||||
for (int i = 0; i < commonPackages.length; i++)
|
||||
packages.forcePackage(commonPackages[i]);
|
||||
|
||||
NativeJavaObject.initJSObject();
|
||||
|
||||
Method[] m = FunctionObject.findMethods(NativeJavaPackage.class,
|
||||
"jsFunction_getClass");
|
||||
FunctionObject f = new FunctionObject("getClass", m[0], global);
|
||||
global.defineProperty("getClass", f, ScriptableObject.DONTENUM);
|
||||
|
||||
// I think I'm supposed to return the prototype, but I don't have one.
|
||||
return packages;
|
||||
}
|
||||
|
||||
// set up a name which is known to be a package so we don't
|
||||
// need to look for a class by that name
|
||||
void forcePackage(String name) {
|
||||
NativeJavaPackage pkg;
|
||||
int end = name.indexOf('.');
|
||||
if (end == -1)
|
||||
end = name.length();
|
||||
|
||||
String id = name.substring(0, end);
|
||||
Object cached = super.get(id, this);
|
||||
if (cached != null && cached instanceof NativeJavaPackage) {
|
||||
pkg = (NativeJavaPackage) cached;
|
||||
} else {
|
||||
String newPackage = packageName.length() == 0
|
||||
? id
|
||||
: packageName + "." + id;
|
||||
pkg = new NativeJavaPackage(newPackage);
|
||||
pkg.setParentScope(this);
|
||||
pkg.setPrototype(this.prototype);
|
||||
super.put(id, this, pkg);
|
||||
}
|
||||
if (end < name.length())
|
||||
pkg.forcePackage(name.substring(end+1));
|
||||
}
|
||||
|
||||
public NativeJavaPackage(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "JavaPackage";
|
||||
}
|
||||
|
||||
public boolean has(String id, int index, Scriptable start) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void put(String id, Scriptable start, Object value) {
|
||||
// Can't add properties to Java packages. Sorry.
|
||||
}
|
||||
|
||||
public void put(int index, Scriptable start, Object value) {
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.pkg.int", null));
|
||||
}
|
||||
|
||||
public Object get(String id, Scriptable start) {
|
||||
return getPkgProperty(id, start, true);
|
||||
}
|
||||
|
||||
public Object get(int index, Scriptable start) {
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
synchronized Object getPkgProperty(String name, Scriptable start,
|
||||
boolean createPkg)
|
||||
{
|
||||
Object cached = super.get(name, start);
|
||||
if (cached != NOT_FOUND)
|
||||
return cached;
|
||||
|
||||
String newPackage = packageName.length() == 0
|
||||
? name
|
||||
: packageName + "." + name;
|
||||
Context cx = Context.getContext();
|
||||
SecuritySupport ss = cx.getSecuritySupport();
|
||||
Scriptable newValue;
|
||||
try {
|
||||
if (ss != null && !ss.visibleToScripts(newPackage))
|
||||
throw new ClassNotFoundException();
|
||||
Class newClass = ScriptRuntime.loadClassName(newPackage);
|
||||
newValue = NativeJavaClass.wrap(getTopLevelScope(this), newClass);
|
||||
newValue.setParentScope(this);
|
||||
newValue.setPrototype(this.prototype);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
if (createPkg) {
|
||||
NativeJavaPackage pkg = new NativeJavaPackage(newPackage);
|
||||
pkg.setParentScope(this);
|
||||
pkg.setPrototype(this.prototype);
|
||||
newValue = pkg;
|
||||
} else {
|
||||
newValue = null;
|
||||
}
|
||||
}
|
||||
if (newValue != null) {
|
||||
// Make it available for fast lookup and sharing of
|
||||
// lazily-reflected constructors and static members.
|
||||
super.put(name, start, newValue);
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
|
||||
public Object getDefaultValue(Class ignored) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "[JavaPackage " + packageName + "]";
|
||||
}
|
||||
|
||||
public static Scriptable jsFunction_getClass(Context cx,
|
||||
Scriptable thisObj,
|
||||
Object[] args,
|
||||
Function funObj)
|
||||
{
|
||||
if (args.length > 0 && args[0] instanceof NativeJavaObject) {
|
||||
NativeJavaObject nativeJavaObj = (NativeJavaObject) args[0];
|
||||
Scriptable result = getTopLevelScope(thisObj);
|
||||
Class cl = nativeJavaObj.unwrap().getClass();
|
||||
// Evaluate the class name by getting successive properties of
|
||||
// the string to find the appropriate NativeJavaClass object
|
||||
String name = "Packages." + cl.getName();
|
||||
int offset = 0;
|
||||
for (;;) {
|
||||
int index = name.indexOf('.', offset);
|
||||
String propName = index == -1
|
||||
? name.substring(offset)
|
||||
: name.substring(offset, index);
|
||||
Object prop = result.get(propName, result);
|
||||
if (!(prop instanceof Scriptable))
|
||||
break; // fall through to error
|
||||
result = (Scriptable) prop;
|
||||
if (index == -1)
|
||||
return result;
|
||||
offset = index+1;
|
||||
}
|
||||
}
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.not.java.obj", null));
|
||||
}
|
||||
|
||||
private String packageName;
|
||||
}
|
||||
198
mozilla/js/rhino/org/mozilla/javascript/NativeMath.java
Normal file
198
mozilla/js/rhino/org/mozilla/javascript/NativeMath.java
Normal file
@@ -0,0 +1,198 @@
|
||||
/* -*- 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.
|
||||
*/
|
||||
|
||||
package org.mozilla.javascript;
|
||||
|
||||
/**
|
||||
* This class implements the Math native object.
|
||||
* See ECMA 15.8.
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public class NativeMath extends ScriptableObject {
|
||||
|
||||
public static Scriptable init(Scriptable scope)
|
||||
throws PropertyException
|
||||
{
|
||||
NativeMath m = new NativeMath();
|
||||
m.setPrototype(getObjectPrototype(scope));
|
||||
m.setParentScope(scope);
|
||||
|
||||
String[] names = { "atan", "atan2", "ceil",
|
||||
"cos", "floor", "random",
|
||||
"sin", "sqrt", "tan" };
|
||||
|
||||
m.defineFunctionProperties(names, java.lang.Math.class,
|
||||
ScriptableObject.DONTENUM);
|
||||
|
||||
// These functions exist in java.lang.Math, but
|
||||
// are overloaded. Define our own wrappers.
|
||||
String[] localNames = { "acos", "asin", "abs", "exp", "max", "min",
|
||||
"round", "pow", "log" };
|
||||
|
||||
m.defineFunctionProperties(localNames, NativeMath.class,
|
||||
ScriptableObject.DONTENUM);
|
||||
|
||||
/*
|
||||
have to fix up the length property for max & min
|
||||
which are varargs form, but need to have a length of 2
|
||||
*/
|
||||
((FunctionObject)m.get("max", scope)).setLength((short)2);
|
||||
((FunctionObject)m.get("min", scope)).setLength((short)2);
|
||||
|
||||
final int attr = ScriptableObject.DONTENUM |
|
||||
ScriptableObject.PERMANENT |
|
||||
ScriptableObject.READONLY;
|
||||
|
||||
m.defineProperty("E", new Double(Math.E), attr);
|
||||
m.defineProperty("PI", new Double(Math.PI), attr);
|
||||
m.defineProperty("LN10", new Double(2.302585092994046), attr);
|
||||
m.defineProperty("LN2", new Double(0.6931471805599453), attr);
|
||||
m.defineProperty("LOG2E", new Double(1.4426950408889634), attr);
|
||||
m.defineProperty("LOG10E", new Double(0.4342944819032518), attr);
|
||||
m.defineProperty("SQRT1_2", new Double(0.7071067811865476), attr);
|
||||
m.defineProperty("SQRT2", new Double(1.4142135623730951), attr);
|
||||
|
||||
// We know that scope is a Scriptable object since we
|
||||
// constrained the type on initStandardObjects.
|
||||
ScriptableObject global = (ScriptableObject) scope;
|
||||
global.defineProperty("Math", m, ScriptableObject.DONTENUM);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
public NativeMath() {
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "Math";
|
||||
}
|
||||
|
||||
public static double abs(double d) {
|
||||
if (d == 0.0)
|
||||
return 0.0; // abs(-0.0) should be 0.0, but -0.0 < 0.0 == false
|
||||
else if (d < 0.0)
|
||||
return -d;
|
||||
else
|
||||
return d;
|
||||
}
|
||||
|
||||
public static double acos(double d) {
|
||||
if ((d != d)
|
||||
|| (d > 1.0)
|
||||
|| (d < -1.0))
|
||||
return Double.NaN;
|
||||
return Math.acos(d);
|
||||
}
|
||||
|
||||
public static double asin(double d) {
|
||||
if ((d != d)
|
||||
|| (d > 1.0)
|
||||
|| (d < -1.0))
|
||||
return Double.NaN;
|
||||
return Math.asin(d);
|
||||
}
|
||||
|
||||
public static double max(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
double result = Double.NEGATIVE_INFINITY;
|
||||
if (args.length == 0)
|
||||
return result;
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
double d = ScriptRuntime.toNumber(args[i]);
|
||||
if (d != d) return d;
|
||||
result = Math.max(result, d);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double min(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
double result = Double.POSITIVE_INFINITY;
|
||||
if (args.length == 0)
|
||||
return result;
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
double d = ScriptRuntime.toNumber(args[i]);
|
||||
if (d != d) return d;
|
||||
result = Math.min(result, d);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double round(double d) {
|
||||
if (d != d)
|
||||
return d; // NaN
|
||||
if (d == Double.POSITIVE_INFINITY || d == Double.NEGATIVE_INFINITY)
|
||||
return d;
|
||||
long l = Math.round(d);
|
||||
if (l == 0) {
|
||||
// We must propagate the sign of d into the result
|
||||
if (d < 0.0)
|
||||
return ScriptRuntime.negativeZero;
|
||||
return d == 0.0 ? d : 0.0;
|
||||
}
|
||||
return (double) l;
|
||||
}
|
||||
|
||||
public static double pow(double x, double y) {
|
||||
if (y == 0)
|
||||
return 1.0; // Java's pow(NaN, 0) = NaN; we need 1
|
||||
if ((x == 0) && (y < 0)) {
|
||||
Double d = new Double(x);
|
||||
if (d.equals(new Double(0))) // x is +0
|
||||
return Double.POSITIVE_INFINITY; // Java is -Infinity
|
||||
/* if x is -0 and y is an odd integer, -Infinity */
|
||||
if (((int)y == y) && (((int)y & 0x1) == 1))
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
return Double.POSITIVE_INFINITY;
|
||||
}
|
||||
return Math.pow(x, y);
|
||||
}
|
||||
|
||||
public static double exp(double d) {
|
||||
if (d == Double.POSITIVE_INFINITY)
|
||||
return d;
|
||||
if (d == Double.NEGATIVE_INFINITY)
|
||||
return 0.0;
|
||||
return Math.exp(d);
|
||||
}
|
||||
|
||||
public static double log(double x) {
|
||||
if (x < 0)
|
||||
return Double.NaN; // Java's log(<0) = -Infinity; we need NaN
|
||||
return Math.log(x);
|
||||
}
|
||||
|
||||
}
|
||||
162
mozilla/js/rhino/org/mozilla/javascript/NativeNumber.java
Normal file
162
mozilla/js/rhino/org/mozilla/javascript/NativeNumber.java
Normal file
@@ -0,0 +1,162 @@
|
||||
/* -*- 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 Number native object.
|
||||
*
|
||||
* See ECMA 15.7.
|
||||
*
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public class NativeNumber extends ScriptableObject {
|
||||
|
||||
public static void finishInit(Scriptable scope,
|
||||
FunctionObject ctor, Scriptable proto)
|
||||
{
|
||||
final int attr = ScriptableObject.DONTENUM |
|
||||
ScriptableObject.PERMANENT |
|
||||
ScriptableObject.READONLY;
|
||||
|
||||
String[] names = { "NaN", "POSITIVE_INFINITY", "NEGATIVE_INFINITY",
|
||||
"MAX_VALUE", "MIN_VALUE" };
|
||||
double[] values = { ScriptRuntime.NaN, Double.POSITIVE_INFINITY,
|
||||
Double.NEGATIVE_INFINITY, Double.MAX_VALUE,
|
||||
Double.MIN_VALUE };
|
||||
for (int i=0; i < names.length; i++) {
|
||||
ctor.defineProperty(names[i], new Double(values[i]), attr);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int MAX_PRECISION = 100;
|
||||
|
||||
/**
|
||||
* Zero-parameter constructor: just used to create Number.prototype
|
||||
*/
|
||||
public NativeNumber() {
|
||||
doubleValue = defaultValue;
|
||||
}
|
||||
|
||||
public NativeNumber(double number) {
|
||||
doubleValue = number;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "Number";
|
||||
}
|
||||
|
||||
public static Object jsConstructor(Context cx, Object[] args,
|
||||
Function funObj, boolean inNewExpr)
|
||||
{
|
||||
double d = args.length >= 1
|
||||
? ScriptRuntime.toNumber(args[0])
|
||||
: defaultValue;
|
||||
if (inNewExpr) {
|
||||
// new Number(val) creates a new Number object.
|
||||
return new NativeNumber(d);
|
||||
}
|
||||
// Number(val) converts val to a number value.
|
||||
return new Double(d);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return jsFunction_toString(Undefined.instance);
|
||||
}
|
||||
|
||||
public String jsFunction_toString(Object base) {
|
||||
int i = base == Undefined.instance
|
||||
? 10
|
||||
: ScriptRuntime.toInt32(base);
|
||||
return ScriptRuntime.numberToString(doubleValue, i);
|
||||
}
|
||||
|
||||
public double jsFunction_valueOf() {
|
||||
return doubleValue;
|
||||
}
|
||||
|
||||
public String jsFunction_toLocaleString(Object arg) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
public String jsFunction_toFixed(Object arg) {
|
||||
/* We allow a larger range of precision than
|
||||
ECMA requires; this is permitted by ECMA. */
|
||||
return num_to(arg, DToA.DTOSTR_FIXED, DToA.DTOSTR_FIXED,
|
||||
-20, MAX_PRECISION, 0);
|
||||
}
|
||||
|
||||
public String jsFunction_toExponential(Object arg) {
|
||||
/* We allow a larger range of precision than
|
||||
ECMA requires; this is permitted by ECMA. */
|
||||
return num_to(arg, DToA.DTOSTR_STANDARD_EXPONENTIAL,
|
||||
DToA.DTOSTR_EXPONENTIAL, 0, MAX_PRECISION, 1);
|
||||
}
|
||||
|
||||
public String jsFunction_toPrecision(Object arg) {
|
||||
/* We allow a larger range of precision than
|
||||
ECMA requires; this is permitted by ECMA. */
|
||||
return num_to(arg, DToA.DTOSTR_STANDARD,
|
||||
DToA.DTOSTR_PRECISION, 1, MAX_PRECISION, 0);
|
||||
}
|
||||
|
||||
private String num_to(Object arg, int zeroArgMode,
|
||||
int oneArgMode, int precisionMin, int precisionMax, int precisionOffset)
|
||||
{
|
||||
int precision;
|
||||
|
||||
if (arg == Undefined.instance) {
|
||||
precision = 0;
|
||||
oneArgMode = zeroArgMode;
|
||||
} else {
|
||||
precision = ScriptRuntime.toInt32(arg);
|
||||
if (precision < precisionMin || precision > precisionMax) {
|
||||
Object args[] = new Object[1];
|
||||
args[0] = Integer.toString(precision);
|
||||
throw NativeGlobal.constructError(
|
||||
Context.getCurrentContext(), "RangeError",
|
||||
ScriptRuntime.getMessage("msg.bad.precision", args),
|
||||
this);
|
||||
}
|
||||
}
|
||||
StringBuffer result = new StringBuffer();
|
||||
DToA.JS_dtostr(result, oneArgMode, precision + precisionOffset, doubleValue);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static final double defaultValue = +0.0;
|
||||
private double doubleValue;
|
||||
}
|
||||
193
mozilla/js/rhino/org/mozilla/javascript/NativeObject.java
Normal file
193
mozilla/js/rhino/org/mozilla/javascript/NativeObject.java
Normal file
@@ -0,0 +1,193 @@
|
||||
/* -*- 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 Object native object.
|
||||
* See ECMA 15.2.
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public class NativeObject extends ScriptableObject {
|
||||
|
||||
public static void finishInit(Scriptable scope, FunctionObject ctor,
|
||||
Scriptable proto)
|
||||
{
|
||||
Object obj = proto.get("valueOf", proto);
|
||||
((FunctionObject) obj).setLength((short) 0);
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "Object";
|
||||
}
|
||||
|
||||
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 || args[0] == null ||
|
||||
args[0] == Undefined.instance)
|
||||
{
|
||||
return new NativeObject();
|
||||
}
|
||||
return ScriptRuntime.toObject(ctorObj.getParentScope(), args[0]);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
Context cx = Context.getContext();
|
||||
if (cx != null)
|
||||
return jsFunction_toString(cx, this, null, null);
|
||||
else
|
||||
return "[object " + getClassName() + "]";
|
||||
}
|
||||
|
||||
public static String jsFunction_toString(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
if (cx.getLanguageVersion() != cx.VERSION_1_2)
|
||||
return "[object " + thisObj.getClassName() + "]";
|
||||
|
||||
return toSource(cx, thisObj, args, funObj);
|
||||
}
|
||||
|
||||
public static String toSource(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
Scriptable m = thisObj;
|
||||
|
||||
if (cx.iterating == null)
|
||||
cx.iterating = new Hashtable(31);
|
||||
|
||||
if (cx.iterating.get(m) == Boolean.TRUE) {
|
||||
return "{}"; // stop recursion
|
||||
} else {
|
||||
StringBuffer result = new StringBuffer("{");
|
||||
Object[] ids = m.getIds();
|
||||
|
||||
for(int i=0; i < ids.length; i++) {
|
||||
if (i > 0)
|
||||
result.append(", ");
|
||||
|
||||
Object id = ids[i];
|
||||
String idString = ScriptRuntime.toString(id);
|
||||
Object p = (id instanceof String)
|
||||
? m.get((String) id, m)
|
||||
: m.get(((Number) id).intValue(), m);
|
||||
if (p instanceof String) {
|
||||
result.append(idString + ":\""
|
||||
+ ScriptRuntime
|
||||
.escapeString(ScriptRuntime.toString(p))
|
||||
+ "\"");
|
||||
} 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 {
|
||||
cx.iterating.put(m, Boolean.TRUE); // stop recursion.
|
||||
result.append(idString + ":" + ScriptRuntime.toString(p));
|
||||
} finally {
|
||||
cx.iterating.remove(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
result.append("}");
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static Object jsFunction_valueOf(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
return thisObj;
|
||||
}
|
||||
|
||||
public static Object jsFunction_hasOwnProperty(Context cx,
|
||||
Scriptable thisObj,
|
||||
Object[] args,
|
||||
Function funObj)
|
||||
{
|
||||
if (args.length != 0)
|
||||
if (thisObj.has(ScriptRuntime.toString(args[0]), thisObj))
|
||||
return Boolean.TRUE;
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
public static Object jsFunction_propertyIsEnumerable(Context cx,
|
||||
Scriptable thisObj,
|
||||
Object[] args,
|
||||
Function funObj)
|
||||
{
|
||||
try {
|
||||
if (args.length != 0) {
|
||||
String name = ScriptRuntime.toString(args[0]);
|
||||
if (thisObj.has(name, thisObj)) {
|
||||
int a = ((ScriptableObject)thisObj).getAttributes(name, thisObj);
|
||||
if ((a & ScriptableObject.DONTENUM) == 0)
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (PropertyException x) {
|
||||
}
|
||||
catch (ClassCastException x) {
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
public static Object jsFunction_isPrototypeOf(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
if (args.length != 0 && args[0] instanceof Scriptable) {
|
||||
Scriptable v = (Scriptable) args[0];
|
||||
do {
|
||||
v = v.getPrototype();
|
||||
if (v == thisObj)
|
||||
return Boolean.TRUE;
|
||||
} while (v != null);
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
172
mozilla/js/rhino/org/mozilla/javascript/NativeScript.java
Normal file
172
mozilla/js/rhino/org/mozilla/javascript/NativeScript.java
Normal file
@@ -0,0 +1,172 @@
|
||||
/* -*- 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
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The JavaScript Script object.
|
||||
*
|
||||
* Note that the C version of the engine uses XDR as the format used
|
||||
* by freeze and thaw. Since this depends on the internal format of
|
||||
* structures in the C runtime, we cannot duplicate it.
|
||||
*
|
||||
* Since we cannot replace 'this' as a result of the compile method,
|
||||
* this class has a dual nature. Generated scripts will have a null
|
||||
* 'script' field and will override 'exec' and 'call'. Scripts created
|
||||
* using the JavaScript constructor will forward requests to the
|
||||
* nonnull 'script' field.
|
||||
*
|
||||
* @since 1.3
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
|
||||
public class NativeScript extends NativeFunction implements Script {
|
||||
|
||||
public NativeScript() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this JavaScript class, "Script".
|
||||
*/
|
||||
public String getClassName() {
|
||||
return "Script";
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize script.
|
||||
*
|
||||
* Does nothing here, but scripts will override with code
|
||||
* to initialize contained functions, regexp literals, etc.
|
||||
*/
|
||||
public void initScript(Scriptable scope) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The Java method defining the JavaScript Script constructor.
|
||||
*
|
||||
*/
|
||||
public static Object jsConstructor(Context cx, Object[] args,
|
||||
Function ctorObj, boolean inNewExpr)
|
||||
{
|
||||
String source = args.length == 0
|
||||
? ""
|
||||
: ScriptRuntime.toString(args[0]);
|
||||
Scriptable scope = cx.ctorScope;
|
||||
if (scope == null)
|
||||
scope = ctorObj;
|
||||
return compile(scope, source);
|
||||
}
|
||||
|
||||
public static Script compile(Scriptable scope, String source) {
|
||||
Context cx = Context.getContext();
|
||||
StringReader reader = new StringReader(source);
|
||||
try {
|
||||
int[] linep = { 0 };
|
||||
String filename = Context.getSourcePositionFromStack(linep);
|
||||
if (filename == null) {
|
||||
filename = "<Script object>";
|
||||
linep[0] = 1;
|
||||
}
|
||||
Object securityDomain =
|
||||
cx.getSecurityDomainForStackDepth(5);
|
||||
return cx.compileReader(scope, reader, filename, linep[0],
|
||||
securityDomain);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException("Unexpected IOException");
|
||||
}
|
||||
}
|
||||
|
||||
public Scriptable jsFunction_compile(String source) {
|
||||
script = compile(null, source);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object jsFunction_exec() throws JavaScriptException {
|
||||
Object[] msgArgs = { "exec" };
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.cant.call.indirect", msgArgs));
|
||||
}
|
||||
|
||||
public static Object jsFunction_toString(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
Script thisScript = ((NativeScript) thisObj).script;
|
||||
if (thisScript == null)
|
||||
thisScript = (Script) thisObj;
|
||||
Scriptable scope = getTopLevelScope(thisObj);
|
||||
return cx.decompileScript(thisScript, scope, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Override method in NativeFunction to avoid ever returning "anonymous"
|
||||
*/
|
||||
public String jsGet_name() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the script.
|
||||
*
|
||||
* Will be overridden by generated scripts; needed to implement Script.
|
||||
*/
|
||||
public Object exec(Context cx, Scriptable scope)
|
||||
throws JavaScriptException
|
||||
{
|
||||
return script == null ? Undefined.instance : script.exec(cx, scope);
|
||||
}
|
||||
|
||||
public Object call(Context cx, Scriptable scope, Scriptable thisObj,
|
||||
Object[] args)
|
||||
throws JavaScriptException
|
||||
{
|
||||
return exec(cx, scope);
|
||||
}
|
||||
|
||||
public Scriptable construct(Context cx, Scriptable scope, Object[] args)
|
||||
throws JavaScriptException
|
||||
{
|
||||
String message = Context.getMessage("msg.script.is.not.constructor", null);
|
||||
throw Context.reportRuntimeError(message);
|
||||
}
|
||||
|
||||
private Script script;
|
||||
}
|
||||
|
||||
747
mozilla/js/rhino/org/mozilla/javascript/NativeString.java
Normal file
747
mozilla/js/rhino/org/mozilla/javascript/NativeString.java
Normal file
@@ -0,0 +1,747 @@
|
||||
/* -*- 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):
|
||||
* Tom Beauvais
|
||||
* 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.lang.reflect.Method;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* This class implements the String native object.
|
||||
*
|
||||
* See ECMA 15.5.
|
||||
*
|
||||
* String methods for dealing with regular expressions are
|
||||
* ported directly from C. Latest port is from version 1.40.12.19
|
||||
* in the JSFUN13_BRANCH.
|
||||
*
|
||||
* @author Mike McCabe
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
public class NativeString extends ScriptableObject implements Wrapper {
|
||||
|
||||
/**
|
||||
* Zero-parameter constructor: just used to create String.prototype
|
||||
*/
|
||||
public NativeString() {
|
||||
string = defaultValue;
|
||||
}
|
||||
|
||||
public static void finishInit(Scriptable scope, FunctionObject ctor,
|
||||
Scriptable proto)
|
||||
{
|
||||
// Most of the methods of String.prototype are "vararg" form
|
||||
// so that they can convert the "this" value to string, rather
|
||||
// than being restricted to just operating on NativeString
|
||||
// objects. However, this means that the values of the "length"
|
||||
// properties of these methods are set to 1 by the constructor
|
||||
// for FunctionObject. We must therefore fetch the function
|
||||
// objects and set the length to the appropriate value.
|
||||
|
||||
String[] specialLengthNames = { "indexOf",
|
||||
"lastIndexOf",
|
||||
"substring",
|
||||
"toUpperCase",
|
||||
"toLowerCase",
|
||||
"toString",
|
||||
};
|
||||
|
||||
short[] specialLengthValues = { 2,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
for (int i=0; i < specialLengthNames.length; i++) {
|
||||
Object obj = proto.get(specialLengthNames[i], proto);
|
||||
((FunctionObject) obj).setLength(specialLengthValues[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public NativeString(String s) {
|
||||
string = s;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "String";
|
||||
}
|
||||
|
||||
public static String jsStaticFunction_fromCharCode(Context cx,
|
||||
Scriptable thisObj,
|
||||
Object[] args,
|
||||
Function funObj)
|
||||
{
|
||||
if (args.length < 1)
|
||||
return "";
|
||||
StringBuffer s = new java.lang.StringBuffer();
|
||||
for (int i=0; i < args.length; i++) {
|
||||
s.append(ScriptRuntime.toUint16(args[i]));
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
public static Object jsConstructor(Context cx, Object[] args,
|
||||
Function ctorObj, boolean inNewExpr)
|
||||
{
|
||||
String s = args.length >= 1
|
||||
? ScriptRuntime.toString(args[0])
|
||||
: defaultValue;
|
||||
if (inNewExpr) {
|
||||
// new String(val) creates a new String object.
|
||||
return new NativeString(s);
|
||||
}
|
||||
// String(val) converts val to a string value.
|
||||
return s;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return string;
|
||||
}
|
||||
|
||||
/* ECMA 15.5.4.2: 'the toString function is not generic.' */
|
||||
public String jsFunction_toString() {
|
||||
return string;
|
||||
}
|
||||
|
||||
public String jsFunction_valueOf() {
|
||||
return string;
|
||||
}
|
||||
|
||||
/* Make array-style property lookup work for strings.
|
||||
* XXX is this ECMA? A version check is probably needed. In js too.
|
||||
*/
|
||||
public Object get(int index, Scriptable start) {
|
||||
if (index >= 0 && index < string.length())
|
||||
return string.substring(index, index + 1);
|
||||
return super.get(index, start);
|
||||
}
|
||||
|
||||
public void put(int index, Scriptable start, Object value) {
|
||||
if (index >= 0 && index < string.length())
|
||||
return;
|
||||
super.put(index, start, value);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* See ECMA 15.5.4.[4,5]
|
||||
*/
|
||||
public static String jsFunction_charAt(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
if (args.length < 1)
|
||||
args = ScriptRuntime.padArguments(args, 1);
|
||||
|
||||
// this'll return 0 if undefined... seems
|
||||
// to be ECMA.
|
||||
String target = ScriptRuntime.toString(thisObj);
|
||||
double pos = ScriptRuntime.toInteger(args[0]);
|
||||
|
||||
if (pos < 0 || pos >= target.length())
|
||||
return "";
|
||||
|
||||
return target.substring((int)pos, (int)pos + 1);
|
||||
}
|
||||
|
||||
public static double jsFunction_charCodeAt(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
if (args.length < 1)
|
||||
args = ScriptRuntime.padArguments(args, 1);
|
||||
|
||||
String target = ScriptRuntime.toString(thisObj);
|
||||
double pos = ScriptRuntime.toInteger(args[0]);
|
||||
|
||||
if (pos < 0 || pos >= target.length()) {
|
||||
return ScriptRuntime.NaN;
|
||||
}
|
||||
|
||||
return target.charAt((int)pos);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* See ECMA 15.5.4.6. Uses Java String.indexOf()
|
||||
* OPT to add - BMH searching from jsstr.c.
|
||||
*/
|
||||
public static int jsFunction_indexOf(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
if (args.length < 2)
|
||||
args = ScriptRuntime.padArguments(args, 2);
|
||||
|
||||
String target = ScriptRuntime.toString(thisObj);
|
||||
String search = ScriptRuntime.toString(args[0]);
|
||||
double begin = ScriptRuntime.toInteger(args[1]);
|
||||
|
||||
if (begin > target.length()) {
|
||||
return -1;
|
||||
} else {
|
||||
if (begin < 0)
|
||||
begin = 0;
|
||||
return target.indexOf(search, (int)begin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* See ECMA 15.5.4.7
|
||||
*
|
||||
*/
|
||||
public static int jsFunction_lastIndexOf(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
if (args.length < 2)
|
||||
args = ScriptRuntime.padArguments(args, 2);
|
||||
|
||||
String target = ScriptRuntime.toString(thisObj);
|
||||
String search = ScriptRuntime.toString(args[0]);
|
||||
double end = ScriptRuntime.toNumber(args[1]);
|
||||
|
||||
if (end != end || end > target.length())
|
||||
end = target.length();
|
||||
else if (end < 0)
|
||||
end = 0;
|
||||
|
||||
return target.lastIndexOf(search, (int)end);
|
||||
}
|
||||
|
||||
/*
|
||||
* Used by js_split to find the next split point in target,
|
||||
* starting at offset ip and looking either for the given
|
||||
* separator substring, or for the next re match. ip and
|
||||
* matchlen must be reference variables (assumed to be arrays of
|
||||
* length 1) so they can be updated in the leading whitespace or
|
||||
* re case.
|
||||
*
|
||||
* Return -1 on end of string, >= 0 for a valid index of the next
|
||||
* separator occurrence if found, or the string length if no
|
||||
* separator is found.
|
||||
*/
|
||||
private static int find_split(Function funObj, String target,
|
||||
String separator, Object re,
|
||||
int[] ip, int[] matchlen, boolean[] matched,
|
||||
String[][] parensp)
|
||||
{
|
||||
int i = ip[0];
|
||||
int length = target.length();
|
||||
Context cx = Context.getContext();
|
||||
int version = cx.getLanguageVersion();
|
||||
|
||||
/*
|
||||
* Perl4 special case for str.split(' '), only if the user has selected
|
||||
* JavaScript1.2 explicitly. Split on whitespace, and skip leading w/s.
|
||||
* Strange but true, apparently modeled after awk.
|
||||
*/
|
||||
if (version == Context.VERSION_1_2 &&
|
||||
re == null && separator.length() == 1 && separator.charAt(0) == ' ')
|
||||
{
|
||||
/* Skip leading whitespace if at front of str. */
|
||||
if (i == 0) {
|
||||
while (i < length && Character.isWhitespace(target.charAt(i)))
|
||||
i++;
|
||||
ip[0] = i;
|
||||
}
|
||||
|
||||
/* Don't delimit whitespace at end of string. */
|
||||
if (i == length)
|
||||
return -1;
|
||||
|
||||
/* Skip over the non-whitespace chars. */
|
||||
while (i < length
|
||||
&& !Character.isWhitespace(target.charAt(i)))
|
||||
i++;
|
||||
|
||||
/* Now skip the next run of whitespace. */
|
||||
int j = i;
|
||||
while (j < length && Character.isWhitespace(target.charAt(j)))
|
||||
j++;
|
||||
|
||||
/* Update matchlen to count delimiter chars. */
|
||||
matchlen[0] = j - i;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop if past end of string. If at end of string, we will
|
||||
* return target length, so that
|
||||
*
|
||||
* "ab,".split(',') => new Array("ab", "")
|
||||
*
|
||||
* and the resulting array converts back to the string "ab,"
|
||||
* for symmetry. NB: This differs from perl, which drops the
|
||||
* trailing empty substring if the LIMIT argument is omitted.
|
||||
*/
|
||||
if (i > length)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Match a regular expression against the separator at or
|
||||
* above index i. Return -1 at end of string instead of
|
||||
* trying for a match, so we don't get stuck in a loop.
|
||||
*/
|
||||
if (re != null) {
|
||||
return cx.getRegExpProxy().find_split(funObj, target,
|
||||
separator, re,
|
||||
ip, matchlen, matched,
|
||||
parensp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Deviate from ECMA by never splitting an empty string by any separator
|
||||
* string into a non-empty array (an array of length 1 that contains the
|
||||
* empty string).
|
||||
*/
|
||||
if (version != Context.VERSION_DEFAULT && version < Context.VERSION_1_3
|
||||
&& length == 0)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Special case: if sep is the empty string, split str into
|
||||
* one character substrings. Let our caller worry about
|
||||
* whether to split once at end of string into an empty
|
||||
* substring.
|
||||
*
|
||||
* For 1.2 compatibility, at the end of the string, we return the length as
|
||||
* the result, and set the separator length to 1 -- this allows the caller
|
||||
* to include an additional null string at the end of the substring list.
|
||||
*/
|
||||
if (separator.length() == 0) {
|
||||
if (version == Context.VERSION_1_2) {
|
||||
if (i == length) {
|
||||
matchlen[0] = 1;
|
||||
return i;
|
||||
}
|
||||
return i + 1;
|
||||
}
|
||||
return (i == length) ? -1 : i + 1;
|
||||
}
|
||||
|
||||
/* Punt to j.l.s.indexOf; return target length if seperator is
|
||||
* not found.
|
||||
*/
|
||||
if (ip[0] >= length)
|
||||
return length;
|
||||
|
||||
i = target.indexOf(separator, ip[0]);
|
||||
|
||||
return (i != -1) ? i : length;
|
||||
}
|
||||
|
||||
/**
|
||||
* See ECMA 15.5.4.8. Modified to match JS 1.2 - optionally takes
|
||||
* a limit argument and accepts a regular expression as the split
|
||||
* argument.
|
||||
*/
|
||||
public static Object jsFunction_split(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
String target = ScriptRuntime.toString(thisObj);
|
||||
|
||||
// create an empty Array to return;
|
||||
Scriptable scope = getTopLevelScope(funObj);
|
||||
Scriptable result = ScriptRuntime.newObject(cx, scope, "Array", null);
|
||||
|
||||
// return an array consisting of the target if no separator given
|
||||
// don't check against undefined, because we want
|
||||
// 'fooundefinedbar'.split(void 0) to split to ['foo', 'bar']
|
||||
if (args.length < 1) {
|
||||
result.put(0, result, target);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Use the second argument as the split limit, if given.
|
||||
boolean limited = (args.length > 1) && (args[1] != Undefined.instance);
|
||||
long limit = 0; // Initialize to avoid warning.
|
||||
if (limited) {
|
||||
/* Clamp limit between 0 and 1 + string length. */
|
||||
limit = ScriptRuntime.toUint32(args[1]);
|
||||
if (limit > target.length())
|
||||
limit = 1 + target.length();
|
||||
}
|
||||
|
||||
String separator = null;
|
||||
int[] matchlen = { 0 };
|
||||
Object re = null;
|
||||
RegExpProxy reProxy = cx.getRegExpProxy();
|
||||
if (reProxy != null && reProxy.isRegExp(args[0])) {
|
||||
re = args[0];
|
||||
} else {
|
||||
separator = ScriptRuntime.toString(args[0]);
|
||||
matchlen[0] = separator.length();
|
||||
}
|
||||
|
||||
// split target with separator or re
|
||||
int[] ip = { 0 };
|
||||
int match;
|
||||
int len = 0;
|
||||
boolean[] matched = { false };
|
||||
String[][] parens = { null };
|
||||
while ((match = find_split(funObj, target, separator, re, ip,
|
||||
matchlen, matched, parens)) >= 0)
|
||||
{
|
||||
if ((limited && len >= limit) || (match > target.length()))
|
||||
break;
|
||||
|
||||
String substr;
|
||||
if (target.length() == 0)
|
||||
substr = target;
|
||||
else
|
||||
substr = target.substring(ip[0], match);
|
||||
|
||||
result.put(len, result, substr);
|
||||
len++;
|
||||
/*
|
||||
* Imitate perl's feature of including parenthesized substrings
|
||||
* that matched part of the delimiter in the new array, after the
|
||||
* split substring that was delimited.
|
||||
*/
|
||||
if (re != null && matched[0] == true) {
|
||||
int size = parens[0].length;
|
||||
for (int num = 0; num < size; num++) {
|
||||
if (limited && len >= limit)
|
||||
break;
|
||||
result.put(len, result, parens[0][num]);
|
||||
len++;
|
||||
}
|
||||
matched[0] = false;
|
||||
}
|
||||
ip[0] = match + matchlen[0];
|
||||
|
||||
if (cx.getLanguageVersion() < Context.VERSION_1_3
|
||||
&& cx.getLanguageVersion() != Context.VERSION_DEFAULT)
|
||||
{
|
||||
/*
|
||||
* Deviate from ECMA to imitate Perl, which omits a final
|
||||
* split unless a limit argument is given and big enough.
|
||||
*/
|
||||
if (!limited && ip[0] == target.length())
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* See ECMA 15.5.4.[9,10]
|
||||
*/
|
||||
public static String jsFunction_substring(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
if (args.length < 1)
|
||||
args = ScriptRuntime.padArguments(args, 1);
|
||||
|
||||
String target = ScriptRuntime.toString(thisObj);
|
||||
int length = target.length();
|
||||
double start = ScriptRuntime.toInteger(args[0]);
|
||||
double end;
|
||||
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
else if (start > length)
|
||||
start = length;
|
||||
|
||||
if (args.length == 1) {
|
||||
end = length;
|
||||
} else {
|
||||
end = ScriptRuntime.toInteger(args[1]);
|
||||
if (end < 0)
|
||||
end = 0;
|
||||
else if (end > length)
|
||||
end = length;
|
||||
|
||||
// swap if end < start
|
||||
if (end < start) {
|
||||
if (cx.getLanguageVersion() != Context.VERSION_1_2) {
|
||||
double temp = start;
|
||||
start = end;
|
||||
end = temp;
|
||||
} else {
|
||||
// Emulate old JDK1.0 java.lang.String.substring()
|
||||
end = start;
|
||||
}
|
||||
}
|
||||
}
|
||||
return target.substring((int)start, (int)end);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* See ECMA 15.5.4.[11,12]
|
||||
*/
|
||||
public static String jsFunction_toLowerCase(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
String target = ScriptRuntime.toString(thisObj);
|
||||
return target.toLowerCase();
|
||||
}
|
||||
|
||||
public static String jsFunction_toUpperCase(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
String target = ScriptRuntime.toString(thisObj);
|
||||
return target.toUpperCase();
|
||||
}
|
||||
|
||||
public double jsGet_length() {
|
||||
return (double) string.length();
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-ECMA methods.
|
||||
*/
|
||||
public static String jsFunction_substr(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
String target = ScriptRuntime.toString(thisObj);
|
||||
|
||||
if (args.length < 1)
|
||||
return target;
|
||||
|
||||
double begin = ScriptRuntime.toInteger(args[0]);
|
||||
double end;
|
||||
int length = target.length();
|
||||
|
||||
if (begin < 0) {
|
||||
begin += length;
|
||||
if (begin < 0)
|
||||
begin = 0;
|
||||
} else if (begin > length) {
|
||||
begin = length;
|
||||
}
|
||||
|
||||
if (args.length == 1) {
|
||||
end = length;
|
||||
} else {
|
||||
end = ScriptRuntime.toInteger(args[1]);
|
||||
if (end < 0)
|
||||
end = 0;
|
||||
end += begin;
|
||||
if (end > length)
|
||||
end = length;
|
||||
}
|
||||
|
||||
return target.substring((int)begin, (int)end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Python-esque sequence operations.
|
||||
*/
|
||||
public static String jsFunction_concat(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
StringBuffer result = new StringBuffer();
|
||||
result.append(ScriptRuntime.toString(thisObj));
|
||||
|
||||
for (int i = 0; i < args.length; i++)
|
||||
result.append(ScriptRuntime.toString(args[i]));
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String jsFunction_slice(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
String target = ScriptRuntime.toString(thisObj);
|
||||
|
||||
if (args.length != 0) {
|
||||
double begin = ScriptRuntime.toInteger(args[0]);
|
||||
double end;
|
||||
int length = target.length();
|
||||
if (begin < 0) {
|
||||
begin += length;
|
||||
if (begin < 0)
|
||||
begin = 0;
|
||||
} else if (begin > length) {
|
||||
begin = length;
|
||||
}
|
||||
|
||||
if (args.length == 1) {
|
||||
end = length;
|
||||
} else {
|
||||
end = ScriptRuntime.toInteger(args[1]);
|
||||
if (end < 0) {
|
||||
end += length;
|
||||
if (end < 0)
|
||||
end = 0;
|
||||
} else if (end > length) {
|
||||
end = length;
|
||||
}
|
||||
if (end < begin)
|
||||
end = begin;
|
||||
}
|
||||
return target.substring((int)begin, (int)end);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML composition aids.
|
||||
*/
|
||||
private String tagify(String begin, String end, String value) {
|
||||
StringBuffer result = new StringBuffer();
|
||||
result.append('<');
|
||||
result.append(begin);
|
||||
if (value != null) {
|
||||
result.append('=');
|
||||
result.append(value);
|
||||
}
|
||||
result.append('>');
|
||||
result.append(this.string);
|
||||
result.append("</");
|
||||
result.append((end == null) ? begin : end);
|
||||
result.append('>');
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public String jsFunction_bold() {
|
||||
return tagify("B", null, null);
|
||||
}
|
||||
|
||||
public String jsFunction_italics() {
|
||||
return tagify("I", null, null);
|
||||
}
|
||||
|
||||
public String jsFunction_fixed() {
|
||||
return tagify("TT", null, null);
|
||||
}
|
||||
|
||||
public String jsFunction_strike() {
|
||||
return tagify("STRIKE", null, null);
|
||||
}
|
||||
|
||||
public String jsFunction_small() {
|
||||
return tagify("SMALL", null, null);
|
||||
}
|
||||
|
||||
public String jsFunction_big() {
|
||||
return tagify("BIG", null, null);
|
||||
}
|
||||
|
||||
public String jsFunction_blink() {
|
||||
return tagify("BLINK", null, null);
|
||||
}
|
||||
|
||||
public String jsFunction_sup() {
|
||||
return tagify("SUP", null, null);
|
||||
}
|
||||
|
||||
public String jsFunction_sub() {
|
||||
return tagify("SUB", null, null);
|
||||
}
|
||||
|
||||
public String jsFunction_fontsize(String value) {
|
||||
return tagify("FONT SIZE", "FONT", value);
|
||||
}
|
||||
|
||||
public String jsFunction_fontcolor(String value) {
|
||||
return tagify("FONT COLOR", "FONT", value);
|
||||
}
|
||||
|
||||
public String jsFunction_link(String value) {
|
||||
return tagify("A HREF", "A", value);
|
||||
}
|
||||
|
||||
public String jsFunction_anchor(String value) {
|
||||
return tagify("A NAME", "A", value);
|
||||
}
|
||||
|
||||
public static Object jsFunction_equals(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
{
|
||||
String target = ScriptRuntime.toString(thisObj);
|
||||
String strOther = ScriptRuntime.toString(args[0]);
|
||||
return new Boolean(target.equals(strOther));
|
||||
}
|
||||
|
||||
|
||||
public static Object jsFunction_equalsIgnoreCase(Context cx,
|
||||
Scriptable thisObj,
|
||||
Object[] args,
|
||||
Function funObj)
|
||||
{
|
||||
String target = ScriptRuntime.toString(thisObj);
|
||||
String strOther = ScriptRuntime.toString(args[0]);
|
||||
return new Boolean(target.equalsIgnoreCase(strOther));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unwrap this NativeString as a j.l.String for LiveConnect use.
|
||||
*/
|
||||
|
||||
public Object unwrap() {
|
||||
return string;
|
||||
}
|
||||
|
||||
public static Object jsFunction_match(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
throws JavaScriptException
|
||||
{
|
||||
return checkReProxy(cx).match(cx, thisObj, args, funObj);
|
||||
}
|
||||
|
||||
public static Object jsFunction_search(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
throws JavaScriptException
|
||||
{
|
||||
return checkReProxy(cx).search(cx, thisObj, args, funObj);
|
||||
}
|
||||
|
||||
public static Object jsFunction_replace(Context cx, Scriptable thisObj,
|
||||
Object[] args, Function funObj)
|
||||
throws JavaScriptException
|
||||
{
|
||||
return checkReProxy(cx).replace(cx, thisObj, args, funObj);
|
||||
}
|
||||
|
||||
private static RegExpProxy checkReProxy(Context cx) {
|
||||
RegExpProxy result = cx.getRegExpProxy();
|
||||
if (result == null) {
|
||||
throw cx.reportRuntimeError(cx.getMessage("msg.no.regexp", null));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final String defaultValue = "";
|
||||
|
||||
private String string;
|
||||
}
|
||||
|
||||
173
mozilla/js/rhino/org/mozilla/javascript/NativeWith.java
Normal file
173
mozilla/js/rhino/org/mozilla/javascript/NativeWith.java
Normal file
@@ -0,0 +1,173 @@
|
||||
/* -*- 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;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* This class implements the object lookup required for the
|
||||
* <code>with</code> statement.
|
||||
* It simply delegates every action to its prototype except
|
||||
* for operations on its parent.
|
||||
*/
|
||||
public class NativeWith implements Scriptable {
|
||||
|
||||
public static void init(Scriptable scope) {
|
||||
NativeWith w = new NativeWith();
|
||||
w.setPrototype(ScriptableObject.getObjectPrototype(scope));
|
||||
Method[] m = FunctionObject.findMethods(NativeWith.class,
|
||||
"jsConstructor");
|
||||
FunctionObject f = new FunctionObject("With", m[0], scope);
|
||||
f.addAsConstructor(scope, w);
|
||||
}
|
||||
|
||||
public NativeWith() {
|
||||
}
|
||||
|
||||
public NativeWith(Scriptable parent, Scriptable prototype) {
|
||||
this.parent = parent;
|
||||
this.prototype = prototype;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "With";
|
||||
}
|
||||
|
||||
public boolean has(String id, Scriptable start) {
|
||||
if (start == this)
|
||||
start = prototype;
|
||||
return prototype.has(id, start);
|
||||
}
|
||||
|
||||
public boolean has(int index, Scriptable start) {
|
||||
if (start == this)
|
||||
start = prototype;
|
||||
return prototype.has(index, start);
|
||||
}
|
||||
|
||||
public Object get(String id, Scriptable start) {
|
||||
if (start == this)
|
||||
start = prototype;
|
||||
return prototype.get(id, start);
|
||||
}
|
||||
|
||||
public Object get(int index, Scriptable start) {
|
||||
if (start == this)
|
||||
start = prototype;
|
||||
return prototype.get(index, start);
|
||||
}
|
||||
|
||||
public void put(String id, Scriptable start, Object value) {
|
||||
if (start == this)
|
||||
start = prototype;
|
||||
prototype.put(id, start, value);
|
||||
}
|
||||
|
||||
public void put(int index, Scriptable start, Object value) {
|
||||
if (start == this)
|
||||
start = prototype;
|
||||
prototype.put(index, start, value);
|
||||
}
|
||||
|
||||
public void delete(String id) {
|
||||
prototype.delete(id);
|
||||
}
|
||||
|
||||
public void delete(int index) {
|
||||
prototype.delete(index);
|
||||
}
|
||||
|
||||
public Scriptable getPrototype() {
|
||||
return prototype;
|
||||
}
|
||||
|
||||
public void setPrototype(Scriptable prototype) {
|
||||
this.prototype = prototype;
|
||||
}
|
||||
|
||||
public Scriptable getParentScope() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParentScope(Scriptable parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public Object[] getIds() {
|
||||
return prototype.getIds();
|
||||
}
|
||||
|
||||
public Object getDefaultValue(Class typeHint) {
|
||||
return prototype.getDefaultValue(typeHint);
|
||||
}
|
||||
|
||||
public boolean hasInstance(Scriptable value) {
|
||||
return prototype.hasInstance(value);
|
||||
}
|
||||
|
||||
public static Object jsConstructor(Context cx, Object[] args,
|
||||
Function ctorObj, boolean inNewExpr)
|
||||
{
|
||||
Object[] msgArgs = { "With" };
|
||||
throw Context.reportRuntimeError(
|
||||
Context.getMessage("msg.cant.call.indirect", msgArgs));
|
||||
}
|
||||
|
||||
public static Object newWithSpecial(Context cx, Object[] args,
|
||||
Function ctorObj, boolean inNewExpr)
|
||||
{
|
||||
if (!inNewExpr) {
|
||||
Object[] errArgs = { "With" };
|
||||
throw Context.reportRuntimeError(Context.getMessage
|
||||
("msg.only.from.new", errArgs));
|
||||
}
|
||||
|
||||
ScriptRuntime.checkDeprecated(cx, "With");
|
||||
|
||||
Scriptable scope = ScriptableObject.getTopLevelScope(ctorObj);
|
||||
NativeWith thisObj = new NativeWith();
|
||||
thisObj.setPrototype(args.length == 0
|
||||
? ScriptableObject.getClassPrototype(scope,
|
||||
"Object")
|
||||
: ScriptRuntime.toObject(scope, args[0]));
|
||||
thisObj.setParentScope(scope);
|
||||
return thisObj;
|
||||
}
|
||||
|
||||
private Scriptable prototype;
|
||||
private Scriptable parent;
|
||||
private Scriptable constructor;
|
||||
}
|
||||
469
mozilla/js/rhino/org/mozilla/javascript/Node.java
Normal file
469
mozilla/js/rhino/org/mozilla/javascript/Node.java
Normal file
@@ -0,0 +1,469 @@
|
||||
/* -*- 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
|
||||
* 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.*;
|
||||
|
||||
/**
|
||||
* This class implements the root of the intermediate representation.
|
||||
*
|
||||
* @author Norris Boyd
|
||||
* @author Mike McCabe
|
||||
*/
|
||||
|
||||
public class Node implements Cloneable {
|
||||
|
||||
public Node(int nodeType) {
|
||||
type = nodeType;
|
||||
}
|
||||
|
||||
public Node(int nodeType, Node child) {
|
||||
type = nodeType;
|
||||
first = last = child;
|
||||
child.next = null;
|
||||
}
|
||||
|
||||
public Node(int nodeType, Node left, Node right) {
|
||||
type = nodeType;
|
||||
first = left;
|
||||
last = right;
|
||||
left.next = right;
|
||||
right.next = null;
|
||||
}
|
||||
|
||||
public Node(int nodeType, Node left, Node mid, Node right) {
|
||||
type = nodeType;
|
||||
first = left;
|
||||
last = right;
|
||||
left.next = mid;
|
||||
mid.next = right;
|
||||
right.next = null;
|
||||
}
|
||||
|
||||
public Node(int nodeType, Object datum) {
|
||||
type = nodeType;
|
||||
this.datum = datum;
|
||||
}
|
||||
|
||||
public Node(int nodeType, Node child, Object datum) {
|
||||
this(nodeType, child);
|
||||
this.datum = datum;
|
||||
}
|
||||
|
||||
public Node(int nodeType, Node left, Node right, Object datum) {
|
||||
this(nodeType, left, right);
|
||||
this.datum = datum;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean hasChildren() {
|
||||
return first != null;
|
||||
}
|
||||
|
||||
public Node getFirstChild() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public Node getLastChild() {
|
||||
return last;
|
||||
}
|
||||
|
||||
public Node getNextSibling() {
|
||||
return next;
|
||||
}
|
||||
|
||||
public Node getChildBefore(Node child) {
|
||||
if (child == first)
|
||||
return null;
|
||||
Node n = first;
|
||||
while (n.next != child) {
|
||||
n = n.next;
|
||||
if (n == null)
|
||||
throw new RuntimeException("node is not a child");
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
public Node getLastSibling() {
|
||||
Node n = this;
|
||||
while (n.next != null) {
|
||||
n = n.next;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
public ShallowNodeIterator getChildIterator() {
|
||||
return new ShallowNodeIterator(first);
|
||||
}
|
||||
|
||||
public PreorderNodeIterator getPreorderIterator() {
|
||||
return new PreorderNodeIterator(this);
|
||||
}
|
||||
|
||||
public void addChildToFront(Node child) {
|
||||
child.next = first;
|
||||
first = child;
|
||||
if (last == null) {
|
||||
last = child;
|
||||
}
|
||||
}
|
||||
|
||||
public void addChildToBack(Node child) {
|
||||
child.next = null;
|
||||
if (last == null) {
|
||||
first = last = child;
|
||||
return;
|
||||
}
|
||||
last.next = child;
|
||||
last = child;
|
||||
}
|
||||
|
||||
public void addChildrenToFront(Node children) {
|
||||
Node lastSib = children.getLastSibling();
|
||||
lastSib.next = first;
|
||||
first = children;
|
||||
if (last == null) {
|
||||
last = lastSib;
|
||||
}
|
||||
}
|
||||
|
||||
public void addChildrenToBack(Node children) {
|
||||
if (last != null) {
|
||||
last.next = children;
|
||||
}
|
||||
last = children.getLastSibling();
|
||||
if (first == null) {
|
||||
first = children;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 'child' before 'node'.
|
||||
*/
|
||||
public void addChildBefore(Node newChild, Node node) {
|
||||
if (newChild.next != null)
|
||||
throw new RuntimeException(
|
||||
"newChild had siblings in addChildBefore");
|
||||
if (first == node) {
|
||||
newChild.next = first;
|
||||
first = newChild;
|
||||
return;
|
||||
}
|
||||
Node prev = getChildBefore(node);
|
||||
addChildAfter(newChild, prev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 'child' after 'node'.
|
||||
*/
|
||||
public void addChildAfter(Node newChild, Node node) {
|
||||
if (newChild.next != null)
|
||||
throw new RuntimeException(
|
||||
"newChild had siblings in addChildAfter");
|
||||
newChild.next = node.next;
|
||||
node.next = newChild;
|
||||
if (last == node)
|
||||
last = newChild;
|
||||
}
|
||||
|
||||
public void removeChild(Node child) {
|
||||
Node prev = getChildBefore(child);
|
||||
if (prev == null)
|
||||
first = first.next;
|
||||
else
|
||||
prev.next = child.next;
|
||||
if (child == last) last = prev;
|
||||
child.next = null;
|
||||
}
|
||||
|
||||
public void replaceChild(Node child, Node newChild) {
|
||||
newChild.next = child.next;
|
||||
if (child == first) {
|
||||
first = newChild;
|
||||
} else {
|
||||
Node prev = getChildBefore(child);
|
||||
prev.next = newChild;
|
||||
}
|
||||
if (child == last)
|
||||
last = newChild;
|
||||
child.next = null;
|
||||
}
|
||||
|
||||
public static final int
|
||||
TARGET_PROP = 1,
|
||||
BREAK_PROP = 2,
|
||||
CONTINUE_PROP = 3,
|
||||
ENUM_PROP = 4,
|
||||
FUNCTION_PROP = 5,
|
||||
TEMP_PROP = 6,
|
||||
LOCAL_PROP = 7,
|
||||
CODEOFFSET_PROP = 8,
|
||||
FIXUPS_PROP = 9,
|
||||
VARS_PROP = 10,
|
||||
USES_PROP = 11,
|
||||
REGEXP_PROP = 12,
|
||||
CASES_PROP = 13,
|
||||
DEFAULT_PROP = 14,
|
||||
CASEARRAY_PROP = 15,
|
||||
SOURCENAME_PROP = 16,
|
||||
SOURCE_PROP = 17,
|
||||
TYPE_PROP = 18,
|
||||
SPECIAL_PROP_PROP = 19,
|
||||
LABEL_PROP = 20,
|
||||
FINALLY_PROP = 21,
|
||||
LOCALCOUNT_PROP = 22,
|
||||
/*
|
||||
the following properties are defined and manipulated by the
|
||||
optimizer -
|
||||
TARGETBLOCK_PROP - the block referenced by a branch node
|
||||
VARIABLE_PROP - the variable referenced by a BIND or NAME node
|
||||
LASTUSE_PROP - that variable node is the last reference before
|
||||
a new def or the end of the block
|
||||
ISNUMBER_PROP - this node generates code on Number children and
|
||||
delivers a Number result (as opposed to Objects)
|
||||
DIRECTCALL_PROP - this call node should emit code to test the function
|
||||
object against the known class and call diret if it
|
||||
matches.
|
||||
*/
|
||||
|
||||
TARGETBLOCK_PROP = 23,
|
||||
VARIABLE_PROP = 24,
|
||||
LASTUSE_PROP = 25,
|
||||
ISNUMBER_PROP = 26,
|
||||
DIRECTCALL_PROP = 27,
|
||||
|
||||
BASE_LINENO_PROP = 28,
|
||||
END_LINENO_PROP = 29,
|
||||
SPECIALCALL_PROP = 30;
|
||||
|
||||
public static final int // this value of the ISNUMBER_PROP specifies
|
||||
BOTH = 0, // which of the children are Number types
|
||||
LEFT = 1,
|
||||
RIGHT = 2;
|
||||
|
||||
private static String propNames[];
|
||||
|
||||
private static final String propToString(int propType) {
|
||||
if (Context.printTrees && propNames == null) {
|
||||
// If Context.printTrees is false, the compiler
|
||||
// can remove all these strings.
|
||||
String[] a = {
|
||||
"target",
|
||||
"break",
|
||||
"continue",
|
||||
"enum",
|
||||
"function",
|
||||
"temp",
|
||||
"local",
|
||||
"codeoffset",
|
||||
"fixups",
|
||||
"vars",
|
||||
"uses",
|
||||
"regexp",
|
||||
"switches",
|
||||
"cases",
|
||||
"default",
|
||||
"casearray",
|
||||
"sourcename",
|
||||
"source",
|
||||
"type",
|
||||
"special_prop",
|
||||
"label",
|
||||
"finally",
|
||||
"localcount",
|
||||
"targetblock",
|
||||
"variable",
|
||||
"lastuse",
|
||||
"isnumber",
|
||||
"directcall",
|
||||
"base_lineno",
|
||||
"end_lineno",
|
||||
"specialcall"
|
||||
};
|
||||
propNames = a;
|
||||
}
|
||||
return propNames[propType-1];
|
||||
}
|
||||
|
||||
public Object getProp(int propType) {
|
||||
if (props == null)
|
||||
return null;
|
||||
return props.get(new Integer(propType));
|
||||
}
|
||||
|
||||
public void putProp(int propType, Object prop) {
|
||||
if (props == null)
|
||||
props = new Hashtable(2);
|
||||
if (prop == null)
|
||||
props.remove(new Integer(propType));
|
||||
else
|
||||
props.put(new Integer(propType), prop);
|
||||
}
|
||||
|
||||
public Object getDatum() {
|
||||
return datum;
|
||||
}
|
||||
|
||||
public void setDatum(Object datum) {
|
||||
this.datum = datum;
|
||||
}
|
||||
|
||||
public int getInt() {
|
||||
return ((Number) datum).intValue();
|
||||
}
|
||||
|
||||
public double getDouble() {
|
||||
return ((Number) datum).doubleValue();
|
||||
}
|
||||
|
||||
public long getLong() {
|
||||
return ((Number) datum).longValue();
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
return (String) datum;
|
||||
}
|
||||
|
||||
public Node cloneNode() {
|
||||
Node result;
|
||||
try {
|
||||
result = (Node) super.clone();
|
||||
result.next = null;
|
||||
result.first = null;
|
||||
result.last = null;
|
||||
}
|
||||
catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (Context.printTrees) {
|
||||
StringBuffer sb = new StringBuffer(TokenStream.tokenToName(type));
|
||||
if (type == TokenStream.TARGET) {
|
||||
sb.append(" ");
|
||||
sb.append(hashCode());
|
||||
}
|
||||
if (datum != null) {
|
||||
sb.append(' ');
|
||||
sb.append(datum.toString());
|
||||
}
|
||||
if (props == null)
|
||||
return sb.toString();
|
||||
|
||||
Enumeration keys = props.keys();
|
||||
Enumeration elems = props.elements();
|
||||
while (keys.hasMoreElements()) {
|
||||
Integer key = (Integer) keys.nextElement();
|
||||
Object elem = elems.nextElement();
|
||||
sb.append(" [");
|
||||
sb.append(propToString(key.intValue()));
|
||||
sb.append(": ");
|
||||
switch (key.intValue()) {
|
||||
case FIXUPS_PROP : // can't add this as it recurses
|
||||
sb.append("fixups property");
|
||||
break;
|
||||
case SOURCE_PROP : // can't add this as it has unprintables
|
||||
sb.append("source property");
|
||||
break;
|
||||
case TARGETBLOCK_PROP : // can't add this as it recurses
|
||||
sb.append("target block property");
|
||||
break;
|
||||
case LASTUSE_PROP : // can't add this as it is dull
|
||||
sb.append("last use property");
|
||||
break;
|
||||
default :
|
||||
sb.append(elem.toString());
|
||||
break;
|
||||
}
|
||||
sb.append("]");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toStringTree() {
|
||||
return toStringTreeHelper(0);
|
||||
}
|
||||
|
||||
|
||||
private String toStringTreeHelper(int level) {
|
||||
if (Context.printTrees) {
|
||||
StringBuffer s = new StringBuffer();
|
||||
for (int i=0; i < level; i++) {
|
||||
s.append(" ");
|
||||
}
|
||||
s.append(toString());
|
||||
s.append('\n');
|
||||
ShallowNodeIterator iterator = getChildIterator();
|
||||
if (iterator != null) {
|
||||
while (iterator.hasMoreElements()) {
|
||||
Node n = (Node) iterator.nextElement();
|
||||
if (n.getType() == TokenStream.FUNCTION) {
|
||||
Node p = (Node) n.getProp(Node.FUNCTION_PROP);
|
||||
if (p != null)
|
||||
n = p;
|
||||
}
|
||||
s.append(n.toStringTreeHelper(level+1));
|
||||
}
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public Node getFirst() { return first; }
|
||||
public Node getNext() { return next; }
|
||||
|
||||
protected int type; // type of the node; TokenStream.NAME for example
|
||||
protected Node next; // next sibling
|
||||
protected Node first; // first element of a linked list of children
|
||||
protected Node last; // last element of a linked list of children
|
||||
protected Hashtable props;
|
||||
protected Object datum; // encapsulated data; depends on type
|
||||
}
|
||||
|
||||
712
mozilla/js/rhino/org/mozilla/javascript/NodeTransformer.java
Normal file
712
mozilla/js/rhino/org/mozilla/javascript/NodeTransformer.java
Normal file
@@ -0,0 +1,712 @@
|
||||
/* -*- 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
|
||||
* 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;
|
||||
import java.util.Stack;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* This class transforms a tree to a lower-level representation for codegen.
|
||||
*
|
||||
* @see Node
|
||||
* @author Norris Boyd
|
||||
*/
|
||||
|
||||
public class NodeTransformer {
|
||||
|
||||
/**
|
||||
* Return new instance of this class. So that derived classes
|
||||
* can override methods of the transformer.
|
||||
*/
|
||||
public NodeTransformer newInstance() {
|
||||
return new NodeTransformer();
|
||||
}
|
||||
|
||||
public IRFactory createIRFactory(TokenStream ts, Scriptable scope) {
|
||||
return new IRFactory(ts, scope);
|
||||
}
|
||||
|
||||
public Node transform(Node tree, Node enclosing, TokenStream ts,
|
||||
Scriptable scope)
|
||||
{
|
||||
loops = new Stack();
|
||||
loopEnds = new Stack();
|
||||
inFunction = tree.getType() == TokenStream.FUNCTION;
|
||||
if (!inFunction) {
|
||||
addVariables(tree, getVariableTable(tree));
|
||||
}
|
||||
irFactory = createIRFactory(ts, scope);
|
||||
|
||||
// to save against upchecks if no finally blocks are used.
|
||||
boolean hasFinally = false;
|
||||
|
||||
PreorderNodeIterator iterator = tree.getPreorderIterator();
|
||||
Node node;
|
||||
while ((node = iterator.nextNode()) != null) {
|
||||
int type = node.getType();
|
||||
|
||||
typeswitch:
|
||||
switch (type) {
|
||||
|
||||
case TokenStream.FUNCTION:
|
||||
if (node == tree) {
|
||||
// Add the variables to variable table, the
|
||||
// parameters were added earlier.
|
||||
VariableTable vars = getVariableTable(tree);
|
||||
addVariables(tree, vars);
|
||||
|
||||
// Add return to end if needed.
|
||||
Node stmts = node.getLastChild();
|
||||
Node lastStmt = stmts.getLastChild();
|
||||
if (lastStmt == null ||
|
||||
lastStmt.getType() != TokenStream.RETURN)
|
||||
{
|
||||
stmts.addChildToBack(new Node(TokenStream.RETURN));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (inFunction) {
|
||||
// Nested functions require activation objects.
|
||||
((FunctionNode) tree).setRequiresActivation(true);
|
||||
}
|
||||
FunctionNode fnNode = (FunctionNode)
|
||||
node.getProp(Node.FUNCTION_PROP);
|
||||
addParameters(fnNode);
|
||||
NodeTransformer inner = newInstance();
|
||||
fnNode = (FunctionNode)
|
||||
inner.transform(fnNode, tree, ts, scope);
|
||||
node.putProp(Node.FUNCTION_PROP, fnNode);
|
||||
Vector fns = (Vector) tree.getProp(Node.FUNCTION_PROP);
|
||||
if (fns == null) {
|
||||
fns = new Vector(7);
|
||||
tree.putProp(Node.FUNCTION_PROP, fns);
|
||||
}
|
||||
fns.addElement(fnNode);
|
||||
}
|
||||
break;
|
||||
|
||||
case TokenStream.LABEL:
|
||||
{
|
||||
Node child = node.getFirstChild();
|
||||
node.removeChild(child);
|
||||
String id = child.getString();
|
||||
|
||||
// check against duplicate labels...
|
||||
for (int i=loops.size()-1; i >= 0; i--) {
|
||||
Node n = (Node) loops.elementAt(i);
|
||||
if (n.getType() == TokenStream.LABEL) {
|
||||
String otherId = (String)n.getProp(Node.LABEL_PROP);
|
||||
if (id.equals(otherId)) {
|
||||
Object[] errArgs = { id };
|
||||
String message = Context.getMessage("msg.dup.label",
|
||||
errArgs);
|
||||
reportMessage(Context.getContext(), message, node,
|
||||
tree, true, scope);
|
||||
break typeswitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node.putProp(Node.LABEL_PROP, id);
|
||||
|
||||
/* Make a target and put it _after_ the following
|
||||
* node. And in the LABEL node, so breaks get the
|
||||
* right target.
|
||||
*/
|
||||
Node breakTarget = new Node(TokenStream.TARGET);
|
||||
Node parent = iterator.getCurrentParent();
|
||||
Node next = node.getNextSibling();
|
||||
while (next != null &&
|
||||
(next.getType() == TokenStream.LABEL ||
|
||||
next.getType() == TokenStream.TARGET))
|
||||
next = next.getNextSibling();
|
||||
if (next == null)
|
||||
break;
|
||||
parent.addChildAfter(breakTarget, next);
|
||||
node.putProp(Node.BREAK_PROP, breakTarget);
|
||||
|
||||
if (next.getType() == TokenStream.LOOP) {
|
||||
node.putProp(Node.CONTINUE_PROP,
|
||||
next.getProp(Node.CONTINUE_PROP));
|
||||
}
|
||||
|
||||
loops.push(node);
|
||||
loopEnds.push(breakTarget);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenStream.SWITCH:
|
||||
{
|
||||
Node breakTarget = new Node(TokenStream.TARGET);
|
||||
Node parent = iterator.getCurrentParent();
|
||||
parent.addChildAfter(breakTarget, node);
|
||||
|
||||
// make all children siblings except for selector
|
||||
Node sib = node;
|
||||
Node child = node.getFirstChild().next;
|
||||
while (child != null) {
|
||||
Node next = child.next;
|
||||
node.removeChild(child);
|
||||
parent.addChildAfter(child, sib);
|
||||
sib = child;
|
||||
child = next;
|
||||
}
|
||||
|
||||
node.putProp(Node.BREAK_PROP, breakTarget);
|
||||
loops.push(node);
|
||||
loopEnds.push(breakTarget);
|
||||
node.putProp(Node.CASES_PROP, new Vector(13));
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenStream.DEFAULT:
|
||||
case TokenStream.CASE:
|
||||
{
|
||||
Node sw = (Node) loops.peek();
|
||||
if (type == TokenStream.CASE) {
|
||||
Vector cases = (Vector) sw.getProp(Node.CASES_PROP);
|
||||
cases.addElement(node);
|
||||
} else {
|
||||
sw.putProp(Node.DEFAULT_PROP, node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenStream.NEWLOCAL : {
|
||||
Integer localCount
|
||||
= (Integer)(tree.getProp(Node.LOCALCOUNT_PROP));
|
||||
if (localCount == null) {
|
||||
tree.putProp(Node.LOCALCOUNT_PROP, new Integer(1));
|
||||
}
|
||||
else {
|
||||
tree.putProp(Node.LOCALCOUNT_PROP,
|
||||
new Integer(localCount.intValue() + 1));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TokenStream.LOOP:
|
||||
loops.push(node);
|
||||
loopEnds.push(node.getProp(Node.BREAK_PROP));
|
||||
break;
|
||||
|
||||
case TokenStream.WITH:
|
||||
{
|
||||
if (inFunction) {
|
||||
// With statements require an activation object.
|
||||
((FunctionNode) tree).setRequiresActivation(true);
|
||||
}
|
||||
loops.push(node);
|
||||
Node leave = node.getNextSibling();
|
||||
if (leave.getType() != TokenStream.LEAVEWITH) {
|
||||
throw new RuntimeException("Unexpected tree");
|
||||
}
|
||||
loopEnds.push(leave);
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenStream.TRY:
|
||||
{
|
||||
Node finallytarget = (Node)node.getProp(Node.FINALLY_PROP);
|
||||
if (finallytarget != null) {
|
||||
hasFinally = true;
|
||||
loops.push(node);
|
||||
loopEnds.push(finallytarget);
|
||||
}
|
||||
Integer localCount
|
||||
= (Integer)(tree.getProp(Node.LOCALCOUNT_PROP));
|
||||
if (localCount == null) {
|
||||
tree.putProp(Node.LOCALCOUNT_PROP, new Integer(1));
|
||||
}
|
||||
else {
|
||||
tree.putProp(Node.LOCALCOUNT_PROP,
|
||||
new Integer(localCount.intValue() + 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenStream.TARGET:
|
||||
case TokenStream.LEAVEWITH:
|
||||
if (!loopEnds.empty() && loopEnds.peek() == node) {
|
||||
loopEnds.pop();
|
||||
loops.pop();
|
||||
}
|
||||
break;
|
||||
|
||||
case TokenStream.RETURN:
|
||||
{
|
||||
/* If we didn't support try/finally, it wouldn't be
|
||||
* necessary to put LEAVEWITH nodes here... but as
|
||||
* we do need a series of JSR FINALLY nodes before
|
||||
* each RETURN, we need to ensure that each finally
|
||||
* block gets the correct scope... which could mean
|
||||
* that some LEAVEWITH nodes are necessary.
|
||||
*/
|
||||
if (!hasFinally)
|
||||
break; // skip the whole mess.
|
||||
|
||||
Node parent = iterator.getCurrentParent();
|
||||
for (int i=loops.size()-1; i >= 0; i--) {
|
||||
Node n = (Node) loops.elementAt(i);
|
||||
int elemtype = n.getType();
|
||||
if (elemtype == TokenStream.TRY) {
|
||||
Node jsrnode = new Node(TokenStream.JSR);
|
||||
Object jsrtarget = n.getProp(Node.FINALLY_PROP);
|
||||
jsrnode.putProp(Node.TARGET_PROP, jsrtarget);
|
||||
parent.addChildBefore(jsrnode, node);
|
||||
} else if (elemtype == TokenStream.WITH) {
|
||||
parent.addChildBefore(new Node(TokenStream.LEAVEWITH),
|
||||
node);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenStream.BREAK:
|
||||
case TokenStream.CONTINUE:
|
||||
{
|
||||
Node loop = null;
|
||||
boolean labelled = node.hasChildren();
|
||||
String id = null;
|
||||
if (labelled) {
|
||||
/* get the label */
|
||||
Node child = node.getFirstChild();
|
||||
id = child.getString();
|
||||
node.removeChild(child);
|
||||
}
|
||||
|
||||
int i;
|
||||
Node parent = iterator.getCurrentParent();
|
||||
for (i=loops.size()-1; i >= 0; i--) {
|
||||
Node n = (Node) loops.elementAt(i);
|
||||
int elemtype = n.getType();
|
||||
if (elemtype == TokenStream.WITH) {
|
||||
parent.addChildBefore(new Node(TokenStream.LEAVEWITH),
|
||||
node);
|
||||
} else if (elemtype == TokenStream.TRY) {
|
||||
Node jsrFinally = new Node(TokenStream.JSR);
|
||||
Object jsrTarget = n.getProp(Node.FINALLY_PROP);
|
||||
jsrFinally.putProp(Node.TARGET_PROP, jsrTarget);
|
||||
parent.addChildBefore(jsrFinally, node);
|
||||
} else if (!labelled &&
|
||||
(elemtype == TokenStream.LOOP ||
|
||||
(elemtype == TokenStream.SWITCH &&
|
||||
type == TokenStream.BREAK)))
|
||||
{
|
||||
/* if it's a simple break/continue, break from the
|
||||
* nearest enclosing loop or switch
|
||||
*/
|
||||
loop = n;
|
||||
break;
|
||||
} else if (labelled &&
|
||||
elemtype == TokenStream.LABEL &&
|
||||
id.equals((String)n.getProp(Node.LABEL_PROP)))
|
||||
{
|
||||
loop = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int propType = type == TokenStream.BREAK
|
||||
? Node.BREAK_PROP
|
||||
: Node.CONTINUE_PROP;
|
||||
Node target = loop == null
|
||||
? null
|
||||
: (Node) loop.getProp(propType);
|
||||
if (loop == null || target == null) {
|
||||
String message;
|
||||
if (!labelled) {
|
||||
// didn't find an appropriate target
|
||||
if (type == TokenStream.CONTINUE) {
|
||||
message = Context.getMessage
|
||||
("msg.continue.outside", null);
|
||||
} else {
|
||||
message = Context.getMessage
|
||||
("msg.bad.break", null);
|
||||
}
|
||||
} else if (loop != null) {
|
||||
message = Context.getMessage("msg.continue.nonloop",
|
||||
null);
|
||||
} else {
|
||||
Object[] errArgs = { id };
|
||||
message = Context.getMessage
|
||||
("msg.undef.label", errArgs);
|
||||
}
|
||||
reportMessage(Context.getContext(), message, node,
|
||||
tree, true, scope);
|
||||
node.setType(TokenStream.NOP);
|
||||
break;
|
||||
}
|
||||
node.setType(TokenStream.GOTO);
|
||||
node.putProp(Node.TARGET_PROP, target);
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenStream.CALL:
|
||||
if (isSpecialCallName(tree, node))
|
||||
node.putProp(Node.SPECIALCALL_PROP, Boolean.TRUE);
|
||||
visitCall(node, tree);
|
||||
break;
|
||||
|
||||
case TokenStream.NEW:
|
||||
if (isSpecialCallName(tree, node))
|
||||
node.putProp(Node.SPECIALCALL_PROP, Boolean.TRUE);
|
||||
visitNew(node, tree);
|
||||
break;
|
||||
|
||||
case TokenStream.DOT:
|
||||
{
|
||||
Node right = node.getLastChild();
|
||||
right.setType(TokenStream.STRING);
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenStream.EXPRSTMT:
|
||||
node.setType(inFunction ? TokenStream.POP : TokenStream.POPV);
|
||||
break;
|
||||
|
||||
case TokenStream.OBJECT:
|
||||
{
|
||||
Vector regexps = (Vector) tree.getProp(Node.REGEXP_PROP);
|
||||
if (regexps == null) {
|
||||
regexps = new Vector(3);
|
||||
tree.putProp(Node.REGEXP_PROP, regexps);
|
||||
}
|
||||
regexps.addElement(node);
|
||||
Node n = new Node(TokenStream.OBJECT);
|
||||
iterator.replaceCurrent(n);
|
||||
n.putProp(Node.REGEXP_PROP, node);
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenStream.VAR:
|
||||
{
|
||||
ShallowNodeIterator i = node.getChildIterator();
|
||||
Node result = new Node(TokenStream.BLOCK);
|
||||
while (i.hasMoreElements()) {
|
||||
Node n = i.nextNode();
|
||||
if (!n.hasChildren())
|
||||
continue;
|
||||
Node init = n.getFirstChild();
|
||||
n.removeChild(init);
|
||||
Node asn = (Node) irFactory.createAssignment(
|
||||
TokenStream.NOP, n, init, null,
|
||||
false);
|
||||
Node pop = new Node(TokenStream.POP, asn, node.getDatum());
|
||||
result.addChildToBack(pop);
|
||||
}
|
||||
iterator.replaceCurrent(result);
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenStream.DELPROP:
|
||||
case TokenStream.SETNAME:
|
||||
{
|
||||
if (!inFunction || inWithStatement())
|
||||
break;
|
||||
Node bind = node.getFirstChild();
|
||||
if (bind == null || bind.getType() != TokenStream.BINDNAME)
|
||||
break;
|
||||
String name = bind.getString();
|
||||
if (name.equals("arguments")) {
|
||||
// use of "arguments" requires an activation object.
|
||||
((FunctionNode) tree).setRequiresActivation(true);
|
||||
}
|
||||
VariableTable vars = getVariableTable(tree);
|
||||
if (vars.get(name) != null) {
|
||||
if (type == TokenStream.SETNAME) {
|
||||
node.setType(TokenStream.SETVAR);
|
||||
bind.setType(TokenStream.STRING);
|
||||
} else {
|
||||
// Local variables are by definition permanent
|
||||
Node n = new Node(TokenStream.PRIMARY,
|
||||
new Integer(TokenStream.FALSE));
|
||||
iterator.replaceCurrent(n);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenStream.GETPROP:
|
||||
if (inFunction) {
|
||||
Node n = node.getFirstChild().getNextSibling();
|
||||
String name = n == null ? "" : n.getString();
|
||||
if (name.equals("arguments") ||
|
||||
(name.equals("length") &&
|
||||
Context.getContext().getLanguageVersion() ==
|
||||
Context.VERSION_1_2))
|
||||
{
|
||||
// Use of "arguments" or "length" in 1.2 requires
|
||||
// an activation object.
|
||||
((FunctionNode) tree).setRequiresActivation(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TokenStream.NAME:
|
||||
{
|
||||
if (!inFunction || inWithStatement())
|
||||
break;
|
||||
String name = node.getString();
|
||||
if (name.equals("arguments")) {
|
||||
// Use of "arguments" requires an activation object.
|
||||
((FunctionNode) tree).setRequiresActivation(true);
|
||||
}
|
||||
VariableTable vars = getVariableTable(tree);
|
||||
if (vars.get(name) != null) {
|
||||
node.setType(TokenStream.GETVAR);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
protected void addVariables(Node tree, VariableTable vars) {
|
||||
// OPT: a whole pass to collect variables seems expensive.
|
||||
// Could special case to go into statements only.
|
||||
boolean inFunction = tree.getType() == TokenStream.FUNCTION;
|
||||
PreorderNodeIterator iterator = tree.getPreorderIterator();
|
||||
Hashtable ht = null;
|
||||
Node node;
|
||||
while ((node = iterator.nextNode()) != null) {
|
||||
int nodeType = node.getType();
|
||||
if (inFunction && nodeType == TokenStream.FUNCTION &&
|
||||
node != tree)
|
||||
{
|
||||
// In a function with both "var x" and "function x",
|
||||
// disregard the var statement, independent of order.
|
||||
String name = node.getString();
|
||||
if (name == null)
|
||||
continue;
|
||||
vars.removeLocal(name);
|
||||
if (ht == null)
|
||||
ht = new Hashtable();
|
||||
ht.put(name, Boolean.TRUE);
|
||||
}
|
||||
if (nodeType != TokenStream.VAR)
|
||||
continue;
|
||||
ShallowNodeIterator i = node.getChildIterator();
|
||||
while (i.hasMoreElements()) {
|
||||
Node n = i.nextNode();
|
||||
if (ht == null || ht.get(n.getString()) == null)
|
||||
vars.addLocal(n.getString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void addParameters(FunctionNode fnNode) {
|
||||
VariableTable vars = fnNode.getVariableTable();
|
||||
Node args = fnNode.getFirstChild();
|
||||
if (args.getType() == TokenStream.LP && vars.getParameterCount() == 0)
|
||||
{
|
||||
// Add parameters
|
||||
ShallowNodeIterator i = args.getChildIterator();
|
||||
while (i.hasMoreElements()) {
|
||||
Node n = i.nextNode();
|
||||
String arg = n.getString();
|
||||
vars.addParameter(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void visitNew(Node node, Node tree) {
|
||||
}
|
||||
|
||||
protected void visitCall(Node node, Node tree) {
|
||||
/*
|
||||
* For
|
||||
* Call(GetProp(a, b), c, d) // or GetElem...
|
||||
* we wish to evaluate as
|
||||
* Call(GetProp(tmp=a, b), tmp, c, d)
|
||||
*
|
||||
* for
|
||||
* Call(Name("a"), b, c)
|
||||
* we wish to evaluate as
|
||||
* Call(GetProp(tmp=GetBase("a"), "a"), tmp, b, c)
|
||||
*
|
||||
* and for
|
||||
* Call(a, b, c);
|
||||
* we wish to evaluate as
|
||||
* Call(tmp=a, Parent(tmp), c, d)
|
||||
*/
|
||||
Node left = node.getFirstChild();
|
||||
// count the arguments
|
||||
int argCount = 0;
|
||||
Node arg = left.getNextSibling();
|
||||
while (arg != null) {
|
||||
arg = arg.getNextSibling();
|
||||
argCount++;
|
||||
}
|
||||
boolean addGetThis = false;
|
||||
if (left.getType() == TokenStream.NAME) {
|
||||
VariableTable vars = getVariableTable(tree);
|
||||
String name = left.getString();
|
||||
if (inFunction && vars.get(name) != null && !inWithStatement()) {
|
||||
// call to a var. Transform to Call(GetVar("a"), b, c)
|
||||
left.setType(TokenStream.GETVAR);
|
||||
// fall through to code to add GetParent
|
||||
} else {
|
||||
// transform to Call(GetProp(GetBase("a"), "a"), b, c)
|
||||
|
||||
node.removeChild(left);
|
||||
left.setType(TokenStream.GETBASE);
|
||||
Node str = left.cloneNode();
|
||||
str.setType(TokenStream.STRING);
|
||||
Node getProp = new Node(TokenStream.GETPROP, left, str);
|
||||
node.addChildToFront(getProp);
|
||||
left = getProp;
|
||||
|
||||
// Conditionally set a flag to add a GETTHIS node.
|
||||
// The getThis entry in the runtime will take a
|
||||
// Scriptable object intended to be used as a 'this'
|
||||
// and make sure that it is neither a With object or
|
||||
// an activation object.
|
||||
// Executing getThis requires at least two instanceof
|
||||
// tests, so we only include it if we are currently
|
||||
// inside a 'with' statement, or if we are executing
|
||||
// a script (to protect against an eval inside a with).
|
||||
addGetThis = inWithStatement() || !inFunction;
|
||||
// fall through to GETPROP code
|
||||
}
|
||||
}
|
||||
if (left.getType() != TokenStream.GETPROP &&
|
||||
left.getType() != TokenStream.GETELEM)
|
||||
{
|
||||
node.removeChild(left);
|
||||
Node tmp = irFactory.createNewTemp(left);
|
||||
Node use = irFactory.createUseTemp(tmp);
|
||||
use.putProp(Node.TEMP_PROP, tmp);
|
||||
Node parent = new Node(TokenStream.PARENT, use);
|
||||
node.addChildToFront(parent);
|
||||
node.addChildToFront(tmp);
|
||||
return;
|
||||
}
|
||||
Node leftLeft = left.getFirstChild();
|
||||
left.removeChild(leftLeft);
|
||||
Node tmp = irFactory.createNewTemp(leftLeft);
|
||||
left.addChildToFront(tmp);
|
||||
Node use = irFactory.createUseTemp(tmp);
|
||||
use.putProp(Node.TEMP_PROP, tmp);
|
||||
if (addGetThis)
|
||||
use = new Node(TokenStream.GETTHIS, use);
|
||||
node.addChildAfter(use, left);
|
||||
}
|
||||
|
||||
protected boolean inWithStatement() {
|
||||
for (int i=loops.size()-1; i >= 0; i--) {
|
||||
Node n = (Node) loops.elementAt(i);
|
||||
if (n.getType() == TokenStream.WITH)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the node is a call to a function that requires
|
||||
* access to the enclosing activation object.
|
||||
*/
|
||||
private boolean isSpecialCallName(Node tree, Node node) {
|
||||
Node left = node.getFirstChild();
|
||||
boolean isSpecial = false;
|
||||
if (left.getType() == TokenStream.NAME) {
|
||||
String name = left.getString();
|
||||
isSpecial = name.equals("eval") || name.equals("With");
|
||||
} else {
|
||||
if (left.getType() == TokenStream.GETPROP) {
|
||||
String name = left.getLastChild().getString();
|
||||
isSpecial = name.equals("exec");
|
||||
}
|
||||
}
|
||||
if (isSpecial) {
|
||||
// Calls to these functions require activation objects.
|
||||
if (inFunction)
|
||||
((FunctionNode) tree).setRequiresActivation(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected VariableTable createVariableTable() {
|
||||
return new VariableTable();
|
||||
}
|
||||
|
||||
protected VariableTable getVariableTable(Node tree) {
|
||||
if (inFunction) {
|
||||
return ((FunctionNode)tree).getVariableTable();
|
||||
}
|
||||
VariableTable result = (VariableTable)(tree.getProp(Node.VARS_PROP));
|
||||
if (result == null) {
|
||||
result = createVariableTable();
|
||||
tree.putProp(Node.VARS_PROP, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void reportMessage(Context cx, String msg, Node stmt,
|
||||
Node tree, boolean isError,
|
||||
Scriptable scope)
|
||||
{
|
||||
Object obj = stmt.getDatum();
|
||||
int lineno = 0;
|
||||
if (obj != null && obj instanceof Integer)
|
||||
lineno = ((Integer) obj).intValue();
|
||||
Object prop = tree == null
|
||||
? null
|
||||
: tree.getProp(Node.SOURCENAME_PROP);
|
||||
if (isError) {
|
||||
if (scope != null)
|
||||
throw NativeGlobal.constructError(
|
||||
cx, "SyntaxError", msg, scope,
|
||||
(String) prop, lineno, 0, null);
|
||||
else
|
||||
cx.reportError(msg, (String) prop, lineno, null, 0);
|
||||
}
|
||||
else
|
||||
cx.reportWarning(msg, (String) prop, lineno, null, 0);
|
||||
}
|
||||
|
||||
protected Stack loops;
|
||||
protected Stack loopEnds;
|
||||
protected boolean inFunction;
|
||||
protected IRFactory irFactory;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/* -*- 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;
|
||||
|
||||
/**
|
||||
* Thrown if call is attempted on an object that is not a function.
|
||||
*/
|
||||
public class NotAFunctionException extends Exception {
|
||||
|
||||
public NotAFunctionException() {
|
||||
}
|
||||
|
||||
public NotAFunctionException(String detail) {
|
||||
super(detail);
|
||||
}
|
||||
|
||||
}
|
||||
1487
mozilla/js/rhino/org/mozilla/javascript/Parser.java
Normal file
1487
mozilla/js/rhino/org/mozilla/javascript/Parser.java
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user