author | Wes Kocher <wkocher@mozilla.com> |
Wed, 12 Aug 2015 15:16:16 -0700 | |
changeset 257498 | 7649ffe28b67aa2dad0f67ea01500c0ff91b2bac |
parent 257497 | cf932fc931dcd19f425934db79bec641ebe2a8a9 (current diff) |
parent 257473 | 8e248632025d5455148a604f6e63f7f167e299ca (diff) |
child 257499 | 6af0674d374e5af4c55d12206670346f81cd666e |
child 257564 | c609d91f04d9422a803c51a47a988fc759738d77 |
child 257581 | 1c1d97b563f410d571e4925dab3f53fcae6c5272 |
push id | 63637 |
push user | kwierso@gmail.com |
push date | Wed, 12 Aug 2015 22:19:42 +0000 |
treeherder | mozilla-inbound@7649ffe28b67 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 43.0a1 |
first release with | nightly linux32
7649ffe28b67
/
43.0a1
/
20150813030208
/
files
nightly linux64
7649ffe28b67
/
43.0a1
/
20150813030208
/
files
nightly mac
7649ffe28b67
/
43.0a1
/
20150813030208
/
files
nightly win32
7649ffe28b67
/
43.0a1
/
20150813030208
/
files
nightly win64
7649ffe28b67
/
43.0a1
/
20150813030208
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
43.0a1
/
20150813030208
/
pushlog to previous
nightly linux64
43.0a1
/
20150813030208
/
pushlog to previous
nightly mac
43.0a1
/
20150813030208
/
pushlog to previous
nightly win32
43.0a1
/
20150813030208
/
pushlog to previous
nightly win64
43.0a1
/
20150813030208
/
pushlog to previous
|
--- a/accessible/generic/Accessible.cpp +++ b/accessible/generic/Accessible.cpp @@ -857,20 +857,20 @@ Accessible::HandleAccEvent(AccEvent* aEv break; case nsIAccessibleEvent::EVENT_STATE_CHANGE: { AccStateChangeEvent* event = downcast_accEvent(aEvent); ipcDoc->SendStateChangeEvent(id, event->GetState(), event->IsStateEnabled()); break; } case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: { - AccCaretMoveEvent* event = downcast_accEvent(aEvent); - ipcDoc->SendEvent(id, event->GetCaretOffset()); - break; - } + AccCaretMoveEvent* event = downcast_accEvent(aEvent); + ipcDoc->SendCaretMoveEvent(id, event->GetCaretOffset()); + break; + } case nsIAccessibleEvent::EVENT_TEXT_INSERTED: case nsIAccessibleEvent::EVENT_TEXT_REMOVED: { AccTextChangeEvent* event = downcast_accEvent(aEvent); ipcDoc->SendTextChangeEvent(id, event->ModifiedText(), event->GetStartOffset(), event->GetLength(), event->IsTextInserted(), event->IsFromUserInput());
--- a/b2g/branding/official/Makefile.in +++ b/b2g/branding/official/Makefile.in @@ -8,16 +8,19 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),windows) BRANDING_FILES := \ app.ico \ $(NULL) endif ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) BRANDING_FILES := \ app.icns \ + background.png \ + disk.icns \ + dsstore \ $(NULL) endif ifdef MOZ_WIDGET_GTK BRANDING_FILES := \ default.png \ $(NULL) endif
--- a/b2g/branding/unofficial/Makefile.in +++ b/b2g/branding/unofficial/Makefile.in @@ -8,16 +8,19 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),windows) BRANDING_FILES := \ app.ico \ $(NULL) endif ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa) BRANDING_FILES := \ app.icns \ + background.png \ + disk.icns \ + dsstore \ $(NULL) endif ifdef MOZ_WIDGET_GTK BRANDING_FILES := \ default.png \ $(NULL) endif
deleted file mode 100755 --- a/build/package/mac_osx/pkg-dmg +++ /dev/null @@ -1,1488 +0,0 @@ -#!/usr/bin/perl -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -use strict; -use warnings; - -=pod - -=head1 NAME - -B<pkg-dmg> - Mac OS X disk image (.dmg) packager - -=head1 SYNOPSIS - -B<pkg-dmg> -B<--source> I<source-folder> -B<--target> I<target-image> -[B<--format> I<format>] -[B<--volname> I<volume-name>] -[B<--tempdir> I<temp-dir>] -[B<--mkdir> I<directory>] -[B<--copy> I<source>[:I<dest>]] -[B<--symlink> I<source>[:I<dest>]] -[B<--license> I<file>] -[B<--resource> I<file>] -[B<--icon> I<icns-file>] -[B<--attribute> I<a>:I<file>[:I<file>...] -[B<--idme>] -[B<--sourcefile>] -[B<--verbosity> I<level>] -[B<--dry-run>] - -=head1 DESCRIPTION - -I<pkg-dmg> takes a directory identified by I<source-folder> and transforms -it into a disk image stored as I<target-image>. The disk image will -occupy the least space possible for its format, or the least space that the -authors have been able to figure out how to achieve. - -=head1 OPTIONS - -=over 5 - -==item B<--source> I<source-folder> - -Identifies the directory that will be packaged up. This directory is not -touched, a copy will be made in a temporary directory for staging purposes. -See B<--tempdir>. - -==item B<--target> I<target-image> - -The disk image to create. If it exists and is not in use, it will be -overwritten. If I<target-image> already contains a suitable extension, -it will be used unmodified. If no extension is present, or the extension -is incorrect for the selected format, the proper extension will be added. -See B<--format>. - -==item B<--format> I<format> - -The format to create the disk image in. Valid values for I<format> are: - - UDZO - zlib-compressed, read-only; extension I<.dmg> - - UDBZ - bzip2-compressed, read-only; extension I<.dmg>; - create and use on 10.4 ("Tiger") and later only - - UDRW - read-write; extension I<.dmg> - - UDSP - read-write, sparse; extension I<.sparseimage> - -UDBZ is the default format. - -See L<hdiutil(1)> for a description of these formats. - -=item B<--volname> I<volume-name> - -The name of the volume in the disk image. If not specified, I<volume-name> -defaults to the name of the source directory from B<--source>. - -=item B<--tempdir> I<temp-dir> - -A temporary directory to stage intermediate files in. I<temp-dir> must -have enough space available to accommodate twice the size of the files -being packaged. If not specified, defaults to the same directory that -the I<target-image> is to be placed in. B<pkg-dmg> will remove any -temporary files it places in I<temp-dir>. - -=item B<--mkdir> I<directory> - -Specifies a directory that should be created in the disk image. -I<directory> and any ancestor directories will be created. This is -useful in conjunction with B<--copy>, when copying files to directories -that may not exist in I<source-folder>. B<--mkdir> may appear multiple -times. - -=item B<--copy> I<source>[:I<dest>] - -Additional files to copy into the disk image. If I<dest> is -specified, I<source> is copied to the location I<dest> identifies, -otherwise, I<source> is copied to the root of the new volume. B<--copy> -provides a way to package up a I<source-folder> by adding files to it -without modifying the original I<source-folder>. B<--copy> may appear -multiple times. - -This option is useful for adding .DS_Store files and window backgrounds -to disk images. - -=item B<--symlink> I<source>[:I<dest>] - -Like B<--copy>, but allows symlinks to point out of the volume. Empty symlink -destinations are interpreted as "like the source path, but inside the dmg" - -This option is useful for adding symlinks to external resources, -e.g. to /Applications. - -=item B<--license> I<file> - -A plain text file containing a license agreement to be displayed before -the disk image is mounted. English is the only supported language. To -include license agreements in other languages, in multiple languages, -or to use formatted text, prepare a resource and use L<--resource>. - -=item B<--resource> I<file> - -A resource file to merge into I<target-image>. If I<format> is UDZO or -UDBZ, the disk image will be flattened to a single-fork file that contains -the resource but may be freely transferred without any special encodings. -I<file> must be in a format suitable for L<Rez(1)>. See L<Rez(1)> for a -description of the format, and L<hdiutil(1)> for a discussion on flattened -disk images. B<--resource> may appear multiple times. - -This option is useful for adding license agreements and other messages -to disk images. - -=item B<--icon> I<icns-file> - -Specifies an I<icns> file that will be used as the icon for the root of -the volume. This file will be copied to the new volume and the custom -icon attribute will be set on the root folder. - -=item B<--attribute> I<a>:I<file>[:I<file>...] - -Sets the attributes of I<file> to the attribute list in I<a>. See -L<SetFile(1)> - -=item B<--idme> - -Enable IDME to make the disk image "Internet-enabled." The first time -the image is mounted, if IDME processing is enabled on the system, the -contents of the image will be copied out of the image and the image will -be placed in the trash with IDME disabled. - -=item B<--sourcefile> - -If this option is present, I<source-folder> is treated as a file, and is -placed as a file within the volume's root folder. Without this option, -I<source-folder> is treated as the volume root itself. - -=item B<--verbosity> I<level> - -Adjusts the level of loudness of B<pkg-dmg>. The possible values for -I<level> are: - 0 - Only error messages are displayed. - 1 - Print error messages and command invocations. - 2 - Print everything, including command output. - -The default I<level> is 2. - -=item B<--dry-run> - -When specified, the commands that would be executed are printed, without -actually executing them. When commands depend on the output of previous -commands, dummy values are displayed. - -=back - -=head1 NON-OPTIONS - -=over 5 - -=item - -Resource forks aren't copied. - -=item - -The root folder of the created volume is designated as the folder -to open when the volume is mounted. See L<bless(8)>. - -=item - -All files in the volume are set to be world-readable, only writable -by the owner, and world-executable when appropriate. All other -permissions bits are cleared. - -=item - -When possible, disk images are created without any partition tables. This -is what L<hdiutil(1)> refers to as I<-layout NONE>, and saves a handful of -kilobytes. The alternative, I<SPUD>, contains a partition table that -is not terribly handy on disk images that are not intended to represent any -physical disk. - -=item - -Read-write images are created with journaling off. Any read-write image -created by this tool is expected to be transient, and the goal of this tool -is to create images which consume a minimum of space. - -=back - -=head1 EXAMPLE - -pkg-dmg --source /Applications/DeerPark.app --target ~/DeerPark.dmg - --sourcefile --volname DeerPark --icon ~/DeerPark.icns - --mkdir /.background - --copy DeerParkBackground.png:/.background/background.png - --copy DeerParkDSStore:/.DS_Store - --symlink /Applications:"/Drag to here" - -=head1 REQUIREMENTS - -I<pkg-dmg> has been tested with Mac OS X releases 10.2 ("Jaguar") -through 10.4 ("Tiger"). Certain adjustments to behavior are made -depending on the host system's release. Mac OS X 10.3 ("Panther") or -later are recommended. - -=head1 LICENSE - -MPL 2. - -=head1 AUTHOR - -Mark Mentovai - -=head1 SEE ALSO - -L<bless(8)>, L<diskutil(8)>, L<hdid(8)>, L<hdiutil(1)>, L<Rez(1)>, -L<rsync(1)>, L<SetFile(1)> - -=cut - -use Fcntl; -use POSIX; -use Getopt::Long; - -sub argumentEscape(@); -sub cleanupDie($); -sub command(@); -sub commandInternal($@); -sub commandInternalVerbosity($$@); -sub commandOutput(@); -sub commandOutputVerbosity($@); -sub commandVerbosity($@); -sub copyFiles($@); -sub diskImageMaker($$$$$$$$); -sub giveExtension($$); -sub hdidMountImage($@); -sub isFormatCompressed($); -sub licenseMaker($$); -sub pathSplit($); -sub setAttributes($@); -sub trapSignal($); -sub usage(); - -# Variables used as globals -my(@gCleanup, %gConfig, $gDarwinMajor, $gDryRun, $gVerbosity); - -# Use the commands by name if they're expected to be in the user's -# $PATH (/bin:/sbin:/usr/bin:/usr/sbin). Otherwise, go by absolute -# path. These may be overridden with --config. -%gConfig = ('cmd_bless' => 'bless', - 'cmd_chmod' => 'chmod', - 'cmd_diskutil' => 'diskutil', - 'cmd_du' => 'du', - 'cmd_hdid' => 'hdid', - 'cmd_hdiutil' => 'hdiutil', - 'cmd_mkdir' => 'mkdir', - 'cmd_mktemp' => 'mktemp', - 'cmd_Rez' => 'Rez', - 'cmd_rm' => 'rm', - 'cmd_rsync' => 'rsync', - 'cmd_SetFile' => 'SetFile', - - # create_directly indicates whether hdiutil create supports - # -srcfolder and -srcdevice. It does on >= 10.3 (Panther). - # This is fixed up for earlier systems below. If false, - # hdiutil create is used to create empty disk images that - # are manually filled. - 'create_directly' => 1, - - # If hdiutil attach -mountpoint exists, use it to avoid - # mounting disk images in the default /Volumes. This reduces - # the likelihood that someone will notice a mounted image and - # interfere with it. Only available on >= 10.3 (Panther), - # fixed up for earlier systems below. - # - # This is presently turned off for all systems, because there - # is an infrequent synchronization problem during ejection. - # diskutil eject might return before the image is actually - # unmounted. If pkg-dmg then attempts to clean up its - # temporary directory, it could remove items from a read-write - # disk image or attempt to remove items from a read-only disk - # image (or a read-only item from a read-write image) and fail, - # causing pkg-dmg to abort. This problem is experienced - # under Tiger, which appears to eject asynchronously where - # previous systems treated it as a synchronous operation. - # Using hdiutil attach -mountpoint didn't always keep images - # from showing up on the desktop anyway. - 'hdiutil_mountpoint' => 0, - - # hdiutil makehybrid results in optimized disk images that - # consume less space and mount more quickly. Use it when - # it's available, but that's only on >= 10.3 (Panther). - # If false, hdiutil create is used instead. Fixed up for - # earlier systems below. - 'makehybrid' => 1, - - # hdiutil create doesn't allow specifying a folder to open - # at volume mount time, so those images are mounted and - # their root folders made holy with bless -openfolder. But - # only on >= 10.3 (Panther). Earlier systems are out of luck. - # Even on Panther, bless refuses to run unless root. - # Fixed up below. - 'openfolder_bless' => 1, - - # It's possible to save a few more kilobytes by including the - # partition only without any partition table in the image. - # This is a good idea on any system, so turn this option off. - # - # Except it's buggy. "-layout NONE" seems to be creating - # disk images with more data than just the partition table - # stripped out. You might wind up losing the end of the - # filesystem - the last file (or several) might be incomplete. - 'partition_table' => 1, - - # To create a partition table-less image from something - # created by makehybrid, the hybrid image needs to be - # mounted and a new image made from the device associated - # with the relevant partition. This requires >= 10.4 - # (Tiger), presumably because earlier systems have - # problems creating images from devices themselves attached - # to images. If this is false, makehybrid images will - # have partition tables, regardless of the partition_table - # setting. Fixed up for earlier systems below. - 'recursive_access' => 1); - -# --verbosity -$gVerbosity = 2; - -# --dry-run -$gDryRun = 0; - -# %gConfig fix-ups based on features and bugs present in certain releases. -my($ignore, $uname_r, $uname_s); -($uname_s, $ignore, $uname_r, $ignore, $ignore) = POSIX::uname(); -if($uname_s eq 'Darwin') { - ($gDarwinMajor, $ignore) = split(/\./, $uname_r, 2); - - # $major is the Darwin major release, which for our purposes, is 4 higher - # than the interesting digit in a Mac OS X release. - if($gDarwinMajor <= 6) { - # <= 10.2 (Jaguar) - # hdiutil create does not support -srcfolder or -srcdevice - $gConfig{'create_directly'} = 0; - # hdiutil attach does not support -mountpoint - $gConfig{'hdiutil_mountpoint'} = 0; - # hdiutil mkhybrid does not exist - $gConfig{'makehybrid'} = 0; - } - if($gDarwinMajor <= 7) { - # <= 10.3 (Panther) - # Can't mount a disk image and then make a disk image from the device - $gConfig{'recursive_access'} = 0; - # bless does not support -openfolder on 10.2 (Jaguar) and must run - # as root under 10.3 (Panther) - $gConfig{'openfolder_bless'} = 0; - } -} -else { - # If it's not Mac OS X, just assume all of those good features are - # available. They're not, but things will fail long before they - # have a chance to make a difference. - # - # Now, if someone wanted to document some of these private formats... - print STDERR ($0.": warning, not running on Mac OS X, ". - "this could be interesting.\n"); -} - -# Non-global variables used in Getopt -my(@attributes, @copyFiles, @createSymlinks, $iconFile, $idme, $licenseFile, - @makeDirs, $outputFormat, @resourceFiles, $sourceFile, $sourceFolder, - $targetImage, $tempDir, $volumeName); - -# --format -$outputFormat = 'UDBZ'; - -# --idme -$idme = 0; - -# --sourcefile -$sourceFile = 0; - -# Leaving this might screw up the Apple tools. -delete $ENV{'NEXT_ROOT'}; - -# This script can get pretty messy, so trap a few signals. -$SIG{'INT'} = \&trapSignal; -$SIG{'HUP'} = \&trapSignal; -$SIG{'TERM'} = \&trapSignal; - -Getopt::Long::Configure('pass_through'); -GetOptions('source=s' => \$sourceFolder, - 'target=s' => \$targetImage, - 'volname=s' => \$volumeName, - 'format=s' => \$outputFormat, - 'tempdir=s' => \$tempDir, - 'mkdir=s' => \@makeDirs, - 'copy=s' => \@copyFiles, - 'symlink=s' => \@createSymlinks, - 'license=s' => \$licenseFile, - 'resource=s' => \@resourceFiles, - 'icon=s' => \$iconFile, - 'attribute=s' => \@attributes, - 'idme' => \$idme, - 'sourcefile' => \$sourceFile, - 'verbosity=i' => \$gVerbosity, - 'dry-run' => \$gDryRun, - 'config=s' => \%gConfig); # "hidden" option not in usage() - -if(@ARGV) { - # All arguments are parsed by Getopt - usage(); - exit(1); -} - -if($gVerbosity<0 || $gVerbosity>2) { - usage(); - exit(1); -} - -if(!defined($sourceFolder) || $sourceFolder eq '' || - !defined($targetImage) || $targetImage eq '') { - # --source and --target are required arguments - usage(); - exit(1); -} - -# Make sure $sourceFolder doesn't contain trailing slashes. It messes with -# rsync. -while(substr($sourceFolder, -1) eq '/') { - chop($sourceFolder); -} - -if(!defined($volumeName)) { - # Default volumeName is the name of the source directory. - my(@components); - @components = pathSplit($sourceFolder); - $volumeName = pop(@components); -} - -my(@tempDirComponents, $targetImageFilename); -@tempDirComponents = pathSplit($targetImage); -$targetImageFilename = pop(@tempDirComponents); - -if(defined($tempDir)) { - @tempDirComponents = pathSplit($tempDir); -} -else { - # Default tempDir is the same directory as what is specified for - # targetImage - $tempDir = join('/', @tempDirComponents); -} - -# Ensure that the path of the target image has a suitable extension. If -# it didn't, hdiutil would add one, and we wouldn't be able to find the -# file. -# -# Note that $targetImageFilename is not being reset. This is because it's -# used to build other names below, and we don't need to be adding all sorts -# of extra unnecessary extensions to the name. -my($originalTargetImage, $requiredExtension); -$originalTargetImage = $targetImage; -if($outputFormat eq 'UDSP') { - $requiredExtension = '.sparseimage'; -} -else { - $requiredExtension = '.dmg'; -} -$targetImage = giveExtension($originalTargetImage, $requiredExtension); - -if($targetImage ne $originalTargetImage) { - print STDERR ($0.": warning: target image extension is being added\n"); - print STDERR (' The new filename is '. - giveExtension($targetImageFilename,$requiredExtension)."\n"); -} - -# Make a temporary directory in $tempDir for our own nefarious purposes. -my(@output, $tempSubdir, $tempSubdirTemplate); -$tempSubdirTemplate=join('/', @tempDirComponents, - 'pkg-dmg.'.$$.'.XXXXXXXX'); -if(!(@output = commandOutput($gConfig{'cmd_mktemp'}, '-d', - $tempSubdirTemplate)) || $#output != 0) { - cleanupDie('mktemp failed'); -} - -if($gDryRun) { - (@output)=($tempSubdirTemplate); -} - -($tempSubdir) = @output; - -push(@gCleanup, - sub {commandVerbosity(0, $gConfig{'cmd_rm'}, '-rf', $tempSubdir);}); - -my($tempMount, $tempRoot, @tempsToMake); -$tempRoot = $tempSubdir.'/stage'; -$tempMount = $tempSubdir.'/mount'; -push(@tempsToMake, $tempRoot); -if($gConfig{'hdiutil_mountpoint'}) { - push(@tempsToMake, $tempMount); -} - -if(command($gConfig{'cmd_mkdir'}, @tempsToMake) != 0) { - cleanupDie('mkdir tempRoot/tempMount failed'); -} - -# This cleanup object is not strictly necessary, because $tempRoot is inside -# of $tempSubdir, but the rest of the script relies on this object being -# on the cleanup stack and expects to remove it. -push(@gCleanup, - sub {commandVerbosity(0, $gConfig{'cmd_rm'}, '-rf', $tempRoot);}); - -# If $sourceFile is true, it means that $sourceFolder is to be treated as -# a file and placed as a file within the volume root, as opposed to being -# treated as the volume root itself. rsync will do this by default, if no -# trailing '/' is present. With a trailing '/', $sourceFolder becomes -# $tempRoot, instead of becoming an entry in $tempRoot. -if(command($gConfig{'cmd_rsync'}, '-a', '--copy-unsafe-links', - $sourceFolder.($sourceFile?'':'/'),$tempRoot) != 0) { - cleanupDie('rsync failed'); -} - -if(@makeDirs) { - my($makeDir, @tempDirsToMake); - foreach $makeDir (@makeDirs) { - if($makeDir =~ /^\//) { - push(@tempDirsToMake, $tempRoot.$makeDir); - } - else { - push(@tempDirsToMake, $tempRoot.'/'.$makeDir); - } - } - if(command($gConfig{'cmd_mkdir'}, '-p', @tempDirsToMake) != 0) { - cleanupDie('mkdir failed'); - } -} - -# copy files and/or create symlinks -copyFiles($tempRoot, 'copy', @copyFiles); -copyFiles($tempRoot, 'symlink', @createSymlinks); - -if($gConfig{'create_directly'}) { - # If create_directly is false, the contents will be rsynced into a - # disk image and they would lose their attributes. - setAttributes($tempRoot, @attributes); -} - -if(defined($iconFile)) { - if(command($gConfig{'cmd_rsync'}, '-a', '--copy-unsafe-links', $iconFile, - $tempRoot.'/.VolumeIcon.icns') != 0) { - cleanupDie('rsync failed for volume icon'); - } - - # It's pointless to set the attributes of the root when diskutil create - # -srcfolder is being used. In that case, the attributes will be set - # later, after the image is already created. - if(isFormatCompressed($outputFormat) && - (command($gConfig{'cmd_SetFile'}, '-a', 'C', $tempRoot) != 0)) { - cleanupDie('SetFile failed'); - } -} - -if(command($gConfig{'cmd_chmod'}, '-R', 'a+rX,a-st,u+w,go-w', - $tempRoot) != 0) { - cleanupDie('chmod failed'); -} - -my($unflattenable); -if(isFormatCompressed($outputFormat)) { - $unflattenable = 1; -} -else { - $unflattenable = 0; -} - -diskImageMaker($tempRoot, $targetImage, $outputFormat, $volumeName, - $tempSubdir, $tempMount, $targetImageFilename, defined($iconFile)); - -if(defined($licenseFile) && $licenseFile ne '') { - my($licenseResource); - $licenseResource = $tempSubdir.'/license.r'; - if(!licenseMaker($licenseFile, $licenseResource)) { - cleanupDie('licenseMaker failed'); - } - push(@resourceFiles, $licenseResource); - # Don't add a cleanup object because licenseResource is in tempSubdir. -} - -if(@resourceFiles) { - # Add resources, such as a license agreement. - - # Only unflatten read-only and compressed images. It's not supported - # on other image times. - if($unflattenable && - (command($gConfig{'cmd_hdiutil'}, 'unflatten', $targetImage)) != 0) { - cleanupDie('hdiutil unflatten failed'); - } - # Don't push flatten onto the cleanup stack. If we fail now, we'll be - # removing $targetImage anyway. - - # Type definitions come from Carbon.r. - if(command($gConfig{'cmd_Rez'}, 'Carbon.r', @resourceFiles, '-a', '-o', - $targetImage) != 0) { - cleanupDie('Rez failed'); - } - - # Flatten. This merges the resource fork into the data fork, so no - # special encoding is needed to transfer the file. - if($unflattenable && - (command($gConfig{'cmd_hdiutil'}, 'flatten', $targetImage)) != 0) { - cleanupDie('hdiutil flatten failed'); - } -} - -# $tempSubdir is no longer needed. It's buried on the stack below the -# rm of the fresh image file. Splice in this fashion is equivalent to -# pop-save, pop, push-save. -splice(@gCleanup, -2, 1); -# No need to remove licenseResource separately, it's in tempSubdir. -if(command($gConfig{'cmd_rm'}, '-rf', $tempSubdir) != 0) { - cleanupDie('rm -rf tempSubdir failed'); -} - -if($idme) { - if(command($gConfig{'cmd_hdiutil'}, 'internet-enable', '-yes', - $targetImage) != 0) { - cleanupDie('hdiutil internet-enable failed'); - } -} - -# Done. - -exit(0); - -# argumentEscape(@arguments) -# -# Takes a list of @arguments and makes them shell-safe. -sub argumentEscape(@) { - my(@arguments); - @arguments = @_; - my($argument, @argumentsOut); - foreach $argument (@arguments) { - $argument =~ s%([^A-Za-z0-9_\-/.=+,])%\\$1%g; - push(@argumentsOut, $argument); - } - return @argumentsOut; -} - -# cleanupDie($message) -# -# Displays $message as an error message, and then runs through the -# @gCleanup stack, performing any cleanup operations needed before -# exiting. Does not return, exits with exit status 1. -sub cleanupDie($) { - my($message); - ($message) = @_; - print STDERR ($0.': '.$message.(@gCleanup?' (cleaning up)':'')."\n"); - while(@gCleanup) { - my($subroutine); - $subroutine = pop(@gCleanup); - &$subroutine; - } - exit(1); -} - -# command(@arguments) -# -# Runs the specified command at the verbosity level defined by $gVerbosity. -# Returns nonzero on failure, returning the exit status if appropriate. -# Discards command output. -sub command(@) { - my(@arguments); - @arguments = @_; - return commandVerbosity($gVerbosity,@arguments); -} - -# commandInternal($command, @arguments) -# -# Runs the specified internal command at the verbosity level defined by -# $gVerbosity. -# Returns zero(!) on failure, because commandInternal is supposed to be a -# direct replacement for the Perl system call wrappers, which, unlike shell -# commands and C equivalent system calls, return true (instead of 0) to -# indicate success. -sub commandInternal($@) { - my(@arguments, $command); - ($command, @arguments) = @_; - return commandInternalVerbosity($gVerbosity, $command, @arguments); -} - -# commandInternalVerbosity($verbosity, $command, @arguments) -# -# Run an internal command, printing a bogus command invocation message if -# $verbosity is true. -# -# If $command is unlink: -# Removes the files specified by @arguments. Wraps unlink. -# -# If $command is symlink: -# Creates the symlink specified by @arguments. Wraps symlink. -sub commandInternalVerbosity($$@) { - my(@arguments, $command, $verbosity); - ($verbosity, $command, @arguments) = @_; - if($command eq 'unlink') { - if($verbosity || $gDryRun) { - print(join(' ', 'rm', '-f', argumentEscape(@arguments))."\n"); - } - if($gDryRun) { - return $#arguments+1; - } - return unlink(@arguments); - } - elsif($command eq 'symlink') { - if($verbosity || $gDryRun) { - print(join(' ', 'ln', '-s', argumentEscape(@arguments))."\n"); - } - if($gDryRun) { - return 1; - } - my($source, $target); - ($source, $target) = @arguments; - return symlink($source, $target); - } -} - -# commandOutput(@arguments) -# -# Runs the specified command at the verbosity level defined by $gVerbosity. -# Output is returned in an array of lines. undef is returned on failure. -# The exit status is available in $?. -sub commandOutput(@) { - my(@arguments); - @arguments = @_; - return commandOutputVerbosity($gVerbosity, @arguments); -} - -# commandOutputVerbosity($verbosity, @arguments) -# -# Runs the specified command at the verbosity level defined by the -# $verbosity argument. Output is returned in an array of lines. undef is -# returned on failure. The exit status is available in $?. -# -# If an error occurs in fork or exec, an error message is printed to -# stderr and undef is returned. -# -# If $verbosity is 0, the command invocation is not printed, and its -# stdout is not echoed back to stdout. -# -# If $verbosity is 1, the command invocation is printed. -# -# If $verbosity is 2, the command invocation is printed and the output -# from stdout is echoed back to stdout. -# -# Regardless of $verbosity, stderr is left connected. -sub commandOutputVerbosity($@) { - my(@arguments, $verbosity); - ($verbosity, @arguments) = @_; - my($pid); - if($verbosity || $gDryRun) { - print(join(' ', argumentEscape(@arguments))."\n"); - } - if($gDryRun) { - return(1); - } - if (!defined($pid = open(*COMMAND, '-|'))) { - printf STDERR ($0.': fork: '.$!."\n"); - return undef; - } - elsif ($pid) { - # parent - my(@lines); - while(!eof(*COMMAND)) { - my($line); - chop($line = <COMMAND>); - if($verbosity > 1) { - print($line."\n"); - } - push(@lines, $line); - } - close(*COMMAND); - if ($? == -1) { - printf STDERR ($0.': fork: '.$!."\n"); - return undef; - } - elsif ($? & 127) { - printf STDERR ($0.': exited on signal '.($? & 127). - ($? & 128 ? ', core dumped' : '')."\n"); - return undef; - } - return @lines; - } - else { - # child; this form of exec is immune to shell games - if(!exec {$arguments[0]} (@arguments)) { - printf STDERR ($0.': exec: '.$!."\n"); - exit(-1); - } - } -} - -# commandVerbosity($verbosity, @arguments) -# -# Runs the specified command at the verbosity level defined by the -# $verbosity argument. Returns nonzero on failure, returning the exit -# status if appropriate. Discards command output. -sub commandVerbosity($@) { - my(@arguments, $verbosity); - ($verbosity, @arguments) = @_; - if(!defined(commandOutputVerbosity($verbosity, @arguments))) { - return -1; - } - return $?; -} - -# copyFiles($tempRoot, $method, @arguments) -# -# Copies files or create symlinks in the disk image. -# See --copy and --symlink descriptions for details. -# If $method is 'copy', @arguments are interpreted as source:target, if $method -# is 'symlink', @arguments are interpreted as symlink:target. -sub copyFiles($@) { - my(@fileList, $method, $tempRoot); - ($tempRoot, $method, @fileList) = @_; - my($file, $isSymlink); - $isSymlink = ($method eq 'symlink'); - foreach $file (@fileList) { - my($source, $target); - ($source, $target) = split(/:/, $file); - if(!defined($target) and $isSymlink) { - # empty symlink targets would result in an invalid target and fail, - # but they shall be interpreted as "like source path, but inside dmg" - $target = $source; - } - if(!defined($target)) { - $target = $tempRoot; - } - elsif($target =~ /^\//) { - $target = $tempRoot.$target; - } - else { - $target = $tempRoot.'/'.$target; - } - - my($success); - if($isSymlink) { - $success = commandInternal('symlink', $source, $target); - } - else { - $success = !command($gConfig{'cmd_rsync'}, '-a', '--copy-unsafe-links', - $source, $target); - } - if(!$success) { - cleanupDie('copyFiles failed for method '.$method); - } - } -} - -# diskImageMaker($source, $destination, $format, $name, $tempDir, $tempMount, -# $baseName, $setRootIcon) -# -# Creates a disk image in $destination of format $format corresponding to the -# source directory $source. $name is the volume name. $tempDir is a good -# place to write temporary files, which should be empty (aside from the other -# things that this script might create there, like stage and mount). -# $tempMount is a mount point for temporary disk images. $baseName is the -# name of the disk image, and is presently unused. $setRootIcon is true if -# a volume icon was added to the staged $source and indicates that the -# custom volume icon bit on the volume root needs to be set. -sub diskImageMaker($$$$$$$$) { - my($baseName, $destination, $format, $name, $setRootIcon, $source, - $tempDir, $tempMount); - ($source, $destination, $format, $name, $tempDir, $tempMount, - $baseName, $setRootIcon) = @_; - if(isFormatCompressed($format)) { - my($uncompressedImage); - - if($gConfig{'makehybrid'}) { - my($hybridImage); - $hybridImage = giveExtension($tempDir.'/hybrid', '.dmg'); - - if(command($gConfig{'cmd_hdiutil'}, 'makehybrid', '-hfs', - '-hfs-volume-name', $name, '-hfs-openfolder', $source, '-ov', - $source, '-o', $hybridImage) != 0) { - cleanupDie('hdiutil makehybrid failed'); - } - - $uncompressedImage = $hybridImage; - - # $source is no longer needed and will be removed before anything - # else can fail. splice in this form is the same as pop/push. - splice(@gCleanup, -1, 1, - sub {commandInternalVerbosity(0, 'unlink', $hybridImage);}); - - if(command($gConfig{'cmd_rm'}, '-rf', $source) != 0) { - cleanupDie('rm -rf failed'); - } - - if(!$gConfig{'partition_table'} && $gConfig{'recursive_access'}) { - # Even if we do want to create disk images without partition tables, - # it's impossible unless recursive_access is set. - my($rootDevice, $partitionDevice, $partitionMountPoint); - - if(!(($rootDevice, $partitionDevice, $partitionMountPoint) = - hdidMountImage($tempMount, '-readonly', $hybridImage))) { - cleanupDie('hdid mount failed'); - } - - push(@gCleanup, sub {commandVerbosity(0, - $gConfig{'cmd_diskutil'}, 'eject', $rootDevice);}); - - my($udrwImage); - $udrwImage = giveExtension($tempDir.'/udrw', '.dmg'); - - if(command($gConfig{'cmd_hdiutil'}, 'create', '-format', 'UDRW', - '-ov', '-srcdevice', $partitionDevice, $udrwImage) != 0) { - cleanupDie('hdiutil create failed'); - } - - $uncompressedImage = $udrwImage; - - # Going to eject before anything else can fail. Get the eject off - # the stack. - pop(@gCleanup); - - # $hybridImage will be removed soon, but until then, it needs to - # stay on the cleanup stack. It needs to wait until after - # ejection. $udrwImage is staying around. Make it appear as - # though it's been done before $hybridImage. - # - # splice in this form is the same as popping one element to - # @tempCleanup and pushing the subroutine. - my(@tempCleanup); - @tempCleanup = splice(@gCleanup, -1, 1, - sub {commandInternalVerbosity(0, 'unlink', $udrwImage);}); - push(@gCleanup, @tempCleanup); - - if(command($gConfig{'cmd_diskutil'}, 'eject', $rootDevice) != 0) { - cleanupDie('diskutil eject failed'); - } - - # Pop unlink of $uncompressedImage - pop(@gCleanup); - - if(commandInternal('unlink', $hybridImage) != 1) { - cleanupDie('unlink hybridImage failed: '.$!); - } - } - } - else { - # makehybrid is not available, fall back to making a UDRW and - # converting to a compressed image. It ought to be possible to - # create a compressed image directly, but those come out far too - # large (journaling?) and need to be read-write to fix up the - # volume icon anyway. Luckily, we can take advantage of a single - # call back into this function. - my($udrwImage); - $udrwImage = giveExtension($tempDir.'/udrw', '.dmg'); - - diskImageMaker($source, $udrwImage, 'UDRW', $name, $tempDir, - $tempMount, $baseName, $setRootIcon); - - # The call back into diskImageMaker already removed $source. - - $uncompressedImage = $udrwImage; - } - - # The uncompressed disk image is now in its final form. Compress it. - # Jaguar doesn't support hdiutil convert -ov, but it always allows - # overwriting. - # bzip2-compressed UDBZ images can only be created and mounted on 10.4 - # and later. The bzip2-level imagekey is only effective when creating - # images in 10.5. In 10.4, bzip2-level is harmlessly ignored, and the - # default value of 1 is always used. - if(command($gConfig{'cmd_hdiutil'}, 'convert', '-format', $format, - '-imagekey', ($format eq 'UDBZ' ? 'bzip2-level=9' : 'zlib-level=9'), - (defined($gDarwinMajor) && $gDarwinMajor <= 6 ? () : ('-ov')), - $uncompressedImage, '-o', $destination) != 0) { - cleanupDie('hdiutil convert failed'); - } - - # $uncompressedImage is going to be unlinked before anything else can - # fail. splice in this form is the same as pop/push. - splice(@gCleanup, -1, 1, - sub {commandInternalVerbosity(0, 'unlink', $destination);}); - - if(commandInternal('unlink', $uncompressedImage) != 1) { - cleanupDie('unlink uncompressedImage failed: '.$!); - } - - # At this point, the only thing that the compressed block has added to - # the cleanup stack is the removal of $destination. $source has already - # been removed, and its cleanup entry has been removed as well. - } - elsif($format eq 'UDRW' || $format eq 'UDSP') { - my(@extraArguments); - if(!$gConfig{'partition_table'}) { - @extraArguments = ('-layout', 'NONE'); - } - - if($gConfig{'create_directly'}) { - # Use -fs HFS+ to suppress the journal. - if(command($gConfig{'cmd_hdiutil'}, 'create', '-format', $format, - @extraArguments, '-fs', 'HFS+', '-volname', $name, - '-ov', '-srcfolder', $source, $destination) != 0) { - cleanupDie('hdiutil create failed'); - } - - # $source is no longer needed and will be removed before anything - # else can fail. splice in this form is the same as pop/push. - splice(@gCleanup, -1, 1, - sub {commandInternalVerbosity(0, 'unlink', $destination);}); - - if(command($gConfig{'cmd_rm'}, '-rf', $source) != 0) { - cleanupDie('rm -rf failed'); - } - } - else { - # hdiutil create does not support -srcfolder or -srcdevice, it only - # knows how to create blank images. Figure out how large an image - # is needed, create it, and fill it. This is needed for Jaguar. - - # Use native block size for hdiutil create -sectors. - delete $ENV{'BLOCKSIZE'}; - - my(@duOutput, $ignore, $sizeBlocks, $sizeOverhead, $sizeTotal, $type); - if(!(@output = commandOutput($gConfig{'cmd_du'}, '-s', $tempRoot)) || - $? != 0) { - cleanupDie('du failed'); - } - ($sizeBlocks, $ignore) = split(' ', $output[0], 2); - - # The filesystem itself takes up 152 blocks of its own blocks for the - # filesystem up to 8192 blocks, plus 64 blocks for every additional - # 4096 blocks or portion thereof. - $sizeOverhead = 152 + 64 * POSIX::ceil( - (($sizeBlocks - 8192) > 0) ? (($sizeBlocks - 8192) / (4096 - 64)) : 0); - - # The number of blocks must be divisible by 8. - my($mod); - if($mod = ($sizeOverhead % 8)) { - $sizeOverhead += 8 - $mod; - } - - # sectors is taken as the size of a disk, not a filesystem, so the - # partition table eats into it. - if($gConfig{'partition_table'}) { - $sizeOverhead += 80; - } - - # That was hard. Leave some breathing room anyway. Use 1024 sectors - # (512kB). These read-write images wouldn't be useful if they didn't - # have at least a little free space. - $sizeTotal = $sizeBlocks + $sizeOverhead + 1024; - - # Minimum sizes - these numbers are larger on Jaguar than on later - # systems. Just use the Jaguar numbers, since it's unlikely to wind - # up here on any other release. - if($gConfig{'partition_table'} && $sizeTotal < 8272) { - $sizeTotal = 8272; - } - if(!$gConfig{'partition_table'} && $sizeTotal < 8192) { - $sizeTotal = 8192; - } - - # hdiutil create without -srcfolder or -srcdevice will not accept - # -format. It uses -type. Fortunately, the two supported formats - # here map directly to the only two supported types. - if ($format eq 'UDSP') { - $type = 'SPARSE'; - } - else { - $type = 'UDIF'; - } - - if(command($gConfig{'cmd_hdiutil'}, 'create', '-type', $type, - @extraArguments, '-fs', 'HFS+', '-volname', $name, - '-ov', '-sectors', $sizeTotal, $destination) != 0) { - cleanupDie('hdiutil create failed'); - } - - push(@gCleanup, - sub {commandInternalVerbosity(0, 'unlink', $destination);}); - - # The rsync will occur shortly. - } - - my($mounted, $rootDevice, $partitionDevice, $partitionMountPoint); - - $mounted=0; - if(!$gConfig{'create_directly'} || $gConfig{'openfolder_bless'} || - $setRootIcon) { - # The disk image only needs to be mounted if: - # create_directly is false, because the content needs to be copied - # openfolder_bless is true, because bless -openfolder needs to run - # setRootIcon is true, because the root needs its attributes set. - if(!(($rootDevice, $partitionDevice, $partitionMountPoint) = - hdidMountImage($tempMount, $destination))) { - cleanupDie('hdid mount failed'); - } - - $mounted=1; - - push(@gCleanup, sub {commandVerbosity(0, - $gConfig{'cmd_diskutil'}, 'eject', $rootDevice);}); - } - - if(!$gConfig{'create_directly'}) { - # Couldn't create and copy directly in one fell swoop. Now that - # the volume is mounted, copy the files. --copy-unsafe-links is - # unnecessary since it was used to copy everything to the staging - # area. There can be no more unsafe links. - if(command($gConfig{'cmd_rsync'}, '-a', - $source.'/',$partitionMountPoint) != 0) { - cleanupDie('rsync to new volume failed'); - } - - # We need to get the rm -rf of $source off the stack, because it's - # being cleaned up here. There are two items now on top of it: - # removing the target image and, above that, ejecting it. Splice it - # out. - my(@tempCleanup); - @tempCleanup = splice(@gCleanup, -2); - # The next splice is the same as popping once and pushing @tempCleanup. - splice(@gCleanup, -1, 1, @tempCleanup); - - if(command($gConfig{'cmd_rm'}, '-rf', $source) != 0) { - cleanupDie('rm -rf failed'); - } - } - - if($gConfig{'openfolder_bless'}) { - # On Tiger, the bless docs say to use --openfolder, but only - # --openfolder is accepted on Panther. Tiger takes it with a single - # dash too. Jaguar is out of luck. - if(command($gConfig{'cmd_bless'}, '-openfolder', - $partitionMountPoint) != 0) { - cleanupDie('bless failed'); - } - } - - setAttributes($partitionMountPoint, @attributes); - - if($setRootIcon) { - # When "hdiutil create -srcfolder" is used, the root folder's - # attributes are not copied to the new volume. Fix up. - - if(command($gConfig{'cmd_SetFile'}, '-a', 'C', - $partitionMountPoint) != 0) { - cleanupDie('SetFile failed'); - } - } - - if($mounted) { - # Pop diskutil eject - pop(@gCleanup); - - if(command($gConfig{'cmd_diskutil'}, 'eject', $rootDevice) != 0) { - cleanupDie('diskutil eject failed'); - } - } - - # End of UDRW/UDSP section. At this point, $source has been removed - # and its cleanup entry has been removed from the stack. - } - else { - cleanupDie('unrecognized format'); - print STDERR ($0.": unrecognized format\n"); - exit(1); - } -} - -# giveExtension($file, $extension) -# -# If $file does not end in $extension, $extension is added. The new -# filename is returned. -sub giveExtension($$) { - my($extension, $file); - ($file, $extension) = @_; - if(substr($file, -length($extension)) ne $extension) { - return $file.$extension; - } - return $file; -} - -# hdidMountImage($mountPoint, @arguments) -# -# Runs the hdid command with arguments specified by @arguments. -# @arguments may be a single-element array containing the name of the -# disk image to mount. Returns a three-element array, with elements -# corresponding to: -# - The root device of the mounted image, suitable for ejection -# - The device corresponding to the mounted partition -# - The mounted partition's mount point -# -# If running on a system that supports easy mounting at points outside -# of the default /Volumes with hdiutil attach, it is used instead of hdid, -# and $mountPoint is used as the mount point. -# -# The root device will differ from the partition device when the disk -# image contains a partition table, otherwise, they will be identical. -# -# If hdid fails, undef is returned. -sub hdidMountImage($@) { - my(@arguments, @command, $mountPoint); - ($mountPoint, @arguments) = @_; - my(@output); - - if($gConfig{'hdiutil_mountpoint'}) { - @command=($gConfig{'cmd_hdiutil'}, 'attach', @arguments, - '-mountpoint', $mountPoint); - } - else { - @command=($gConfig{'cmd_hdid'}, @arguments); - } - - if(!(@output = commandOutput(@command)) || - $? != 0) { - return undef; - } - - if($gDryRun) { - return('/dev/diskX','/dev/diskXsY','/Volumes/'.$volumeName); - } - - my($line, $restOfLine, $rootDevice); - - foreach $line (@output) { - my($device, $mountpoint); - if($line !~ /^\/dev\//) { - # Consider only lines that correspond to /dev entries - next; - } - ($device, $restOfLine) = split(' ', $line, 2); - - if(!defined($rootDevice) || $rootDevice eq '') { - # If this is the first device seen, it's the root device to be - # used for ejection. Keep it. - $rootDevice = $device; - } - - if($restOfLine =~ /(\/.*)/) { - # The first partition with a mount point is the interesting one. It's - # usually Apple_HFS and usually the last one in the list, but beware of - # the possibility of other filesystem types and the Apple_Free partition. - # If the disk image contains no partition table, the partition will not - # have a type, so look for the mount point by looking for a slash. - $mountpoint = $1; - return($rootDevice, $device, $mountpoint); - } - } - - # No mount point? This is bad. If there's a root device, eject it. - if(defined($rootDevice) && $rootDevice ne '') { - # Failing anyway, so don't care about failure - commandVerbosity(0, $gConfig{'cmd_diskutil'}, 'eject', $rootDevice); - } - - return undef; -} - -# isFormatCompressed($format) -# -# Returns true if $format corresponds to a compressed disk image format. -# Returns false otherwise. -sub isFormatCompressed($) { - my($format); - ($format) = @_; - return $format eq 'UDZO' || $format eq 'UDBZ'; -} - -# licenseMaker($text, $resource) -# -# Takes a plain text file at path $text and creates a license agreement -# resource containing the text at path $license. English-only, and -# no special formatting. This is the bare-bones stuff. For more -# intricate license agreements, create your own resource. -# -# ftp://ftp.apple.com/developer/Development_Kits/SLAs_for_UDIFs_1.0.dmg -sub licenseMaker($$) { - my($resource, $text); - ($text, $resource) = @_; - if(!sysopen(*TEXT, $text, O_RDONLY)) { - print STDERR ($0.': licenseMaker: sysopen text: '.$!."\n"); - return 0; - } - if(!sysopen(*RESOURCE, $resource, O_WRONLY|O_CREAT|O_EXCL)) { - print STDERR ($0.': licenseMaker: sysopen resource: '.$!."\n"); - return 0; - } - print RESOURCE << '__EOT__'; -// See /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers/Script.h for language IDs. -data 'LPic' (5000) { - // Default language ID, 0 = English - $"0000" - // Number of entries in list - $"0001" - - // Entry 1 - // Language ID, 0 = English - $"0000" - // Resource ID, 0 = STR#/TEXT/styl 5000 - $"0000" - // Multibyte language, 0 = no - $"0000" -}; - -resource 'STR#' (5000, "English") { - { - // Language (unused?) = English - "English", - // Agree - "Agree", - // Disagree - "Disagree", -__EOT__ - # This stuff needs double-quotes for interpolations to work. - print RESOURCE (" // Print, ellipsis is 0xC9\n"); - print RESOURCE (" \"Print\xc9\",\n"); - print RESOURCE (" // Save As, ellipsis is 0xC9\n"); - print RESOURCE (" \"Save As\xc9\",\n"); - print RESOURCE (' // Descriptive text, curly quotes are 0xD2 and 0xD3'. - "\n"); - print RESOURCE (' "If you agree to the terms of this license '. - "agreement, click \xd2Agree\xd3 to access the software. If you ". - "do not agree, press \xd2Disagree.\xd3\"\n"); -print RESOURCE << '__EOT__'; - }; -}; - -// Beware of 1024(?) byte (character?) line length limitation. Split up long -// lines. -// If straight quotes are used ("), remember to escape them (\"). -// Newline is \n, to leave a blank line, use two of them. -// 0xD2 and 0xD3 are curly double-quotes ("), 0xD4 and 0xD5 are curly -// single quotes ('), 0xD5 is also the apostrophe. -data 'TEXT' (5000, "English") { -__EOT__ - - while(!eof(*TEXT)) { - my($line); - chop($line = <TEXT>); - - while(defined($line)) { - my($chunk); - - # Rez doesn't care for lines longer than (1024?) characters. Split - # at less than half of that limit, in case everything needs to be - # backwhacked. - if(length($line)>500) { - $chunk = substr($line, 0, 500); - $line = substr($line, 500); - } - else { - $chunk = $line; - $line = undef; - } - - if(length($chunk) > 0) { - # Unsafe characters are the double-quote (") and backslash (\), escape - # them with backslashes. - $chunk =~ s/(["\\])/\\$1/g; - - print RESOURCE ' "'.$chunk.'"'."\n"; - } - } - print RESOURCE ' "\n"'."\n"; - } - close(*TEXT); - - print RESOURCE << '__EOT__'; -}; - -data 'styl' (5000, "English") { - // Number of styles following = 1 - $"0001" - - // Style 1. This is used to display the first two lines in bold text. - // Start character = 0 - $"0000 0000" - // Height = 16 - $"0010" - // Ascent = 12 - $"000C" - // Font family = 1024 (Lucida Grande) - $"0400" - // Style bitfield, 0x1=bold 0x2=italic 0x4=underline 0x8=outline - // 0x10=shadow 0x20=condensed 0x40=extended - $"00" - // Style, unused? - $"02" - // Size = 12 point - $"000C" - // Color, RGB - $"0000 0000 0000" -}; -__EOT__ - close(*RESOURCE); - - return 1; -} - -# pathSplit($pathname) -# -# Splits $pathname into an array of path components. -sub pathSplit($) { - my($pathname); - ($pathname) = @_; - return split(/\//, $pathname); -} - -# setAttributes($root, @attributeList) -# -# @attributeList is an array, each element of which must be in the form -# <a>:<file>. <a> is a list of attributes, per SetFile. <file> is a file -# which is taken as relative to $root (even if it appears as an absolute -# path.) SetFile is called to set the attributes on each file in -# @attributeList. -sub setAttributes($@) { - my(@attributes, $root); - ($root, @attributes) = @_; - my($attribute); - foreach $attribute (@attributes) { - my($attrList, $file, @fileList, @fixedFileList); - ($attrList, @fileList) = split(/:/, $attribute); - if(!defined($attrList) || !@fileList) { - cleanupDie('--attribute requires <attributes>:<file>'); - } - @fixedFileList=(); - foreach $file (@fileList) { - if($file =~ /^\//) { - push(@fixedFileList, $root.$file); - } - else { - push(@fixedFileList, $root.'/'.$file); - } - } - if(command($gConfig{'cmd_SetFile'}, '-a', $attrList, @fixedFileList)) { - cleanupDie('SetFile failed to set attributes'); - } - } - return; -} - -sub trapSignal($) { - my($signalName); - ($signalName) = @_; - cleanupDie('exiting on SIG'.$signalName); -} - -sub usage() { - print STDERR ( -"usage: pkg-dmg --source <source-folder>\n". -" --target <target-image>\n". -" [--format <format>] (default: UDZO)\n". -" [--volname <volume-name>] (default: same name as source)\n". -" [--tempdir <temp-dir>] (default: same dir as target)\n". -" [--mkdir <directory>] (make directory in image)\n". -" [--copy <source>[:<dest>]] (extra files to add)\n". -" [--symlink <source>[:<dest>]] (extra symlinks to add)\n". -" [--license <file>] (plain text license agreement)\n". -" [--resource <file>] (flat .r files to merge)\n". -" [--icon <icns-file>] (volume icon)\n". -" [--attribute <a>:<file>] (set file attributes)\n". -" [--idme] (make Internet-enabled image)\n". -" [--sourcefile] (treat --source as a file)\n". -" [--verbosity <level>] (0, 1, 2; default=2)\n". -" [--dry-run] (print what would be done)\n"); - return; -}
--- a/build/virtualenv_packages.txt +++ b/build/virtualenv_packages.txt @@ -25,8 +25,9 @@ packages.txt:testing/mozbase/packages.tx objdir:build gyp.pth:media/webrtc/trunk/tools/gyp/pylib pyasn1.pth:python/pyasn1 pyasn1_modules.pth:python/pyasn1-modules bitstring.pth:python/bitstring redo.pth:python/redo requests.pth:python/requests rsa.pth:python/rsa +futures.pth:python/futures
--- a/config/check_macroassembler_style.py +++ b/config/check_macroassembler_style.py @@ -25,18 +25,18 @@ from __future__ import print_function import difflib import os import re import subprocess import sys from check_utils import get_all_toplevel_filenames architecture_independent = set([ 'generic' ]) -all_architecture_names = set([ 'x86', 'x64', 'arm', 'arm64', 'mips' ]) -all_shared_architecture_names = set([ 'x86_shared', 'arm', 'arm64', 'mips' ]) +all_architecture_names = set([ 'x86', 'x64', 'arm', 'arm64', 'mips32' ]) +all_shared_architecture_names = set([ 'x86_shared', 'arm', 'arm64', 'mips32' ]) def get_normalized_signatures(signature, fileAnnot = None): # Remove semicolon. signature = signature.replace(';', ' ') # Normalize spaces. signature = re.sub(r'\s+', ' ', signature).strip() # Remove argument names. signature = re.sub(r'(?P<type>(?:[(]|,\s)[\w\s:*&]+)(?P<name>\s\w+)(?=[,)])', '\g<type>', signature)
--- a/dom/base/DOMRequest.cpp +++ b/dom/base/DOMRequest.cpp @@ -4,18 +4,18 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "DOMRequest.h" #include "DOMError.h" #include "nsThreadUtils.h" #include "DOMCursor.h" -#include "nsIDOMEvent.h" #include "mozilla/ErrorResult.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/ScriptSettings.h" using mozilla::dom::AnyCallback; using mozilla::dom::DOMError; using mozilla::dom::DOMRequest; using mozilla::dom::DOMRequestService; using mozilla::dom::DOMCursor; @@ -187,18 +187,17 @@ DOMRequest::FireDetailedError(DOMError* void DOMRequest::FireEvent(const nsAString& aType, bool aBubble, bool aCancelable) { if (NS_FAILED(CheckInnerWindowCorrectness())) { return; } - nsCOMPtr<nsIDOMEvent> event; - NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); nsresult rv = event->InitEvent(aType, aBubble, aCancelable); if (NS_FAILED(rv)) { return; } event->SetTrusted(true); bool dummy;
--- a/dom/base/EventSource.cpp +++ b/dom/base/EventSource.cpp @@ -840,22 +840,17 @@ EventSource::AnnounceConnection() mReadyState = OPEN; nsresult rv = CheckInnerWindowCorrectness(); if (NS_FAILED(rv)) { return; } - nsCOMPtr<nsIDOMEvent> event; - rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to create the open event!!!"); - return; - } + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); // it doesn't bubble, and it isn't cancelable rv = event->InitEvent(NS_LITERAL_STRING("open"), false, false); if (NS_FAILED(rv)) { NS_WARNING("Failed to init the open event!!!"); return; } @@ -905,22 +900,17 @@ EventSource::ReestablishConnection() return; } rv = CheckInnerWindowCorrectness(); if (NS_FAILED(rv)) { return; } - nsCOMPtr<nsIDOMEvent> event; - rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to create the error event!!!"); - return; - } + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); // it doesn't bubble, and it isn't cancelable rv = event->InitEvent(NS_LITERAL_STRING("error"), false, false); if (NS_FAILED(rv)) { NS_WARNING("Failed to init the error event!!!"); return; } @@ -1061,22 +1051,17 @@ EventSource::FailConnection() Close(); // it sets mReadyState to CLOSED rv = CheckInnerWindowCorrectness(); if (NS_FAILED(rv)) { return; } - nsCOMPtr<nsIDOMEvent> event; - rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to create the error event!!!"); - return; - } + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); // it doesn't bubble, and it isn't cancelable rv = event->InitEvent(NS_LITERAL_STRING("error"), false, false); if (NS_FAILED(rv)) { NS_WARNING("Failed to init the error event!!!"); return; } @@ -1229,37 +1214,30 @@ EventSource::DispatchAllMessageEvents() NS_ENSURE_TRUE_VOID(jsString); jsData.setString(jsString); } // create an event that uses the MessageEvent interface, // which does not bubble, is not cancelable, and has no default action - nsCOMPtr<nsIDOMEvent> event; - rv = NS_NewDOMMessageEvent(getter_AddRefs(event), this, nullptr, nullptr); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to create the message event!!!"); - return; - } + nsRefPtr<MessageEvent> event = + NS_NewDOMMessageEvent(this, nullptr, nullptr); - nsCOMPtr<nsIDOMMessageEvent> messageEvent = do_QueryInterface(event); - rv = messageEvent->InitMessageEvent(message->mEventName, - false, false, - jsData, - mOrigin, - message->mLastEventID, nullptr); + rv = event->InitMessageEvent(message->mEventName, false, false, jsData, + mOrigin, message->mLastEventID, nullptr); if (NS_FAILED(rv)) { NS_WARNING("Failed to init the message event!!!"); return; } - messageEvent->SetTrusted(true); + event->SetTrusted(true); - rv = DispatchDOMEvent(nullptr, event, nullptr, nullptr); + rv = DispatchDOMEvent(nullptr, static_cast<Event*>(event), nullptr, + nullptr); if (NS_FAILED(rv)) { NS_WARNING("Failed to dispatch the message event!!!"); return; } mLastEventID.Assign(message->mLastEventID); } }
--- a/dom/base/WebSocket.cpp +++ b/dom/base/WebSocket.cpp @@ -8,16 +8,17 @@ #include "mozilla/dom/WebSocketBinding.h" #include "mozilla/net/WebSocketChannel.h" #include "jsapi.h" #include "jsfriendapi.h" #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/net/WebSocketChannel.h" #include "mozilla/dom/File.h" +#include "mozilla/dom/MessageEvent.h" #include "mozilla/dom/nsCSPContext.h" #include "mozilla/dom/nsCSPUtils.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/WorkerRunnable.h" #include "mozilla/dom/WorkerScope.h" #include "nsIScriptGlobalObject.h" #include "nsIDOMWindow.h" @@ -25,17 +26,16 @@ #include "nsXPCOM.h" #include "nsIXPConnect.h" #include "nsContentUtils.h" #include "nsError.h" #include "nsIScriptObjectPrincipal.h" #include "nsIURL.h" #include "nsIUnicodeEncoder.h" #include "nsThreadUtils.h" -#include "nsIDOMMessageEvent.h" #include "nsIPromptFactory.h" #include "nsIWindowWatcher.h" #include "nsIPrompt.h" #include "nsIStringBundle.h" #include "nsIConsoleService.h" #include "mozilla/dom/CloseEvent.h" #include "nsICryptoHash.h" #include "nsJSUtils.h" @@ -1732,19 +1732,17 @@ WebSocket::CreateAndDispatchSimpleEvent( MOZ_ASSERT(mImpl); AssertIsOnTargetThread(); nsresult rv = CheckInnerWindowCorrectness(); if (NS_FAILED(rv)) { return NS_OK; } - nsCOMPtr<nsIDOMEvent> event; - rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); - NS_ENSURE_SUCCESS(rv, rv); + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); // it doesn't bubble, and it isn't cancelable rv = event->InitEvent(aName, false, false); NS_ENSURE_SUCCESS(rv, rv); event->SetTrusted(true); return DispatchDOMEvent(nullptr, event, nullptr, nullptr); @@ -1812,31 +1810,27 @@ WebSocket::CreateAndDispatchMessageEvent NS_ENSURE_TRUE(jsString, NS_ERROR_FAILURE); jsData.setString(jsString); } // create an event that uses the MessageEvent interface, // which does not bubble, is not cancelable, and has no default action - nsCOMPtr<nsIDOMEvent> event; - rv = NS_NewDOMMessageEvent(getter_AddRefs(event), this, nullptr, nullptr); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr<nsIDOMMessageEvent> messageEvent = do_QueryInterface(event); - rv = messageEvent->InitMessageEvent(NS_LITERAL_STRING("message"), - false, false, - jsData, - mImpl->mUTF16Origin, - EmptyString(), nullptr); + nsRefPtr<MessageEvent> event = NS_NewDOMMessageEvent(this, nullptr, nullptr); + + rv = event->InitMessageEvent(NS_LITERAL_STRING("message"), false, false, + jsData, mImpl->mUTF16Origin, EmptyString(), + nullptr); NS_ENSURE_SUCCESS(rv, rv); event->SetTrusted(true); - return DispatchDOMEvent(nullptr, event, nullptr, nullptr); + return DispatchDOMEvent(nullptr, static_cast<Event*>(event), nullptr, + nullptr); } nsresult WebSocket::CreateAndDispatchCloseEvent(bool aWasClean, uint16_t aCode, const nsAString &aReason) { MOZ_ASSERT(mImpl);
--- a/dom/base/nsDOMDataChannel.cpp +++ b/dom/base/nsDOMDataChannel.cpp @@ -12,19 +12,19 @@ extern PRLogModuleInfo* GetDataChannelLog(); #undef LOG #define LOG(args) MOZ_LOG(GetDataChannelLog(), mozilla::LogLevel::Debug, args) #include "nsDOMDataChannelDeclarations.h" #include "nsDOMDataChannel.h" #include "nsIDOMDataChannel.h" -#include "nsIDOMMessageEvent.h" #include "mozilla/DOMEventTargetHelper.h" #include "mozilla/dom/File.h" +#include "mozilla/dom/MessageEvent.h" #include "mozilla/dom/ScriptSettings.h" #include "nsError.h" #include "nsAutoPtr.h" #include "nsContentUtils.h" #include "nsCycleCollectionParticipant.h" #include "nsIScriptObjectPrincipal.h" @@ -396,30 +396,25 @@ nsDOMDataChannel::DoOnMessageAvailable(c } else { NS_ConvertUTF8toUTF16 utf16data(aData); JSString* jsString = JS_NewUCStringCopyN(cx, utf16data.get(), utf16data.Length()); NS_ENSURE_TRUE(jsString, NS_ERROR_FAILURE); jsData.setString(jsString); } - nsCOMPtr<nsIDOMEvent> event; - rv = NS_NewDOMMessageEvent(getter_AddRefs(event), this, nullptr, nullptr); - NS_ENSURE_SUCCESS(rv,rv); + nsRefPtr<MessageEvent> event = NS_NewDOMMessageEvent(this, nullptr, nullptr); - nsCOMPtr<nsIDOMMessageEvent> messageEvent = do_QueryInterface(event); - rv = messageEvent->InitMessageEvent(NS_LITERAL_STRING("message"), - false, false, - jsData, mOrigin, EmptyString(), - nullptr); + rv = event->InitMessageEvent(NS_LITERAL_STRING("message"), false, false, + jsData, mOrigin, EmptyString(), nullptr); NS_ENSURE_SUCCESS(rv,rv); event->SetTrusted(true); LOG(("%p(%p): %s - Dispatching\n",this,(void*)mDataChannel,__FUNCTION__)); - rv = DispatchDOMEvent(nullptr, event, nullptr, nullptr); + rv = DispatchDOMEvent(nullptr, static_cast<Event*>(event), nullptr, nullptr); if (NS_FAILED(rv)) { NS_WARNING("Failed to dispatch the message event!!!"); } return rv; } nsresult nsDOMDataChannel::OnMessageAvailable(nsISupports* aContext, @@ -442,19 +437,17 @@ nsDOMDataChannel::OnSimpleEvent(nsISuppo { MOZ_ASSERT(NS_IsMainThread()); nsresult rv = CheckInnerWindowCorrectness(); if (NS_FAILED(rv)) { return NS_OK; } - nsCOMPtr<nsIDOMEvent> event; - rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); - NS_ENSURE_SUCCESS(rv,rv); + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); rv = event->InitEvent(aName, false, false); NS_ENSURE_SUCCESS(rv,rv); event->SetTrusted(true); return DispatchDOMEvent(nullptr, event, nullptr, nullptr); }
--- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -8127,27 +8127,27 @@ nsIDocument::CreateEvent(const nsAString nsPresContext *presContext = nullptr; if (shell) { // Retrieve the context presContext = shell->GetPresContext(); } // Create event even without presContext. - nsCOMPtr<nsIDOMEvent> ev; - rv = EventDispatcher::CreateEvent(const_cast<nsIDocument*>(this), - presContext, nullptr, aEventType, - getter_AddRefs(ev)); + nsRefPtr<Event> ev = + EventDispatcher::CreateEvent(const_cast<nsIDocument*>(this), presContext, + nullptr, aEventType); if (!ev) { + rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return nullptr; } WidgetEvent* e = ev->GetInternalNSEvent(); e->mFlags.mBubbles = false; e->mFlags.mCancelable = false; - return dont_AddRef(ev.forget().take()->InternalDOMEvent()); + return ev.forget(); } void nsDocument::FlushPendingNotifications(mozFlushType aType) { nsDocumentOnStack dos(this); // We need to flush the sink for non-HTML documents (because the XML @@ -9204,18 +9204,17 @@ NotifyPageHide(nsIDocument* aDocument, v aDocument->OnPageHide(*aPersistedPtr, nullptr); return true; } static void DispatchCustomEventWithFlush(nsINode* aTarget, const nsAString& aEventType, bool aBubbles, bool aOnlyChromeDispatch) { - nsCOMPtr<nsIDOMEvent> event; - NS_NewDOMEvent(getter_AddRefs(event), aTarget, nullptr, nullptr); + nsRefPtr<Event> event = NS_NewDOMEvent(aTarget, nullptr, nullptr); nsresult rv = event->InitEvent(aEventType, aBubbles, false); if (NS_FAILED(rv)) { return; } event->SetTrusted(true); if (aOnlyChromeDispatch) { event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true; }
--- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -9096,18 +9096,17 @@ nsGlobalWindow::LeaveModalState() } // Remember the time of the last dialog quit. nsGlobalWindow *inner = topWin->GetCurrentInnerWindowInternal(); if (inner) inner->mLastDialogQuitTime = TimeStamp::Now(); if (topWin->mModalStateDepth == 0) { - nsCOMPtr<nsIDOMEvent> event; - NS_NewDOMEvent(getter_AddRefs(event), topWin, nullptr, nullptr); + nsRefPtr<Event> event = NS_NewDOMEvent(topWin, nullptr, nullptr); event->InitEvent(NS_LITERAL_STRING("endmodalstate"), true, false); event->SetTrusted(true); event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true; bool dummy; topWin->DispatchEvent(event, &dummy); } } @@ -11885,18 +11884,17 @@ nsGlobalWindow::Observe(nsISupports* aSu #ifdef MOZ_B2G if (!nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC) || !nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC)) { MOZ_ASSERT(IsInnerWindow()); if (!IsCurrentInnerWindow()) { return NS_OK; } - nsCOMPtr<nsIDOMEvent> event; - NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); nsresult rv = event->InitEvent( !nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC) ? NETWORK_UPLOAD_EVENT_NAME : NETWORK_DOWNLOAD_EVENT_NAME, false, false); NS_ENSURE_SUCCESS(rv, rv); event->SetTrusted(true); @@ -11922,18 +11920,17 @@ nsGlobalWindow::Observe(nsISupports* aSu NavigatorBinding::ClearCachedLanguagesValue(mNavigator); } // The event has to be dispatched only to the current inner window. if (!IsCurrentInnerWindow()) { return NS_OK; } - nsCOMPtr<nsIDOMEvent> event; - NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); nsresult rv = event->InitEvent(NS_LITERAL_STRING("languagechange"), false, false); NS_ENSURE_SUCCESS(rv, rv); event->SetTrusted(true); bool dummy; return DispatchEvent(event, &dummy); }
--- a/dom/base/nsPerformance.cpp +++ b/dom/base/nsPerformance.cpp @@ -473,26 +473,25 @@ nsPerformance::Timing() mDOMTiming->GetNavigationStart()); } return mTiming; } void nsPerformance::DispatchBufferFullEvent() { - nsCOMPtr<nsIDOMEvent> event; - nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); - if (NS_SUCCEEDED(rv)) { - // it bubbles, and it isn't cancelable - rv = event->InitEvent(NS_LITERAL_STRING("resourcetimingbufferfull"), true, false); - if (NS_SUCCEEDED(rv)) { - event->SetTrusted(true); - DispatchDOMEvent(nullptr, event, nullptr, nullptr); - } + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); + // it bubbles, and it isn't cancelable + nsresult rv = event->InitEvent(NS_LITERAL_STRING("resourcetimingbufferfull"), + true, false); + if (NS_FAILED(rv)) { + return; } + event->SetTrusted(true); + DispatchDOMEvent(nullptr, event, nullptr, nullptr); } nsPerformanceNavigation* nsPerformance::Navigation() { if (!mNavigation) { mNavigation = new nsPerformanceNavigation(this); }
--- a/dom/base/nsXMLHttpRequest.cpp +++ b/dom/base/nsXMLHttpRequest.cpp @@ -1462,22 +1462,18 @@ nsXMLHttpRequest::GetLoadGroup() const } return nullptr; } nsresult nsXMLHttpRequest::CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent) { - nsresult rv = EventDispatcher::CreateEvent(this, nullptr, nullptr, - NS_LITERAL_STRING("Events"), - aDOMEvent); - if (NS_FAILED(rv)) { - return rv; - } + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); + event.forget(aDOMEvent); (*aDOMEvent)->InitEvent(NS_LITERAL_STRING(READYSTATE_STR), false, false); // We assume anyone who managed to call CreateReadystatechangeEvent is trusted (*aDOMEvent)->SetTrusted(true); return NS_OK;
--- a/dom/bluetooth/bluetooth1/BluetoothAdapter.cpp +++ b/dom/bluetooth/bluetooth1/BluetoothAdapter.cpp @@ -11,16 +11,17 @@ #include "nsThreadUtils.h" #include "mozilla/dom/bluetooth/BluetoothTypes.h" #include "mozilla/dom/BluetoothAdapterBinding.h" #include "mozilla/dom/BluetoothDeviceEvent.h" #include "mozilla/dom/BluetoothDiscoveryStateChangedEvent.h" #include "mozilla/dom/BluetoothStatusChangedEvent.h" #include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/File.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/LazyIdleThread.h" #include "BluetoothAdapter.h" #include "BluetoothDevice.h" #include "BluetoothReplyRunnable.h" #include "BluetoothService.h" @@ -356,21 +357,19 @@ BluetoothAdapter::Notify(const Bluetooth init.mBubbles = false; init.mCancelable = false; init.mAddress = address; init.mStatus = status; nsRefPtr<BluetoothStatusChangedEvent> event = BluetoothStatusChangedEvent::Constructor(this, aData.name(), init); DispatchTrustedEvent(event); } else if (aData.name().EqualsLiteral(REQUEST_MEDIA_PLAYSTATUS_ID)) { - nsCOMPtr<nsIDOMEvent> event; - nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); - NS_ENSURE_SUCCESS_VOID(rv); + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); - rv = event->InitEvent(aData.name(), false, false); + nsresult rv = event->InitEvent(aData.name(), false, false); NS_ENSURE_SUCCESS_VOID(rv); DispatchTrustedEvent(event); } else { #ifdef DEBUG nsCString warningMsg; warningMsg.AssignLiteral("Not handling adapter signal: "); warningMsg.Append(NS_ConvertUTF16toUTF8(aData.name()));
--- a/dom/bluetooth/bluetooth2/BluetoothAdapter.cpp +++ b/dom/bluetooth/bluetooth2/BluetoothAdapter.cpp @@ -11,16 +11,17 @@ #include "nsIDocument.h" #include "nsIPrincipal.h" #include "nsTArrayHelpers.h" #include "mozilla/dom/BluetoothAdapter2Binding.h" #include "mozilla/dom/BluetoothAttributeEvent.h" #include "mozilla/dom/BluetoothStatusChangedEvent.h" #include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/File.h" #include "mozilla/dom/bluetooth/BluetoothAdapter.h" #include "mozilla/dom/bluetooth/BluetoothClassOfDevice.h" #include "mozilla/dom/bluetooth/BluetoothDevice.h" #include "mozilla/dom/bluetooth/BluetoothDiscoveryHandle.h" #include "mozilla/dom/bluetooth/BluetoothGattServer.h" #include "mozilla/dom/bluetooth/BluetoothPairingListener.h" @@ -1191,21 +1192,19 @@ BluetoothAdapter::DispatchDeviceEvent(co nsRefPtr<BluetoothDeviceEvent> event = BluetoothDeviceEvent::Constructor(this, aType, aInit); DispatchTrustedEvent(event); } void BluetoothAdapter::DispatchEmptyEvent(const nsAString& aType) { - nsCOMPtr<nsIDOMEvent> event; - nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); - NS_ENSURE_SUCCESS_VOID(rv); + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); - rv = event->InitEvent(aType, false, false); + nsresult rv = event->InitEvent(aType, false, false); NS_ENSURE_SUCCESS_VOID(rv); DispatchTrustedEvent(event); } already_AddRefed<DOMRequest> BluetoothAdapter::Connect(BluetoothDevice& aDevice, const Optional<short unsigned int>& aServiceUuid,
--- a/dom/bluetooth/bluetooth2/BluetoothGatt.cpp +++ b/dom/bluetooth/bluetooth2/BluetoothGatt.cpp @@ -7,16 +7,17 @@ #include "BluetoothReplyRunnable.h" #include "BluetoothService.h" #include "BluetoothUtils.h" #include "mozilla/dom/bluetooth/BluetoothCommon.h" #include "mozilla/dom/bluetooth/BluetoothGatt.h" #include "mozilla/dom/bluetooth/BluetoothTypes.h" #include "mozilla/dom/BluetoothGattBinding.h" #include "mozilla/dom/BluetoothGattCharacteristicEvent.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/Promise.h" #include "nsServiceManagerUtils.h" using namespace mozilla; using namespace mozilla::dom; USING_BLUETOOTH_NAMESPACE @@ -235,23 +236,22 @@ BluetoothGatt::DiscoverServices(ErrorRes void BluetoothGatt::UpdateConnectionState(BluetoothConnectionState aState) { BT_LOGR("GATT connection state changes to: %d", int(aState)); mConnectionState = aState; // Dispatch connectionstatechanged event to application - nsCOMPtr<nsIDOMEvent> event; - nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); - NS_ENSURE_SUCCESS_VOID(rv); + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); - rv = event->InitEvent(NS_LITERAL_STRING(GATT_CONNECTION_STATE_CHANGED_ID), - false, - false); + nsresult rv = + event->InitEvent(NS_LITERAL_STRING(GATT_CONNECTION_STATE_CHANGED_ID), + false, + false); NS_ENSURE_SUCCESS_VOID(rv); DispatchTrustedEvent(event); } void BluetoothGatt::HandleServicesDiscovered(const BluetoothValue& aValue) {
--- a/dom/browser-element/BrowserElementParent.cpp +++ b/dom/browser-element/BrowserElementParent.cpp @@ -97,41 +97,36 @@ DispatchCustomDOMEvent(Element* aFrameEl { NS_ENSURE_TRUE(aFrameElement, false); nsIPresShell *shell = aFrameElement->OwnerDoc()->GetShell(); nsRefPtr<nsPresContext> presContext; if (shell) { presContext = shell->GetPresContext(); } - nsCOMPtr<nsIDOMEvent> domEvent; - EventDispatcher::CreateEvent(aFrameElement, presContext, nullptr, - NS_LITERAL_STRING("customevent"), - getter_AddRefs(domEvent)); - NS_ENSURE_TRUE(domEvent, false); + nsRefPtr<CustomEvent> event = + NS_NewDOMCustomEvent(aFrameElement, presContext, nullptr); - nsCOMPtr<nsIDOMCustomEvent> customEvent = do_QueryInterface(domEvent); - NS_ENSURE_TRUE(customEvent, false); ErrorResult res; - CustomEvent* event = static_cast<CustomEvent*>(customEvent.get()); event->InitCustomEvent(cx, aEventName, /* bubbles = */ true, /* cancelable = */ true, aDetailValue, res); if (res.Failed()) { return false; } - customEvent->SetTrusted(true); + event->SetTrusted(true); // Dispatch the event. *aStatus = nsEventStatus_eConsumeNoDefault; nsresult rv = EventDispatcher::DispatchDOMEvent(aFrameElement, nullptr, - domEvent, presContext, aStatus); + static_cast<Event*>(event), + presContext, aStatus); return NS_SUCCEEDED(rv); } } // namespace namespace mozilla { /**
--- a/dom/events/AnimationEvent.cpp +++ b/dom/events/AnimationEvent.cpp @@ -83,19 +83,17 @@ AnimationEvent::GetPseudoElement(nsAStri } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMAnimationEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<AnimationEvent> +NS_NewDOMAnimationEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalAnimationEvent* aEvent) { - AnimationEvent* it = new AnimationEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<AnimationEvent> it = + new AnimationEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/AnimationEvent.h +++ b/dom/events/AnimationEvent.h @@ -47,9 +47,14 @@ public: protected: ~AnimationEvent() {} }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::AnimationEvent> +NS_NewDOMAnimationEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::InternalAnimationEvent* aEvent); + #endif // mozilla_dom_AnimationEvent_h_
--- a/dom/events/AsyncEventDispatcher.cpp +++ b/dom/events/AsyncEventDispatcher.cpp @@ -21,35 +21,36 @@ using namespace dom; ******************************************************************************/ AsyncEventDispatcher::AsyncEventDispatcher(EventTarget* aTarget, WidgetEvent& aEvent) : mTarget(aTarget) , mOnlyChromeDispatch(false) { MOZ_ASSERT(mTarget); - EventDispatcher::CreateEvent(aTarget, nullptr, &aEvent, EmptyString(), - getter_AddRefs(mEvent)); + nsRefPtr<Event> event = + EventDispatcher::CreateEvent(aTarget, nullptr, &aEvent, EmptyString()); + mEvent = do_QueryInterface(event); NS_ASSERTION(mEvent, "Should never fail to create an event"); mEvent->DuplicatePrivateData(); mEvent->SetTrusted(aEvent.mFlags.mIsTrusted); } NS_IMETHODIMP AsyncEventDispatcher::Run() { - nsCOMPtr<nsIDOMEvent> event = mEvent; + nsRefPtr<Event> event = mEvent ? mEvent->InternalDOMEvent() : nullptr; if (!event) { - NS_NewDOMEvent(getter_AddRefs(event), mTarget, nullptr, nullptr); + event = NS_NewDOMEvent(mTarget, nullptr, nullptr); nsresult rv = event->InitEvent(mEventType, mBubbles, false); NS_ENSURE_SUCCESS(rv, rv); event->SetTrusted(true); } if (mOnlyChromeDispatch) { - MOZ_ASSERT(event->InternalDOMEvent()->IsTrusted()); + MOZ_ASSERT(event->IsTrusted()); event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true; } bool dummy; mTarget->DispatchEvent(event, &dummy); return NS_OK; } nsresult
--- a/dom/events/BeforeAfterKeyboardEvent.cpp +++ b/dom/events/BeforeAfterKeyboardEvent.cpp @@ -73,21 +73,17 @@ BeforeAfterKeyboardEvent::GetEmbeddedCan } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMBeforeAfterKeyboardEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<BeforeAfterKeyboardEvent> +NS_NewDOMBeforeAfterKeyboardEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalBeforeAfterKeyboardEvent* aEvent) { - BeforeAfterKeyboardEvent* it = + nsRefPtr<BeforeAfterKeyboardEvent> it = new BeforeAfterKeyboardEvent(aOwner, aPresContext, aEvent); - - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + return it.forget(); }
--- a/dom/events/BeforeAfterKeyboardEvent.h +++ b/dom/events/BeforeAfterKeyboardEvent.h @@ -38,9 +38,14 @@ public: // This function returns a boolean value when event typs is either // "mozbrowserafterkeydown" or "mozbrowserafterkeyup". Nullable<bool> GetEmbeddedCancelled(); }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::BeforeAfterKeyboardEvent> +NS_NewDOMBeforeAfterKeyboardEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::InternalBeforeAfterKeyboardEvent* aEvent); + #endif // mozilla_dom_BeforeAfterKeyboardEvent_h_
--- a/dom/events/BeforeUnloadEvent.cpp +++ b/dom/events/BeforeUnloadEvent.cpp @@ -31,19 +31,17 @@ BeforeUnloadEvent::GetReturnValue(nsAStr } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMBeforeUnloadEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<BeforeUnloadEvent> +NS_NewDOMBeforeUnloadEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) { - BeforeUnloadEvent* it = new BeforeUnloadEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<BeforeUnloadEvent> it = + new BeforeUnloadEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/BeforeUnloadEvent.h +++ b/dom/events/BeforeUnloadEvent.h @@ -42,9 +42,14 @@ protected: ~BeforeUnloadEvent() {} nsString mText; }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::BeforeUnloadEvent> +NS_NewDOMBeforeUnloadEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetEvent* aEvent); + #endif // mozilla_dom_BeforeUnloadEvent_h_
--- a/dom/events/ClipboardEvent.cpp +++ b/dom/events/ClipboardEvent.cpp @@ -118,19 +118,17 @@ ClipboardEvent::GetClipboardData() } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMClipboardEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<ClipboardEvent> +NS_NewDOMClipboardEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalClipboardEvent* aEvent) { - ClipboardEvent* it = new ClipboardEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<ClipboardEvent> it = + new ClipboardEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/ClipboardEvent.h +++ b/dom/events/ClipboardEvent.h @@ -51,9 +51,14 @@ public: protected: ~ClipboardEvent() {} }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::ClipboardEvent> +NS_NewDOMClipboardEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::InternalClipboardEvent* aEvent); + #endif // mozilla_dom_ClipboardEvent_h_
--- a/dom/events/CommandEvent.cpp +++ b/dom/events/CommandEvent.cpp @@ -59,19 +59,17 @@ CommandEvent::InitCommandEvent(const nsA } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMCommandEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<CommandEvent> +NS_NewDOMCommandEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetCommandEvent* aEvent) { - CommandEvent* it = new CommandEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<CommandEvent> it = + new CommandEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/CommandEvent.h +++ b/dom/events/CommandEvent.h @@ -46,9 +46,14 @@ public: protected: ~CommandEvent() {} }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::CommandEvent> +NS_NewDOMCommandEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetCommandEvent* aEvent); + #endif // mozilla_dom_CommandEvent_h_
--- a/dom/events/CompositionEvent.cpp +++ b/dom/events/CompositionEvent.cpp @@ -75,17 +75,17 @@ CompositionEvent::InitCompositionEvent(c } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMCompositionEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<CompositionEvent> +NS_NewDOMCompositionEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetCompositionEvent* aEvent) { - CompositionEvent* event = new CompositionEvent(aOwner, aPresContext, aEvent); - return CallQueryInterface(event, aInstancePtrResult); + nsRefPtr<CompositionEvent> event = + new CompositionEvent(aOwner, aPresContext, aEvent); + return event.forget(); }
--- a/dom/events/CompositionEvent.h +++ b/dom/events/CompositionEvent.h @@ -49,9 +49,14 @@ protected: nsString mData; nsString mLocale; }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::CompositionEvent> +NS_NewDOMCompositionEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetCompositionEvent* aEvent); + #endif // mozilla_dom_CompositionEvent_h_
--- a/dom/events/CustomEvent.cpp +++ b/dom/events/CustomEvent.cpp @@ -106,19 +106,17 @@ CustomEvent::GetDetail(JSContext* aCx, if (!mDetail) { aRetval.setNull(); return; } VariantToJsval(aCx, mDetail, aRetval); } -nsresult -NS_NewDOMCustomEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, +already_AddRefed<CustomEvent> +NS_NewDOMCustomEvent(EventTarget* aOwner, nsPresContext* aPresContext, mozilla::WidgetEvent* aEvent) { - CustomEvent* it = new CustomEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<CustomEvent> it = + new CustomEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/CustomEvent.h +++ b/dom/events/CustomEvent.h @@ -53,9 +53,14 @@ public: bool aCancelable, JS::Handle<JS::Value> aDetail, ErrorResult& aRv); }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::CustomEvent> +NS_NewDOMCustomEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetEvent* aEvent); + #endif // CustomEvent_h__
--- a/dom/events/DOMEventTargetHelper.cpp +++ b/dom/events/DOMEventTargetHelper.cpp @@ -257,18 +257,17 @@ DOMEventTargetHelper::DispatchEvent(nsID *aRetVal = (status != nsEventStatus_eConsumeNoDefault); return rv; } nsresult DOMEventTargetHelper::DispatchTrustedEvent(const nsAString& aEventName) { - nsCOMPtr<nsIDOMEvent> event; - NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); nsresult rv = event->InitEvent(aEventName, false, false); NS_ENSURE_SUCCESS(rv, rv); return DispatchTrustedEvent(event); } nsresult DOMEventTargetHelper::DispatchTrustedEvent(nsIDOMEvent* event)
--- a/dom/events/DataContainerEvent.cpp +++ b/dom/events/DataContainerEvent.cpp @@ -82,20 +82,18 @@ DataContainerEvent::SetData(JSContext* a } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMDataContainerEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<DataContainerEvent> +NS_NewDOMDataContainerEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) { - DataContainerEvent* it = new DataContainerEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<DataContainerEvent> it = + new DataContainerEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/DataContainerEvent.h +++ b/dom/events/DataContainerEvent.h @@ -52,9 +52,14 @@ protected: private: nsInterfaceHashtable<nsStringHashKey, nsIVariant> mData; }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::DataContainerEvent> +NS_NewDOMDataContainerEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetEvent* aEvent); + #endif // mozilla_dom_DataContainerEvent_h_
--- a/dom/events/DeviceMotionEvent.cpp +++ b/dom/events/DeviceMotionEvent.cpp @@ -140,21 +140,17 @@ DeviceRotationRate::~DeviceRotationRate( } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMDeviceMotionEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<DeviceMotionEvent> +NS_NewDOMDeviceMotionEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) { - NS_ENSURE_ARG_POINTER(aInstancePtrResult); - - DeviceMotionEvent* it = new DeviceMotionEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<DeviceMotionEvent> it = + new DeviceMotionEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/DeviceMotionEvent.h +++ b/dom/events/DeviceMotionEvent.h @@ -144,9 +144,14 @@ protected: nsRefPtr<DeviceAcceleration> mAccelerationIncludingGravity; nsRefPtr<DeviceRotationRate> mRotationRate; Nullable<double> mInterval; }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::DeviceMotionEvent> +NS_NewDOMDeviceMotionEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetEvent* aEvent); + #endif // mozilla_dom_DeviceMotionEvent_h_
--- a/dom/events/DragEvent.cpp +++ b/dom/events/DragEvent.cpp @@ -154,17 +154,17 @@ DragEvent::Constructor(const GlobalObjec } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMDragEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<DragEvent> +NS_NewDOMDragEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetDragEvent* aEvent) { - DragEvent* event = new DragEvent(aOwner, aPresContext, aEvent); - return CallQueryInterface(event, aInstancePtrResult); + nsRefPtr<DragEvent> event = + new DragEvent(aOwner, aPresContext, aEvent); + return event.forget(); }
--- a/dom/events/DragEvent.h +++ b/dom/events/DragEvent.h @@ -56,9 +56,14 @@ public: protected: ~DragEvent() {} }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::DragEvent> +NS_NewDOMDragEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetDragEvent* aEvent); + #endif // mozilla_dom_DragEvent_h_
--- a/dom/events/Event.cpp +++ b/dom/events/Event.cpp @@ -1252,19 +1252,16 @@ Event::GetShadowRelatedTarget(nsIContent } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<Event> +NS_NewDOMEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) { - Event* it = new Event(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<Event> it = new Event(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/Event.h +++ b/dom/events/Event.h @@ -335,9 +335,14 @@ ToSupports(mozilla::dom::Event* e) } inline nsISupports* ToCanonicalSupports(mozilla::dom::Event* e) { return static_cast<nsIDOMEvent*>(e); } +already_AddRefed<mozilla::dom::Event> +NS_NewDOMEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetEvent* aEvent); + #endif // mozilla_dom_Event_h_
--- a/dom/events/EventDispatcher.cpp +++ b/dom/events/EventDispatcher.cpp @@ -10,23 +10,38 @@ #include <new> #include "nsIContent.h" #include "nsIDocument.h" #include "nsINode.h" #include "nsPIDOMWindow.h" #include "GeckoProfiler.h" #include "mozilla/ContentEvents.h" #include "mozilla/dom/CloseEvent.h" +#include "mozilla/dom/CustomEvent.h" #include "mozilla/dom/DeviceOrientationEvent.h" #include "mozilla/dom/EventTarget.h" +#include "mozilla/dom/FocusEvent.h" #include "mozilla/dom/HashChangeEvent.h" +#include "mozilla/dom/InputEvent.h" +#include "mozilla/dom/MessageEvent.h" +#include "mozilla/dom/MouseScrollEvent.h" +#include "mozilla/dom/MutationEvent.h" +#include "mozilla/dom/NotifyPaintEvent.h" #include "mozilla/dom/PageTransitionEvent.h" +#include "mozilla/dom/PointerEvent.h" #include "mozilla/dom/PopStateEvent.h" +#include "mozilla/dom/ScrollAreaEvent.h" +#include "mozilla/dom/SimpleGestureEvent.h" #include "mozilla/dom/StorageEvent.h" +#include "mozilla/dom/SVGZoomEvent.h" +#include "mozilla/dom/TimeEvent.h" #include "mozilla/dom/TouchEvent.h" +#include "mozilla/dom/TransitionEvent.h" +#include "mozilla/dom/WheelEvent.h" +#include "mozilla/dom/XULCommandEvent.h" #include "mozilla/EventDispatcher.h" #include "mozilla/EventListenerManager.h" #include "mozilla/InternalMutationEvent.h" #include "mozilla/ipc/MessageChannel.h" #include "mozilla/MiscEvents.h" #include "mozilla/MouseEvents.h" #include "mozilla/TextEvents.h" #include "mozilla/TouchEvents.h" @@ -700,198 +715,177 @@ EventDispatcher::DispatchDOMEvent(nsISup aDOMEvent, aEventStatus); } else if (aEvent) { return EventDispatcher::Dispatch(aTarget, aPresContext, aEvent, aDOMEvent, aEventStatus); } return NS_ERROR_ILLEGAL_VALUE; } -/* static */ nsresult +/* static */ already_AddRefed<dom::Event> EventDispatcher::CreateEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent, - const nsAString& aEventType, - nsIDOMEvent** aDOMEvent) + const nsAString& aEventType) { - *aDOMEvent = nullptr; - if (aEvent) { switch(aEvent->mClass) { case eMutationEventClass: - return NS_NewDOMMutationEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMMutationEvent(aOwner, aPresContext, aEvent->AsMutationEvent()); case eGUIEventClass: case eScrollPortEventClass: case eUIEventClass: - return NS_NewDOMUIEvent(aDOMEvent, aOwner, aPresContext, - aEvent->AsGUIEvent()); + return NS_NewDOMUIEvent(aOwner, aPresContext, aEvent->AsGUIEvent()); case eScrollAreaEventClass: - return NS_NewDOMScrollAreaEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMScrollAreaEvent(aOwner, aPresContext, aEvent->AsScrollAreaEvent()); case eKeyboardEventClass: - return NS_NewDOMKeyboardEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMKeyboardEvent(aOwner, aPresContext, aEvent->AsKeyboardEvent()); case eBeforeAfterKeyboardEventClass: - return NS_NewDOMBeforeAfterKeyboardEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMBeforeAfterKeyboardEvent(aOwner, aPresContext, aEvent->AsBeforeAfterKeyboardEvent()); case eCompositionEventClass: - return NS_NewDOMCompositionEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMCompositionEvent(aOwner, aPresContext, aEvent->AsCompositionEvent()); case eMouseEventClass: - return NS_NewDOMMouseEvent(aDOMEvent, aOwner, aPresContext, - aEvent->AsMouseEvent()); + return NS_NewDOMMouseEvent(aOwner, aPresContext, aEvent->AsMouseEvent()); case eFocusEventClass: - return NS_NewDOMFocusEvent(aDOMEvent, aOwner, aPresContext, - aEvent->AsFocusEvent()); + return NS_NewDOMFocusEvent(aOwner, aPresContext, aEvent->AsFocusEvent()); case eMouseScrollEventClass: - return NS_NewDOMMouseScrollEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMMouseScrollEvent(aOwner, aPresContext, aEvent->AsMouseScrollEvent()); case eWheelEventClass: - return NS_NewDOMWheelEvent(aDOMEvent, aOwner, aPresContext, - aEvent->AsWheelEvent()); + return NS_NewDOMWheelEvent(aOwner, aPresContext, aEvent->AsWheelEvent()); case eEditorInputEventClass: - return NS_NewDOMInputEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMInputEvent(aOwner, aPresContext, aEvent->AsEditorInputEvent()); case eDragEventClass: - return NS_NewDOMDragEvent(aDOMEvent, aOwner, aPresContext, - aEvent->AsDragEvent()); + return NS_NewDOMDragEvent(aOwner, aPresContext, aEvent->AsDragEvent()); case eClipboardEventClass: - return NS_NewDOMClipboardEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMClipboardEvent(aOwner, aPresContext, aEvent->AsClipboardEvent()); case eSVGZoomEventClass: - return NS_NewDOMSVGZoomEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMSVGZoomEvent(aOwner, aPresContext, aEvent->AsSVGZoomEvent()); case eSMILTimeEventClass: - return NS_NewDOMTimeEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMTimeEvent(aOwner, aPresContext, aEvent->AsSMILTimeEvent()); case eCommandEventClass: - return NS_NewDOMCommandEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMCommandEvent(aOwner, aPresContext, aEvent->AsCommandEvent()); case eSimpleGestureEventClass: - return NS_NewDOMSimpleGestureEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMSimpleGestureEvent(aOwner, aPresContext, aEvent->AsSimpleGestureEvent()); case ePointerEventClass: - return NS_NewDOMPointerEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMPointerEvent(aOwner, aPresContext, aEvent->AsPointerEvent()); case eTouchEventClass: - return NS_NewDOMTouchEvent(aDOMEvent, aOwner, aPresContext, - aEvent->AsTouchEvent()); + return NS_NewDOMTouchEvent(aOwner, aPresContext, aEvent->AsTouchEvent()); case eTransitionEventClass: - return NS_NewDOMTransitionEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMTransitionEvent(aOwner, aPresContext, aEvent->AsTransitionEvent()); case eAnimationEventClass: - return NS_NewDOMAnimationEvent(aDOMEvent, aOwner, aPresContext, + return NS_NewDOMAnimationEvent(aOwner, aPresContext, aEvent->AsAnimationEvent()); default: // For all other types of events, create a vanilla event object. - return NS_NewDOMEvent(aDOMEvent, aOwner, aPresContext, aEvent); + return NS_NewDOMEvent(aOwner, aPresContext, aEvent); } } // And if we didn't get an event, check the type argument. if (aEventType.LowerCaseEqualsLiteral("mouseevent") || aEventType.LowerCaseEqualsLiteral("mouseevents") || aEventType.LowerCaseEqualsLiteral("popupevents")) - return NS_NewDOMMouseEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMMouseEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("mousescrollevents")) - return NS_NewDOMMouseScrollEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMMouseScrollEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("dragevent") || aEventType.LowerCaseEqualsLiteral("dragevents")) - return NS_NewDOMDragEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMDragEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("keyboardevent") || aEventType.LowerCaseEqualsLiteral("keyevents")) - return NS_NewDOMKeyboardEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMKeyboardEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("compositionevent") || aEventType.LowerCaseEqualsLiteral("textevent") || aEventType.LowerCaseEqualsLiteral("textevents")) { - return NS_NewDOMCompositionEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMCompositionEvent(aOwner, aPresContext, nullptr); } if (aEventType.LowerCaseEqualsLiteral("mutationevent") || aEventType.LowerCaseEqualsLiteral("mutationevents")) - return NS_NewDOMMutationEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMMutationEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("deviceorientationevent")) { DeviceOrientationEventInit init; - nsRefPtr<DeviceOrientationEvent> event = - DeviceOrientationEvent::Constructor(aOwner, EmptyString(), init); - event.forget(aDOMEvent); - return NS_OK; + return DeviceOrientationEvent::Constructor(aOwner, EmptyString(), init); } if (aEventType.LowerCaseEqualsLiteral("devicemotionevent")) - return NS_NewDOMDeviceMotionEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMDeviceMotionEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("uievent") || aEventType.LowerCaseEqualsLiteral("uievents")) - return NS_NewDOMUIEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMUIEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("event") || aEventType.LowerCaseEqualsLiteral("events") || aEventType.LowerCaseEqualsLiteral("htmlevents") || aEventType.LowerCaseEqualsLiteral("svgevent") || aEventType.LowerCaseEqualsLiteral("svgevents")) - return NS_NewDOMEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("svgzoomevent") || aEventType.LowerCaseEqualsLiteral("svgzoomevents")) - return NS_NewDOMSVGZoomEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMSVGZoomEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("timeevent") || aEventType.LowerCaseEqualsLiteral("timeevents")) - return NS_NewDOMTimeEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMTimeEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("xulcommandevent") || aEventType.LowerCaseEqualsLiteral("xulcommandevents")) - return NS_NewDOMXULCommandEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMXULCommandEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("commandevent") || aEventType.LowerCaseEqualsLiteral("commandevents")) - return NS_NewDOMCommandEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMCommandEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("datacontainerevent") || aEventType.LowerCaseEqualsLiteral("datacontainerevents")) - return NS_NewDOMDataContainerEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMDataContainerEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("messageevent")) - return NS_NewDOMMessageEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMMessageEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("notifypaintevent")) - return NS_NewDOMNotifyPaintEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMNotifyPaintEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("simplegestureevent")) - return NS_NewDOMSimpleGestureEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMSimpleGestureEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("beforeunloadevent")) - return NS_NewDOMBeforeUnloadEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMBeforeUnloadEvent(aOwner, aPresContext, nullptr); // XXXkhuey this is broken if (aEventType.LowerCaseEqualsLiteral("pagetransition")) { PageTransitionEventInit init; - nsRefPtr<PageTransitionEvent> event = - PageTransitionEvent::Constructor(aOwner, EmptyString(), init); - event.forget(aDOMEvent); - return NS_OK; + return PageTransitionEvent::Constructor(aOwner, EmptyString(), init); } if (aEventType.LowerCaseEqualsLiteral("scrollareaevent")) - return NS_NewDOMScrollAreaEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMScrollAreaEvent(aOwner, aPresContext, nullptr); // XXXkhuey Chrome supports popstateevent here, even though it provides no // initPopStateEvent method. This is nuts ... but copying it is unlikely to // break the web. if (aEventType.LowerCaseEqualsLiteral("popstateevent")) { AutoJSContext cx; RootedDictionary<PopStateEventInit> init(cx); - nsRefPtr<PopStateEvent> event = - PopStateEvent::Constructor(aOwner, EmptyString(), init); - event.forget(aDOMEvent); - return NS_OK; + return PopStateEvent::Constructor(aOwner, EmptyString(), init); } if (aEventType.LowerCaseEqualsLiteral("touchevent") && TouchEvent::PrefEnabled()) - return NS_NewDOMTouchEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMTouchEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("hashchangeevent")) { HashChangeEventInit init; - nsRefPtr<HashChangeEvent> event = - HashChangeEvent::Constructor(aOwner, EmptyString(), init); - event.forget(aDOMEvent); - return NS_OK; + return HashChangeEvent::Constructor(aOwner, EmptyString(), init); } if (aEventType.LowerCaseEqualsLiteral("customevent")) - return NS_NewDOMCustomEvent(aDOMEvent, aOwner, aPresContext, nullptr); + return NS_NewDOMCustomEvent(aOwner, aPresContext, nullptr); if (aEventType.LowerCaseEqualsLiteral("storageevent")) { - return NS_NewDOMStorageEvent(aDOMEvent, aOwner); + return NS_NewDOMStorageEvent(aOwner); } // NEW EVENT TYPES SHOULD NOT BE ADDED HERE; THEY SHOULD USE ONLY EVENT // CONSTRUCTORS - return NS_ERROR_DOM_NOT_SUPPORTED_ERR; + return nullptr; } } // namespace mozilla
--- a/dom/events/EventDispatcher.h +++ b/dom/events/EventDispatcher.h @@ -18,16 +18,17 @@ class nsIContent; class nsIDOMEvent; class nsPresContext; template<class E> class nsCOMArray; namespace mozilla { namespace dom { +class Event; class EventTarget; } // namespace dom /** * About event dispatching: * When either EventDispatcher::Dispatch or * EventDispatcher::DispatchDOMEvent is called an event target chain is * created. EventDispatcher creates the chain by calling PreHandleEvent @@ -267,23 +268,22 @@ public: */ static nsresult DispatchDOMEvent(nsISupports* aTarget, WidgetEvent* aEvent, nsIDOMEvent* aDOMEvent, nsPresContext* aPresContext, nsEventStatus* aEventStatus); /** - * Creates a DOM Event. + * Creates a DOM Event. Returns null if the event type is unsupported. */ - static nsresult CreateEvent(dom::EventTarget* aOwner, - nsPresContext* aPresContext, - WidgetEvent* aEvent, - const nsAString& aEventType, - nsIDOMEvent** aDOMEvent); + static already_AddRefed<dom::Event> CreateEvent(dom::EventTarget* aOwner, + nsPresContext* aPresContext, + WidgetEvent* aEvent, + const nsAString& aEventType); /** * Called at shutting down. */ static void Shutdown(); }; } // namespace mozilla
--- a/dom/events/EventListenerManager.cpp +++ b/dom/events/EventListenerManager.cpp @@ -1104,18 +1104,20 @@ EventListenerManager::HandleEventInterna hasListener = true; if (listener->IsListening(aEvent) && (aEvent->mFlags.mIsTrusted || listener->mFlags.mAllowUntrustedEvents)) { if (!*aDOMEvent) { // This is tiny bit slow, but happens only once per event. nsCOMPtr<EventTarget> et = do_QueryInterface(aEvent->originalTarget); - EventDispatcher::CreateEvent(et, aPresContext, - aEvent, EmptyString(), aDOMEvent); + nsRefPtr<Event> event = EventDispatcher::CreateEvent(et, aPresContext, + aEvent, + EmptyString()); + event.forget(aDOMEvent); } if (*aDOMEvent) { if (!aEvent->currentTarget) { aEvent->currentTarget = aCurrentTarget->GetTargetForDOMEvent(); if (!aEvent->currentTarget) { break; } }
--- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -11,16 +11,17 @@ #include "mozilla/IMEStateManager.h" #include "mozilla/MiscEvents.h" #include "mozilla/MathAlgorithms.h" #include "mozilla/MouseEvents.h" #include "mozilla/TextComposition.h" #include "mozilla/TextEvents.h" #include "mozilla/TouchEvents.h" #include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/DragEvent.h" #include "mozilla/dom/Event.h" #include "mozilla/dom/TabParent.h" #include "mozilla/dom/UIEvent.h" #include "ContentEventHandler.h" #include "IMEContentObserver.h" #include "WheelHandlingHelper.h" @@ -49,17 +50,16 @@ #include "nsIContentViewer.h" #include "nsFrameManager.h" #include "nsIDOMXULElement.h" #include "nsIDOMKeyEvent.h" #include "nsIObserverService.h" #include "nsIDocShell.h" #include "nsIDOMWheelEvent.h" -#include "nsIDOMDragEvent.h" #include "nsIDOMUIEvent.h" #include "nsIMozBrowserFrame.h" #include "nsSubDocumentFrame.h" #include "nsLayoutUtils.h" #include "nsIInterfaceRequestorUtils.h" #include "nsUnicharUtils.h" #include "nsContentUtils.h" @@ -1876,32 +1876,26 @@ EventStateManager::DoDefaultDragStart(ns nsCOMPtr<nsISupportsArray> transArray = aDataTransfer->GetTransferables(dragTarget->AsDOMNode()); if (!transArray) return false; // XXXndeakin don't really want to create a new drag DOM event // here, but we need something to pass to the InvokeDragSession // methods. - nsCOMPtr<nsIDOMEvent> domEvent; - NS_NewDOMDragEvent(getter_AddRefs(domEvent), dragTarget, - aPresContext, aDragEvent); - - nsCOMPtr<nsIDOMDragEvent> domDragEvent = do_QueryInterface(domEvent); - // if creating a drag event failed, starting a drag session will - // just fail. + nsRefPtr<DragEvent> event = + NS_NewDOMDragEvent(dragTarget, aPresContext, aDragEvent); // Use InvokeDragSessionWithSelection if a selection is being dragged, // such that the image can be generated from the selected text. However, // use InvokeDragSessionWithImage if a custom image was set or something // other than a selection is being dragged. if (!dragImage && aSelection) { dragService->InvokeDragSessionWithSelection(aSelection, transArray, - action, domDragEvent, - aDataTransfer); + action, event, aDataTransfer); } else { // if dragging within a XUL tree and no custom drag image was // set, the region argument to InvokeDragSessionWithImage needs // to be set to the area encompassing the selected rows of the // tree to ensure that the drag feedback gets clipped to those // rows. For other content, region should be null. nsCOMPtr<nsIScriptableRegion> region; @@ -1917,18 +1911,17 @@ EventStateManager::DoDefaultDragStart(ns } } #endif dragService->InvokeDragSessionWithImage(dragTarget->AsDOMNode(), transArray, region, action, dragImage ? dragImage->AsDOMNode() : nullptr, - imageX, - imageY, domDragEvent, + imageX, imageY, event, aDataTransfer); } return true; } nsresult EventStateManager::GetContentViewer(nsIContentViewer** aCv)
--- a/dom/events/FocusEvent.cpp +++ b/dom/events/FocusEvent.cpp @@ -72,19 +72,16 @@ FocusEvent::Constructor(const GlobalObje } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMFocusEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<FocusEvent> +NS_NewDOMFocusEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalFocusEvent* aEvent) { - FocusEvent* it = new FocusEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<FocusEvent> it = new FocusEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/FocusEvent.h +++ b/dom/events/FocusEvent.h @@ -48,9 +48,14 @@ protected: nsIDOMWindow* aView, int32_t aDetail, EventTarget* aRelatedTarget); }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::FocusEvent> +NS_NewDOMFocusEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::InternalFocusEvent* aEvent); + #endif // mozilla_dom_FocusEvent_h_
--- a/dom/events/InputEvent.cpp +++ b/dom/events/InputEvent.cpp @@ -58,19 +58,16 @@ InputEvent::Constructor(const GlobalObje } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMInputEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<InputEvent> +NS_NewDOMInputEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalEditorInputEvent* aEvent) { - InputEvent* it = new InputEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<InputEvent> it = new InputEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/InputEvent.h +++ b/dom/events/InputEvent.h @@ -41,9 +41,14 @@ public: protected: ~InputEvent() {} }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::InputEvent> +NS_NewDOMInputEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::InternalEditorInputEvent* aEvent); + #endif // mozilla_dom_InputEvent_h_
--- a/dom/events/KeyboardEvent.cpp +++ b/dom/events/KeyboardEvent.cpp @@ -304,19 +304,16 @@ KeyboardEvent::InitKeyEvent(const nsAStr } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMKeyboardEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<KeyboardEvent> +NS_NewDOMKeyboardEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetKeyboardEvent* aEvent) { - KeyboardEvent* it = new KeyboardEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<KeyboardEvent> it = new KeyboardEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/KeyboardEvent.h +++ b/dom/events/KeyboardEvent.h @@ -88,9 +88,14 @@ private: // value. mInitializedWhichValue stores it. I.e., this is invalid when // mInitializedByCtor is false. uint32_t mInitializedWhichValue; }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::KeyboardEvent> +NS_NewDOMKeyboardEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetKeyboardEvent* aEvent); + #endif // mozilla_dom_KeyboardEvent_h_
--- a/dom/events/MessageEvent.cpp +++ b/dom/events/MessageEvent.cpp @@ -167,17 +167,17 @@ MessageEvent::Constructor(EventTarget* a } if (aParam.mPorts.WasPassed() && !aParam.mPorts.Value().IsNull()) { nsTArray<nsRefPtr<MessagePortBase>> ports; for (uint32_t i = 0, len = aParam.mPorts.Value().Value().Length(); i < len; ++i) { ports.AppendElement(aParam.mPorts.Value().Value()[i].get()); } - event->mPorts = new MessagePortList(static_cast<EventBase*>(event), ports); + event->mPorts = new MessagePortList(static_cast<Event*>(event), ports); } return event.forget(); } NS_IMETHODIMP MessageEvent::InitMessageEvent(const nsAString& aType, bool aCanBubble, @@ -219,19 +219,16 @@ MessageEvent::SetSource(mozilla::dom::wo } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMMessageEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<MessageEvent> +NS_NewDOMMessageEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent) { - MessageEvent* it = new MessageEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<MessageEvent> it = new MessageEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/MessageEvent.h +++ b/dom/events/MessageEvent.h @@ -97,9 +97,14 @@ private: nsRefPtr<MessagePortBase> mPortSource; nsRefPtr<workers::ServiceWorkerClient> mClientSource; nsRefPtr<MessagePortList> mPorts; }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::MessageEvent> +NS_NewDOMMessageEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetEvent* aEvent); + #endif // mozilla_dom_MessageEvent_h_
--- a/dom/events/MouseEvent.cpp +++ b/dom/events/MouseEvent.cpp @@ -499,19 +499,16 @@ MouseEvent::GetMozInputSource(uint16_t* } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMMouseEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<MouseEvent> +NS_NewDOMMouseEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetMouseEvent* aEvent) { - MouseEvent* it = new MouseEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<MouseEvent> it = new MouseEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/MouseEvent.h +++ b/dom/events/MouseEvent.h @@ -127,9 +127,14 @@ protected: } // namespace dom } // namespace mozilla #define NS_FORWARD_TO_MOUSEEVENT \ NS_FORWARD_NSIDOMMOUSEEVENT(MouseEvent::) \ NS_FORWARD_TO_UIEVENT +already_AddRefed<mozilla::dom::MouseEvent> +NS_NewDOMMouseEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetMouseEvent* aEvent); + #endif // mozilla_dom_MouseEvent_h_
--- a/dom/events/MouseScrollEvent.cpp +++ b/dom/events/MouseScrollEvent.cpp @@ -83,19 +83,17 @@ MouseScrollEvent::Axis() } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace dom; -nsresult -NS_NewDOMMouseScrollEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<MouseScrollEvent> +NS_NewDOMMouseScrollEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetMouseScrollEvent* aEvent) { - MouseScrollEvent* it = new MouseScrollEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<MouseScrollEvent> it = + new MouseScrollEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/MouseScrollEvent.h +++ b/dom/events/MouseScrollEvent.h @@ -54,9 +54,14 @@ public: protected: ~MouseScrollEvent() {} }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::MouseScrollEvent> +NS_NewDOMMouseScrollEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetMouseScrollEvent* aEvent); + #endif // mozilla_dom_MouseScrollEvent_h_
--- a/dom/events/MutationEvent.cpp +++ b/dom/events/MutationEvent.cpp @@ -114,19 +114,16 @@ MutationEvent::InitMutationEvent(const n } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMMutationEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<MutationEvent> +NS_NewDOMMutationEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalMutationEvent* aEvent) { - MutationEvent* it = new MutationEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<MutationEvent> it = new MutationEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/MutationEvent.h +++ b/dom/events/MutationEvent.h @@ -60,9 +60,14 @@ public: protected: ~MutationEvent() {} }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::MutationEvent> +NS_NewDOMMutationEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::InternalMutationEvent* aEvent); + #endif // mozilla_dom_MutationEvent_h_
--- a/dom/events/NotifyPaintEvent.cpp +++ b/dom/events/NotifyPaintEvent.cpp @@ -157,22 +157,20 @@ NotifyPaintEvent::Deserialize(const IPC: } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMNotifyPaintEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<NotifyPaintEvent> +NS_NewDOMNotifyPaintEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetEvent* aEvent, uint32_t aEventType, nsInvalidateRequestList* aInvalidateRequests) { - NotifyPaintEvent* it = new NotifyPaintEvent(aOwner, aPresContext, aEvent, - aEventType, aInvalidateRequests); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<NotifyPaintEvent> it = + new NotifyPaintEvent(aOwner, aPresContext, aEvent, aEventType, + aInvalidateRequests); + return it.forget(); }
--- a/dom/events/NotifyPaintEvent.h +++ b/dom/events/NotifyPaintEvent.h @@ -62,9 +62,17 @@ private: nsRegion GetRegion(); nsTArray<nsInvalidateRequestList::Request> mInvalidateRequests; }; } // namespace dom } // namespace mozilla +// This empties aInvalidateRequests. +already_AddRefed<mozilla::dom::NotifyPaintEvent> +NS_NewDOMNotifyPaintEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetEvent* aEvent, + uint32_t aEventType = 0, + nsInvalidateRequestList* aInvalidateRequests = nullptr); + #endif // mozilla_dom_NotifyPaintEvent_h_
--- a/dom/events/PointerEvent.cpp +++ b/dom/events/PointerEvent.cpp @@ -159,19 +159,16 @@ PointerEvent::IsPrimary() } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMPointerEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<PointerEvent> +NS_NewDOMPointerEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetPointerEvent *aEvent) { - PointerEvent *it = new PointerEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<PointerEvent> it = new PointerEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/PointerEvent.h +++ b/dom/events/PointerEvent.h @@ -50,9 +50,14 @@ public: void GetPointerType(nsAString& aPointerType); }; void ConvertPointerTypeToString(uint16_t aPointerTypeSrc, nsAString& aPointerTypeDest); } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::PointerEvent> +NS_NewDOMPointerEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetPointerEvent* aEvent); + #endif // mozilla_dom_PointerEvent_h_
--- a/dom/events/ScrollAreaEvent.cpp +++ b/dom/events/ScrollAreaEvent.cpp @@ -95,17 +95,17 @@ ScrollAreaEvent::Deserialize(const IPC:: } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMScrollAreaEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<ScrollAreaEvent> +NS_NewDOMScrollAreaEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalScrollAreaEvent* aEvent) { - ScrollAreaEvent* ev = new ScrollAreaEvent(aOwner, aPresContext, aEvent); - return CallQueryInterface(ev, aInstancePtrResult); + nsRefPtr<ScrollAreaEvent> ev = + new ScrollAreaEvent(aOwner, aPresContext, aEvent); + return ev.forget(); }
--- a/dom/events/ScrollAreaEvent.h +++ b/dom/events/ScrollAreaEvent.h @@ -81,9 +81,14 @@ protected: ~ScrollAreaEvent() {} nsRefPtr<DOMRect> mClientArea; }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::ScrollAreaEvent> +NS_NewDOMScrollAreaEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::InternalScrollAreaEvent* aEvent); + #endif // mozilla_dom_ScrollAreaEvent_h_
--- a/dom/events/SimpleGestureEvent.cpp +++ b/dom/events/SimpleGestureEvent.cpp @@ -141,19 +141,17 @@ SimpleGestureEvent::InitSimpleGestureEve } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMSimpleGestureEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<SimpleGestureEvent> +NS_NewDOMSimpleGestureEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetSimpleGestureEvent* aEvent) { - SimpleGestureEvent* it = new SimpleGestureEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<SimpleGestureEvent> it = + new SimpleGestureEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/SimpleGestureEvent.h +++ b/dom/events/SimpleGestureEvent.h @@ -73,9 +73,14 @@ public: protected: ~SimpleGestureEvent() {} }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::SimpleGestureEvent> +NS_NewDOMSimpleGestureEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetSimpleGestureEvent* aEvent); + #endif // mozilla_dom_SimpleGestureEvent_h_
--- a/dom/events/StorageEvent.cpp +++ b/dom/events/StorageEvent.cpp @@ -98,21 +98,20 @@ StorageEvent::InitStorageEvent(const nsA mNewValue = aNewValue; mUrl = aURL; mStorageArea = aStorageArea; } } // namespace dom } // namespace mozilla -nsresult -NS_NewDOMStorageEvent(nsIDOMEvent** aDOMEvent, - mozilla::dom::EventTarget* aOwner) +using namespace mozilla; +using namespace mozilla::dom; + +already_AddRefed<StorageEvent> +NS_NewDOMStorageEvent(EventTarget* aOwner) { - nsRefPtr<mozilla::dom::StorageEvent> e = - new mozilla::dom::StorageEvent(aOwner); + nsRefPtr<StorageEvent> e = new StorageEvent(aOwner); e->SetTrusted(e->Init(aOwner)); - e.forget(aDOMEvent); - - return NS_OK; + return e.forget(); }
--- a/dom/events/StorageEvent.h +++ b/dom/events/StorageEvent.h @@ -9,18 +9,18 @@ #include "mozilla/Attributes.h" #include "mozilla/ErrorResult.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/Event.h" #include "mozilla/dom/StorageEventBinding.h" // Helper for EventDispatcher. -nsresult NS_NewDOMStorageEvent(nsIDOMEvent** aDOMEvent, - mozilla::dom::EventTarget* aOwner); +already_AddRefed<mozilla::dom::StorageEvent> +NS_NewDOMStorageEvent(mozilla::dom::EventTarget* aOwner); namespace mozilla { namespace dom { class DOMStorage; class StorageEvent : public Event {
--- a/dom/events/TouchEvent.cpp +++ b/dom/events/TouchEvent.cpp @@ -233,19 +233,16 @@ TouchEvent::ShiftKey() } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<TouchEvent> +NS_NewDOMTouchEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetTouchEvent* aEvent) { - TouchEvent* it = new TouchEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<TouchEvent> it = new TouchEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/TouchEvent.h +++ b/dom/events/TouchEvent.h @@ -127,9 +127,14 @@ protected: nsRefPtr<TouchList> mTouches; nsRefPtr<TouchList> mTargetTouches; nsRefPtr<TouchList> mChangedTouches; }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::TouchEvent> +NS_NewDOMTouchEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetTouchEvent* aEvent); + #endif // mozilla_dom_TouchEvent_h_
--- a/dom/events/TransitionEvent.cpp +++ b/dom/events/TransitionEvent.cpp @@ -83,19 +83,17 @@ TransitionEvent::GetPseudoElement(nsAStr } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMTransitionEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<TransitionEvent> +NS_NewDOMTransitionEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalTransitionEvent* aEvent) { - TransitionEvent *it = new TransitionEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<TransitionEvent> it = + new TransitionEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/TransitionEvent.h +++ b/dom/events/TransitionEvent.h @@ -47,9 +47,14 @@ public: protected: ~TransitionEvent() {} }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::TransitionEvent> +NS_NewDOMTransitionEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::InternalTransitionEvent* aEvent); + #endif // mozilla_dom_TransitionEvent_h_
--- a/dom/events/UIEvent.cpp +++ b/dom/events/UIEvent.cpp @@ -494,19 +494,16 @@ UIEvent::InitModifiers(const EventModifi } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<UIEvent> +NS_NewDOMUIEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetGUIEvent* aEvent) { - UIEvent* it = new UIEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<UIEvent> it = new UIEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/UIEvent.h +++ b/dom/events/UIEvent.h @@ -189,9 +189,14 @@ protected: UIEvent::Serialize(aMsg, aSerializeInterfaceType); \ } \ NS_IMETHOD_(bool) Deserialize(const IPC::Message* aMsg, \ void** aIter) override \ { \ return UIEvent::Deserialize(aMsg, aIter); \ } +already_AddRefed<mozilla::dom::UIEvent> +NS_NewDOMUIEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetGUIEvent* aEvent); + #endif // mozilla_dom_UIEvent_h_
--- a/dom/events/WheelEvent.cpp +++ b/dom/events/WheelEvent.cpp @@ -170,19 +170,16 @@ WheelEvent::Constructor(const GlobalObje } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMWheelEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<WheelEvent> +NS_NewDOMWheelEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetWheelEvent* aEvent) { - WheelEvent* it = new WheelEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<WheelEvent> it = new WheelEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/WheelEvent.h +++ b/dom/events/WheelEvent.h @@ -55,9 +55,14 @@ protected: private: int32_t mAppUnitsPerDevPixel; }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::WheelEvent> +NS_NewDOMWheelEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetWheelEvent* aEvent); + #endif // mozilla_dom_WheelEvent_h_
--- a/dom/events/XULCommandEvent.cpp +++ b/dom/events/XULCommandEvent.cpp @@ -124,19 +124,17 @@ XULCommandEvent::InitCommandEvent(const } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMXULCommandEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<XULCommandEvent> +NS_NewDOMXULCommandEvent(EventTarget* aOwner, nsPresContext* aPresContext, WidgetInputEvent* aEvent) { - XULCommandEvent* it = new XULCommandEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<XULCommandEvent> it = + new XULCommandEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/events/XULCommandEvent.h +++ b/dom/events/XULCommandEvent.h @@ -66,9 +66,14 @@ protected: ~XULCommandEvent() {} nsCOMPtr<nsIDOMEvent> mSourceEvent; }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::XULCommandEvent> +NS_NewDOMXULCommandEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::WidgetInputEvent* aEvent); + #endif // mozilla_dom_XULCommandEvent_h_
--- a/dom/events/moz.build +++ b/dom/events/moz.build @@ -130,16 +130,17 @@ include('/ipc/chromium/chromium-config.m FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [ '/docshell/base', '/dom/base', '/dom/html', '/dom/settings', '/dom/storage', + '/dom/svg', '/dom/workers', '/dom/xml', '/dom/xul', '/js/xpconnect/wrappers', '/layout/generic', '/layout/xul', '/layout/xul/tree/', ]
--- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -5398,27 +5398,23 @@ HTMLInputElement::GetPhonetic(nsAString& } #ifdef ACCESSIBILITY /*static*/ nsresult FireEventForAccessibility(nsIDOMHTMLInputElement* aTarget, nsPresContext* aPresContext, const nsAString& aEventType) { - nsCOMPtr<nsIDOMEvent> event; nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aTarget); - if (NS_SUCCEEDED(EventDispatcher::CreateEvent(element, aPresContext, nullptr, - NS_LITERAL_STRING("Events"), - getter_AddRefs(event)))) { - event->InitEvent(aEventType, true, true); - event->SetTrusted(true); - - EventDispatcher::DispatchDOMEvent(aTarget, nullptr, event, aPresContext, - nullptr); - } + nsRefPtr<Event> event = NS_NewDOMEvent(element, aPresContext, nullptr); + event->InitEvent(aEventType, true, true); + event->SetTrusted(true); + + EventDispatcher::DispatchDOMEvent(aTarget, nullptr, event, aPresContext, + nullptr); return NS_OK; } #endif nsresult HTMLInputElement::SetDefaultValueAsValue() {
--- a/dom/interfaces/events/nsIDOMEvent.idl +++ b/dom/interfaces/events/nsIDOMEvent.idl @@ -210,167 +210,8 @@ interface nsIDOMEvent : nsISupports [noscript,notxpcom] void SetTrusted(in boolean aTrusted); [notxpcom] void Serialize(in IPCMessagePtr aMsg, in boolean aSerializeInterfaceType); [notxpcom] boolean Deserialize(in ConstIPCMessagePtr aMsg, out voidPtr aIter); [noscript,notxpcom] void SetOwner(in EventTargetPtr aOwner); [notxpcom] DOMEventPtr InternalDOMEvent(); [noscript] void stopCrossProcessForwarding(); }; - -%{C++ - -nsresult -NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent); -nsresult -NS_NewDOMDataContainerEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent); -nsresult -NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetGUIEvent* aEvent); -nsresult -NS_NewDOMMouseEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetMouseEvent* aEvent); -nsresult -NS_NewDOMFocusEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::InternalFocusEvent* aEvent); -nsresult -NS_NewDOMMouseScrollEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetMouseScrollEvent* aEvent); -nsresult -NS_NewDOMWheelEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetWheelEvent* aEvent); -nsresult -NS_NewDOMDragEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetDragEvent* aEvent); -nsresult -NS_NewDOMClipboardEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::InternalClipboardEvent* aEvent); -nsresult -NS_NewDOMInputEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::InternalEditorInputEvent* aEvent); -nsresult -NS_NewDOMKeyboardEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetKeyboardEvent* aEvent); - -nsresult -NS_NewDOMBeforeAfterKeyboardEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::InternalBeforeAfterKeyboardEvent* aEvent); - -nsresult -NS_NewDOMCompositionEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetCompositionEvent* aEvent); -nsresult -NS_NewDOMMutationEvent(nsIDOMEvent** aResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::InternalMutationEvent* aEvent); -nsresult -NS_NewDOMDeviceMotionEvent(nsIDOMEvent** aResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent); -nsresult -NS_NewDOMBeforeUnloadEvent(nsIDOMEvent** aResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent); -nsresult -NS_NewDOMSVGEvent(nsIDOMEvent** aResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent); -nsresult -NS_NewDOMSVGZoomEvent(nsIDOMEvent** aResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::InternalSVGZoomEvent* aEvent); -nsresult -NS_NewDOMTimeEvent(nsIDOMEvent** aResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::InternalSMILTimeEvent* aEvent); -nsresult -NS_NewDOMXULCommandEvent(nsIDOMEvent** aResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetInputEvent* aEvent); -nsresult -NS_NewDOMCommandEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetCommandEvent* aEvent); -nsresult -NS_NewDOMMessageEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent); -// This empties aInvalidateRequests. -nsresult -NS_NewDOMNotifyPaintEvent(nsIDOMEvent** aResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent, - uint32_t aEventType = 0, - nsInvalidateRequestList* aInvalidateRequests = nullptr); -nsresult -NS_NewDOMSimpleGestureEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetSimpleGestureEvent* aEvent); -nsresult -NS_NewDOMScrollAreaEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::InternalScrollAreaEvent* aEvent); -nsresult -NS_NewDOMTransitionEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::InternalTransitionEvent* aEvent); -nsresult -NS_NewDOMAnimationEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::InternalAnimationEvent* aEvent); -nsresult -NS_NewDOMPointerEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetPointerEvent* aEvent); -nsresult -NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetTouchEvent* aEvent); -nsresult -NS_NewDOMCustomEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, - nsPresContext* aPresContext, - mozilla::WidgetEvent* aEvent); -%}
--- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -140,16 +140,22 @@ parent: sync PPluginWidget(); /** * Return native data of root widget */ sync GetWidgetNativeData() returns (WindowsHandle value); /** + * Sends an NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW to be adopted by the + * widget's shareable window on the chrome side. Only used on Windows. + */ + async SetNativeChildOfShareableWindow(uintptr_t childWindow); + + /** * When content moves focus from a native plugin window that's a child * of the native browser window we need to move native focus to the * browser. Otherwise the plugin window will never relinquish focus. */ sync DispatchFocusToTopLevelWindow(); parent: /**
--- a/dom/ipc/TabMessageUtils.cpp +++ b/dom/ipc/TabMessageUtils.cpp @@ -1,33 +1,30 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/EventDispatcher.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/TabMessageUtils.h" #include "nsCOMPtr.h" -#include "nsIDOMEvent.h" namespace mozilla { namespace dom { bool ReadRemoteEvent(const IPC::Message* aMsg, void** aIter, RemoteDOMEvent* aResult) { aResult->mEvent = nullptr; nsString type; NS_ENSURE_TRUE(ReadParam(aMsg, aIter, &type), false); - nsCOMPtr<nsIDOMEvent> event; - EventDispatcher::CreateEvent(nullptr, nullptr, nullptr, type, - getter_AddRefs(event)); - aResult->mEvent = do_QueryInterface(event); - NS_ENSURE_TRUE(aResult->mEvent, false); + aResult->mEvent = EventDispatcher::CreateEvent(nullptr, nullptr, nullptr, + type); return aResult->mEvent->Deserialize(aMsg, aIter); } } // namespace dom } // namespace mozilla
--- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -2533,16 +2533,34 @@ TabParent::RecvGetWidgetNativeData(Windo if (widget) { *aValue = reinterpret_cast<WindowsHandle>( widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW)); } return true; } bool +TabParent::RecvSetNativeChildOfShareableWindow(const uintptr_t& aChildWindow) +{ +#if defined(XP_WIN) + nsCOMPtr<nsIWidget> widget = GetTopLevelWidget(); + if (widget) { + // Note that this call will probably cause a sync native message to the + // process that owns the child window. + widget->SetNativeData(NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW, aChildWindow); + } + return true; +#else + NS_NOTREACHED( + "TabParent::RecvSetNativeChildOfShareableWindow not implemented!"); + return false; +#endif +} + +bool TabParent::RecvDispatchFocusToTopLevelWindow() { nsCOMPtr<nsIWidget> widget = GetTopLevelWidget(); if (widget) { widget->SetFocus(false); } return true; } @@ -3017,18 +3035,17 @@ bool TabParent::LayerTreeUpdate(bool aActive) { nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryInterface(mFrameElement); if (!target) { NS_WARNING("Could not locate target for layer tree message."); return true; } - nsCOMPtr<nsIDOMEvent> event; - NS_NewDOMEvent(getter_AddRefs(event), mFrameElement, nullptr, nullptr); + nsRefPtr<Event> event = NS_NewDOMEvent(mFrameElement, nullptr, nullptr); if (aActive) { event->InitEvent(NS_LITERAL_STRING("MozLayerTreeReady"), true, false); } else { event->InitEvent(NS_LITERAL_STRING("MozLayerTreeCleared"), true, false); } event->SetTrusted(true); event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true; bool dummy; @@ -3057,18 +3074,17 @@ bool TabParent::RecvRemotePaintIsReady() { nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryInterface(mFrameElement); if (!target) { NS_WARNING("Could not locate target for MozAfterRemotePaint message."); return true; } - nsCOMPtr<nsIDOMEvent> event; - NS_NewDOMEvent(getter_AddRefs(event), mFrameElement, nullptr, nullptr); + nsRefPtr<Event> event = NS_NewDOMEvent(mFrameElement, nullptr, nullptr); event->InitEvent(NS_LITERAL_STRING("MozAfterRemotePaint"), false, false); event->SetTrusted(true); event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true; bool dummy; mFrameElement->DispatchEvent(event, &dummy); return true; }
--- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -216,16 +216,17 @@ public: virtual bool RecvIsParentWindowMainWidgetVisible(bool* aIsVisible) override; virtual bool RecvShowTooltip(const uint32_t& aX, const uint32_t& aY, const nsString& aTooltip) override; virtual bool RecvHideTooltip() override; virtual bool RecvGetTabOffset(LayoutDeviceIntPoint* aPoint) override; virtual bool RecvGetDPI(float* aValue) override; virtual bool RecvGetDefaultScale(double* aValue) override; virtual bool RecvGetMaxTouchPoints(uint32_t* aTouchPoints) override; virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue) override; + virtual bool RecvSetNativeChildOfShareableWindow(const uintptr_t& childWindow) override; virtual bool RecvDispatchFocusToTopLevelWindow() override; virtual bool RecvZoomToRect(const uint32_t& aPresShellId, const ViewID& aViewId, const CSSRect& aRect) override; virtual bool RecvUpdateZoomConstraints(const uint32_t& aPresShellId, const ViewID& aViewId, const MaybeZoomConstraints& aConstraints) override; virtual bool RecvContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
--- a/dom/media/AbstractMediaDecoder.h +++ b/dom/media/AbstractMediaDecoder.h @@ -98,17 +98,17 @@ public: // Return true if the media layer supports seeking. virtual bool IsTransportSeekable() = 0; // Return true if the transport layer supports seeking. virtual bool IsMediaSeekable() = 0; virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags, MediaDecoderEventVisibility aEventVisibility) = 0; - virtual void QueueMetadata(int64_t aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) = 0; + virtual void QueueMetadata(const media::TimeUnit& aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) = 0; virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo, MediaDecoderEventVisibility aEventVisibility) = 0; virtual void RemoveMediaTracks() = 0; // May be called by the reader to notify this decoder that the metadata from // the media file has been read. Call on the decode thread only. virtual void OnReadMetadataCompleted() = 0;
--- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -633,17 +633,17 @@ double MediaDecoder::GetCurrentTime() } already_AddRefed<nsIPrincipal> MediaDecoder::GetCurrentPrincipal() { MOZ_ASSERT(NS_IsMainThread()); return mResource ? mResource->GetCurrentPrincipal() : nullptr; } -void MediaDecoder::QueueMetadata(int64_t aPublishTime, +void MediaDecoder::QueueMetadata(const TimeUnit& aPublishTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) { MOZ_ASSERT(OnDecodeTaskQueue()); GetReentrantMonitor().AssertCurrentThreadIn(); mDecoderStateMachine->QueueMetadata(aPublishTime, aInfo, aTags); }
--- a/dom/media/MediaDecoder.h +++ b/dom/media/MediaDecoder.h @@ -577,17 +577,17 @@ public: bool CanPlayThrough(); void SetAudioChannel(dom::AudioChannel aChannel) { mAudioChannel = aChannel; } dom::AudioChannel GetAudioChannel() { return mAudioChannel; } // Send a new set of metadata to the state machine, to be dispatched to the // main thread to be presented when the |currentTime| of the media is greater // or equal to aPublishTime. - void QueueMetadata(int64_t aPublishTime, + void QueueMetadata(const media::TimeUnit& aPublishTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) override; /****** * The following methods must only be called on the main * thread. ******/
--- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -1101,17 +1101,17 @@ void MediaDecoderStateMachine::UpdatePla } void MediaDecoderStateMachine::UpdatePlaybackPosition(int64_t aTime) { MOZ_ASSERT(OnTaskQueue()); UpdatePlaybackPositionInternal(aTime); bool fragmentEnded = mFragmentEndTime >= 0 && GetMediaTime() >= mFragmentEndTime; - mMetadataManager.DispatchMetadataIfNeeded(mDecoder, aTime); + mMetadataManager.DispatchMetadataIfNeeded(mDecoder, TimeUnit::FromMicroseconds(aTime)); if (fragmentEnded) { StopPlayback(); } } void MediaDecoderStateMachine::ClearPositionChangeFlag() { @@ -3002,17 +3002,17 @@ void MediaDecoderStateMachine::Preserves } bool MediaDecoderStateMachine::IsShutdown() { MOZ_ASSERT(OnTaskQueue()); return mIsShutdown; } -void MediaDecoderStateMachine::QueueMetadata(int64_t aPublishTime, +void MediaDecoderStateMachine::QueueMetadata(const TimeUnit& aPublishTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) { MOZ_ASSERT(OnDecodeTaskQueue()); AssertCurrentThreadInMonitor(); TimedMetadata* metadata = new TimedMetadata; metadata->mPublishTime = aPublishTime; metadata->mInfo = aInfo.forget();
--- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -327,17 +327,17 @@ public: void FinishStreamData(); bool HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs); bool HaveEnoughDecodedVideo(); // Returns true if the state machine has shutdown or is in the process of // shutting down. The decoder monitor must be held while calling this. bool IsShutdown(); - void QueueMetadata(int64_t aPublishTime, + void QueueMetadata(const media::TimeUnit& aPublishTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags); // Returns true if we're currently playing. The decoder monitor must // be held. bool IsPlaying() const; // Called when the reader may have acquired the hardware resources required
--- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -757,18 +757,18 @@ MediaFormatReader::OnAudioDemuxCompleted mAudio.mQueuedSamples.AppendElements(aSamples->mSamples); ScheduleUpdate(TrackInfo::kAudioTrack); } void MediaFormatReader::NotifyNewOutput(TrackType aTrack, MediaData* aSample) { MOZ_ASSERT(OnTaskQueue()); - LOGV("Received new sample time:%lld duration:%lld", - aSample->mTime, aSample->mDuration); + LOGV("Received new %s sample time:%lld duration:%lld", + TrackTypeToStr(aTrack), aSample->mTime, aSample->mDuration); auto& decoder = GetDecoderData(aTrack); if (!decoder.mOutputRequested) { LOG("MediaFormatReader produced output while flushing, discarding."); return; } decoder.mOutput.AppendElement(aSample); decoder.mNumSamplesOutput++; ScheduleUpdate(aTrack); @@ -810,17 +810,16 @@ MediaFormatReader::NotifyError(TrackType } void MediaFormatReader::NotifyWaitingForData(TrackType aTrack) { MOZ_ASSERT(OnTaskQueue()); auto& decoder = GetDecoderData(aTrack); decoder.mWaitingForData = true; - decoder.mNeedDraining = true; ScheduleUpdate(aTrack); } void MediaFormatReader::NotifyEndOfStream(TrackType aTrack) { MOZ_ASSERT(OnTaskQueue()); auto& decoder = GetDecoderData(aTrack); @@ -974,17 +973,17 @@ MediaFormatReader::DecodeDemuxedSamples( if (decoder.mNextStreamSourceID.isNothing() || decoder.mNextStreamSourceID.ref() != info->GetID()) { LOG("%s stream id has changed from:%d to:%d, draining decoder.", TrackTypeToStr(aTrack), decoder.mLastStreamSourceID, info->GetID()); decoder.mNeedDraining = true; decoder.mNextStreamSourceID = Some(info->GetID()); - DrainDecoder(aTrack); + ScheduleUpdate(aTrack); return; } LOG("%s stream id has changed from:%d to:%d, recreating decoder.", TrackTypeToStr(aTrack), decoder.mLastStreamSourceID, info->GetID()); decoder.mInfo = info; decoder.mLastStreamSourceID = info->GetID(); @@ -1089,16 +1088,22 @@ MediaFormatReader::Update(TrackType aTra auto& decoder = GetDecoderData(aTrack); decoder.mUpdateScheduled = false; if (UpdateReceivedNewData(aTrack)) { LOGV("Nothing more to do"); return; } + if (!decoder.HasPromise() && decoder.mWaitingForData) { + // Nothing more we can do at present. + LOGV("Still waiting for data."); + return; + } + // Record number of frames decoded and parsed. Automatically update the // stats counters using the AutoNotifyDecoded stack-based class. AbstractMediaDecoder::AutoNotifyDecoded a(mDecoder); if (aTrack == TrackInfo::kVideoTrack) { uint64_t delta = decoder.mNumSamplesOutput - mLastReportedNumDecodedFrames; a.mDecoded = static_cast<uint32_t>(delta); @@ -1133,42 +1138,43 @@ MediaFormatReader::Update(TrackType aTra decoder.mDrainComplete = false; decoder.mDraining = false; if (decoder.mError) { LOG("Decoding Error"); decoder.RejectPromise(DECODE_ERROR, __func__); return; } else if (decoder.mDemuxEOS) { decoder.RejectPromise(END_OF_STREAM, __func__); - } else if (decoder.mWaitingForData) { - LOG("Waiting For Data"); - decoder.RejectPromise(WAITING_FOR_DATA, __func__); } } else if (decoder.mError && !decoder.mDecoder) { decoder.RejectPromise(DECODE_ERROR, __func__); return; + } else if (decoder.mWaitingForData) { + LOG("Waiting For Data"); + decoder.RejectPromise(WAITING_FOR_DATA, __func__); + return; } } - if (decoder.mError || decoder.mDemuxEOS || decoder.mWaitingForData) { + if (decoder.mNeedDraining) { DrainDecoder(aTrack); return; } if (!NeedInput(decoder)) { LOGV("No need for additional input"); return; } needInput = true; - LOGV("Update(%s) ni=%d no=%d ie=%d, in:%d out:%d qs=%d sid:%d", + LOGV("Update(%s) ni=%d no=%d ie=%d, in:%llu out:%llu qs=%u sid:%u", TrackTypeToStr(aTrack), needInput, needOutput, decoder.mInputExhausted, decoder.mNumSamplesInput, decoder.mNumSamplesOutput, - size_t(decoder.mSizeOfQueue), decoder.mLastStreamSourceID); + uint32_t(size_t(decoder.mSizeOfQueue)), decoder.mLastStreamSourceID); // Demux samples if we don't have some. RequestDemuxSamples(aTrack); // Decode all pending demuxed samples. DecodeDemuxedSamples(aTrack, a); } void
--- a/dom/media/MediaMetadataManager.h +++ b/dom/media/MediaMetadataManager.h @@ -1,68 +1,74 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=2 sw=2 sts=2 et cindent: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #if !defined(MediaMetadataManager_h__) #define MediaMetadataManager_h__ -#include "VideoUtils.h" + #include "mozilla/LinkedList.h" + +#include "nsAutoPtr.h" #include "AbstractMediaDecoder.h" -#include "nsAutoPtr.h" +#include "TimeUnits.h" +#include "VideoUtils.h" namespace mozilla { - // A struct that contains the metadata of a media, and the time at which those - // metadata should start to be reported. - class TimedMetadata : public LinkedListElement<TimedMetadata> { - public: - // The time, in microseconds, at which those metadata should be available. - int64_t mPublishTime; - // The metadata. The ownership is transfered to the element when dispatching to - // the main threads. - nsAutoPtr<MetadataTags> mTags; - // The media info, including the info of audio tracks and video tracks. - // The ownership is transfered to MediaDecoder when dispatching to the - // main thread. - nsAutoPtr<MediaInfo> mInfo; - }; +// A struct that contains the metadata of a media, and the time at which those +// metadata should start to be reported. +class TimedMetadata : public LinkedListElement<TimedMetadata> { +public: + // The time, in microseconds, at which those metadata should be available. + media::TimeUnit mPublishTime; + // The metadata. The ownership is transfered to the element when dispatching to + // the main threads. + nsAutoPtr<MetadataTags> mTags; + // The media info, including the info of audio tracks and video tracks. + // The ownership is transfered to MediaDecoder when dispatching to the + // main thread. + nsAutoPtr<MediaInfo> mInfo; +}; + +// This class encapsulate the logic to give the metadata from the reader to +// the content, at the right time. +class MediaMetadataManager +{ +public: + ~MediaMetadataManager() { + TimedMetadata* element; + while((element = mMetadataQueue.popFirst()) != nullptr) { + delete element; + } + } - // This class encapsulate the logic to give the metadata from the reader to - // the content, at the right time. - class MediaMetadataManager - { - public: - ~MediaMetadataManager() { - TimedMetadata* element; - while((element = mMetadataQueue.popFirst()) != nullptr) { - delete element; - } - } - void QueueMetadata(TimedMetadata* aMetadata) { - mMetadataQueue.insertBack(aMetadata); - } + void QueueMetadata(TimedMetadata* aMetadata) { + mMetadataQueue.insertBack(aMetadata); + } + + void DispatchMetadataIfNeeded(AbstractMediaDecoder* aDecoder, const media::TimeUnit& aCurrentTime) { + TimedMetadata* metadata = mMetadataQueue.getFirst(); + while (metadata && aCurrentTime >= metadata->mPublishTime) { + // Remove all media tracks from the list first. + nsCOMPtr<nsIRunnable> removeTracksEvent = + new RemoveMediaTracksEventRunner(aDecoder); + NS_DispatchToMainThread(removeTracksEvent); - void DispatchMetadataIfNeeded(AbstractMediaDecoder* aDecoder, double aCurrentTime) { - TimedMetadata* metadata = mMetadataQueue.getFirst(); - while (metadata && aCurrentTime >= static_cast<double>(metadata->mPublishTime) / USECS_PER_S) { - // Remove all media tracks from the list first. - nsCOMPtr<nsIRunnable> removeTracksEvent = - new RemoveMediaTracksEventRunner(aDecoder); - NS_DispatchToMainThread(removeTracksEvent); + nsCOMPtr<nsIRunnable> metadataUpdatedEvent = + new MetadataUpdatedEventRunner(aDecoder, + metadata->mInfo, + metadata->mTags); + NS_DispatchToMainThread(metadataUpdatedEvent); + delete mMetadataQueue.popFirst(); + metadata = mMetadataQueue.getFirst(); + } + } - nsCOMPtr<nsIRunnable> metadataUpdatedEvent = - new MetadataUpdatedEventRunner(aDecoder, - metadata->mInfo, - metadata->mTags); - NS_DispatchToMainThread(metadataUpdatedEvent); - delete mMetadataQueue.popFirst(); - metadata = mMetadataQueue.getFirst(); - } - } - protected: - LinkedList<TimedMetadata> mMetadataQueue; - }; +protected: + LinkedList<TimedMetadata> mMetadataQueue; +}; + } // namespace mozilla #endif
--- a/dom/media/MediaRecorder.cpp +++ b/dom/media/MediaRecorder.cpp @@ -1025,22 +1025,17 @@ void MediaRecorder::DispatchSimpleEvent(const nsAString & aStr) { MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread"); nsresult rv = CheckInnerWindowCorrectness(); if (NS_FAILED(rv)) { return; } - nsCOMPtr<nsIDOMEvent> event; - rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to create the error event!!!"); - return; - } + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); rv = event->InitEvent(aStr, false, false); if (NS_FAILED(rv)) { NS_WARNING("Failed to init the error event!!!"); return; } event->SetTrusted(true);
--- a/dom/media/MediaResource.cpp +++ b/dom/media/MediaResource.cpp @@ -1109,17 +1109,16 @@ bool ChannelMediaResource::IsSuspendedByCache() { return mCacheStream.AreAllStreamsForResourceSuspended(); } bool ChannelMediaResource::IsSuspended() { - MutexAutoLock lock(mLock); return mSuspendCount > 0; } void ChannelMediaResource::SetReadMode(MediaCacheStream::ReadMode aMode) { mCacheStream.SetReadMode(aMode); }
--- a/dom/media/MediaResource.h +++ b/dom/media/MediaResource.h @@ -11,16 +11,17 @@ #include "nsIURI.h" #include "nsISeekableStream.h" #include "nsIStreamingProtocolController.h" #include "nsIStreamListener.h" #include "nsIChannelEventSink.h" #include "nsIInterfaceRequestor.h" #include "MediaCache.h" #include "MediaData.h" +#include "mozilla/Atomics.h" #include "mozilla/Attributes.h" #include "mozilla/TimeStamp.h" #include "nsThreadUtils.h" #include <algorithm> // For HTTP seeking, if number of bytes needing to be // seeked forward is less than this value then a read is // done rather than a byte range request. @@ -773,17 +774,17 @@ protected: void PossiblyResume(); // Main thread access only int64_t mOffset; nsRefPtr<Listener> mListener; // A data received event for the decoder that has been dispatched but has // not yet been processed. nsRevocableEventPtr<nsRunnableMethod<ChannelMediaResource, void, false> > mDataReceivedEvent; - uint32_t mSuspendCount; + Atomic<uint32_t> mSuspendCount; // When this flag is set, if we get a network error we should silently // reopen the stream. bool mReopenOnError; // When this flag is set, we should not report the next close of the // channel. bool mIgnoreClose; // Any thread access
--- a/dom/media/TextTrackList.cpp +++ b/dom/media/TextTrackList.cpp @@ -155,24 +155,19 @@ nsresult TextTrackList::DispatchTrackEvent(nsIDOMEvent* aEvent) { return DispatchTrustedEvent(aEvent); } void TextTrackList::CreateAndDispatchChangeEvent() { - nsCOMPtr<nsIDOMEvent> event; - nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to create the error event!"); - return; - } + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); - rv = event->InitEvent(NS_LITERAL_STRING("change"), false, false); + nsresult rv = event->InitEvent(NS_LITERAL_STRING("change"), false, false); if (NS_FAILED(rv)) { NS_WARNING("Failed to init the change event!"); return; } event->SetTrusted(true); nsCOMPtr<nsIRunnable> eventRunner = new TrackEventRunner(this, event);
--- a/dom/media/mediasource/SourceBufferDecoder.cpp +++ b/dom/media/mediasource/SourceBufferDecoder.cpp @@ -95,17 +95,17 @@ SourceBufferDecoder::MetadataLoaded(nsAu void SourceBufferDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo, MediaDecoderEventVisibility aEventVisibility) { MSE_DEBUG("UNIMPLEMENTED"); } void -SourceBufferDecoder::QueueMetadata(int64_t aTime, +SourceBufferDecoder::QueueMetadata(const media::TimeUnit& aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) { MSE_DEBUG("UNIMPLEMENTED"); } void SourceBufferDecoder::RemoveMediaTracks()
--- a/dom/media/mediasource/SourceBufferDecoder.h +++ b/dom/media/mediasource/SourceBufferDecoder.h @@ -46,17 +46,17 @@ public: MediaDecoderEventVisibility aEventVisibility) final override; virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo, MediaDecoderEventVisibility aEventVisibility) final override; virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) final override; virtual void NotifyDataArrived(uint32_t aLength, int64_t aOffset, bool aThrottleUpdates) final override; virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded, uint32_t aDropped) final override; virtual void NotifyWaitingForResourcesStatusChanged() final override; virtual void OnReadMetadataCompleted() final override; - virtual void QueueMetadata(int64_t aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) final override; + virtual void QueueMetadata(const media::TimeUnit& aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) final override; virtual void RemoveMediaTracks() final override; virtual void SetMediaSeekable(bool aMediaSeekable) final override; virtual bool HasInitializationData() final override; // SourceBufferResource specific interface below. int64_t GetTimestampOffset() const { return mTimestampOffset; } void SetTimestampOffset(int64_t aOffset) { mTimestampOffset = aOffset; }
--- a/dom/media/mediasource/TrackBuffersManager.cpp +++ b/dom/media/mediasource/TrackBuffersManager.cpp @@ -1615,18 +1615,16 @@ TrackBuffersManager::RemoveFrames(const TimeUnit::FromMicroseconds(sample->GetEndTime())); removedIntervals += sampleInterval; if (sample->mDuration > maxSampleDuration) { maxSampleDuration = sample->mDuration; } aTrackData.mSizeBuffer -= sample->ComputedSizeOfIncludingThis(); } - removedIntervals.SetFuzz(TimeUnit::FromMicroseconds(maxSampleDuration)); - MSE_DEBUG("Removing frames from:%u (frames:%u) ([%f, %f))", firstRemovedIndex.ref(), lastRemovedIndex - firstRemovedIndex.ref() + 1, removedIntervals.GetStart().ToSeconds(), removedIntervals.GetEnd().ToSeconds()); if (aTrackData.mNextGetSampleIndex.isSome()) { if (aTrackData.mNextGetSampleIndex.ref() >= firstRemovedIndex.ref() &&
--- a/dom/media/mediasource/test/mochitest.ini +++ b/dom/media/mediasource/test/mochitest.ini @@ -35,28 +35,28 @@ support-files = bipbop/bipbop13.m4s^headers^ bipbop/bipbop_video13.m4s^headers^ [test_BufferedSeek.html] [test_BufferedSeek_mp4.html] skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+ [test_BufferingWait.html] skip-if = true # bug 1190776 [test_BufferingWait_mp4.html] -skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+ +skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac") || (os == "win" && os_version == "6.1")) # Only supported on osx and vista+, disabling on win7 bug 1191138 [test_EndOfStream.html] skip-if = (true || toolkit == 'android' || buildapp == 'mulet') #timeout android/mulet only bug 1101187 and bug 1182946 [test_EndOfStream_mp4.html] skip-if = (toolkit == 'android' || buildapp == 'mulet') || ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+ [test_DurationUpdated.html] [test_DurationUpdated_mp4.html] skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+ [test_FrameSelection.html] [test_HaveMetadataUnbufferedSeek.html] [test_HaveMetadataUnbufferedSeek_mp4.html] -skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+ +skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac") || (os == "win" && os_version == "6.1")) # Only supported on osx and vista+, disabling on win7 bug 1191138 [test_LoadedMetadataFired.html] [test_LoadedMetadataFired_mp4.html] skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+ [test_MediaSource.html] [test_MediaSource_mp4.html] skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+ [test_MediaSource_disabled.html] [test_MultipleInitSegments.html] @@ -84,15 +84,16 @@ skip-if = ((os == "win" && os_version == skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+ [test_SplitAppend.html] [test_SplitAppend_mp4.html] skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+ [test_TimestampOffset_mp4.html] skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+ [test_TruncatedDuration.html] [test_TruncatedDuration_mp4.html] -skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+ +skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac") || (os == "win" && os_version == "6.1")) # Only supported on osx and vista+, disabling on win7 bug 1191138 [test_WaitingOnMissingData.html] skip-if = true # Disabled due to bug 1124493 and friends. WebM MSE is deprioritized. [test_WaitingOnMissingData_mp4.html] -skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+ +skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac") || (os == "win" && os_version == "6.1")) # Only supported on osx and vista+, disabling on win7 bug 1191138 [test_WaitingToEndedTransition_mp4.html] -skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+ +skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac") || (os == "win" && os_version == "6.1")) # Only supported on osx and vista+, disabling on win7 bug 1191138 +
--- a/dom/media/mediasource/test/test_BufferingWait_mp4.html +++ b/dom/media/mediasource/test/test_BufferingWait_mp4.html @@ -36,24 +36,28 @@ runWithMSE(function(ms, v) { sb.addEventListener('error', (e) => { ok(false, "Got Error: " + e); SimpleTest.finish(); }); fetchAndLoad(sb, 'bipbop/bipbop', ['init'], '.mp4') .then(fetchAndLoad.bind(null, sb, 'bipbop/bipbop', ['1'], '.m4s')) .then(fetchAndLoad.bind(null, sb, 'bipbop/bipbop', ['2'], '.m4s')) /* Note - Missing |bipbop3| segment here corresponding to (1.62, 2.41] */ /* Note - Missing |bipbop4| segment here corresponding to (2.41, 3.20] */ .then(fetchAndLoad.bind(null, sb, 'bipbop/bipbop', ['5'], '.m4s')) .then(function() { - var promise = waitUntilTime(1.4); + // Some decoders (Windows in particular) may keep up to 25 frames queued + // before returning a sample. 0.7 is 1.62s - 25 * 0.03333 + var promise = waitUntilTime(0.7); info("Playing video. It should play for a bit, then fire 'waiting'"); v.play(); return promise; }).then(function() { window.firstStop = Date.now(); fetchAndLoad(sb, 'bipbop/bipbop', ['3'], '.m4s'); - return waitUntilTime(2.2); + // Some decoders (Windows in particular) may keep up to 25 frames queued + // before returning a sample. 1.5 is 2.41s - 25 * 0.03333 + return waitUntilTime(1.5); }).then(function() { var waitDuration = (Date.now() - window.firstStop) / 1000; ok(waitDuration < 15, "Should not spend an inordinate amount of time buffering: " + waitDuration); once(v, 'ended', SimpleTest.finish.bind(SimpleTest)); return fetchAndLoad(sb, 'bipbop/bipbop', ['4'], '.m4s'); }).then(function() { ms.endOfStream(); });;
--- a/dom/media/mediasource/test/test_WaitingOnMissingData_mp4.html +++ b/dom/media/mediasource/test/test_WaitingOnMissingData_mp4.html @@ -35,18 +35,19 @@ runWithMSE(function(ms, el) { ok(true, "Video playing. It should play for a bit, then fire 'waiting'"); var p = once(el, 'waiting'); el.play(); return p; }).then(function() { // currentTime is based on the current video frame, so if the audio ends just before // the next video frame, currentTime can be up to 1 frame's worth earlier than // min(audioEnd, videoEnd). + // Some decoders (Windows in particular) may keep up to 25 frames queued. isfuzzy(el.currentTime, Math.min(audiosb.buffered.end(0), videosb.buffered.end(0)) - 1/60, - 1/30, "Got a waiting event at " + el.currentTime); + 25 * 1/30, "Got a waiting event at " + el.currentTime); info("Loading more data"); var p = once(el, 'ended'); var loads = Promise.all([fetchAndLoad(audiosb, 'bipbop/bipbop_audio', [5], '.m4s'), fetchAndLoad(videosb, 'bipbop/bipbop_video', [6], '.m4s')]); loads.then(() => ms.endOfStream()); return p; }).then(function() { // These fuzz factors are bigger than they should be. We should investigate
--- a/dom/media/mediasource/test/test_WaitingToEndedTransition_mp4.html +++ b/dom/media/mediasource/test/test_WaitingToEndedTransition_mp4.html @@ -33,18 +33,19 @@ runWithMSE(function(ms, el) { ok(true, "Video playing. It should play for a bit, then fire 'waiting'"); var p = once(el, 'waiting'); el.play(); return p; }).then(function() { // currentTime is based on the current video frame, so if the audio ends just before // the next video frame, currentTime can be up to 1 frame's worth earlier than // min(audioEnd, videoEnd). + // Some decoders (Windows in particular) may keep up to 25 frames queued. isfuzzy(el.currentTime, Math.min(audiosb.buffered.end(0), videosb.buffered.end(0)) - 1/60, - 1/30, "Got a waiting event at " + el.currentTime); + 25 * 1/30, "Got a waiting event at " + el.currentTime); }).then(function() { var p = once(el, 'ended'); ms.endOfStream(); return p; }).then(function() { is(el.duration, 4.005, "Video has correct duration: " + el.duration); is(el.currentTime, el.duration, "Video has correct currentTime."); SimpleTest.finish();
--- a/dom/media/ogg/OggReader.cpp +++ b/dom/media/ogg/OggReader.cpp @@ -809,21 +809,20 @@ bool OggReader::ReadOggChain() chained = true; tags = newOpusState->GetTags(); } if (chained) { SetChained(true); { - nsAutoPtr<MediaInfo> info(new MediaInfo()); - *info = mInfo; + nsAutoPtr<MediaInfo> info(new MediaInfo(mInfo)); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); - mDecoder->QueueMetadata((mDecodedAudioFrames * USECS_PER_S) / mInfo.mAudio.mRate, - info, tags); + auto t = mDecodedAudioFrames * USECS_PER_S / mInfo.mAudio.mRate; + mDecoder->QueueMetadata(media::TimeUnit::FromMicroseconds(t), info, tags); } return true; } return false; } nsresult OggReader::DecodeTheora(ogg_packet* aPacket, int64_t aTimeThreshold)
--- a/dom/media/platforms/apple/AppleUtils.h +++ b/dom/media/platforms/apple/AppleUtils.h @@ -38,11 +38,61 @@ public: } private: // Copy operator isn't supported and is not implemented. AutoCFRelease<T>& operator=(const AutoCFRelease<T>&); T mRef; }; +// CFRefPtr: A CoreFoundation smart pointer. +template <class T> +class CFRefPtr { +public: + explicit CFRefPtr(T aRef) + : mRef(aRef) + { + if (mRef) { + CFRetain(mRef); + } + } + // Copy constructor. + CFRefPtr(const CFRefPtr<T>& aCFRefPtr) + : mRef(aCFRefPtr.mRef) + { + if (mRef) { + CFRetain(mRef); + } + } + // Copy operator + CFRefPtr<T>& operator=(const CFRefPtr<T>& aCFRefPtr) + { + if (mRef == aCFRefPtr.mRef) { + return; + } + if (mRef) { + CFRelease(mRef); + } + mRef = aCFRefPtr.mRef; + if (mRef) { + CFRetain(mRef); + } + return *this; + } + ~CFRefPtr() + { + if (mRef) { + CFRelease(mRef); + } + } + // Return the wrapped ref so it can be used as an in parameter. + operator T() + { + return mRef; + } + +private: + T mRef; +}; + } // namespace mozilla #endif // mozilla_AppleUtils_h
--- a/dom/media/platforms/apple/AppleVDADecoder.cpp +++ b/dom/media/platforms/apple/AppleVDADecoder.cpp @@ -35,18 +35,22 @@ AppleVDADecoder::AppleVDADecoder(const V layers::ImageContainer* aImageContainer) : mTaskQueue(aVideoTaskQueue) , mCallback(aCallback) , mImageContainer(aImageContainer) , mPictureWidth(aConfig.mImage.width) , mPictureHeight(aConfig.mImage.height) , mDisplayWidth(aConfig.mDisplay.width) , mDisplayHeight(aConfig.mDisplay.height) + , mInputIncoming(0) + , mIsShutDown(false) , mUseSoftwareImages(false) , mIs106(!nsCocoaFeatures::OnLionOrLater()) + , mMonitor("AppleVideoDecoder") + , mIsFlushing(false) , mDecoder(nullptr) { MOZ_COUNT_CTOR(AppleVDADecoder); // TODO: Verify aConfig.mime_type. mExtraData = aConfig.mExtraData; mMaxRefFrames = 4; // Retrieve video dimensions from H264 SPS NAL. @@ -77,69 +81,116 @@ nsRefPtr<MediaDataDecoder::InitPromise> AppleVDADecoder::Init() { return InitPromise::CreateAndResolve(TrackType::kVideoTrack, __func__); } nsresult AppleVDADecoder::Shutdown() { + MOZ_DIAGNOSTIC_ASSERT(!mIsShutDown); + mIsShutDown = true; + if (mTaskQueue) { + nsCOMPtr<nsIRunnable> runnable = + NS_NewRunnableMethod(this, &AppleVDADecoder::ProcessShutdown); + mTaskQueue->Dispatch(runnable.forget()); + } else { + ProcessShutdown(); + } + return NS_OK; +} + +void +AppleVDADecoder::ProcessShutdown() +{ if (mDecoder) { LOG("%s: cleaning up decoder %p", __func__, mDecoder); VDADecoderDestroy(mDecoder); mDecoder = nullptr; } - return NS_OK; } nsresult AppleVDADecoder::Input(MediaRawData* aSample) { + MOZ_ASSERT(mCallback->OnReaderTaskQueue()); + LOG("mp4 input sample %p pts %lld duration %lld us%s %d bytes", aSample, aSample->mTime, aSample->mDuration, aSample->mKeyframe ? " keyframe" : "", aSample->Size()); + mInputIncoming++; + nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>( this, &AppleVDADecoder::SubmitFrame, nsRefPtr<MediaRawData>(aSample)); mTaskQueue->Dispatch(runnable.forget()); return NS_OK; } nsresult AppleVDADecoder::Flush() { + MOZ_ASSERT(mCallback->OnReaderTaskQueue()); + mIsFlushing = true; mTaskQueue->Flush(); + nsCOMPtr<nsIRunnable> runnable = + NS_NewRunnableMethod(this, &AppleVDADecoder::ProcessFlush); + MonitorAutoLock mon(mMonitor); + mTaskQueue->Dispatch(runnable.forget()); + while (mIsFlushing) { + mon.Wait(); + } + mInputIncoming = 0; + return NS_OK; +} + +nsresult +AppleVDADecoder::Drain() +{ + MOZ_ASSERT(mCallback->OnReaderTaskQueue()); + nsCOMPtr<nsIRunnable> runnable = + NS_NewRunnableMethod(this, &AppleVDADecoder::ProcessDrain); + mTaskQueue->Dispatch(runnable.forget()); + return NS_OK; +} + +void +AppleVDADecoder::ProcessFlush() +{ + MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); + OSStatus rv = VDADecoderFlush(mDecoder, 0 /*dont emit*/); if (rv != noErr) { LOG("AppleVDADecoder::Flush failed waiting for platform decoder " "with error:%d.", rv); } ClearReorderedFrames(); - - return NS_OK; + MonitorAutoLock mon(mMonitor); + mIsFlushing = false; + mon.NotifyAll(); } -nsresult -AppleVDADecoder::Drain() +void +AppleVDADecoder::ProcessDrain() { - mTaskQueue->AwaitIdle(); + MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); + OSStatus rv = VDADecoderFlush(mDecoder, kVDADecoderFlush_EmitFrames); if (rv != noErr) { LOG("AppleVDADecoder::Drain failed waiting for platform decoder " "with error:%d.", rv); } DrainReorderedFrames(); mCallback->DrainComplete(); - return NS_OK; } // // Implementation details. // // Callback passed to the VideoToolbox decoder for returning data. // This needs to be static because the API takes a C-style pair of @@ -194,27 +245,29 @@ PlatformCallback(void* decompressionOutp char is_sync_point; CFNumberGetValue(ptsref, kCFNumberSInt64Type, &pts); CFNumberGetValue(dtsref, kCFNumberSInt64Type, &dts); CFNumberGetValue(durref, kCFNumberSInt64Type, &duration); CFNumberGetValue(boref, kCFNumberSInt64Type, &byte_offset); CFNumberGetValue(kfref, kCFNumberSInt8Type, &is_sync_point); - nsAutoPtr<AppleVDADecoder::AppleFrameRef> frameRef( - new AppleVDADecoder::AppleFrameRef( + AppleVDADecoder::AppleFrameRef frameRef( media::TimeUnit::FromMicroseconds(dts), media::TimeUnit::FromMicroseconds(pts), media::TimeUnit::FromMicroseconds(duration), byte_offset, - is_sync_point == 1)); + is_sync_point == 1); // Forward the data back to an object method which can access - // the correct MP4Reader callback. - decoder->OutputFrame(image, frameRef); + // the correct reader's callback. + nsCOMPtr<nsIRunnable> task = + NS_NewRunnableMethodWithArgs<CFRefPtr<CVPixelBufferRef>, AppleVDADecoder::AppleFrameRef>( + decoder, &AppleVDADecoder::OutputFrame, image, frameRef); + decoder->DispatchOutputTask(task.forget()); } AppleVDADecoder::AppleFrameRef* AppleVDADecoder::CreateAppleFrameRef(const MediaRawData* aSample) { MOZ_ASSERT(aSample); return new AppleFrameRef(*aSample); } @@ -232,25 +285,32 @@ AppleVDADecoder::ClearReorderedFrames() { while (!mReorderQueue.IsEmpty()) { mReorderQueue.Pop(); } } // Copy and return a decoded frame. nsresult -AppleVDADecoder::OutputFrame(CVPixelBufferRef aImage, - nsAutoPtr<AppleVDADecoder::AppleFrameRef> aFrameRef) +AppleVDADecoder::OutputFrame(CFRefPtr<CVPixelBufferRef> aImage, + AppleVDADecoder::AppleFrameRef aFrameRef) { + MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); + + if (mIsFlushing) { + // We are in the process of flushing; ignore frame. + return NS_OK; + } + LOG("mp4 output frame %lld dts %lld pts %lld duration %lld us%s", - aFrameRef->byte_offset, - aFrameRef->decode_timestamp.ToMicroseconds(), - aFrameRef->composition_timestamp.ToMicroseconds(), - aFrameRef->duration.ToMicroseconds(), - aFrameRef->is_sync_point ? " keyframe" : "" + aFrameRef.byte_offset, + aFrameRef.decode_timestamp.ToMicroseconds(), + aFrameRef.composition_timestamp.ToMicroseconds(), + aFrameRef.duration.ToMicroseconds(), + aFrameRef.is_sync_point ? " keyframe" : "" ); // Where our resulting image will end up. nsRefPtr<VideoData> data; // Bounds. VideoInfo info; info.mDisplay = nsIntSize(mDisplayWidth, mDisplayHeight); gfx::IntRect visible = gfx::IntRect(0, @@ -298,22 +358,22 @@ AppleVDADecoder::OutputFrame(CVPixelBuff buffer.mPlanes[2].mOffset = 1; buffer.mPlanes[2].mSkip = 1; // Copy the image data into our own format. data = VideoData::Create(info, mImageContainer, nullptr, - aFrameRef->byte_offset, - aFrameRef->composition_timestamp.ToMicroseconds(), - aFrameRef->duration.ToMicroseconds(), + aFrameRef.byte_offset, + aFrameRef.composition_timestamp.ToMicroseconds(), + aFrameRef.duration.ToMicroseconds(), buffer, - aFrameRef->is_sync_point, - aFrameRef->decode_timestamp.ToMicroseconds(), + aFrameRef.is_sync_point, + aFrameRef.decode_timestamp.ToMicroseconds(), visible); // Unlock the returned image data. CVPixelBufferUnlockBaseAddress(aImage, kCVPixelBufferLock_ReadOnly); } else { IOSurfacePtr surface = MacIOSurfaceLib::CVPixelBufferGetIOSurface(aImage); MOZ_ASSERT(surface, "Decoder didn't return an IOSurface backed buffer"); nsRefPtr<MacIOSurface> macSurface = new MacIOSurface(surface); @@ -322,22 +382,22 @@ AppleVDADecoder::OutputFrame(CVPixelBuff mImageContainer->CreateImage(ImageFormat::MAC_IOSURFACE); layers::MacIOSurfaceImage* videoImage = static_cast<layers::MacIOSurfaceImage*>(image.get()); videoImage->SetSurface(macSurface); data = VideoData::CreateFromImage(info, mImageContainer, - aFrameRef->byte_offset, - aFrameRef->composition_timestamp.ToMicroseconds(), - aFrameRef->duration.ToMicroseconds(), + aFrameRef.byte_offset, + aFrameRef.composition_timestamp.ToMicroseconds(), + aFrameRef.duration.ToMicroseconds(), image.forget(), - aFrameRef->is_sync_point, - aFrameRef->decode_timestamp.ToMicroseconds(), + aFrameRef.is_sync_point, + aFrameRef.decode_timestamp.ToMicroseconds(), visible); } if (!data) { NS_ERROR("Couldn't create VideoData for frame"); mCallback->Error(); return NS_ERROR_FAILURE; } @@ -352,16 +412,20 @@ AppleVDADecoder::OutputFrame(CVPixelBuff static_cast<unsigned long long>(mReorderQueue.Length())); return NS_OK; } nsresult AppleVDADecoder::SubmitFrame(MediaRawData* aSample) { + MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); + + mInputIncoming--; + AutoCFRelease<CFDataRef> block = CFDataCreate(kCFAllocatorDefault, aSample->Data(), aSample->Size()); if (!block) { NS_ERROR("Couldn't create CFData"); return NS_ERROR_FAILURE; } AutoCFRelease<CFNumberRef> pts = @@ -425,17 +489,17 @@ AppleVDADecoder::SubmitFrame(MediaRawDat // This dictionary can contain client provided information associated with // the frame being decoded, for example presentation time. // The CFDictionaryRef will be retained by the framework. // In 10.6, it is released one too many. So retain it. CFRetain(frameInfo); } // Ask for more data. - if (mTaskQueue->IsEmpty()) { + if (!mInputIncoming) { LOG("AppleVDADecoder task queue empty; requesting more data"); mCallback->InputExhausted(); } return NS_OK; } nsresult
--- a/dom/media/platforms/apple/AppleVDADecoder.h +++ b/dom/media/platforms/apple/AppleVDADecoder.h @@ -3,16 +3,17 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_AppleVDADecoder_h #define mozilla_AppleVDADecoder_h #include "PlatformDecoderModule.h" +#include "mozilla/Atomics.h" #include "mozilla/ReentrantMonitor.h" #include "MP4Decoder.h" #include "nsIThread.h" #include "ReorderQueue.h" #include "TimeUnits.h" #include "VideoDecodeAcceleration/VDADecoder.h" @@ -75,45 +76,70 @@ public: virtual nsresult Flush() override; virtual nsresult Drain() override; virtual nsresult Shutdown() override; virtual bool IsHardwareAccelerated() const override { return true; } - nsresult OutputFrame(CVPixelBufferRef aImage, - nsAutoPtr<AppleFrameRef> aFrameRef); + void DispatchOutputTask(already_AddRefed<nsIRunnable> aTask) + { + nsCOMPtr<nsIRunnable> task = aTask; + if (mIsShutDown || mIsFlushing) { + return; + } + mTaskQueue->Dispatch(task.forget()); + } - // Method to set up the decompression session. - nsresult InitializeSession(); + nsresult OutputFrame(CFRefPtr<CVPixelBufferRef> aImage, + AppleFrameRef aFrameRef); - protected: +protected: + // Flush and Drain operation, always run + virtual void ProcessFlush(); + virtual void ProcessDrain(); + virtual void ProcessShutdown(); + AppleFrameRef* CreateAppleFrameRef(const MediaRawData* aSample); void DrainReorderedFrames(); void ClearReorderedFrames(); CFDictionaryRef CreateOutputConfiguration(); - nsresult InitDecoder(); nsRefPtr<MediaByteBuffer> mExtraData; nsRefPtr<FlushableTaskQueue> mTaskQueue; MediaDataDecoderCallback* mCallback; nsRefPtr<layers::ImageContainer> mImageContainer; ReorderQueue mReorderQueue; uint32_t mPictureWidth; uint32_t mPictureHeight; uint32_t mDisplayWidth; uint32_t mDisplayHeight; uint32_t mMaxRefFrames; + // Increased when Input is called, and decreased when ProcessFrame runs. + // Reaching 0 indicates that there's no pending Input. + Atomic<uint32_t> mInputIncoming; + Atomic<bool> mIsShutDown; + bool mUseSoftwareImages; bool mIs106; + // For wait on mIsFlushing during Shutdown() process. + Monitor mMonitor; + // Set on reader/decode thread calling Flush() to indicate that output is + // not required and so input samples on mTaskQueue need not be processed. + // Cleared on mTaskQueue in ProcessDrain(). + Atomic<bool> mIsFlushing; + private: VDADecoder mDecoder; + // Method to set up the decompression session. + nsresult InitializeSession(); + // Method to pass a frame to VideoToolbox for decoding. nsresult SubmitFrame(MediaRawData* aSample); CFDictionaryRef CreateDecoderSpecification(); }; } // namespace mozilla #endif // mozilla_AppleVDADecoder_h
--- a/dom/media/platforms/apple/AppleVTDecoder.cpp +++ b/dom/media/platforms/apple/AppleVTDecoder.cpp @@ -58,36 +58,37 @@ AppleVTDecoder::Init() if (NS_SUCCEEDED(rv)) { return InitPromise::CreateAndResolve(TrackType::kVideoTrack, __func__); } return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__); } -nsresult -AppleVTDecoder::Shutdown() +void +AppleVTDecoder::ProcessShutdown() { if (mSession) { LOG("%s: cleaning up session %p", __func__, mSession); VTDecompressionSessionInvalidate(mSession); CFRelease(mSession); mSession = nullptr; } if (mFormat) { LOG("%s: releasing format %p", __func__, mFormat); CFRelease(mFormat); mFormat = nullptr; } - return NS_OK; } nsresult AppleVTDecoder::Input(MediaRawData* aSample) { + MOZ_ASSERT(mCallback->OnReaderTaskQueue()); + LOG("mp4 input sample %p pts %lld duration %lld us%s %d bytes", aSample, aSample->mTime, aSample->mDuration, aSample->mKeyframe ? " keyframe" : "", aSample->Size()); #ifdef LOG_MEDIA_SHA1 @@ -97,51 +98,51 @@ AppleVTDecoder::Input(MediaRawData* aSam hash.finish(digest_buf); nsAutoCString digest; for (size_t i = 0; i < sizeof(digest_buf); i++) { digest.AppendPrintf("%02x", digest_buf[i]); } LOG(" sha1 %s", digest.get()); #endif // LOG_MEDIA_SHA1 + mInputIncoming++; + nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>( - this, - &AppleVTDecoder::SubmitFrame, - nsRefPtr<MediaRawData>(aSample)); + this, &AppleVTDecoder::SubmitFrame, aSample); mTaskQueue->Dispatch(runnable.forget()); return NS_OK; } -nsresult -AppleVTDecoder::Flush() +void +AppleVTDecoder::ProcessFlush() { - mTaskQueue->Flush(); + MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); nsresult rv = WaitForAsynchronousFrames(); if (NS_FAILED(rv)) { LOG("AppleVTDecoder::Flush failed waiting for platform decoder " "with error:%d.", rv); } ClearReorderedFrames(); - - return rv; + MonitorAutoLock mon(mMonitor); + mIsFlushing = false; + mon.NotifyAll(); } -nsresult -AppleVTDecoder::Drain() +void +AppleVTDecoder::ProcessDrain() { - mTaskQueue->AwaitIdle(); + MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); nsresult rv = WaitForAsynchronousFrames(); if (NS_FAILED(rv)) { LOG("AppleVTDecoder::Drain failed waiting for platform decoder " "with error:%d.", rv); } DrainReorderedFrames(); mCallback->DrainComplete(); - return NS_OK; } // // Implementation details. // // Callback passed to the VideoToolbox decoder for returning data. // This needs to be static because the API takes a C-style pair of @@ -169,19 +170,20 @@ PlatformCallback(void* decompressionOutp return; } if (flags & kVTDecodeInfo_FrameDropped) { NS_WARNING(" ...frame tagged as dropped..."); } MOZ_ASSERT(CFGetTypeID(image) == CVPixelBufferGetTypeID(), "VideoToolbox returned an unexpected image type"); - // Forward the data back to an object method which can access - // the correct MP4Reader callback. - decoder->OutputFrame(image, frameRef); + nsCOMPtr<nsIRunnable> task = + NS_NewRunnableMethodWithArgs<CFRefPtr<CVPixelBufferRef>, AppleVTDecoder::AppleFrameRef>( + decoder, &AppleVTDecoder::OutputFrame, image, *frameRef); + decoder->DispatchOutputTask(task.forget()); } nsresult AppleVTDecoder::WaitForAsynchronousFrames() { OSStatus rv = VTDecompressionSessionWaitForAsynchronousFrames(mSession); if (rv != noErr) { LOG("AppleVTDecoder: Error %d waiting for asynchronous frames", rv); @@ -203,16 +205,18 @@ TimingInfoFromSample(MediaRawData* aSamp CMTimeMake(aSample->mTimecode, USECS_PER_S); return timestamp; } nsresult AppleVTDecoder::SubmitFrame(MediaRawData* aSample) { + MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); + mInputIncoming--; // For some reason this gives me a double-free error with stagefright. AutoCFRelease<CMBlockBufferRef> block = nullptr; AutoCFRelease<CMSampleBufferRef> sample = nullptr; VTDecodeInfoFlags infoFlags; OSStatus rv; // FIXME: This copies the sample data. I think we can provide // a custom block source which reuses the aSample buffer. @@ -248,17 +252,17 @@ AppleVTDecoder::SubmitFrame(MediaRawData if (rv != noErr && !(infoFlags & kVTDecodeInfo_FrameDropped)) { LOG("AppleVTDecoder: Error %d VTDecompressionSessionDecodeFrame", rv); NS_WARNING("Couldn't pass frame to decoder"); mCallback->Error(); return NS_ERROR_FAILURE; } // Ask for more data. - if (mTaskQueue->IsEmpty()) { + if (!mInputIncoming) { LOG("AppleVTDecoder task queue empty; requesting more data"); mCallback->InputExhausted(); } return NS_OK; } nsresult
--- a/dom/media/platforms/apple/AppleVTDecoder.h +++ b/dom/media/platforms/apple/AppleVTDecoder.h @@ -17,24 +17,26 @@ class AppleVTDecoder : public AppleVDADe public: AppleVTDecoder(const VideoInfo& aConfig, FlushableTaskQueue* aVideoTaskQueue, MediaDataDecoderCallback* aCallback, layers::ImageContainer* aImageContainer); virtual ~AppleVTDecoder(); virtual nsRefPtr<InitPromise> Init() override; virtual nsresult Input(MediaRawData* aSample) override; - virtual nsresult Flush() override; - virtual nsresult Drain() override; - virtual nsresult Shutdown() override; virtual bool IsHardwareAccelerated() const override { return mIsHardwareAccelerated; } +protected: + void ProcessFlush() override; + void ProcessDrain() override; + void ProcessShutdown() override; + private: CMVideoFormatDescriptionRef mFormat; VTDecompressionSessionRef mSession; // Method to pass a frame to VideoToolbox for decoding. nsresult SubmitFrame(MediaRawData* aSample); // Method to set up the decompression session. nsresult InitializeSession();
--- a/dom/media/tests/mochitest/ipc/mochitest.ini +++ b/dom/media/tests/mochitest/ipc/mochitest.ini @@ -1,9 +1,9 @@ [DEFAULT] tags=msg support-files = ipc.json skip-if = e10s [test_ipc.html] -skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #bug 910661 # b2g(nested ipc not working) b2g-debug(debug-only failure) b2g-desktop(nested ipc not working) +skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || os == 'win' #bug 910661 # b2g(nested ipc not working) b2g-debug(debug-only failure) b2g-desktop(nested ipc not working)(win : Bug 1179826)
--- a/dom/media/tests/mochitest/mochitest.ini +++ b/dom/media/tests/mochitest/mochitest.ini @@ -97,17 +97,17 @@ skip-if = toolkit == 'gonk' || buildapp [test_peerConnection_captureStream_canvas_webgl.html] skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) # [test_peerConnection_certificates.html] # bug 1180968 # skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867) [test_peerConnection_close.html] [test_peerConnection_closeDuringIce.html] [test_peerConnection_errorCallbacks.html] [test_peerConnection_iceFailure.html] -skip-if = toolkit == 'gonk' || buildapp == 'mulet' # Disabling because of test failures on B2G emulator +skip-if = toolkit == 'gonk' || buildapp == 'mulet' || os == 'linux' || os == 'mac' || os == 'win' # Disabling because of test failures on B2G emulator (Bug 1180388 for win, mac and linux) [test_peerConnection_forwarding_basicAudioVideoCombined.html] skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) [test_peerConnection_noTrickleAnswer.html] skip-if = toolkit == 'gonk' # B2G emulator is too slow to handle a two-way audio call reliably [test_peerConnection_noTrickleOffer.html] skip-if = toolkit == 'gonk' # B2G emulator is too slow to handle a two-way audio call reliably [test_peerConnection_noTrickleOfferAnswer.html] skip-if = toolkit == 'gonk' # B2G emulator is too slow to handle a two-way audio call reliably
--- a/dom/media/webaudio/BufferDecoder.cpp +++ b/dom/media/webaudio/BufferDecoder.cpp @@ -125,17 +125,17 @@ BufferDecoder::MetadataLoaded(nsAutoPtr< void BufferDecoder::FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo, MediaDecoderEventVisibility aEventVisibility) { // ignore } void -BufferDecoder::QueueMetadata(int64_t aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) +BufferDecoder::QueueMetadata(const media::TimeUnit& aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) { // ignore } void BufferDecoder::RemoveMediaTracks() { // ignore
--- a/dom/media/webaudio/BufferDecoder.h +++ b/dom/media/webaudio/BufferDecoder.h @@ -53,17 +53,17 @@ public: virtual bool IsTransportSeekable() final override; virtual bool IsMediaSeekable() final override; virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags, MediaDecoderEventVisibility aEventVisibility) final override; - virtual void QueueMetadata(int64_t aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) final override; + virtual void QueueMetadata(const media::TimeUnit& aTime, nsAutoPtr<MediaInfo> aInfo, nsAutoPtr<MetadataTags> aTags) final override; virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo, MediaDecoderEventVisibility aEventVisibility) final override; virtual void RemoveMediaTracks() final override; virtual void OnReadMetadataCompleted() final override; virtual MediaDecoderOwner* GetOwner() final override;
--- a/dom/mobilemessage/ipc/SmsChild.cpp +++ b/dom/mobilemessage/ipc/SmsChild.cpp @@ -194,17 +194,16 @@ SmsRequestChild::ActorDestroy(ActorDestr // Nothing needed here. } bool SmsRequestChild::Recv__delete__(const MessageReply& aReply) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mReplyRequest); - nsCOMPtr<SmsMessage> message; switch(aReply.type()) { case MessageReply::TReplyMessageSend: { const MobileMessageData& data = aReply.get_ReplyMessageSend().messageData(); nsCOMPtr<nsISupports> msg = CreateMessageFromMessageData(data); mReplyRequest->NotifyMessageSent(msg); } break;
--- a/dom/notification/DesktopNotification.cpp +++ b/dom/notification/DesktopNotification.cpp @@ -168,26 +168,24 @@ DesktopNotification::~DesktopNotificatio void DesktopNotification::DispatchNotificationEvent(const nsString& aName) { if (NS_FAILED(CheckInnerWindowCorrectness())) { return; } - nsCOMPtr<nsIDOMEvent> event; - nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); - if (NS_SUCCEEDED(rv)) { - // it doesn't bubble, and it isn't cancelable - rv = event->InitEvent(aName, false, false); - if (NS_SUCCEEDED(rv)) { - event->SetTrusted(true); - DispatchDOMEvent(nullptr, event, nullptr, nullptr); - } + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); + // it doesn't bubble, and it isn't cancelable + nsresult rv = event->InitEvent(aName, false, false); + if (NS_FAILED(rv)) { + return; } + event->SetTrusted(true); + DispatchDOMEvent(nullptr, event, nullptr, nullptr); } nsresult DesktopNotification::SetAllow(bool aAllow) { mAllow = aAllow; // if we have called Show() already, lets go ahead and post a notification
--- a/dom/notification/Notification.cpp +++ b/dom/notification/Notification.cpp @@ -1072,18 +1072,17 @@ Notification::DispatchNotificationClickE // Client.focus() API if it wishes. return false; } bool Notification::DispatchClickEvent() { AssertIsOnTargetThread(); - nsCOMPtr<nsIDOMEvent> event; - NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); nsresult rv = event->InitEvent(NS_LITERAL_STRING("click"), false, true); NS_ENSURE_SUCCESS(rv, false); event->SetTrusted(true); WantsPopupControlCheck popupControlCheck(event); bool doDefaultAction = true; DispatchEvent(event, &doDefaultAction); return doDefaultAction; }
--- a/dom/offline/nsDOMOfflineResourceList.cpp +++ b/dom/offline/nsDOMOfflineResourceList.cpp @@ -16,16 +16,17 @@ #include "nsServiceManagerUtils.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIOfflineCacheUpdate.h" #include "nsAutoPtr.h" #include "nsContentUtils.h" #include "nsIObserverService.h" #include "nsIScriptGlobalObject.h" #include "nsIWebNavigation.h" +#include "mozilla/dom/Event.h" #include "mozilla/dom/OfflineResourceListBinding.h" #include "mozilla/EventDispatcher.h" #include "mozilla/Preferences.h" #include "nsXULAppAPI.h" #define IS_CHILD_PROCESS() \ (GeckoProcessType_Default != XRE_GetProcessType()) @@ -542,21 +543,17 @@ nsDOMOfflineResourceList::SendEvent(cons if (!GetOwner()) { return NS_OK; } if (!GetOwner()->GetDocShell()) { return NS_OK; } - nsCOMPtr<nsIDOMEvent> event; - nsresult rv = EventDispatcher::CreateEvent(this, nullptr, nullptr, - NS_LITERAL_STRING("Events"), - getter_AddRefs(event)); - NS_ENSURE_SUCCESS(rv, rv); + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); event->InitEvent(aEventName, false, true); // We assume anyone that managed to call SendEvent is trusted event->SetTrusted(true); // If the window is frozen or we're still catching up on events that were // queued while frozen, save the event for later. if (GetOwner()->IsFrozen() || mPendingEvents.Count() > 0) {
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -637,33 +637,27 @@ NS_IMETHODIMP nsPluginInstanceOwner::RedrawPlugin() { if (mPluginFrame) { mPluginFrame->InvalidateLayer(nsDisplayItem::TYPE_PLUGIN); } return NS_OK; } -NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value) +#if defined(XP_WIN) +nsIWidget* +nsPluginInstanceOwner::GetContainingWidgetIfOffset() { - if (!mPluginFrame) { - NS_WARNING("plugin owner has no owner in getting doc's window handle"); - return NS_ERROR_FAILURE; - } - -#if defined(XP_WIN) - void** pvalue = (void**)value; - nsViewManager* vm = mPluginFrame->PresContext()->GetPresShell()->GetViewManager(); - if (!vm) - return NS_ERROR_FAILURE; + MOZ_ASSERT(mPluginFrame, "Caller should have checked for null mPluginFrame."); + // This property is provided to allow a "windowless" plugin to determine the window it is drawing // in, so it can translate mouse coordinates it receives directly from the operating system // to coordinates relative to itself. - // The original code (outside this #if) returns the document's window, which is OK if the window the "windowless" plugin + // The original code returns the document's window, which is OK if the window the "windowless" plugin // is drawing into has the same origin as the document's window, but this is not the case for "windowless" plugins inside of scrolling DIVs etc // To make sure "windowless" plugins always get the right origin for translating mouse coordinates, this code // determines the window handle of the mozilla window containing the "windowless" plugin. // Given that this HWND may not be that of the document's window, there is a slight risk // of confusing a plugin that is using this HWND for illicit purposes, but since the documentation // does not suggest this HWND IS that of the document window, rather that of the window @@ -687,27 +681,63 @@ NS_IMETHODIMP nsPluginInstanceOwner::Get if (win) { nsView *view = nsView::GetViewFor(win); NS_ASSERTION(view, "No view for widget"); nsPoint offset = view->GetOffsetTo(nullptr); if (offset.x || offset.y) { // in the case the two windows are offset from eachother, we do go ahead and return the correct enclosing window // so that mouse co-ordinates are not messed up. - *pvalue = (void*)win->GetNativeData(NS_NATIVE_WINDOW); - if (*pvalue) - return NS_OK; + return win; } } } + + return nullptr; +} + +static already_AddRefed<nsIWidget> +GetRootWidgetForPluginFrame(const nsPluginFrame* aPluginFrame) +{ + MOZ_ASSERT(aPluginFrame); + + nsViewManager* vm = + aPluginFrame->PresContext()->GetPresShell()->GetViewManager(); + if (!vm) { + NS_WARNING("Could not find view manager for plugin frame."); + return nullptr; + } + + nsCOMPtr<nsIWidget> rootWidget; + vm->GetRootWidget(getter_AddRefs(rootWidget)); + return rootWidget.forget(); +} +#endif + +NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value) +{ + if (!mPluginFrame) { + NS_WARNING("plugin owner has no owner in getting doc's window handle"); + return NS_ERROR_FAILURE; + } + +#if defined(XP_WIN) + void** pvalue = (void**)value; + nsIWidget* offsetContainingWidget = GetContainingWidgetIfOffset(); + if (offsetContainingWidget) { + *pvalue = (void*)offsetContainingWidget->GetNativeData(NS_NATIVE_WINDOW); + if (*pvalue) { + return NS_OK; + } + } + // simply return the topmost document window - nsCOMPtr<nsIWidget> widget; - vm->GetRootWidget(getter_AddRefs(widget)); + nsCOMPtr<nsIWidget> widget = GetRootWidgetForPluginFrame(mPluginFrame); if (widget) { - *pvalue = (void*)widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW); + *pvalue = widget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW); } else { NS_ASSERTION(widget, "couldn't get doc's widget in getting doc's window handle"); } return NS_OK; #elif (defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)) && defined(MOZ_X11) // X11 window managers want the toplevel window for WM_TRANSIENT_FOR. nsIWidget* win = mPluginFrame->GetNearestWidget(); @@ -715,16 +745,58 @@ NS_IMETHODIMP nsPluginInstanceOwner::Get return NS_ERROR_FAILURE; *static_cast<Window*>(value) = (long unsigned int)win->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW); return NS_OK; #else return NS_ERROR_NOT_IMPLEMENTED; #endif } +#if defined(XP_WIN) +void +nsPluginInstanceOwner::SetWidgetWindowAsParent(HWND aWindowToAdopt) +{ + if (!mWidget) { + NS_ERROR("mWidget should exist before this gets called."); + return; + } + + mWidget->SetNativeData(NS_NATIVE_CHILD_WINDOW, + reinterpret_cast<uintptr_t>(aWindowToAdopt)); +} + +nsresult +nsPluginInstanceOwner::SetNetscapeWindowAsParent(HWND aWindowToAdopt) +{ + if (!mPluginFrame) { + NS_WARNING("Plugin owner has no plugin frame."); + return NS_ERROR_FAILURE; + } + + // If there is a containing window that is offset then ask that to adopt. + nsIWidget* offsetWidget = GetContainingWidgetIfOffset(); + if (offsetWidget) { + offsetWidget->SetNativeData(NS_NATIVE_CHILD_WINDOW, + reinterpret_cast<uintptr_t>(aWindowToAdopt)); + return NS_OK; + } + + // Otherwise ask the topmost document window to adopt. + nsCOMPtr<nsIWidget> rootWidget = GetRootWidgetForPluginFrame(mPluginFrame); + if (!rootWidget) { + NS_ASSERTION(rootWidget, "Couldn't get topmost document's widget."); + return NS_ERROR_FAILURE; + } + + rootWidget->SetNativeData(NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW, + reinterpret_cast<uintptr_t>(aWindowToAdopt)); + return NS_OK; +} +#endif + NS_IMETHODIMP nsPluginInstanceOwner::SetEventModel(int32_t eventModel) { #ifdef XP_MACOSX mEventModel = static_cast<NPEventModel>(eventModel); return NS_OK; #else return NS_ERROR_NOT_IMPLEMENTED; #endif
--- a/dom/plugins/base/nsPluginInstanceOwner.h +++ b/dom/plugins/base/nsPluginInstanceOwner.h @@ -107,16 +107,21 @@ public: //locals nsresult Init(nsIContent* aContent); void* GetPluginPort(); void ReleasePluginPort(void* pluginPort); nsEventStatus ProcessEvent(const mozilla::WidgetGUIEvent& anEvent); + +#if defined(XP_WIN) + void SetWidgetWindowAsParent(HWND aWindowToAdopt); + nsresult SetNetscapeWindowAsParent(HWND aWindowToAdopt); +#endif #ifdef XP_MACOSX enum { ePluginPaintEnable, ePluginPaintDisable }; void WindowFocusMayHaveChanged(); void ResolutionMayHaveChanged(); bool WindowIsActive(); @@ -268,16 +273,20 @@ private: #ifdef MOZ_WIDGET_ANDROID mozilla::LayoutDeviceRect GetPluginRect(); bool AddPluginView(const mozilla::LayoutDeviceRect& aRect = mozilla::LayoutDeviceRect(0, 0, 0, 0)); void RemovePluginView(); bool mFullScreen; void* mJavaView; #endif + +#if defined(XP_WIN) + nsIWidget* GetContainingWidgetIfOffset(); +#endif nsPluginNativeWindow *mPluginWindow; nsRefPtr<nsNPAPIPluginInstance> mInstance; nsPluginFrame *mPluginFrame; nsWeakPtr mContent; // WEAK, content owns us nsCString mDocumentBase; bool mWidgetCreationComplete; nsCOMPtr<nsIWidget> mWidget;
--- a/dom/plugins/ipc/PPluginInstance.ipdl +++ b/dom/plugins/ipc/PPluginInstance.ipdl @@ -65,18 +65,21 @@ intr protocol PPluginInstance manages PStreamNotify; manages PPluginSurface; child: intr __delete__(); // This is only used on Windows and, for windowed plugins, must be called // before the first call to NPP_SetWindow. - intr CreateChildPluginWindow(NPRemoteWindow window) - returns (NPRemoteWindow createdChild); + intr CreateChildPluginWindow() + returns (NativeWindowHandle childPluginWindow); + + // This is only used on Windows and, for windowless plugins. + async CreateChildPopupSurrogate(NativeWindowHandle netscapeWindow); intr NPP_SetWindow(NPRemoteWindow window); intr NPP_GetValue_NPPVpluginWantsAllNetworkStreams() returns (bool value, NPError result); // this message is not used on non-X platforms intr NPP_GetValue_NPPVpluginNeedsXEmbed() @@ -214,16 +217,20 @@ parent: // Send notification that a plugin tried to negotiate Carbon NPAPI so that // users can be notified that restarting the browser in i386 mode may allow // them to use the plugin. sync NegotiatedCarbon(); // Notifies the parent of its NPP_New result code. async AsyncNPP_NewResult(NPError aResult); + // Sends a native window to be adopted by the native window that would be + // returned by NPN_GetValue_NPNVnetscapeWindow. Only used on Windows. + async SetNetscapeWindowAsParent(NativeWindowHandle childWindow); + both: async PPluginScriptableObject(); child: /* NPP_NewStream */ async PBrowserStream(nsCString url, uint32_t length, uint32_t lastmodified,
--- a/dom/plugins/ipc/PluginInstanceChild.cpp +++ b/dom/plugins/ipc/PluginInstanceChild.cpp @@ -192,27 +192,27 @@ PluginInstanceChild::PluginInstanceChild mWsInfo.display = DefaultXDisplay(); #endif #endif // MOZ_X11 && XP_UNIX && !XP_MACOSX #if defined(OS_WIN) memset(&mAlphaExtract, 0, sizeof(mAlphaExtract)); #endif // OS_WIN #if defined(OS_WIN) InitPopupMenuHook(); - if (GetQuirks() & PluginModuleChild::QUIRK_UNITY_FIXUP_MOUSE_CAPTURE) { + if (GetQuirks() & QUIRK_UNITY_FIXUP_MOUSE_CAPTURE) { SetUnityHooks(); } #endif // OS_WIN } PluginInstanceChild::~PluginInstanceChild() { #if defined(OS_WIN) NS_ASSERTION(!mPluginWindowHWND, "Destroying PluginInstanceChild without NPP_Destroy?"); - if (GetQuirks() & PluginModuleChild::QUIRK_UNITY_FIXUP_MOUSE_CAPTURE) { + if (GetQuirks() & QUIRK_UNITY_FIXUP_MOUSE_CAPTURE) { ClearUnityHooks(); } #endif #if defined(MOZ_WIDGET_COCOA) if (mShColorSpace) { ::CGColorSpaceRelease(mShColorSpace); } if (mShContext) { @@ -400,17 +400,17 @@ PluginInstanceChild::NPN_GetValue(NPNVar case NPNVdocumentOrigin: { nsCString v; NPError result; if (!CallNPN_GetValue_NPNVdocumentOrigin(&v, &result)) { return NPERR_GENERIC_ERROR; } if (result == NPERR_NO_ERROR || (GetQuirks() & - PluginModuleChild::QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN)) { + QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN)) { *static_cast<char**>(aValue) = ToNewCString(v); } return result; } case NPNVWindowNPObject: // Intentional fall-through case NPNVPluginElementNPObject: { NPObject* object; @@ -1023,17 +1023,17 @@ PluginInstanceChild::AnswerNPP_HandleEve PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not " "provide CALayer.")); *handled = false; return false; } mCARenderer->SetupRenderer(caLayer, mWindow.width, mWindow.height, mContentsScaleFactor, - GetQuirks() & PluginModuleChild::QUIRK_ALLOW_OFFLINE_RENDERER ? + GetQuirks() & QUIRK_ALLOW_OFFLINE_RENDERER ? ALLOW_OFFLINE_RENDERER : DISALLOW_OFFLINE_RENDERER); // Flash needs to have the window set again after this step if (mPluginIface->setwindow) (void) mPluginIface->setwindow(&mData, &mWindow); } } else { PLUGIN_LOG_DEBUG(("Invalid event type for " @@ -1141,35 +1141,41 @@ void PluginInstanceChild::DeleteWindow() #endif // We don't have to keep the plug-in window ID any longer. mWindow.window = nullptr; } #endif bool -PluginInstanceChild::AnswerCreateChildPluginWindow(const NPRemoteWindow& aWindow, - NPRemoteWindow* aCreatedChild) +PluginInstanceChild::AnswerCreateChildPluginWindow(NativeWindowHandle* aChildPluginWindow) { #if defined(XP_WIN) - MOZ_ASSERT(aWindow.type == NPWindowTypeWindow); MOZ_ASSERT(!mPluginWindowHWND); - if ((GetQuirks() & PluginModuleChild::QUIRK_QUICKTIME_AVOID_SETWINDOW) && - aWindow.width == 0 && aWindow.height == 0) { - - // Skip CreateChildPluginWindow call for hidden QuickTime plugins. - return true; - } - if (!CreatePluginWindow()) { return false; } - aCreatedChild->window = reinterpret_cast<uint64_t>(mPluginWindowHWND); + MOZ_ASSERT(mPluginWindowHWND); + + *aChildPluginWindow = mPluginWindowHWND; + return true; +#else + NS_NOTREACHED("PluginInstanceChild::CreateChildPluginWindow not implemented!"); + return false; +#endif +} + +bool +PluginInstanceChild::RecvCreateChildPopupSurrogate(const NativeWindowHandle& aNetscapeWindow) +{ +#if defined(XP_WIN) + mCachedWinlessPluginHWND = aNetscapeWindow; + CreateWinlessPopupSurrogate(); return true; #else NS_NOTREACHED("PluginInstanceChild::CreateChildPluginWindow not implemented!"); return false; #endif } bool @@ -1249,22 +1255,20 @@ PluginInstanceChild::AnswerNPP_SetWindow if (mPluginIface->setwindow) (void) mPluginIface->setwindow(&mData, &mWindow); #elif defined(OS_WIN) switch (aWindow.type) { case NPWindowTypeWindow: { - if ((GetQuirks() & PluginModuleChild::QUIRK_QUICKTIME_AVOID_SETWINDOW) && - aWindow.width == 0 && - aWindow.height == 0) { - // Skip SetWindow call for hidden QuickTime plugins - return true; - } + // This check is now done in PluginInstanceParent before this call, so + // we should never see it here. + MOZ_ASSERT(!(GetQuirks() & QUIRK_QUICKTIME_AVOID_SETWINDOW) || + aWindow.width != 0 || aWindow.height != 0); MOZ_ASSERT(mPluginWindowHWND, "Child plugin window must exist before call to SetWindow"); HWND parentHWND = reinterpret_cast<HWND>(aWindow.window); if (mPluginWindowHWND != parentHWND) { mPluginParentHWND = parentHWND; ShowWindow(mPluginWindowHWND, SW_SHOWNA); @@ -1293,19 +1297,17 @@ PluginInstanceChild::AnswerNPP_SetWindow RemoveProp(mPluginWindowHWND, kPluginIgnoreSubclassProperty); HookSetWindowLongPtr(); } } break; case NPWindowTypeDrawable: mWindow.type = aWindow.type; - if (GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK) - CreateWinlessPopupSurrogate(); - if (GetQuirks() & PluginModuleChild::QUIRK_FLASH_THROTTLE_WMUSER_EVENTS) + if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS) SetupFlashMsgThrottle(); return SharedSurfaceSetWindow(aWindow); break; default: NS_NOTREACHED("Bad plugin window type."); return false; break; @@ -1549,34 +1551,34 @@ PluginInstanceChild::PluginWindowProcInt } } if (message == WM_KILLFOCUS) { self->CallPluginFocusChange(false); } if (message == WM_USER+1 && - (self->GetQuirks() & PluginModuleChild::QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)) { + (self->GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)) { self->FlashThrottleMessage(hWnd, message, wParam, lParam, true); return 0; } NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, "Self-referential windowproc happened inside our hook proc. " "Infinite recursion will happen soon."); LRESULT res = CallWindowProc(self->mPluginWndProc, hWnd, message, wParam, lParam); // Make sure capture is released by the child on mouse events. Fixes a // problem with flash full screen mode mouse input. Appears to be // caused by a bug in flash, since we are not setting the capture // on the window. if (message == WM_LBUTTONDOWN && - self->GetQuirks() & PluginModuleChild::QUIRK_FLASH_FIXUP_MOUSE_CAPTURE) { + self->GetQuirks() & QUIRK_FLASH_FIXUP_MOUSE_CAPTURE) { wchar_t szClass[26]; HWND hwnd = GetForegroundWindow(); if (hwnd && GetClassNameW(hwnd, szClass, sizeof(szClass)/sizeof(char16_t)) && !wcscmp(szClass, kFlashFullscreenClass)) { ReleaseCapture(); SetFocus(hwnd); } @@ -1727,17 +1729,17 @@ PluginInstanceChild::SetWindowLongWHook( NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, "Infinite recursion coming up!"); } return proc; } void PluginInstanceChild::HookSetWindowLongPtr() { - if (!(GetQuirks() & PluginModuleChild::QUIRK_FLASH_HOOK_SETLONGPTR)) + if (!(GetQuirks() & QUIRK_FLASH_HOOK_SETLONGPTR)) return; sUser32Intercept.Init("user32.dll"); #ifdef _WIN64 if (!sUser32SetWindowLongAHookStub) sUser32Intercept.AddHook("SetWindowLongPtrA", reinterpret_cast<intptr_t>(SetWindowLongPtrAHook), (void**) &sUser32SetWindowLongAHookStub); if (!sUser32SetWindowLongWHookStub) @@ -1814,17 +1816,17 @@ PluginInstanceChild::SetCaptureHook(HWND sSetCaptureHookData = new SetCaptureHookData(aHwnd); } return sUser32SetCaptureHookStub(aHwnd); } void PluginInstanceChild::SetUnityHooks() { - if (!(GetQuirks() & PluginModuleChild::QUIRK_UNITY_FIXUP_MOUSE_CAPTURE)) { + if (!(GetQuirks() & QUIRK_UNITY_FIXUP_MOUSE_CAPTURE)) { return; } sUser32Intercept.Init("user32.dll"); if (!sUser32SetCaptureHookStub) { sUser32Intercept.AddHook("SetCapture", reinterpret_cast<intptr_t>(SetCaptureHook), (void**) &sUser32SetCaptureHookStub); @@ -1941,17 +1943,17 @@ PluginInstanceChild::TrackPopupHookProc( } return res; } void PluginInstanceChild::InitPopupMenuHook() { - if (!(GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK) || + if (!(GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK) || sUser32TrackPopupMenuStub) return; // Note, once WindowsDllInterceptor is initialized for a module, // it remains initialized for that particular module for it's // lifetime. Additional instances are needed if other modules need // to be hooked. if (!sUser32TrackPopupMenuStub) { @@ -1963,31 +1965,25 @@ PluginInstanceChild::InitPopupMenuHook() void PluginInstanceChild::CreateWinlessPopupSurrogate() { // already initialized if (mWinlessPopupSurrogateHWND) return; - HWND hwnd = nullptr; - NPError result; - if (!CallNPN_GetValue_NPNVnetscapeWindow(&hwnd, &result)) { - NS_ERROR("CallNPN_GetValue_NPNVnetscapeWindow failed."); - return; - } - mWinlessPopupSurrogateHWND = - CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"Static", nullptr, WS_CHILD, - 0, 0, 0, 0, hwnd, 0, GetModuleHandle(nullptr), 0); + CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"Static", nullptr, WS_POPUP, + 0, 0, 0, 0, nullptr, 0, GetModuleHandle(nullptr), 0); if (!mWinlessPopupSurrogateHWND) { NS_ERROR("CreateWindowEx failed for winless placeholder!"); return; } - return; + + SendSetNetscapeWindowAsParent(mWinlessPopupSurrogateHWND); } void PluginInstanceChild::DestroyWinlessPopupSurrogate() { if (mWinlessPopupSurrogateHWND) DestroyWindow(mWinlessPopupSurrogateHWND); mWinlessPopupSurrogateHWND = nullptr; @@ -2003,17 +1999,17 @@ PluginInstanceChild::WinlessHandleEvent( // special handling during delivery. int16_t handled; HWND focusHwnd = nullptr; // TrackPopupMenu will fail if the parent window is not associated with // our ui thread. So we hook TrackPopupMenu so we can hand in a surrogate // parent created in the child process. - if ((GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK) && // XXX turn on by default? + if ((GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK) && // XXX turn on by default? (event.event == WM_RBUTTONDOWN || // flash event.event == WM_RBUTTONUP)) { // silverlight sWinlessPopupSurrogateHWND = mWinlessPopupSurrogateHWND; // A little trick scrounged from chromium's code - set the focus // to our surrogate parent so keyboard nav events go to the menu. focusHwnd = SetFocus(mWinlessPopupSurrogateHWND); } @@ -2395,17 +2391,17 @@ PluginInstanceChild::AnswerSetPluginFocu #if defined(OS_WIN) // Parent is letting us know the dom set focus to the plugin. Note, // focus can change during transit in certain edge cases, for example // when a button click brings up a full screen window. Since we send // this in response to a WM_SETFOCUS event on our parent, the parent // should have focus when we receive this. If not, ignore the call. if (::GetFocus() == mPluginWindowHWND || - ((GetQuirks() & PluginModuleChild::QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT) && + ((GetQuirks() & QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT) && (::GetFocus() != mPluginParentHWND))) return true; ::SetFocus(mPluginWindowHWND); return true; #else NS_NOTREACHED("PluginInstanceChild::AnswerSetPluginFocus not implemented!"); return false; #endif @@ -2820,27 +2816,25 @@ PluginInstanceChild::DoAsyncSetWindow(co mWindow.width = aWindow.width; mWindow.height = aWindow.height; mWindow.clipRect = aWindow.clipRect; mWindow.type = aWindow.type; #ifdef XP_MACOSX mContentsScaleFactor = aWindow.contentsScaleFactor; #endif - if (GetQuirks() & PluginModuleChild::QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT) + if (GetQuirks() & QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT) mIsTransparent = true; mLayersRendering = true; mSurfaceType = aSurfaceType; UpdateWindowAttributes(true); #ifdef XP_WIN - if (GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK) - CreateWinlessPopupSurrogate(); - if (GetQuirks() & PluginModuleChild::QUIRK_FLASH_THROTTLE_WMUSER_EVENTS) + if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS) SetupFlashMsgThrottle(); #endif if (!mAccumulatedInvalidRect.IsEmpty()) { AsyncShowPluginFrame(); } } @@ -3022,17 +3016,17 @@ PluginInstanceChild::EnsureCurrentBuffer return true; #elif defined(XP_MACOSX) if (!mDoubleBufferCARenderer.HasCALayer()) { void *caLayer = nullptr; if (mDrawingModel == NPDrawingModelCoreGraphics) { if (!mCGLayer) { bool avoidCGCrashes = !nsCocoaFeatures::OnMountainLionOrLater() && - (GetQuirks() & PluginModuleChild::QUIRK_FLASH_AVOID_CGMODE_CRASHES); + (GetQuirks() & QUIRK_FLASH_AVOID_CGMODE_CRASHES); caLayer = mozilla::plugins::PluginUtilsOSX::GetCGLayer(CallCGDraw, this, avoidCGCrashes, mContentsScaleFactor); if (!caLayer) { PLUGIN_LOG_DEBUG(("GetCGLayer failed.")); return false; } @@ -3056,17 +3050,17 @@ PluginInstanceChild::EnsureCurrentBuffer mDoubleBufferCARenderer.GetFrontSurfaceHeight() != mWindow.height || mDoubleBufferCARenderer.GetContentsScaleFactor() != mContentsScaleFactor)) { mDoubleBufferCARenderer.ClearFrontSurface(); } if (!mDoubleBufferCARenderer.HasFrontSurface()) { bool allocSurface = mDoubleBufferCARenderer.InitFrontSurface( mWindow.width, mWindow.height, mContentsScaleFactor, - GetQuirks() & PluginModuleChild::QUIRK_ALLOW_OFFLINE_RENDERER ? + GetQuirks() & QUIRK_ALLOW_OFFLINE_RENDERER ? ALLOW_OFFLINE_RENDERER : DISALLOW_OFFLINE_RENDERER); if (!allocSurface) { PLUGIN_LOG_DEBUG(("Fail to allocate front IOSurface")); return false; } if (mPluginIface->setwindow) (void) mPluginIface->setwindow(&mData, &mWindow); @@ -3229,17 +3223,17 @@ void PluginInstanceChild::PaintRectToSurface(const nsIntRect& aRect, gfxASurface* aSurface, const gfxRGBA& aColor) { // Render using temporary X surface, with copy to image surface nsIntRect plPaintRect(aRect); nsRefPtr<gfxASurface> renderSurface = aSurface; #ifdef MOZ_X11 - if (mIsTransparent && (GetQuirks() & PluginModuleChild::QUIRK_FLASH_EXPOSE_COORD_TRANSLATION)) { + if (mIsTransparent && (GetQuirks() & QUIRK_FLASH_EXPOSE_COORD_TRANSLATION)) { // Work around a bug in Flash up to 10.1 d51 at least, where expose event // top left coordinates within the plugin-rect and not at the drawable // origin are misinterpreted. (We can move the top left coordinate // provided it is within the clipRect.), see bug 574583 plPaintRect.SetRect(0, 0, aRect.XMost(), aRect.YMost()); } if (mHelperSurface) { // On X11 we can paint to non Xlib surface only with HelperSurface
--- a/dom/plugins/ipc/PluginInstanceChild.h +++ b/dom/plugins/ipc/PluginInstanceChild.h @@ -60,20 +60,24 @@ class PluginInstanceChild : public PPlug LPARAM lParam); static LRESULT CALLBACK PluginWindowProcInternal(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); #endif protected: - bool AnswerCreateChildPluginWindow(const NPRemoteWindow& window, - NPRemoteWindow* aCreatedChild) override; + virtual bool + AnswerCreateChildPluginWindow(NativeWindowHandle* aChildPluginWindow) override; - bool AnswerNPP_SetWindow(const NPRemoteWindow& window) override; + virtual bool + RecvCreateChildPopupSurrogate(const NativeWindowHandle& aNetscapeWindow) override; + + virtual bool + AnswerNPP_SetWindow(const NPRemoteWindow& window) override; virtual bool AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(bool* wantsAllStreams, NPError* rv) override; virtual bool AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(bool* needs, NPError* rv) override; virtual bool AnswerNPP_GetValue_NPPVpluginScriptableNPObject(PPluginScriptableObjectChild** value, NPError* result) override;
--- a/dom/plugins/ipc/PluginInstanceParent.cpp +++ b/dom/plugins/ipc/PluginInstanceParent.cpp @@ -46,16 +46,17 @@ #if defined(OS_WIN) #include <windowsx.h> #include "gfxWindowsPlatform.h" #include "mozilla/plugins/PluginSurfaceParent.h" #include "nsClassHashtable.h" #include "nsHashKeys.h" #include "nsIWidget.h" #include "nsPluginNativeWindow.h" +#include "PluginQuirks.h" extern const wchar_t* kFlashFullscreenClass; #elif defined(MOZ_WIDGET_GTK) #include <gdk/gdk.h> #elif defined(XP_MACOSX) #include <ApplicationServices/ApplicationServices.h> #endif // defined(XP_MACOSX) // This is the pref used to determine whether to use Shumway on a Flash object @@ -674,16 +675,21 @@ PluginInstanceParent::AsyncSetWindow(NPW window.height = aWindow->height; window.clipRect = aWindow->clipRect; window.type = aWindow->type; #ifdef XP_MACOSX double scaleFactor = 1.0; mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &scaleFactor); window.contentsScaleFactor = scaleFactor; #endif + +#if defined(OS_WIN) + MaybeCreateChildPopupSurrogate(); +#endif + if (!SendAsyncSetWindow(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType(), window)) return NS_ERROR_FAILURE; return NS_OK; } nsresult @@ -962,26 +968,39 @@ PluginInstanceParent::NPP_SetWindow(cons #if defined(OS_WIN) // On windowless controls, reset the shared memory surface as needed. if (mWindowType == NPWindowTypeDrawable) { // SharedSurfaceSetWindow will take care of NPRemoteWindow. if (!SharedSurfaceSetWindow(aWindow, window)) { return NPERR_OUT_OF_MEMORY_ERROR; } - } - else { + + MaybeCreateChildPopupSurrogate(); + } else { SubclassPluginWindow(reinterpret_cast<HWND>(aWindow->window)); + // Skip SetWindow call for hidden QuickTime plugins. + if ((mParent->GetQuirks() & QUIRK_QUICKTIME_AVOID_SETWINDOW) && + aWindow->width == 0 && aWindow->height == 0) { + return NPERR_NO_ERROR; + } + window.window = reinterpret_cast<uint64_t>(aWindow->window); window.x = aWindow->x; window.y = aWindow->y; window.width = aWindow->width; window.height = aWindow->height; window.type = aWindow->type; + + // On Windows we need to create and set the parent before we set the + // window on the plugin, or keyboard interaction will not work. + if (!MaybeCreateAndParentChildPluginWindow()) { + return NPERR_GENERIC_ERROR; + } } #else window.window = reinterpret_cast<uint64_t>(aWindow->window); window.x = aWindow->x; window.y = aWindow->y; window.width = aWindow->width; window.height = aWindow->height; window.clipRect = aWindow->clipRect; // MacOS specific @@ -1022,43 +1041,16 @@ PluginInstanceParent::NPP_SetWindow(cons #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) const NPSetWindowCallbackStruct* ws_info = static_cast<NPSetWindowCallbackStruct*>(aWindow->ws_info); window.visualID = ws_info->visual ? ws_info->visual->visualid : None; window.colormap = ws_info->colormap; #endif -#if defined(XP_WIN) - // On Windows we need to create and set the parent before we set the window - // on the plugin, or certain things like keyboard interaction will not work. - if (!mChildPluginHWND && mWindowType == NPWindowTypeWindow) { - NPRemoteWindow childWindow; - if (!CallCreateChildPluginWindow(window, &childWindow)) { - return NPERR_GENERIC_ERROR; - } - - mChildPluginHWND = reinterpret_cast<HWND>(childWindow.window); - } - - // It's not clear if the parent window would ever change, but when this was - // done in the NPAPI child it used to allow for this. - if (mChildPluginHWND && mPluginHWND != mChildPluginsParentHWND) { - nsCOMPtr<nsIWidget> widget; - static_cast<const nsPluginNativeWindow*>(aWindow)-> - GetPluginWidget(getter_AddRefs(widget)); - if (widget) { - widget->SetNativeData(NS_NATIVE_CHILD_WINDOW, - reinterpret_cast<uintptr_t>(mChildPluginHWND)); - } - - mChildPluginsParentHWND = mPluginHWND; - } -#endif - if (!CallNPP_SetWindow(window)) { return NPERR_GENERIC_ERROR; } return NPERR_NO_ERROR; } NPError @@ -1801,16 +1793,32 @@ PluginInstanceParent::RecvAsyncNPP_NewRe owner->NotifyHostCreateWidget(); MOZ_ASSERT(mSurrogate); mSurrogate->OnInstanceCreated(this); return true; } +bool +PluginInstanceParent::RecvSetNetscapeWindowAsParent(const NativeWindowHandle& childWindow) +{ +#if defined(XP_WIN) + nsPluginInstanceOwner* owner = GetOwner(); + if (!owner || NS_FAILED(owner->SetNetscapeWindowAsParent(childWindow))) { + NS_WARNING("Failed to set Netscape window as parent."); + } + + return true; +#else + NS_NOTREACHED("PluginInstanceParent::RecvSetNetscapeWindowAsParent not implemented!"); + return false; +#endif +} + #if defined(OS_WIN) /* plugin focus changes between processes focus from dom -> child: Focus manager calls on widget to set the focus on the window. We pick up the resulting wm_setfocus event here, and forward @@ -2045,16 +2053,75 @@ PluginInstanceParent::SharedSurfaceAfter dirtyRect.width, dirtyRect.height, mSharedSurfaceDib.GetHDC(), dirtyRect.x, dirtyRect.y, SRCCOPY); } +bool +PluginInstanceParent::MaybeCreateAndParentChildPluginWindow() +{ + // On Windows we need to create and set the parent before we set the + // window on the plugin, or keyboard interaction will not work. + if (!mChildPluginHWND) { + if (!CallCreateChildPluginWindow(&mChildPluginHWND) || + !mChildPluginHWND) { + return false; + } + } + + // It's not clear if the parent window would ever change, but when this + // was done in the NPAPI child it used to allow for this. + if (mPluginHWND == mChildPluginsParentHWND) { + return true; + } + + nsPluginInstanceOwner* owner = GetOwner(); + if (!owner) { + // We can't reparent without an owner, the plugin is probably shutting + // down, just return true to allow any calls to continue. + return true; + } + + // Note that this call will probably cause a sync native message to the + // process that owns the child window. + owner->SetWidgetWindowAsParent(mChildPluginHWND); + mChildPluginsParentHWND = mPluginHWND; + return true; +} + +void +PluginInstanceParent::MaybeCreateChildPopupSurrogate() +{ + // Already created or not required for this plugin. + if (mChildPluginHWND || mWindowType != NPWindowTypeDrawable || + !(mParent->GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK)) { + return; + } + + // We need to pass the netscape window down to be cached as part of the call + // to create the surrogate, because the reparenting of the surrogate in the + // main process can cause sync Windows messages to the plugin process, which + // then cause sync messages from the plugin child for the netscape window + // which causes a deadlock. + NativeWindowHandle netscapeWindow; + NPError result = mNPNIface->getvalue(mNPP, NPNVnetscapeWindow, + &netscapeWindow); + if (NPERR_NO_ERROR != result) { + NS_WARNING("Can't get netscape window to pass to plugin child."); + return; + } + + if (!SendCreateChildPopupSurrogate(netscapeWindow)) { + NS_WARNING("Failed to create popup surrogate in child."); + } +} + #endif // defined(OS_WIN) bool PluginInstanceParent::AnswerPluginFocusChange(const bool& gotFocus) { PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION)); // Currently only in use on windows - an event we receive from the child
--- a/dom/plugins/ipc/PluginInstanceParent.h +++ b/dom/plugins/ipc/PluginInstanceParent.h @@ -216,16 +216,19 @@ public: RecvRedrawPlugin() override; virtual bool RecvNegotiatedCarbon() override; virtual bool RecvAsyncNPP_NewResult(const NPError& aResult) override; + virtual bool + RecvSetNetscapeWindowAsParent(const NativeWindowHandle& childWindow) override; + NPError NPP_SetWindow(const NPWindow* aWindow); NPError NPP_GetValue(NPPVariable variable, void* retval); NPError NPP_SetValue(NPNVariable variable, void* value); void NPP_URLRedirectNotify(const char* url, int32_t status, void* notifyData); @@ -356,21 +359,26 @@ private: void SharedSurfaceAfterPaint(NPEvent* npevent); void SharedSurfaceRelease(); // Used in handling parent/child forwarding of events. static LRESULT CALLBACK PluginWindowHookProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); void SubclassPluginWindow(HWND aWnd); void UnsubclassPluginWindow(); + bool MaybeCreateAndParentChildPluginWindow(); + void MaybeCreateChildPopupSurrogate(); + private: gfx::SharedDIBWin mSharedSurfaceDib; nsIntRect mPluginPort; nsIntRect mSharedSize; HWND mPluginHWND; + // This is used for the normal child plugin HWND for windowed plugins and, + // if needed, also the child popup surrogate HWND for windowless plugins. HWND mChildPluginHWND; HWND mChildPluginsParentHWND; WNDPROC mPluginWndProc; bool mNestedEventState; // This will automatically release the textures when this object goes away. nsRefPtrHashtable<nsPtrHashKey<void>, ID3D10Texture2D> mTextureMap; #endif // defined(XP_WIN)
--- a/dom/plugins/ipc/PluginModuleChild.cpp +++ b/dom/plugins/ipc/PluginModuleChild.cpp @@ -2106,65 +2106,21 @@ PluginModuleChild::AllocPPluginInstanceC return new PluginInstanceChild(&mFunctions, aMimeType, aMode, aNames, aValues); } void PluginModuleChild::InitQuirksModes(const nsCString& aMimeType) { - if (mQuirks != QUIRKS_NOT_INITIALIZED) + if (mQuirks != QUIRKS_NOT_INITIALIZED) { return; - mQuirks = 0; - - nsPluginHost::SpecialType specialType = nsPluginHost::GetSpecialType(aMimeType); - - if (specialType == nsPluginHost::eSpecialType_Silverlight) { - mQuirks |= QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT; -#ifdef OS_WIN - mQuirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK; - mQuirks |= QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT; -#endif - } - - if (specialType == nsPluginHost::eSpecialType_Flash) { - mQuirks |= QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN; -#ifdef OS_WIN - mQuirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK; - mQuirks |= QUIRK_FLASH_THROTTLE_WMUSER_EVENTS; - mQuirks |= QUIRK_FLASH_HOOK_SETLONGPTR; - mQuirks |= QUIRK_FLASH_HOOK_GETWINDOWINFO; - mQuirks |= QUIRK_FLASH_FIXUP_MOUSE_CAPTURE; -#endif } -#ifdef OS_WIN - // QuickTime plugin usually loaded with audio/mpeg mimetype - NS_NAMED_LITERAL_CSTRING(quicktime, "npqtplugin"); - if (FindInReadable(quicktime, mPluginFilename)) { - mQuirks |= QUIRK_QUICKTIME_AVOID_SETWINDOW; - } -#endif - -#ifdef XP_MACOSX - // Whitelist Flash and Quicktime to support offline renderer - NS_NAMED_LITERAL_CSTRING(quicktime, "QuickTime Plugin.plugin"); - if (specialType == nsPluginHost::eSpecialType_Flash) { - mQuirks |= QUIRK_FLASH_AVOID_CGMODE_CRASHES; - mQuirks |= QUIRK_ALLOW_OFFLINE_RENDERER; - } else if (FindInReadable(quicktime, mPluginFilename)) { - mQuirks |= QUIRK_ALLOW_OFFLINE_RENDERER; - } -#endif - -#ifdef OS_WIN - if (specialType == nsPluginHost::eSpecialType_Unity) { - mQuirks |= QUIRK_UNITY_FIXUP_MOUSE_CAPTURE; - } -#endif + mQuirks = GetQuirksFromMimeTypeAndFilename(aMimeType, mPluginFilename); } bool PluginModuleChild::RecvPPluginInstanceConstructor(PPluginInstanceChild* aActor, const nsCString& aMimeType, const uint16_t& aMode, InfallibleTArray<nsCString>&& aNames, InfallibleTArray<nsCString>&& aValues)
--- a/dom/plugins/ipc/PluginModuleChild.h +++ b/dom/plugins/ipc/PluginModuleChild.h @@ -26,16 +26,17 @@ #ifdef MOZ_WIDGET_COCOA #include "PluginInterposeOSX.h" #endif #include "mozilla/plugins/PPluginModuleChild.h" #include "mozilla/plugins/PluginInstanceChild.h" #include "mozilla/plugins/PluginMessageUtils.h" +#include "mozilla/plugins/PluginQuirks.h" // NOTE: stolen from nsNPAPIPlugin.h #if defined(XP_WIN) #define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (__stdcall * _name) #else #define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (* _name) #endif @@ -237,66 +238,16 @@ public: SendPopCursor(); } bool GetNativeCursorsSupported() { return Settings().nativeCursorsSupported(); } #endif - // Quirks mode support for various plugin mime types - enum PluginQuirks { - QUIRKS_NOT_INITIALIZED = 0, - // Silverlight assumes it is transparent in windowless mode. This quirk - // matches the logic in nsNPAPIPluginInstance::SetWindowless. - QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT = 1 << 0, - // Win32: Hook TrackPopupMenu api so that we can swap out parent - // hwnds. The api will fail with parents not associated with our - // child ui thread. See WinlessHandleEvent for details. - QUIRK_WINLESS_TRACKPOPUP_HOOK = 1 << 1, - // Win32: Throttle flash WM_USER+1 heart beat messages to prevent - // flooding chromium's dispatch loop, which can cause ipc traffic - // processing lag. - QUIRK_FLASH_THROTTLE_WMUSER_EVENTS = 1 << 2, - // Win32: Catch resets on our subclass by hooking SetWindowLong. - QUIRK_FLASH_HOOK_SETLONGPTR = 1 << 3, - // X11: Work around a bug in Flash up to 10.1 d51 at least, where - // expose event top left coordinates within the plugin-rect and - // not at the drawable origin are misinterpreted. - QUIRK_FLASH_EXPOSE_COORD_TRANSLATION = 1 << 4, - // Win32: Catch get window info calls on the browser and tweak the - // results so mouse input works when flash is displaying it's settings - // window. - QUIRK_FLASH_HOOK_GETWINDOWINFO = 1 << 5, - // Win: Addresses a flash bug with mouse capture and full screen - // windows. - QUIRK_FLASH_FIXUP_MOUSE_CAPTURE = 1 << 6, - // Win: QuickTime steals focus on SetWindow calls even if it's hidden. - // Avoid calling SetWindow in that case. - QUIRK_QUICKTIME_AVOID_SETWINDOW = 1 << 7, - // Win: Check to make sure the parent window has focus before calling - // set focus on the child. Addresses a full screen dialog prompt - // problem in Silverlight. - QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT = 1 << 8, - // Mac: Allow the plugin to use offline renderer mode. - // Use this only if the plugin is certified the support the offline renderer. - QUIRK_ALLOW_OFFLINE_RENDERER = 1 << 9, - // Mac: Work around a Flash bug that can cause plugin process crashes - // in CoreGraphics mode: The Flash plugin sometimes accesses the - // CGContextRef we pass to it in NPP_HandleEvent(NPCocoaEventDrawRect) - // outside of that call. See bug 804606. - QUIRK_FLASH_AVOID_CGMODE_CRASHES = 1 << 10, - // Work around a Flash bug where it fails to check the error code of a - // NPN_GetValue(NPNVdocumentOrigin) call before trying to dereference - // its char* output. - QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN = 1 << 11, - // Win: Addresses a Unity bug with mouse capture. - QUIRK_UNITY_FIXUP_MOUSE_CAPTURE = 1 << 12, - }; - int GetQuirks() { return mQuirks; } const PluginSettings& Settings() const { return mCachedSettings; } private: NPError DoNP_Initialize(const PluginSettings& aSettings); void AddQuirk(PluginQuirks quirk) { if (mQuirks == QUIRKS_NOT_INITIALIZED)
--- a/dom/plugins/ipc/PluginModuleParent.cpp +++ b/dom/plugins/ipc/PluginModuleParent.cpp @@ -31,16 +31,17 @@ #include "mozilla/unused.h" #include "nsAutoPtr.h" #include "nsCRT.h" #include "nsIFile.h" #include "nsIObserverService.h" #include "nsNPAPIPlugin.h" #include "nsPrintfCString.h" #include "prsystem.h" +#include "PluginQuirks.h" #include "GeckoProfiler.h" #include "nsPluginTags.h" #include "nsUnicharUtils.h" #ifdef XP_WIN #include "mozilla/plugins/PluginSurfaceParent.h" #include "mozilla/widget/AudioSession.h" #include "PluginHangUIParent.h" @@ -620,17 +621,18 @@ PluginModuleChromeParent::WaitForIPCConn process->SetCallRunnableImmediately(true); if (!process->WaitUntilConnected()) { return false; } return true; } PluginModuleParent::PluginModuleParent(bool aIsChrome) - : mIsChrome(aIsChrome) + : mQuirks(QUIRKS_NOT_INITIALIZED) + , mIsChrome(aIsChrome) , mShutdown(false) , mHadLocalInstance(false) , mClearSiteDataSupported(false) , mGetSitesWithDataSupported(false) , mNPNIface(nullptr) , mNPPIface(nullptr) , mPlugin(nullptr) , mTaskFactory(this) @@ -1338,20 +1340,31 @@ PluginModuleParent::GetPluginDetails() return false; } nsPluginTag* pluginTag = host->TagForPlugin(mPlugin); if (!pluginTag) { return false; } mPluginName = pluginTag->Name(); mPluginVersion = pluginTag->Version(); + mPluginFilename = pluginTag->FileName(); mIsFlashPlugin = pluginTag->mIsFlashPlugin; return true; } +void +PluginModuleParent::InitQuirksModes(const nsCString& aMimeType) +{ + if (mQuirks != QUIRKS_NOT_INITIALIZED) { + return; + } + + mQuirks = GetQuirksFromMimeTypeAndFilename(aMimeType, mPluginFilename); +} + #ifdef XP_WIN void PluginModuleChromeParent::EvaluateHangUIState(const bool aReset) { int32_t minDispSecs = Preferences::GetInt(kHangUIMinDisplayPref, 10); int32_t autoStopSecs = Preferences::GetInt(kChildTimeoutPref, 0); int32_t timeoutSecs = 0; if (autoStopSecs > 0 && autoStopSecs < minDispSecs) { @@ -2534,16 +2547,17 @@ PluginModuleParent::NPP_New(NPMIMEType p mSurrogateInstances.AppendElement(surrogate); *error = NPERR_NO_ERROR; return NS_PLUGIN_INIT_PENDING; } } if (mPluginName.IsEmpty()) { GetPluginDetails(); + InitQuirksModes(nsDependentCString(pluginType)); /** mTimeBlocked measures the time that the main thread has been blocked * on plugin module initialization. As implemented, this is the sum of * plugin-container launch + toolhelp32 snapshot + NP_Initialize. * We don't accumulate its value until here because the plugin info * is not available until *after* NP_Initialize. */ Telemetry::Accumulate(Telemetry::BLOCKED_ON_PLUGIN_MODULE_INIT_MS, GetHistogramKey(),
--- a/dom/plugins/ipc/PluginModuleParent.h +++ b/dom/plugins/ipc/PluginModuleParent.h @@ -132,16 +132,18 @@ public: return mPluginName + mPluginVersion; } virtual nsresult GetRunID(uint32_t* aRunID) override; virtual void SetHasLocalInstance() override { mHadLocalInstance = true; } + int GetQuirks() { return mQuirks; } + protected: virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(const Message& parent, const Message& child) override { return MediateRace(parent, child); } virtual bool @@ -273,16 +275,20 @@ protected: virtual nsresult NPP_ClearSiteData(const char* site, uint64_t flags, uint64_t maxAge, nsCOMPtr<nsIClearSiteDataCallback> callback) override; virtual nsresult NPP_GetSitesWithData(nsCOMPtr<nsIGetSitesWithDataCallback> callback) override; private: std::map<uint64_t, nsCOMPtr<nsIClearSiteDataCallback>> mClearSiteDataCallbacks; std::map<uint64_t, nsCOMPtr<nsIGetSitesWithDataCallback>> mSitesWithDataCallbacks; + nsCString mPluginFilename; + int mQuirks; + void InitQuirksModes(const nsCString& aMimeType); + public: #if defined(XP_MACOSX) virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) override; virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor) override; #endif void InitAsyncSurrogates();
new file mode 100644 --- /dev/null +++ b/dom/plugins/ipc/PluginQuirks.cpp @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: sw=4 ts=4 et : + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "PluginQuirks.h" + +#include "nsPluginHost.h" + +namespace mozilla { +namespace plugins { + +int GetQuirksFromMimeTypeAndFilename(const nsCString& aMimeType, + const nsCString& aPluginFilename) +{ + int quirks = 0; + + nsPluginHost::SpecialType specialType = nsPluginHost::GetSpecialType(aMimeType); + + if (specialType == nsPluginHost::eSpecialType_Silverlight) { + quirks |= QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT; +#ifdef OS_WIN + quirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK; + quirks |= QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT; +#endif + } + + if (specialType == nsPluginHost::eSpecialType_Flash) { + quirks |= QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN; +#ifdef OS_WIN + quirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK; + quirks |= QUIRK_FLASH_THROTTLE_WMUSER_EVENTS; + quirks |= QUIRK_FLASH_HOOK_SETLONGPTR; + quirks |= QUIRK_FLASH_HOOK_GETWINDOWINFO; + quirks |= QUIRK_FLASH_FIXUP_MOUSE_CAPTURE; +#endif + } + +#ifdef OS_WIN + // QuickTime plugin usually loaded with audio/mpeg mimetype + NS_NAMED_LITERAL_CSTRING(quicktime, "npqtplugin"); + if (FindInReadable(quicktime, aPluginFilename)) { + quirks |= QUIRK_QUICKTIME_AVOID_SETWINDOW; + } +#endif + +#ifdef XP_MACOSX + // Whitelist Flash and Quicktime to support offline renderer + NS_NAMED_LITERAL_CSTRING(quicktime, "QuickTime Plugin.plugin"); + if (specialType == nsPluginHost::eSpecialType_Flash) { + quirks |= QUIRK_FLASH_AVOID_CGMODE_CRASHES; + quirks |= QUIRK_ALLOW_OFFLINE_RENDERER; + } else if (FindInReadable(quicktime, aPluginFilename)) { + quirks |= QUIRK_ALLOW_OFFLINE_RENDERER; + } +#endif + +#ifdef OS_WIN + if (specialType == nsPluginHost::eSpecialType_Unity) { + quirks |= QUIRK_UNITY_FIXUP_MOUSE_CAPTURE; + } +#endif + + return quirks; +} + +} /* namespace plugins */ +} /* namespace mozilla */
new file mode 100644 --- /dev/null +++ b/dom/plugins/ipc/PluginQuirks.h @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: sw=4 ts=4 et : + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef dom_plugins_PluginQuirks_h +#define dom_plugins_PluginQuirks_h + +namespace mozilla { +namespace plugins { + +// Quirks mode support for various plugin mime types +enum PluginQuirks { + QUIRKS_NOT_INITIALIZED = 0, + // Silverlight assumes it is transparent in windowless mode. This quirk + // matches the logic in nsNPAPIPluginInstance::SetWindowless. + QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT = 1 << 0, + // Win32: Hook TrackPopupMenu api so that we can swap out parent + // hwnds. The api will fail with parents not associated with our + // child ui thread. See WinlessHandleEvent for details. + QUIRK_WINLESS_TRACKPOPUP_HOOK = 1 << 1, + // Win32: Throttle flash WM_USER+1 heart beat messages to prevent + // flooding chromium's dispatch loop, which can cause ipc traffic + // processing lag. + QUIRK_FLASH_THROTTLE_WMUSER_EVENTS = 1 << 2, + // Win32: Catch resets on our subclass by hooking SetWindowLong. + QUIRK_FLASH_HOOK_SETLONGPTR = 1 << 3, + // X11: Work around a bug in Flash up to 10.1 d51 at least, where + // expose event top left coordinates within the plugin-rect and + // not at the drawable origin are misinterpreted. + QUIRK_FLASH_EXPOSE_COORD_TRANSLATION = 1 << 4, + // Win32: Catch get window info calls on the browser and tweak the + // results so mouse input works when flash is displaying it's settings + // window. + QUIRK_FLASH_HOOK_GETWINDOWINFO = 1 << 5, + // Win: Addresses a flash bug with mouse capture and full screen + // windows. + QUIRK_FLASH_FIXUP_MOUSE_CAPTURE = 1 << 6, + // Win: QuickTime steals focus on SetWindow calls even if it's hidden. + // Avoid calling SetWindow in that case. + QUIRK_QUICKTIME_AVOID_SETWINDOW = 1 << 7, + // Win: Check to make sure the parent window has focus before calling + // set focus on the child. Addresses a full screen dialog prompt + // problem in Silverlight. + QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT = 1 << 8, + // Mac: Allow the plugin to use offline renderer mode. + // Use this only if the plugin is certified the support the offline renderer. + QUIRK_ALLOW_OFFLINE_RENDERER = 1 << 9, + // Mac: Work around a Flash bug that can cause plugin process crashes + // in CoreGraphics mode: The Flash plugin sometimes accesses the + // CGContextRef we pass to it in NPP_HandleEvent(NPCocoaEventDrawRect) + // outside of that call. See bug 804606. + QUIRK_FLASH_AVOID_CGMODE_CRASHES = 1 << 10, + // Work around a Flash bug where it fails to check the error code of a + // NPN_GetValue(NPNVdocumentOrigin) call before trying to dereference + // its char* output. + QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN = 1 << 11, + // Win: Addresses a Unity bug with mouse capture. + QUIRK_UNITY_FIXUP_MOUSE_CAPTURE = 1 << 12, +}; + +int GetQuirksFromMimeTypeAndFilename(const nsCString& aMimeType, + const nsCString& aPluginFilename); + +} /* namespace plugins */ +} /* namespace mozilla */ + +#endif // ifndef dom_plugins_PluginQuirks_h
--- a/dom/plugins/ipc/moz.build +++ b/dom/plugins/ipc/moz.build @@ -26,16 +26,17 @@ EXPORTS.mozilla.plugins += [ 'PluginDataResolver.h', 'PluginInstanceChild.h', 'PluginInstanceParent.h', 'PluginMessageUtils.h', 'PluginModuleChild.h', 'PluginModuleParent.h', 'PluginProcessChild.h', 'PluginProcessParent.h', + 'PluginQuirks.h', 'PluginScriptableObjectChild.h', 'PluginScriptableObjectParent.h', 'PluginScriptableObjectUtils-inl.h', 'PluginScriptableObjectUtils.h', 'PluginStreamChild.h', 'PluginStreamParent.h', 'PluginUtilsOSX.h', 'PluginWidgetChild.h', @@ -81,16 +82,17 @@ UNIFIED_SOURCES += [ 'ChildTimer.cpp', 'PluginAsyncSurrogate.cpp', 'PluginBackgroundDestroyer.cpp', 'PluginInstanceParent.cpp', 'PluginMessageUtils.cpp', 'PluginModuleParent.cpp', 'PluginProcessChild.cpp', 'PluginProcessParent.cpp', + 'PluginQuirks.cpp', 'PluginScriptableObjectChild.cpp', 'PluginScriptableObjectParent.cpp', 'PluginStreamChild.cpp', 'PluginStreamParent.cpp', ] SOURCES += [ 'PluginInstanceChild.cpp', # 'PluginThreadCallback' : ambiguous symbol
--- a/dom/presentation/PresentationSession.cpp +++ b/dom/presentation/PresentationSession.cpp @@ -1,17 +1,17 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=2 sw=2 sts=2 et cindent: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/AsyncEventDispatcher.h" +#include "mozilla/dom/MessageEvent.h" #include "nsCycleCollectionParticipant.h" -#include "nsIDOMMessageEvent.h" #include "nsIPresentationService.h" #include "nsServiceManagerUtils.h" #include "nsStringStream.h" #include "PresentationSession.h" using namespace mozilla; using namespace mozilla::dom; @@ -255,30 +255,26 @@ PresentationSession::DispatchMessageEven // Get the origin. nsAutoString origin; nsresult rv = nsContentUtils::GetUTFOrigin(global->PrincipalOrNull(), origin); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } - nsCOMPtr<nsIDOMEvent> event; - rv = NS_NewDOMMessageEvent(getter_AddRefs(event), this, nullptr, nullptr); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } + nsRefPtr<MessageEvent> messageEvent = + NS_NewDOMMessageEvent(this, nullptr, nullptr); - nsCOMPtr<nsIDOMMessageEvent> messageEvent = do_QueryInterface(event); rv = messageEvent->InitMessageEvent(NS_LITERAL_STRING("message"), false, false, aData, origin, EmptyString(), nullptr); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } - event->SetTrusted(true); + messageEvent->SetTrusted(true); nsRefPtr<AsyncEventDispatcher> asyncDispatcher = - new AsyncEventDispatcher(this, event); + new AsyncEventDispatcher(this, static_cast<Event*>(messageEvent)); return asyncDispatcher->PostDOMEvent(); }
--- a/dom/smil/TimeEvent.cpp +++ b/dom/smil/TimeEvent.cpp @@ -75,19 +75,16 @@ TimeEvent::InitTimeEvent(const nsAString } } // namespace dom } // namespace mozilla using namespace mozilla; using namespace mozilla::dom; -nsresult -NS_NewDOMTimeEvent(nsIDOMEvent** aInstancePtrResult, - EventTarget* aOwner, +already_AddRefed<TimeEvent> +NS_NewDOMTimeEvent(EventTarget* aOwner, nsPresContext* aPresContext, InternalSMILTimeEvent* aEvent) { - TimeEvent* it = new TimeEvent(aOwner, aPresContext, aEvent); - NS_ADDREF(it); - *aInstancePtrResult = static_cast<Event*>(it); - return NS_OK; + nsRefPtr<TimeEvent> it = new TimeEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/smil/TimeEvent.h +++ b/dom/smil/TimeEvent.h @@ -58,9 +58,14 @@ private: nsCOMPtr<nsIDOMWindow> mView; int32_t mDetail; }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::TimeEvent> +NS_NewDOMTimeEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::InternalSMILTimeEvent* aEvent); + #endif // mozilla_dom_TimeEvent_h_
--- a/dom/speakermanager/SpeakerManager.cpp +++ b/dom/speakermanager/SpeakerManager.cpp @@ -1,24 +1,27 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "SpeakerManager.h" + +#include "mozilla/Services.h" + +#include "mozilla/dom/Event.h" + +#include "AudioChannelService.h" +#include "nsIDocShell.h" #include "nsIDOMClassInfo.h" -#include "nsIDOMEvent.h" #include "nsIDOMEventListener.h" -#include "SpeakerManagerService.h" +#include "nsIInterfaceRequestorUtils.h" #include "nsIPermissionManager.h" -#include "nsIInterfaceRequestorUtils.h" -#include "nsIDocShell.h" -#include "AudioChannelService.h" -#include "mozilla/Services.h" +#include "SpeakerManagerService.h" namespace mozilla { namespace dom { NS_IMPL_QUERY_INTERFACE_INHERITED(SpeakerManager, DOMEventTargetHelper, nsIDOMEventListener) NS_IMPL_ADDREF_INHERITED(SpeakerManager, DOMEventTargetHelper) NS_IMPL_RELEASE_INHERITED(SpeakerManager, DOMEventTargetHelper) @@ -81,22 +84,17 @@ void SpeakerManager::DispatchSimpleEvent(const nsAString& aStr) { MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread"); nsresult rv = CheckInnerWindowCorrectness(); if (NS_FAILED(rv)) { return; } - nsCOMPtr<nsIDOMEvent> event; - rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr); - if (NS_FAILED(rv)) { - NS_WARNING("Failed to create the error event!!!"); - return; - } + nsRefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr); rv = event->InitEvent(aStr, false, false); if (NS_FAILED(rv)) { NS_WARNING("Failed to init the error event!!!"); return; } event->SetTrusted(true);
--- a/dom/svg/SVGZoomEvent.cpp +++ b/dom/svg/SVGZoomEvent.cpp @@ -85,18 +85,19 @@ SVGZoomEvent::~SVGZoomEvent() } // namespace dom } // namespace mozilla //////////////////////////////////////////////////////////////////////// // Exported creation functions: -nsresult -NS_NewDOMSVGZoomEvent(nsIDOMEvent** aInstancePtrResult, - mozilla::dom::EventTarget* aOwner, +using namespace mozilla; +using namespace mozilla::dom; + +already_AddRefed<SVGZoomEvent> +NS_NewDOMSVGZoomEvent(EventTarget* aOwner, nsPresContext* aPresContext, mozilla::InternalSVGZoomEvent* aEvent) { - mozilla::dom::SVGZoomEvent* it = - new mozilla::dom::SVGZoomEvent(aOwner, aPresContext, aEvent); - return CallQueryInterface(it, aInstancePtrResult); + nsRefPtr<SVGZoomEvent> it = new SVGZoomEvent(aOwner, aPresContext, aEvent); + return it.forget(); }
--- a/dom/svg/SVGZoomEvent.h +++ b/dom/svg/SVGZoomEvent.h @@ -66,9 +66,14 @@ private: float mNewScale; nsRefPtr<DOMSVGPoint> mPreviousTranslate; nsRefPtr<DOMSVGPoint> mNewTranslate; }; } // namespace dom } // namespace mozilla +already_AddRefed<mozilla::dom::SVGZoomEvent> +NS_NewDOMSVGZoomEvent(mozilla::dom::EventTarget* aOwner, + nsPresContext* aPresContext, + mozilla::InternalSVGZoomEvent* aEvent); + #endif // mozilla_dom_SVGZoomEvent_h
--- a/dom/tests/mochitest/pointerlock/mochitest.ini +++ b/dom/tests/mochitest/pointerlock/mochitest.ini @@ -16,9 +16,9 @@ support-files = file_targetOutOfFocus.html file_screenClientXYConst.html file_suppressSomeMouseEvents.html file_locksvgelement.html file_allowPointerLockSandboxFlag.html iframe_differentDOM.html [test_pointerlock-api.html] -skip-if = buildapp == 'b2g' || toolkit == 'android' || buildapp == 'mulet' || e10s # B2G - window.open focus issues using fullscreen +skip-if = buildapp == 'b2g' || toolkit == 'android' || buildapp == 'mulet' || e10s || os == 'linux' || os == 'win' # B2G - window.open focus issues using fullscreen. (For Linux & Win) Bug1180351
--- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -1452,36 +1452,35 @@ RuntimeService::RegisterWorker(JSContext nsCString sharedWorkerScriptSpec; const bool isServiceWorker = aWorkerPrivate->IsServiceWorker(); if (isServiceWorker) { AssertIsOnMainThread(); Telemetry::Accumulate(Telemetry::SERVICE_WORKER_SPAWN_ATTEMPTS, 1); } - bool isSharedOrServiceWorker = aWorkerPrivate->IsSharedWorker() || - aWorkerPrivate->IsServiceWorker(); - if (isSharedOrServiceWorker) { + const bool isSharedWorker = aWorkerPrivate->IsSharedWorker(); + if (isSharedWorker || isServiceWorker) { AssertIsOnMainThread(); nsCOMPtr<nsIURI> scriptURI = aWorkerPrivate->GetResolvedScriptURI(); NS_ASSERTION(scriptURI, "Null script URI!"); nsresult rv = scriptURI->GetSpec(sharedWorkerScriptSpec); if (NS_FAILED(rv)) { NS_WARNING("GetSpec failed?!"); xpc::Throw(aCx, rv); return false; } NS_ASSERTION(!sharedWorkerScriptSpec.IsEmpty(), "Empty spec!"); } bool exemptFromPerDomainMax = false; - if (aWorkerPrivate->IsServiceWorker()) { + if (isServiceWorker) { AssertIsOnMainThread(); exemptFromPerDomainMax = Preferences::GetBool("dom.serviceWorkers.exemptFromPerDomainMax", false); } const nsCString& domain = aWorkerPrivate->Domain(); WorkerDomainInfo* domainInfo; @@ -1499,41 +1498,42 @@ RuntimeService::RegisterWorker(JSContext queued = gMaxWorkersPerDomain && domainInfo->ActiveWorkerCount() >= gMaxWorkersPerDomain && !domain.IsEmpty() && !exemptFromPerDomainMax; if (queued) { domainInfo->mQueuedWorkers.AppendElement(aWorkerPrivate); - if (isServiceWorker) { + if (isServiceWorker || isSharedWorker) { AssertIsOnMainThread(); // ServiceWorker spawn gets queued due to hitting max workers per domain // limit so let's log a warning. // Note: aWorkerPrivate->GetDocument() call might result nullptr due to // no window so the message warning will show up in the browser console. nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, NS_LITERAL_CSTRING("DOM"), aWorkerPrivate->GetDocument(), nsContentUtils::eDOM_PROPERTIES, "HittingMaxWorkersPerDomain"); - Telemetry::Accumulate(Telemetry::SERVICE_WORKER_SPAWN_GETS_QUEUED, 1); + Telemetry::Accumulate(isSharedWorker ? Telemetry::SHARED_WORKER_SPAWN_GETS_QUEUED + : Telemetry::SERVICE_WORKER_SPAWN_GETS_QUEUED, 1); } } else if (parent) { domainInfo->mChildWorkerCount++; } else if (isServiceWorker) { domainInfo->mActiveServiceWorkers.AppendElement(aWorkerPrivate); } else { domainInfo->mActiveWorkers.AppendElement(aWorkerPrivate); } - if (isSharedOrServiceWorker) { + if (isSharedWorker || isServiceWorker) { const nsCString& sharedWorkerName = aWorkerPrivate->SharedWorkerName(); const nsCString& cacheName = aWorkerPrivate->IsServiceWorker() ? NS_ConvertUTF16toUTF8(aWorkerPrivate->ServiceWorkerCacheName()) : EmptyCString(); nsAutoCString key; GenerateSharedWorkerKey(sharedWorkerScriptSpec, sharedWorkerName,
--- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -2369,24 +2369,20 @@ public: bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { MOZ_ASSERT(aWorkerPrivate); WorkerGlobalScope* globalScope = aWorkerPrivate->GlobalScope(); - nsCOMPtr<nsIDOMEvent> event; - nsresult rv = - NS_NewDOMEvent(getter_AddRefs(event), globalScope, nullptr, nullptr); - if (NS_WARN_IF(NS_FAILED(rv))) { - return false; - } - - rv = event->InitEvent(NS_LITERAL_STRING("pushsubscriptionchange"), false, false); + nsRefPtr<Event> event = NS_NewDOMEvent(globalScope, nullptr, nullptr); + + nsresult rv = event->InitEvent(NS_LITERAL_STRING("pushsubscriptionchange"), + false, false); if (NS_WARN_IF(NS_FAILED(rv))) { return false; } event->SetTrusted(true); globalScope->DispatchDOMEvent(nullptr, event, nullptr, nullptr); return true;
--- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -1043,25 +1043,19 @@ private: { JS::Rooted<JSObject*> target(aCx, JS::CurrentGlobalOrNull(aCx)); NS_ASSERTION(target, "This must never be null!"); aWorkerPrivate->CloseHandlerStarted(); WorkerGlobalScope* globalScope = aWorkerPrivate->GlobalScope(); - nsCOMPtr<nsIDOMEvent> event; - nsresult rv = - NS_NewDOMEvent(getter_AddRefs(event), globalScope, nullptr, nullptr); - if (NS_FAILED(rv)) { - Throw(aCx, rv); - return false; - } - - rv = event->InitEvent(NS_LITERAL_STRING("close"), false, false); + nsRefPtr<Event> event = NS_NewDOMEvent(globalScope, nullptr, nullptr); + + nsresult rv = event->InitEvent(NS_LITERAL_STRING("close"), false, false); if (NS_FAILED(rv)) { Throw(aCx, rv); return false; } event->SetTrusted(true); globalScope->DispatchDOMEvent(nullptr, event, nullptr, nullptr); @@ -3614,22 +3608,19 @@ WorkerPrivate::OfflineStatusChangeEventI nsString eventType; if (aIsOffline) { eventType.AssignLiteral("offline"); } else { eventType.AssignLiteral("online"); } - nsCOMPtr<nsIDOMEvent> event; - nsresult rv = - NS_NewDOMEvent(getter_AddRefs(event), globalScope, nullptr, nullptr); - NS_ENSURE_SUCCESS_VOID(rv); - - rv = event->InitEvent(eventType, false, false); + nsRefPtr<Event> event = NS_NewDOMEvent(globalScope, nullptr, nullptr); + + nsresult rv = event->InitEvent(eventType, false, false); NS_ENSURE_SUCCESS_VOID(rv); event->SetTrusted(true); globalScope->DispatchDOMEvent(nullptr, event, nullptr, nullptr); } template <class Derived>
--- a/dom/workers/XMLHttpRequest.cpp +++ b/dom/workers/XMLHttpRequest.cpp @@ -1390,29 +1390,29 @@ EventRunnable::WorkerRun(JSContext* aCx, target = xhr->GetUploadObjectNoCreate(); } else { target = xhr; } MOZ_ASSERT(target); - nsCOMPtr<nsIDOMEvent> event; + nsRefPtr<Event> event; if (mProgressEvent) { ProgressEventInit init; init.mBubbles = false; init.mCancelable = false; init.mLengthComputable = mLengthComputable; init.mLoaded = mLoaded; init.mTotal = mTotal; event = ProgressEvent::Constructor(target, mType, init); } else { - NS_NewDOMEvent(getter_AddRefs(event), target, nullptr, nullptr); + event = NS_NewDOMEvent(target, nullptr, nullptr); if (event) { event->InitEvent(mType, false, false); } } if (!event) { return false; @@ -1791,23 +1791,20 @@ XMLHttpRequest::DispatchPrematureAbortEv mWorkerPrivate->AssertIsOnWorkerThread(); MOZ_ASSERT(aTarget); if (!mProxy) { aRv.Throw(NS_ERROR_FAILURE); return; } - nsCOMPtr<nsIDOMEvent> event; + nsRefPtr<Event> event; if (aEventType.EqualsLiteral("readystatechange")) { - NS_NewDOMEvent(getter_AddRefs(event), aTarget, nullptr, nullptr); - - if (event) { - event->InitEvent(aEventType, false, false); - } + event = NS_NewDOMEvent(aTarget, nullptr, nullptr); + event->InitEvent(aEventType, false, false); } else { ProgressEventInit init; init.mBubbles = false; init.mCancelable = false; if (aUploadTarget) { init.mLengthComputable = mProxy->mLastUploadLengthComputable; init.mLoaded = mProxy->mLastUploadLoaded;
--- a/dom/workers/test/serviceworkers/fetch/index.html +++ b/dom/workers/test/serviceworkers/fetch/index.html @@ -113,16 +113,43 @@ elem.id = 'intercepted-iframe'; elem.src = "nonexistent_page.html"; return elem; }, function() { my_ok(this.test_result, "iframe load should be intercepted"); }); gExpected++; + var xmlDoc = document.implementation.createDocument(null, null, null); + xmlDoc.load('load_cross_origin_xml_document_synthetic.xml'); + xmlDoc.onload = function(evt) { + var content = new XMLSerializer().serializeToString(evt.target); + my_ok(!content.includes('parsererror'), "Load synthetic cross origin XML Document should be allowed"); + finish(); + }; + + gExpected++; + var xmlDoc = document.implementation.createDocument(null, null, null); + xmlDoc.load('load_cross_origin_xml_document_cors.xml'); + xmlDoc.onload = function(evt) { + var content = new XMLSerializer().serializeToString(evt.target); + my_ok(!content.includes('parsererror'), "Load CORS cross origin XML Document should be allowed"); + finish(); + }; + + gExpected++; + var xmlDoc = document.implementation.createDocument(null, null, null); + xmlDoc.load('load_cross_origin_xml_document_opaque.xml'); + xmlDoc.onload = function(evt) { + var content = new XMLSerializer().serializeToString(evt.target); + my_ok(content.includes('parsererror'), "Load opaque cross origin XML Document should not be allowed"); + finish(); + }; + + gExpected++; var worker = new Worker('nonexistent_worker_script.js'); worker.onmessage = function(e) { my_ok(e.data == "worker-intercept-success", "worker load intercepted"); finish(); }; worker.onerror = function() { my_ok(false, "worker load should be intercepted"); };
--- a/dom/workers/test/serviceworkers/fetch_event_worker.js +++ b/dom/workers/test/serviceworkers/fetch_event_worker.js @@ -230,9 +230,42 @@ onfetch = function(ev) { else if (ev.request.url.includes('redirect_serviceworker.sjs')) { // The redirect_serviceworker.sjs server-side JavaScript file redirects to // 'http://mochi.test:8888/tests/dom/workers/test/serviceworkers/worker.js' // The redirected fetch should not go through the SW since the original // fetch was initiated from a SW. ev.respondWith(fetch('redirect_serviceworker.sjs')); } + + else if (ev.request.url.includes('load_cross_origin_xml_document_synthetic.xml')) { + if (ev.request.mode != 'same-origin') { + ev.respondWith(Promise.reject()); + return; + } + + ev.respondWith(Promise.resolve( + new Response("<response>body</response>", { headers: {'Content-Type': 'text/xtml'}}) + )); + } + + else if (ev.request.url.includes('load_cross_origin_xml_document_cors.xml')) { + if (ev.request.mode != 'same-origin') { + ev.respondWith(Promise.reject()); + return; + } + + var url = 'http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200&allowOrigin=*'; + ev.respondWith(fetch(url, { mode: 'cors' })); + } + + else if (ev.request.url.includes('load_cross_origin_xml_document_opaque.xml')) { + if (ev.request.mode != 'same-origin') { + Promise.resolve( + new Response("<error>Invalid Request mode</error>", { headers: {'Content-Type': 'text/xtml'}}) + ); + return; + } + + var url = 'http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200'; + ev.respondWith(fetch(url, { mode: 'no-cors' })); + } };
--- a/dom/xml/XMLDocument.cpp +++ b/dom/xml/XMLDocument.cpp @@ -17,17 +17,17 @@ #include "nsHTMLParts.h" #include "nsIComponentManager.h" #include "nsIDOMElement.h" #include "nsIBaseWindow.h" #include "nsIDOMWindow.h" #include "nsIDOMDocumentType.h" #include "nsCOMPtr.h" #include "nsXPIDLString.h" -#include "nsIHttpChannel.h" +#include "nsIHttpChannelInternal.h" #include "nsIURI.h" #include "nsIServiceManager.h" #include "nsNetUtil.h" #include "nsError.h" #include "nsIScriptSecurityManager.h" #include "nsIPrincipal.h" #include "nsLayoutCID.h" #include "mozilla/dom/Attr.h" @@ -416,16 +416,24 @@ XMLDocument::Load(const nsAString& aUrl, req, nsIRequest::LOAD_BACKGROUND); if (NS_FAILED(rv)) { aRv.Throw(rv); return false; } + // TODO Bug 1189945: Remove nsIChannel CorsMode flag and set Request.mode + // based on nsILoadInfo securityFlags instead. This block will be removed + // when Request.mode set correctly. + nsCOMPtr<nsIHttpChannelInternal> httpChannel = do_QueryInterface(channel); + if (httpChannel) { + httpChannel->SetCorsMode(nsIHttpChannelInternal::CORS_MODE_SAME_ORIGIN); + } + // StartDocumentLoad asserts that readyState is uninitialized, so // uninitialize it. SetReadyStateInternal make this transition invisible to // Web content. But before doing that, assert that the current readyState // is complete as it should be after the call to ResetToURI() above. MOZ_ASSERT(GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE, "Bad readyState"); SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED);
--- a/dom/xml/nsXMLPrettyPrinter.cpp +++ b/dom/xml/nsXMLPrettyPrinter.cpp @@ -18,17 +18,17 @@ #include "mozilla/dom/Element.h" #include "nsIDOMDocumentFragment.h" #include "nsBindingManager.h" #include "nsXBLService.h" #include "nsIScriptSecurityManager.h" #include "mozilla/Preferences.h" #include "nsIDocument.h" #include "nsVariant.h" -#include "nsIDOMCustomEvent.h" +#include "mozilla/dom/CustomEvent.h" using namespace mozilla; using namespace mozilla::dom; NS_IMPL_ISUPPORTS(nsXMLPrettyPrinter, nsIDocumentObserver, nsIMutationObserver) @@ -151,32 +151,29 @@ nsXMLPrettyPrinter::PrettyPrint(nsIDocum // Load the bindings. nsRefPtr<nsXBLBinding> unused; bool ignored; rv = xblService->LoadBindings(rootCont, bindingUri, sysPrincipal, getter_AddRefs(unused), &ignored); NS_ENSURE_SUCCESS(rv, rv); // Fire an event at the bound element to pass it |resultFragment|. - nsCOMPtr<nsIDOMEvent> domEvent; - rv = NS_NewDOMCustomEvent(getter_AddRefs(domEvent), rootCont, - nullptr, nullptr); - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr<nsIDOMCustomEvent> customEvent = do_QueryInterface(domEvent); - MOZ_ASSERT(customEvent); + nsRefPtr<CustomEvent> event = + NS_NewDOMCustomEvent(rootCont, nullptr, nullptr); + MOZ_ASSERT(event); nsCOMPtr<nsIWritableVariant> resultFragmentVariant = new nsVariant(); rv = resultFragmentVariant->SetAsISupports(resultFragment); MOZ_ASSERT(NS_SUCCEEDED(rv)); - rv = customEvent->InitCustomEvent(NS_LITERAL_STRING("prettyprint-dom-created"), - /* bubbles = */ false, /* cancelable = */ false, - /* detail = */ resultFragmentVariant); + rv = event->InitCustomEvent(NS_LITERAL_STRING("prettyprint-dom-created"), + /* bubbles = */ false, /* cancelable = */ false, + /* detail = */ resultFragmentVariant); NS_ENSURE_SUCCESS(rv, rv); - customEvent->SetTrusted(true); + event->SetTrusted(true); bool dummy; - rv = rootCont->DispatchEvent(domEvent, &dummy); + rv = rootCont->DispatchEvent(static_cast<Event*>(event), &dummy); NS_ENSURE_SUCCESS(rv, rv); // Observe the document so we know when to switch to "normal" view aDocument->AddObserver(this); mDocument = aDocument; NS_ADDREF_THIS();
--- a/js/public/TraceKind.h +++ b/js/public/TraceKind.h @@ -93,17 +93,19 @@ JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF); // Downcast the |void *thing| to the specific type designated by |traceKind|, // and pass it to the functor |f| along with |... args|, forwarded. Pass the // type designated by |traceKind| as the functor's template argument. The // |thing| parameter is optional; without it, we simply pass through |... args|. // GCC and Clang require an explicit template declaration in front of the // specialization of operator() because it is a dependent template. MSVC, on // the other hand, gets very confused if we have a |template| token there. -#ifdef _MSC_VER +// The clang-cl front end defines _MSC_VER, but still requires the explicit +// template declaration, so we must test for __clang__ here as well. +#if defined(_MSC_VER) && !defined(__clang__) # define JS_DEPENDENT_TEMPLATE_HINT #else # define JS_DEPENDENT_TEMPLATE_HINT template #endif template <typename F, typename... Args> auto DispatchTraceKindTyped(F f, JS::TraceKind traceKind, Args&&... args) -> decltype(f. JS_DEPENDENT_TEMPLATE_HINT operator()<JSObject>(mozilla::Forward<Args>(args)...))
--- a/js/src/asmjs/AsmJSFrameIterator.cpp +++ b/js/src/asmjs/AsmJSFrameIterator.cpp @@ -131,17 +131,17 @@ static const unsigned PushedRetAddr = 4; static const unsigned PushedFP = 16; static const unsigned StoredFP = 20; static const unsigned PostStorePrePopFP = 4; #elif defined(JS_CODEGEN_ARM64) static const unsigned PushedRetAddr = 0; static const unsigned PushedFP = 0; static const unsigned StoredFP = 0; static const unsigned PostStorePrePopFP = 0; -#elif defined(JS_CODEGEN_MIPS) +#elif defined(JS_CODEGEN_MIPS32) static const unsigned PushedRetAddr = 8; static const unsigned PushedFP = 24; static const unsigned StoredFP = 28; static const unsigned PostStorePrePopFP = 4; #elif defined(JS_CODEGEN_NONE) # if defined(DEBUG) static const unsigned PushedRetAddr = 0; static const unsigned PostStorePrePopFP = 0; @@ -152,17 +152,17 @@ static const unsigned StoredFP = 1; # error "Unknown architecture!" #endif static void PushRetAddr(MacroAssembler& masm) { #if defined(JS_CODEGEN_ARM) masm.push(lr); -#elif defined(JS_CODEGEN_MIPS) +#elif defined(JS_CODEGEN_MIPS32) masm.push(ra); #else // The x86/x64 call instruction pushes the return address. #endif } // Generate a prologue that maintains AsmJSActivation::fp as the virtual frame // pointer so that AsmJSProfilingFrameIterator can walk the stack at any pc in @@ -216,17 +216,17 @@ GenerateProfilingPrologue(MacroAssembler } // Generate the inverse of GenerateProfilingPrologue. static void GenerateProfilingEpilogue(MacroAssembler& masm, unsigned framePushed, AsmJSExit::Reason reason, Label* profilingReturn) { Register scratch = ABIArgGenerator::NonReturn_VolatileReg0; -#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_MIPS) +#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_MIPS32) Register scratch2 = ABIArgGenerator::NonReturn_VolatileReg1; #endif if (framePushed) masm.addToStackPtr(Imm32(framePushed)); masm.loadAsmJSActivation(scratch); @@ -240,17 +240,17 @@ GenerateProfilingEpilogue(MacroAssembler #if defined(JS_CODEGEN_ARM) AutoForbidPools afp(&masm, /* number of instructions in scope = */ 4); #endif // sp protects the stack from clobber via asynchronous signal handlers // and the async interrupt exit. Since activation.fp can be read at any // time and still points to the current frame, be careful to only update // sp after activation.fp has been repointed to the caller's frame. -#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_MIPS) +#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_MIPS32) masm.loadPtr(Address(masm.getStackPointer(), 0), scratch2); masm.storePtr(scratch2, Address(scratch, AsmJSActivation::offsetOfFP())); DebugOnly<uint32_t> prePop = masm.currentOffset(); masm.addToStackPtr(Imm32(sizeof(void *))); MOZ_ASSERT(PostStorePrePopFP == masm.currentOffset() - prePop); #else masm.pop(Address(scratch, AsmJSActivation::offsetOfFP())); MOZ_ASSERT(PostStorePrePopFP == 0); @@ -334,17 +334,17 @@ js::GenerateAsmJSFunctionEpilogue(MacroA // The exact form of this instruction must be kept consistent with the // patching in AsmJSModule::setProfilingEnabled. masm.bind(&labels->profilingJump); #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) masm.twoByteNop(); #elif defined(JS_CODEGEN_ARM) masm.nop(); -#elif defined(JS_CODEGEN_MIPS) +#elif defined(JS_CODEGEN_MIPS32) masm.nop(); masm.nop(); masm.nop(); masm.nop(); #endif } // Normal epilogue: @@ -561,17 +561,17 @@ AsmJSProfilingFrameIterator::AsmJSProfil // innermost call. To avoid this problem, we use the static structure of // the code in the prologue and epilogue to do the Right Thing. uint32_t offsetInModule = (uint8_t*)state.pc - module_->codeBase(); MOZ_ASSERT(offsetInModule < module_->codeBytes()); MOZ_ASSERT(offsetInModule >= codeRange->begin()); MOZ_ASSERT(offsetInModule < codeRange->end()); uint32_t offsetInCodeRange = offsetInModule - codeRange->begin(); void** sp = (void**)state.sp; -#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS) +#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) if (offsetInCodeRange < PushedRetAddr) { // First instruction of the ARM/MIPS function; the return address is // still in lr and fp still holds the caller's fp. callerPC_ = state.lr; callerFP_ = fp; AssertMatchesCallSite(*module_, codeRange, callerPC_, callerFP_, sp - 2); } else if (offsetInModule == codeRange->profilingReturn() - PostStorePrePopFP) { // Second-to-last instruction of the ARM/MIPS function; fp points to
--- a/js/src/asmjs/AsmJSModule.cpp +++ b/js/src/asmjs/AsmJSModule.cpp @@ -284,17 +284,17 @@ AsmJSModule::lookupHeapAccess(void* pc) bool AsmJSModule::finish(ExclusiveContext* cx, TokenStream& tokenStream, MacroAssembler& masm, const Label& interruptLabel, const Label& outOfBoundsLabel) { MOZ_ASSERT(isFinishedWithFunctionBodies() && !isFinished()); uint32_t endBeforeCurly = tokenStream.currentToken().pos.end; TokenPos pos; - if (!tokenStream.peekTokenPos(&pos)) + if (!tokenStream.peekTokenPos(&pos, TokenStream::Operand)) return false; uint32_t endAfterCurly = pos.end; MOZ_ASSERT(endBeforeCurly >= srcBodyStart_); MOZ_ASSERT(endAfterCurly >= srcBodyStart_); pod.srcLength_ = endBeforeCurly - srcStart_; pod.srcLengthWithRightBrace_ = endAfterCurly - srcStart_; // Start global data on a new page so JIT code may be given independent @@ -400,17 +400,17 @@ AsmJSModule::finish(ExclusiveContext* cx RelativeLink link(RelativeLink::InstructionImmediate); link.patchAtOffset = masm.labelOffsetToPatchOffset(a.patchAt.offset()); link.targetOffset = offsetOfGlobalData() + a.globalDataOffset; if (!staticLinkData_.relativeLinks.append(link)) return false; } #endif -#if defined(JS_CODEGEN_MIPS) +#if defined(JS_CODEGEN_MIPS32) // On MIPS we need to update all the long jumps because they contain an // absolute adress. for (size_t i = 0; i < masm.numLongJumps(); i++) { RelativeLink link(RelativeLink::InstructionImmediate); link.patchAtOffset = masm.longJump(i); InstImm* inst = (InstImm*)(code_ + masm.longJump(i)); link.targetOffset = Assembler::ExtractLuiOriValue(inst, inst->next()) - (uint32_t)code_; if (!staticLinkData_.relativeLinks.append(link)) @@ -867,17 +867,17 @@ AsmJSModule::initHeap(Handle<ArrayBuffer // CodeGeneratorX64::visitAsmJS{Load,Store,CompareExchange,Exchange,AtomicBinop}Heap) uint32_t heapLength = heap->byteLength(); for (size_t i = 0; i < heapAccesses_.length(); i++) { const jit::AsmJSHeapAccess& access = heapAccesses_[i]; // See comment above for x86 codegen. if (access.hasLengthCheck()) X86Encoding::AddInt32(access.patchLengthAt(code_), heapLength); } -#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS) +#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) uint32_t heapLength = heap->byteLength(); for (unsigned i = 0; i < heapAccesses_.length(); i++) { jit::Assembler::UpdateBoundsCheck(heapLength, (jit::Instruction*)(heapAccesses_[i].insnOffset() + code_)); } #endif } @@ -1798,17 +1798,17 @@ AsmJSModule::setProfilingEnabled(bool en uint8_t* caller = callerRetAddr - 4; Instruction* callerInsn = reinterpret_cast<Instruction*>(caller); BOffImm calleeOffset; callerInsn->as<InstBLImm>()->extractImm(&calleeOffset); void* callee = calleeOffset.getDest(callerInsn); #elif defined(JS_CODEGEN_ARM64) MOZ_CRASH(); void* callee = nullptr; -#elif defined(JS_CODEGEN_MIPS) +#elif defined(JS_CODEGEN_MIPS32) Instruction* instr = (Instruction*)(callerRetAddr - 4 * sizeof(uint32_t)); void* callee = (void*)Assembler::ExtractLuiOriValue(instr, instr->next()); #elif defined(JS_CODEGEN_NONE) MOZ_CRASH(); void* callee = nullptr; #else # error "Missing architecture" #endif @@ -1824,17 +1824,17 @@ AsmJSModule::setProfilingEnabled(bool en uint8_t* newCallee = enabled ? profilingEntry : entry; #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) X86Encoding::SetRel32(callerRetAddr, newCallee); #elif defined(JS_CODEGEN_ARM) new (caller) InstBLImm(BOffImm(newCallee - caller), Assembler::Always); #elif defined(JS_CODEGEN_ARM64) MOZ_CRASH(); -#elif defined(JS_CODEGEN_MIPS) +#elif defined(JS_CODEGEN_MIPS32) Assembler::WriteLuiOriInstructions(instr, instr->next(), ScratchRegister, (uint32_t)newCallee); instr[2] = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr); #elif defined(JS_CODEGEN_NONE) MOZ_CRASH(); #else # error "Missing architecture" #endif @@ -1889,17 +1889,17 @@ AsmJSModule::setProfilingEnabled(bool en MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstNOP>()); new (jump) InstBImm(BOffImm(profilingEpilogue - jump), Assembler::Always); } else { MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstBImm>()); new (jump) InstNOP(); } #elif defined(JS_CODEGEN_ARM64) MOZ_CRASH(); -#elif defined(JS_CODEGEN_MIPS) +#elif defined(JS_CODEGEN_MIPS32) Instruction* instr = (Instruction*)jump; if (enabled) { Assembler::WriteLuiOriInstructions(instr, instr->next(), ScratchRegister, (uint32_t)profilingEpilogue); instr[2] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr); } else { instr[0].makeNop(); instr[1].makeNop(); @@ -1955,17 +1955,17 @@ GetCPUID(uint32_t* cpuId) #elif defined(JS_CODEGEN_X64) MOZ_ASSERT(uint32_t(CPUInfo::GetSSEVersion()) <= (UINT32_MAX >> ARCH_BITS)); *cpuId = X64 | (uint32_t(CPUInfo::GetSSEVersion()) << ARCH_BITS); return true; #elif defined(JS_CODEGEN_ARM) MOZ_ASSERT(GetARMFlags() <= (UINT32_MAX >> ARCH_BITS)); *cpuId = ARM | (GetARMFlags() << ARCH_BITS); return true; -#elif defined(JS_CODEGEN_MIPS) +#elif defined(JS_CODEGEN_MIPS32) MOZ_ASSERT(GetMIPSFlags() <= (UINT32_MAX >> ARCH_BITS)); *cpuId = MIPS | (GetMIPSFlags() << ARCH_BITS); return true; #else return false; #endif } @@ -2041,17 +2041,17 @@ class ModuleChars public: static uint32_t beginOffset(AsmJSParser& parser) { return parser.pc->maybeFunction->pn_pos.begin; } static uint32_t endOffset(AsmJSParser& parser) { TokenPos pos(0, 0); // initialize to silence GCC warning - MOZ_ALWAYS_TRUE(parser.tokenStream.peekTokenPos(&pos)); + MOZ_ALWAYS_TRUE(parser.tokenStream.peekTokenPos(&pos, TokenStream::Operand)); return pos.end; } }; class ModuleCharsForStore : ModuleChars { uint32_t uncompressedSize_; uint32_t compressedSize_;
--- a/js/src/asmjs/AsmJSModule.h +++ b/js/src/asmjs/AsmJSModule.h @@ -725,35 +725,35 @@ class AsmJSModule InstructionImmediate }; RelativeLink() { } explicit RelativeLink(Kind kind) { -#if defined(JS_CODEGEN_MIPS) +#if defined(JS_CODEGEN_MIPS32) kind_ = kind; #elif defined(JS_CODEGEN_ARM) // On ARM, CodeLabels are only used to label raw pointers, so in // all cases on ARM, a RelativePatch means patching a raw pointer. MOZ_ASSERT(kind == CodeLabel || kind == RawPointer); #endif // On X64 and X86, all RelativePatch-es are patched as raw pointers. } bool isRawPointerPatch() { -#if defined(JS_CODEGEN_MIPS) +#if defined(JS_CODEGEN_MIPS32) return kind_ == RawPointer; #else return true; #endif } -#ifdef JS_CODEGEN_MIPS +#ifdef JS_CODEGEN_MIPS32 Kind kind_; #endif uint32_t patchAtOffset; uint32_t targetOffset; }; typedef Vector<RelativeLink, 0, SystemAllocPolicy> RelativeLinkVector;
--- a/js/src/asmjs/AsmJSValidate.cpp +++ b/js/src/asmjs/AsmJSValidate.cpp @@ -480,17 +480,17 @@ PeekToken(AsmJSParser& parser, TokenKind { TokenStream& ts = parser.tokenStream; TokenKind tk; while (true) { if (!ts.peekToken(&tk, TokenStream::Operand)) return false; if (tk != TOK_SEMI) break; - ts.consumeKnownToken(TOK_SEMI); + ts.consumeKnownToken(TOK_SEMI, TokenStream::Operand); } *tkp = tk; return true; } static bool ParseVarOrConstStatement(AsmJSParser& parser, ParseNode** var) { @@ -1600,17 +1600,18 @@ class MOZ_STACK_CLASS ModuleCompiler return failOffset(pn->pn_pos.begin, str); // The exact rooting static analysis does not perform dataflow analysis, so it believes // that unrooted things on the stack during compilation may still be accessed after this. // Since pn is typically only null under OOM, this suppression simply forces any GC to be // delayed until the compilation is off the stack and more memory can be freed. gc::AutoSuppressGC nogc(cx_); TokenPos pos; - if (!tokenStream().peekTokenPos(&pos)) + TokenStream::Modifier modifier = tokenStream().hasLookahead() ? tokenStream().getLookaheadModifier() : TokenStream::None; + if (!tokenStream().peekTokenPos(&pos, modifier)) return false; return failOffset(pos.begin, str); } bool failfVA(ParseNode* pn, const char* fmt, va_list ap) { MOZ_ASSERT(!errorString_); MOZ_ASSERT(errorOffset_ == UINT32_MAX); MOZ_ASSERT(fmt); @@ -4906,17 +4907,17 @@ CheckModuleGlobal(ModuleCompiler& m, Par } static bool CheckModuleProcessingDirectives(ModuleCompiler& m) { TokenStream& ts = m.parser().tokenStream; while (true) { bool matched; - if (!ts.matchToken(&matched, TOK_STRING)) + if (!ts.matchToken(&matched, TOK_STRING, TokenStream::Operand)) return false; if (!matched) return true; if (!IsIgnoredDirectiveName(m.cx(), ts.currentToken().atom())) return m.fail(nullptr, "unsupported processing directive"); if (!ts.matchToken(&matched, TOK_SEMI)) @@ -9772,22 +9773,22 @@ CheckChangeHeap(ModuleCompiler& m, Parse return m.addChangeHeap(changeHeapName, fn, mask, min, max); } static bool ParseFunction(ModuleCompiler& m, ParseNode** fnOut) { TokenStream& tokenStream = m.tokenStream(); - tokenStream.consumeKnownToken(TOK_FUNCTION); + tokenStream.consumeKnownToken(TOK_FUNCTION, TokenStream::Operand); RootedPropertyName name(m.cx()); TokenKind tk; - if (!tokenStream.getToken(&tk)) + if (!tokenStream.getToken(&tk, TokenStream::Operand)) return false; if (tk == TOK_NAME) { name = tokenStream.currentName(); } else if (tk == TOK_YIELD) { if (!m.parser().checkYieldNameValidity()) return false; name = m.cx()->names().yield; } else { @@ -10889,17 +10890,17 @@ static const LiveRegisterSet NonVolatile | (1ULL << FloatRegisters::d15) | (1ULL << FloatRegisters::s31))); #else static const LiveRegisterSet NonVolatileRegs = LiveRegisterSet(GeneralRegisterSet(Registers::NonVolatileMask), FloatRegisterSet(FloatRegisters::NonVolatileMask)); #endif -#if defined(JS_CODEGEN_MIPS) +#if defined(JS_CODEGEN_MIPS32) // Mips is using one more double slot due to stack alignment for double values. // Look at MacroAssembler::PushRegsInMask(RegisterSet set) static const unsigned FramePushedAfterSave = NonVolatileRegs.gprs().size() * sizeof(intptr_t) + NonVolatileRegs.fpus().getPushSizeInBytes() + sizeof(double); #elif defined(JS_CODEGEN_NONE) static const unsigned FramePushedAfterSave = 0; #else @@ -10915,32 +10916,32 @@ GenerateEntry(ModuleCompiler& m, unsigne Label begin; masm.haltingAlign(CodeAlignment); masm.bind(&begin); // Save the return address if it wasn't already saved by the call insn. #if defined(JS_CODEGEN_ARM) masm.push(lr); -#elif defined(JS_CODEGEN_MIPS) +#elif defined(JS_CODEGEN_MIPS32) masm.push(ra); #elif defined(JS_CODEGEN_X86) static const unsigned EntryFrameSize = sizeof(void*); #endif // Save all caller non-volatile registers before we clobber them here and in // the asm.js callee (which does not preserve non-volatile registers). masm.setFramePushed(0); masm.PushRegsInMask(NonVolatileRegs); MOZ_ASSERT(masm.framePushed() == FramePushedAfterSave); // ARM and MIPS have a globally-pinned GlobalReg (x64 uses RIP-relative // addressing, x86 uses immediates in effective addresses). For the // AsmJSGlobalRegBias addition, see Assembler-(mips,arm).h. -#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS) +#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) masm.movePtr(IntArgReg1, GlobalReg); masm.addPtr(Imm32(AsmJSGlobalRegBias), GlobalReg); #endif // ARM, MIPS and x64 have a globally-pinned HeapReg (x86 uses immediates in // effective addresses). Loading the heap register depends on the global // register already having been loaded. masm.loadAsmJSHeapRegisterFromGlobalData(); @@ -11234,17 +11235,17 @@ GenerateFFIInterpExit(ModuleCompiler& m, masm.loadAsmJSHeapRegisterFromGlobalData(); GenerateCheckForHeapDetachment(m, ABIArgGenerator::NonReturn_VolatileReg0); Label profilingReturn; GenerateAsmJSExitEpilogue(masm, framePushed, AsmJSExit::SlowFFI, &profilingReturn); return !masm.oom() && m.finishGeneratingInterpExit(exitIndex, &begin, &profilingReturn); } -#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS) +#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) static const unsigned MaybeSavedGlobalReg = sizeof(void*); #else static const unsigned MaybeSavedGlobalReg = 0; #endif static bool GenerateFFIIonExit(ModuleCompiler& m, const ModuleCompiler::ExitDescriptor& exit, unsigned exitIndex, Label* throwLabel) @@ -11278,17 +11279,17 @@ GenerateFFIIonExit(ModuleCompiler& m, co Register scratch = ABIArgGenerator::NonArgReturnReg1; // repeatedly clobbered // 2.1. Get ExitDatum unsigned globalDataOffset = m.module().exitIndexToGlobalDataOffset(exitIndex); #if defined(JS_CODEGEN_X64) m.masm().append(AsmJSGlobalAccess(masm.leaRipRelative(callee), globalDataOffset)); #elif defined(JS_CODEGEN_X86) m.masm().append(AsmJSGlobalAccess(masm.movlWithPatch(Imm32(0), callee), globalDataOffset)); -#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS) +#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) masm.computeEffectiveAddress(Address(GlobalReg, globalDataOffset - AsmJSGlobalRegBias), callee); #endif // 2.2. Get callee masm.loadPtr(Address(callee, offsetof(AsmJSModule::ExitDatum, fun)), callee); // 2.3. Save callee masm.storePtr(callee, Address(masm.getStackPointer(), argOffset)); @@ -11314,17 +11315,17 @@ GenerateFFIIonExit(ModuleCompiler& m, co MOZ_ASSERT(argOffset == ionFrameBytes); // 6. Jit code will clobber all registers, even non-volatiles. GlobalReg and // HeapReg are removed from the general register set for asm.js code, so // these will not have been saved by the caller like all other registers, // so they must be explicitly preserved. Only save GlobalReg since // HeapReg must be reloaded (from global data) after the call since the // heap may change during the FFI call. -#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS) +#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) static_assert(MaybeSavedGlobalReg == sizeof(void*), "stack frame accounting"); masm.storePtr(GlobalReg, Address(masm.getStackPointer(), ionFrameBytes)); #endif { // Enable Activation. // // This sequence requires four registers, and needs to preserve the 'callee' @@ -11430,17 +11431,17 @@ GenerateFFIIonExit(ModuleCompiler& m, co masm.storePtr(reg2, Address(reg0, offsetOfJitJSContext)); // rt->jitActivation = prevJitActivation_; masm.loadPtr(Address(reg1, JitActivation::offsetOfPrevJitActivation()), reg2); masm.storePtr(reg2, Address(reg0, offsetOfJitActivation)); } // Reload the global register since Ion code can clobber any register. -#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS) +#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS32) static_assert(MaybeSavedGlobalReg == sizeof(void*), "stack frame accounting"); masm.loadPtr(Address(masm.getStackPointer(), ionFrameBytes), GlobalReg); #endif // As explained above, the frame was aligned for Ion such that // (sp + sizeof(void*)) % JitStackAlignment == 0 // But now we possibly want to call one of several different C++ functions, // so subtract the sizeof(void*) so that sp is aligned for an ABI call. @@ -11745,17 +11746,17 @@ GenerateAsyncInterruptExit(ModuleCompile // Restore the StackPointer to its position before the call. masm.moveToStackPtr(ABIArgGenerator::NonVolatileReg); // Restore the machine state to before the interrupt. masm.PopRegsInMask(AllRegsExceptSP); // restore all GP/FP registers (except SP) masm.popFlags(); // after this, nothing that sets conditions masm.ret(); // pop resumePC into PC -#elif defined(JS_CODEGEN_MIPS) +#elif defined(JS_CODEGEN_MIPS32) // Reserve space to store resumePC. masm.subFromStackPtr(Imm32(sizeof(intptr_t))); // set to zero so we can use masm.framePushed() below. masm.setFramePushed(0); // When this platform supports SIMD extensions, we'll need to push high lanes // of SIMD registers as well. JS_STATIC_ASSERT(!SupportsSimd); // save all registers,except sp. After this stack is alligned.
--- a/js/src/builtin/SIMD.cpp +++ b/js/src/builtin/SIMD.cpp @@ -478,50 +478,50 @@ SIMDObject::initClass(JSContext* cx, Han SingletonObject)); if (!SIMD) return nullptr; RootedObject i8x16(cx); i8x16 = CreateAndBindSimdClass<Int8x16Defn>(cx, global, SIMD, cx->names().int8x16); if (!i8x16) return nullptr; - global->setInt8x16TypeDescr(*i8x16); RootedObject i16x8(cx); i16x8 = CreateAndBindSimdClass<Int16x8Defn>(cx, global, SIMD, cx->names().int16x8); if (!i16x8) return nullptr; - global->setInt16x8TypeDescr(*i16x8); RootedObject f32x4(cx); f32x4 = CreateAndBindSimdClass<Float32x4Defn>(cx, global, SIMD, cx->names().float32x4); if (!f32x4) return nullptr; - global->setFloat32x4TypeDescr(*f32x4); RootedObject i32x4(cx); i32x4 = CreateAndBindSimdClass<Int32x4Defn>(cx, global, SIMD, cx->names().int32x4); if (!i32x4) return nullptr; - global->setInt32x4TypeDescr(*i32x4); RootedObject f64x2(cx); f64x2 = CreateAndBindSimdClass<Float64x2Defn>(cx, global, SIMD, cx->names().float64x2); if (!f64x2) return nullptr; - global->setFloat64x2TypeDescr(*f64x2); // Everything is set up, install SIMD on the global object. RootedValue SIMDValue(cx, ObjectValue(*SIMD)); if (!DefineProperty(cx, global, cx->names().SIMD, SIMDValue, nullptr, nullptr, JSPROP_RESOLVING)) { return nullptr; } + global->setInt8x16TypeDescr(*i8x16); + global->setInt16x8TypeDescr(*i16x8); + global->setFloat32x4TypeDescr(*f32x4); + global->setInt32x4TypeDescr(*i32x4); + global->setFloat64x2TypeDescr(*f64x2); global->setConstructor(JSProto_SIMD, SIMDValue); return SIMD; } JSObject* js::InitSIMDClass(JSContext* cx, HandleObject obj) { MOZ_ASSERT(obj->is<GlobalObject>());
--- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -1372,22 +1372,21 @@ ShellObjectMetadataCallback(JSContext* c stackIndex++; } } return obj; } static bool -SetObjectMetadataCallback(JSContext* cx, unsigned argc, Value* vp) +EnableShellObjectMetadataCallback(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - bool enabled = args.length() ? ToBoolean(args[0]) : false; - SetObjectMetadataCallback(cx, enabled ? ShellObjectMetadataCallback : nullptr); + SetObjectMetadataCallback(cx, ShellObjectMetadataCallback); args.rval().setUndefined(); return true; } static bool GetObjectMetadata(JSContext* cx, unsigned argc, Value* vp) { @@ -2000,16 +1999,19 @@ GetBacktrace(JSContext* cx, unsigned arg showLocals = ToBoolean(v); if (!JS_GetProperty(cx, cfg, "thisprops", &v)) return false; showThisProps = ToBoolean(v); } char* buf = JS::FormatStackDump(cx, nullptr, showArgs, showLocals, showThisProps); + if (!buf) + return false; + RootedString str(cx); if (!(str = JS_NewStringCopyZ(cx, buf))) return false; JS_smprintf_free(buf); args.rval().setString(str); return true; } @@ -2926,19 +2928,19 @@ gc::ZealModeHelpText), JS_FN_HELP("isLazyFunction", IsLazyFunction, 1, 0, "isLazyFunction(fun)", " True if fun is a lazy JSFunction."), JS_FN_HELP("isRelazifiableFunction", IsRelazifiableFunction, 1, 0, "isRelazifiableFunction(fun)", " Ture if fun is a JSFunction with a relazifiable JSScript."), - JS_FN_HELP("setObjectMetadataCallback", SetObjectMetadataCallback, 1, 0, -"setObjectMetadataCallback(fn)", -" Specify function to supply metadata for all newly created objects."), + JS_FN_HELP("enableShellObjectMetadataCallback", EnableShellObjectMetadataCallback, 0, 0, +"enableShellObjectMetadataCallback()", +" Use ShellObjectMetadataCallback to supply metadata for all newly created objects."), JS_FN_HELP("getObjectMetadata", GetObjectMetadata, 1, 0, "getObjectMetadata(obj)", " Get the metadata for an object."), JS_FN_HELP("bailout", testingFunc_bailout, 0, 0, "bailout()", " Force a bailout out of ionmonkey (if running in ionmonkey)."),
--- a/js/src/configure.in +++ b/js/src/configure.in @@ -969,17 +969,17 @@ x86_64 | ia64) CPU_ARCH="$OS_TEST" ;; arm*) CPU_ARCH=arm ;; mips|mipsel) - CPU_ARCH="mips" + CPU_ARCH="mips32" ;; aarch64*) CPU_ARCH=aarch64 ;; esac @@ -3053,26 +3053,26 @@ fi AC_SUBST(MOZ_VALGRIND) dnl ======================================================== dnl = Use a JIT code simulator for a foreign architecture. dnl ======================================================== MOZ_ARG_ENABLE_STRING(simulator, [ --enable-simulator=ARCH Enable a JIT code simulator for the specified arch. - (arm, arm64, mips).], + (arm, arm64, mips32).], JS_SIMULATOR="$enableval") if test -n "$JS_SIMULATOR"; then case "$JS_SIMULATOR" in - arm|arm64|mips) ;; + arm|arm64|mips32) ;; no) JS_SIMULATOR= ;; - *) AC_MSG_ERROR([Invalid simulator. Valid simulators are: arm, arm64, mips.]) ;; + *) AC_MSG_ERROR([Invalid simulator. Valid simulators are: arm, arm64, mips32.]) ;; esac fi if test -z "$ENABLE_ION"; then AC_DEFINE(JS_CODEGEN_NONE) JS_CODEGEN_NONE=1 elif test "$JS_SIMULATOR" = arm; then if test "$CPU_ARCH" != "x86"; then @@ -3087,51 +3087,51 @@ elif test "$JS_SIMULATOR" = arm64; then if test "$CPU_ARCH" != "x86_64"; then AC_MSG_ERROR([The ARM64 simulator only works on x86_64.]) fi AC_DEFINE(JS_SIMULATOR) AC_DEFINE(JS_SIMULATOR_ARM64) AC_DEFINE(JS_CODEGEN_ARM64) JS_SIMULATOR_ARM64=1 JS_CODEGEN_ARM64=1 -elif test "$JS_SIMULATOR" = mips; then +elif test "$JS_SIMULATOR" = mips32; then if test "$CPU_ARCH" != "x86"; then - AC_MSG_ERROR([The MIPS simulator only works on x86.]) + AC_MSG_ERROR([The MIPS32 simulator only works on x86.]) fi AC_DEFINE(JS_SIMULATOR) - AC_DEFINE(JS_SIMULATOR_MIPS) - AC_DEFINE(JS_CODEGEN_MIPS) - JS_SIMULATOR_MIPS=1 - JS_CODEGEN_MIPS=1 + AC_DEFINE(JS_SIMULATOR_MIPS32) + AC_DEFINE(JS_CODEGEN_MIPS32) + JS_SIMULATOR_MIPS32=1 + JS_CODEGEN_MIPS32=1 elif test "$CPU_ARCH" = "x86"; then AC_DEFINE(JS_CODEGEN_X86) JS_CODEGEN_X86=1 elif test "$CPU_ARCH" = "x86_64"; then AC_DEFINE(JS_CODEGEN_X64) JS_CODEGEN_X64=1 dnl Signal-handler OOM checking requires large mprotected guard regions, so dnl currently it is only implemented on x64. AC_DEFINE(ASMJS_MAY_USE_SIGNAL_HANDLERS_FOR_OOB) ASMJS_MAY_USE_SIGNAL_HANDLERS_FOR_OOB=1 elif test "$CPU_ARCH" = "arm"; then AC_DEFINE(JS_CODEGEN_ARM) JS_CODEGEN_ARM=1 -elif test "$CPU_ARCH" = "mips"; then - AC_DEFINE(JS_CODEGEN_MIPS) - JS_CODEGEN_MIPS=1 +elif test "$CPU_ARCH" = "mips32"; then + AC_DEFINE(JS_CODEGEN_MIPS32) + JS_CODEGEN_MIPS32=1 fi AC_SUBST(JS_SIMULATOR) AC_SUBST(JS_SIMULATOR_ARM) AC_SUBST(JS_SIMULATOR_ARM64) -AC_SUBST(JS_SIMULATOR_MIPS) +AC_SUBST(JS_SIMULATOR_MIPS32) AC_SUBST(JS_CODEGEN_ARM) AC_SUBST(JS_CODEGEN_ARM64) -AC_SUBST(JS_CODEGEN_MIPS) +AC_SUBST(JS_CODEGEN_MIPS32) AC_SUBST(JS_CODEGEN_X86) AC_SUBST(JS_CODEGEN_X64) AC_SUBST(JS_CODEGEN_NONE) AC_SUBST(ASMJS_MAY_USE_SIGNAL_HANDLERS_FOR_OOB) dnl ======================================================== dnl jprof dnl ========================================================
--- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -52,27 +52,28 @@ namespace js { namespace frontend { typedef Rooted<StaticBlockObject*> RootedStaticBlockObject; typedef Handle<StaticBlockObject*> HandleStaticBlockObject; typedef Rooted<NestedScopeObject*> RootedNestedScopeObject; typedef Handle<NestedScopeObject*> HandleNestedScopeObject; /* Read a token. Report an error and return null() if that token isn't of type tt. */ -#define MUST_MATCH_TOKEN(tt, errno) \ +#define MUST_MATCH_TOKEN_MOD(tt, modifier, errno) \ JS_BEGIN_MACRO \ TokenKind token; \ - if (!tokenStream.getToken(&token)) \ + if (!tokenStream.getToken(&token, modifier)) \ return null(); \ if (token != tt) { \ report(ParseError, false, null(), errno); \ return null(); \ } \ JS_END_MACRO +#define MUST_MATCH_TOKEN(tt, errno) MUST_MATCH_TOKEN_MOD(tt, TokenStream::None, errno) template <> bool ParseContext<FullParseHandler>::checkLocalsOverflow(TokenStream& ts) { if (vars_.length() + bodyLevelLexicals_.length() >= LOCALNO_LIMIT) { ts.reportError(JSMSG_TOO_MANY_LOCALS); return false; @@ -737,17 +738,17 @@ Parser<ParseHandler>::parse() &globalsc, /* newDirectives = */ nullptr, /* blockScopeDepth = */ 0); if (!globalpc.init(*this)) return null(); Node pn = statements(YieldIsName); if (pn) { TokenKind tt; - if (!tokenStream.getToken(&tt)) + if (!tokenStream.getToken(&tt, TokenStream::Operand)) return null(); if (tt != TOK_EOF) { report(ParseError, false, null(), JSMSG_GARBAGE_AFTER_INPUT, "script", TokenKindToDesc(tt)); return null(); } if (foldConstants) { if (!FoldConstants(context, &pn, this)) @@ -835,17 +836,17 @@ Parser<FullParseHandler>::standaloneFunc } YieldHandling yieldHandling = generatorKind != NotGenerator ? YieldIsKeyword : YieldIsName; ParseNode* pn = functionBody(InAllowed, yieldHandling, Statement, StatementListBody); if (!pn) return null(); TokenKind tt; - if (!tokenStream.getToken(&tt)) + if (!tokenStream.getToken(&tt, TokenStream::Operand)) return null(); if (tt != TOK_EOF) { report(ParseError, false, null(), JSMSG_GARBAGE_AFTER_INPUT, "function body", TokenKindToDesc(tt)); return null(); } if (!FoldConstants(context, &pn, this)) @@ -1342,29 +1343,33 @@ Parser<ParseHandler>::newFunction(Handle if (!fun) return nullptr; if (options().selfHostingMode) fun->setIsSelfHostedBuiltin(); return fun; } static bool -MatchOrInsertSemicolon(TokenStream& ts) +MatchOrInsertSemicolon(TokenStream& ts, TokenStream::Modifier modifier = TokenStream::None) { TokenKind tt; - if (!ts.peekTokenSameLine(&tt, TokenStream::Operand)) + if (!ts.peekTokenSameLine(&tt, modifier)) return false; if (tt != TOK_EOF && tt != TOK_EOL && tt != TOK_SEMI && tt != TOK_RC) { /* Advance the scanner for proper error location reporting. */ - ts.consumeKnownToken(tt); + ts.consumeKnownToken(tt, modifier); ts.reportError(JSMSG_SEMI_BEFORE_STMNT); return false; } - bool ignored; - return ts.matchToken(&ignored, TOK_SEMI); + bool matched; + if (!ts.matchToken(&matched, TOK_SEMI, modifier)) + return false; + if (!matched && modifier == TokenStream::None) + ts.addModifierException(TokenStream::OperandIsNone); + return true; } /* * The function LexicalLookup searches a static binding for the given name in * the stack of statements enclosing the statement currently being parsed. Each * statement that introduces a new scope has a corresponding scope object, on * which the bindings for that scope are stored. LexicalLookup either returns * the innermost statement which has a scope object containing a binding with @@ -1699,26 +1704,29 @@ bool Parser<ParseHandler>::functionArguments(YieldHandling yieldHandling, FunctionSyntaxKind kind, Node funcpn, bool* hasRest) { FunctionBox* funbox = pc->sc->asFunctionBox(); *hasRest = false; bool parenFreeArrow = false; + TokenStream::Modifier modifier = TokenStream::None; if (kind == Arrow) { TokenKind tt; - if (!tokenStream.peekToken(&tt)) + if (!tokenStream.peekToken(&tt, TokenStream::Operand)) return false; if (tt == TOK_NAME) parenFreeArrow = true; + else + modifier = TokenStream::Operand; } if (!parenFreeArrow) { TokenKind tt; - if (!tokenStream.getToken(&tt)) + if (!tokenStream.getToken(&tt, modifier)) return false; if (tt != TOK_LP) { report(ParseError, false, null(), kind == Arrow ? JSMSG_BAD_ARROW_ARGS : JSMSG_PAREN_BEFORE_FORMAL); return false; } // Record the start of function source (for FunctionToString). If we @@ -1731,17 +1739,17 @@ Parser<ParseHandler>::functionArguments( return false; handler.setFunctionBody(funcpn, argsbody); bool hasArguments = false; if (parenFreeArrow) { hasArguments = true; } else { bool matched; - if (!tokenStream.matchToken(&matched, TOK_RP)) + if (!tokenStream.matchToken(&matched, TOK_RP, TokenStream::Operand)) return false; if (!matched) hasArguments = true; } if (hasArguments) { bool hasDefaults = false; Node duplicatedArg = null(); bool disallowDuplicateArgs = kind == Arrow || kind == Method || kind == ClassConstructor; @@ -1753,17 +1761,17 @@ Parser<ParseHandler>::functionArguments( while (true) { if (*hasRest) { report(ParseError, false, null(), JSMSG_PARAMETER_AFTER_REST); return false; } TokenKind tt; - if (!tokenStream.getToken(&tt)) + if (!tokenStream.getToken(&tt, TokenStream::Operand)) return false; MOZ_ASSERT_IF(parenFreeArrow, tt == TOK_NAME); switch (tt) { case TOK_LB: case TOK_LC: { /* See comment below in the TOK_NAME case. */ disallowDuplicateArgs = true; @@ -2690,17 +2698,17 @@ Parser<ParseHandler>::functionArgsAndBod if ((kind != Method && !IsConstructorKind(kind)) && fun->name() && !checkStrictBinding(fun->name(), pn)) { return false; } if (bodyType == StatementListBody) { bool matched; - if (!tokenStream.matchToken(&matched, TOK_RC)) + if (!tokenStream.matchToken(&matched, TOK_RC, TokenStream::Operand)) return false; if (!matched) { report(ParseError, false, null(), JSMSG_CURLY_AFTER_BODY); return false; } funbox->bufEnd = pos().begin + 1; } else { #if !JS_HAS_EXPR_CLOSURES @@ -3042,25 +3050,25 @@ template <typename ParseHandler> bool Parser<ParseHandler>::matchLabel(YieldHandling yieldHandling, MutableHandle<PropertyName*> label) { TokenKind tt; if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand)) return false; if (tt == TOK_NAME) { - tokenStream.consumeKnownToken(TOK_NAME); + tokenStream.consumeKnownToken(TOK_NAME, TokenStream::Operand); MOZ_ASSERT_IF(tokenStream.currentName() == context->names().yield, yieldHandling == YieldIsName); label.set(tokenStream.currentName()); } else if (tt == TOK_YIELD) { // We might still consider |yield| to be valid here, contrary to ES6. // Fix bug 1104014, then stop shipping legacy generators in chrome // code, then remove this check! - tokenStream.consumeKnownToken(TOK_YIELD); + tokenStream.consumeKnownToken(TOK_YIELD, TokenStream::Operand); if (!checkYieldNameValidity()) return false; label.set(tokenStream.currentName()); } else { label.set(nullptr); } return true; } @@ -3854,17 +3862,17 @@ Parser<ParseHandler>::deprecatedLetBlock if (!block) return null(); MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_LET); Node expr = statements(yieldHandling); if (!expr) return null(); - MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_LET); + MUST_MATCH_TOKEN_MOD(TOK_RC, TokenStream::Operand, JSMSG_CURLY_AFTER_LET); addTelemetry(JSCompartment::DeprecatedLetBlock); if (!report(ParseWarning, pc->sc->strict(), expr, JSMSG_DEPRECATED_LET_BLOCK)) return null(); handler.setLexicalScopeBody(block, expr); TokenPos letPos(begin, pos().end); @@ -3881,17 +3889,17 @@ Parser<ParseHandler>::blockStatement(Yie AutoPushStmtInfoPC stmtInfo(*this, StmtType::BLOCK); if (!stmtInfo.generateBlockId()) return null(); Node list = statements(yieldHandling); if (!list) return null(); - MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_IN_COMPOUND); + MUST_MATCH_TOKEN_MOD(TOK_RC, TokenStream::Operand, JSMSG_CURLY_IN_COMPOUND); return list; } template <typename ParseHandler> typename ParseHandler::Node Parser<ParseHandler>::newBindingNode(PropertyName* name, bool functionScope, VarContext varContext) { /* @@ -4338,30 +4346,31 @@ Parser<SyntaxParseHandler>::letDeclarati return SyntaxParseHandler::NodeFailure; } template<> bool Parser<FullParseHandler>::namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet) { if (tt == TOK_LC) { + TokenStream::Modifier modifier = TokenStream::KeywordIsName; while (true) { // Handle the forms |import {} from 'a'| and // |import { ..., } from 'a'| (where ... is non empty), by // escaping the loop early if the next token is }. if (!tokenStream.peekToken(&tt, TokenStream::KeywordIsName)) return false; if (tt == TOK_RC) break; // If the next token is a keyword, the previous call to // peekToken matched it as a TOK_NAME, and put it in the // lookahead buffer, so this call will match keywords as well. - MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_IMPORT_NAME); + MUST_MATCH_TOKEN_MOD(TOK_NAME, TokenStream::KeywordIsName, JSMSG_NO_IMPORT_NAME); Node importName = newName(tokenStream.currentName()); if (!importName) return false; if (!tokenStream.getToken(&tt)) return false; if (tt == TOK_NAME && tokenStream.currentName() == context->names().as) { @@ -4389,21 +4398,23 @@ Parser<FullParseHandler>::namedImportsOr return false; handler.addList(importSpecSet, importSpec); bool matched; if (!tokenStream.matchToken(&matched, TOK_COMMA)) return false; - if (!matched) + if (!matched) { + modifier = TokenStream::None; break; - } - - MUST_MATCH_TOKEN(TOK_RC, JSMSG_RC_AFTER_IMPORT_SPEC_LIST); + } + } + + MUST_MATCH_TOKEN_MOD(TOK_RC, modifier, JSMSG_RC_AFTER_IMPORT_SPEC_LIST); } else { MOZ_ASSERT(tt == TOK_MUL); if (!tokenStream.getToken(&tt)) return false; if (tt != TOK_NAME || tokenStream.currentName() != context->names().as) { report(ParseError, false, null(), JSMSG_AS_AFTER_IMPORT_STAR); return false; @@ -4514,17 +4525,17 @@ Parser<ParseHandler>::importDeclaration( report(ParseError, false, null(), JSMSG_DECLARATION_AFTER_IMPORT); return null(); } Node moduleSpec = stringLiteral(); if (!moduleSpec) return null(); - if (!MatchOrInsertSemicolon(tokenStream)) + if (!MatchOrInsertSemicolon(tokenStream, TokenStream::Operand)) return null(); return handler.newImportDeclaration(importSpecSet, moduleSpec, TokenPos(begin, pos().end)); } template<> SyntaxParseHandler::Node Parser<SyntaxParseHandler>::importDeclaration() @@ -4661,17 +4672,17 @@ Parser<FullParseHandler>::exportDeclarat kid->pn_xflags = PNX_POPVAR; kid = MatchOrInsertSemicolon(tokenStream) ? kid : nullptr; if (!kid) return null(); break; case TOK_DEFAULT: { - if (!tokenStream.getToken(&tt)) + if (!tokenStream.getToken(&tt, TokenStream::Operand)) return null(); switch (tt) { case TOK_FUNCTION: kid = functionStmt(YieldIsKeyword, AllowDefaultName); break; case TOK_CLASS: kid = classDefinition(YieldIsKeyword, ClassStatement, AllowDefaultName); @@ -4790,29 +4801,31 @@ template <typename ParseHandler> typename ParseHandler::Node Parser<ParseHandler>::doWhileStatement(YieldHandling yieldHandling) { uint32_t begin = pos().begin; AutoPushStmtInfoPC stmtInfo(*this, StmtType::DO_LOOP); Node body = statement(yieldHandling); if (!body) return null(); - MUST_MATCH_TOKEN(TOK_WHILE, JSMSG_WHILE_AFTER_DO); + MUST_MATCH_TOKEN_MOD(TOK_WHILE, TokenStream::Operand, JSMSG_WHILE_AFTER_DO); Node cond = condition(InAllowed, yieldHandling); if (!cond) return null(); // The semicolon after do-while is even more optional than most // semicolons in JS. Web compat required this by 2004: // http://bugzilla.mozilla.org/show_bug.cgi?id=238945 // ES3 and ES5 disagreed, but ES6 conforms to Web reality: // https://bugs.ecmascript.org/show_bug.cgi?id=157 - bool ignored; - if (!tokenStream.matchToken(&ignored, TOK_SEMI)) - return null(); + bool matched; + if (!tokenStream.matchToken(&matched, TOK_SEMI)) + return null(); + if (!matched) + tokenStream.addModifierException(TokenStream::OperandIsNone); return handler.newDoWhileStatement(body, cond, TokenPos(begin, pos().end)); } template <typename ParseHandler> typename ParseHandler::Node Parser<ParseHandler>::whileStatement(YieldHandling yieldHandling) { uint32_t begin = pos().begin; @@ -4916,16 +4929,17 @@ Parser<FullParseHandler>::forStatement(Y bool isForDecl = false; /* Non-null when isForDecl is true for a 'for (let ...)' statement. */ RootedStaticBlockObject blockObj(context); /* Set to 'x' in 'for (x ;... ;...)' or 'for (x in ...)'. */ ParseNode* pn1; + TokenStream::Modifier modifier = TokenStream::Operand; { TokenKind tt; if (!tokenStream.peekToken(&tt, TokenStream::Operand)) return null(); if (tt == TOK_SEMI) { pn1 = nullptr; } else { // Set pn1 to a variable list or an initializing expression. @@ -4934,37 +4948,38 @@ Parser<FullParseHandler>::forStatement(Y // to trigger |for|-specific parsing for that one position. In a // normal variable declaration, any initializer may be an |in| // expression. But for declarations at the start of a for-loop // head, initializers can't contain |in|. (Such syntax conflicts // with ES5's |for (var i = 0 in foo)| syntax, removed in ES6, that // we "support" by ignoring the |= 0|.) if (tt == TOK_VAR) { isForDecl = true; - tokenStream.consumeKnownToken(tt); + tokenStream.consumeKnownToken(tt, TokenStream::Operand); pn1 = variables(yieldHandling, PNK_VAR, InForInit); } else if (tt == TOK_LET || tt == TOK_CONST) { handler.disableSyntaxParser(); bool constDecl = tt == TOK_CONST; - tokenStream.consumeKnownToken(tt); + tokenStream.consumeKnownToken(tt, TokenStream::Operand); isForDecl = true; blockObj = StaticBlockObject::create(context); if (!blockObj) return null(); pn1 = variables(yieldHandling, constDecl ? PNK_CONST : PNK_LET, InForInit, nullptr, blockObj, DontHoistVars); } else { // Pass |InProhibited| when parsing an expression so that |in| // isn't parsed in a RelationalExpression as a binary operator. // In this context, |in| is part of a for-in loop -- *not* part // of a binary expression. pn1 = expr(InProhibited, yieldHandling); } if (!pn1) return null(); + modifier = TokenStream::None; } } MOZ_ASSERT_IF(isForDecl, pn1->isArity(PN_LIST)); MOZ_ASSERT(!!blockObj == (isForDecl && pn1->isOp(JSOP_NOP))); // All forms of for-loop (for(;;), for-in, for-of) generate an implicit // block to store any lexical variables declared by the loop-head. We @@ -5087,16 +5102,17 @@ Parser<FullParseHandler>::forStatement(Y return null(); } pn3 = (headKind == PNK_FOROF) ? assignExpr(InAllowed, yieldHandling) : expr(InAllowed, yieldHandling); if (!pn3) return null(); + modifier = TokenStream::None; if (blockObj) { /* * Now that the pn3 has been parsed, push the let scope. To hold * the blockObj for the emitter, wrap the PNK_LEXICALSCOPE node * created by pushLetScope around the for's initializer. This also * serves to indicate the let-decl to the emitter. */ @@ -5174,42 +5190,46 @@ Parser<FullParseHandler>::forStatement(Y } else { pn1 = handler.newFreshenBlock(pn1->pn_pos); if (!pn1) return null(); } } /* Parse the loop condition or null into pn2. */ - MUST_MATCH_TOKEN(TOK_SEMI, JSMSG_SEMI_AFTER_FOR_INIT); + MUST_MATCH_TOKEN_MOD(TOK_SEMI, modifier, JSMSG_SEMI_AFTER_FOR_INIT); TokenKind tt; if (!tokenStream.peekToken(&tt, TokenStream::Operand)) return null(); if (tt == TOK_SEMI) { pn2 = nullptr; + modifier = TokenStream::Operand; } else { pn2 = expr(InAllowed, yieldHandling); if (!pn2) return null(); + modifier = TokenStream::None; } /* Parse the update expression or null into pn3. */ - MUST_MATCH_TOKEN(TOK_SEMI, JSMSG_SEMI_AFTER_FOR_COND); + MUST_MATCH_TOKEN_MOD(TOK_SEMI, modifier, JSMSG_SEMI_AFTER_FOR_COND); if (!tokenStream.peekToken(&tt, TokenStream::Operand)) return null(); if (tt == TOK_RP) { pn3 = nullptr; + modifier = TokenStream::Operand; } else { pn3 = expr(InAllowed, yieldHandling); if (!pn3) return null(); - } - } - - MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FOR_CTRL); + modifier = TokenStream::None; + } + } + + MUST_MATCH_TOKEN_MOD(TOK_RP, modifier, JSMSG_PAREN_AFTER_FOR_CTRL); TokenPos headPos(begin, pos().end); ParseNode* forHead = handler.newForHead(headKind, pn1, pn2, pn3, headPos); if (!forHead) return null(); /* Parse the loop body. */ ParseNode* body = statement(yieldHandling); @@ -5259,38 +5279,40 @@ Parser<SyntaxParseHandler>::forStatement /* True if we have 'for (var ...)'. */ bool isForDecl = false; bool simpleForDecl = true; /* Set to 'x' in 'for (x ;... ;...)' or 'for (x in ...)'. */ Node lhsNode; + TokenStream::Modifier modifier = TokenStream::Operand; { TokenKind tt; if (!tokenStream.peekToken(&tt, TokenStream::Operand)) return null(); if (tt == TOK_SEMI) { lhsNode = null(); } else { /* Set lhsNode to a var list or an initializing expression. */ if (tt == TOK_VAR) { isForDecl = true; - tokenStream.consumeKnownToken(tt); + tokenStream.consumeKnownToken(tt, TokenStream::Operand); lhsNode = variables(yieldHandling, PNK_VAR, InForInit, &simpleForDecl); } else if (tt == TOK_CONST || tt == TOK_LET) { JS_ALWAYS_FALSE(abortIfSyntaxParser()); return null(); } else { lhsNode = expr(InProhibited, yieldHandling); } if (!lhsNode) return null(); + modifier = TokenStream::None; } } // If there's an |in| keyword here, it's a for-in loop, by dint of careful // parsing of |pn1|. bool isForIn = false, isForOf = false; if (lhsNode) { if (!matchInOrOf(&isForIn, &isForOf)) @@ -5314,38 +5336,43 @@ Parser<SyntaxParseHandler>::forStatement return null(); } if (!isForDecl && !checkAndMarkAsAssignmentLhs(lhsNode, PlainAssignment)) return null(); if (!(isForIn ? expr(InAllowed, yieldHandling) : assignExpr(InAllowed, yieldHandling))) return null(); + modifier = TokenStream::None; } else { /* Parse the loop condition or null. */ - MUST_MATCH_TOKEN(TOK_SEMI, JSMSG_SEMI_AFTER_FOR_INIT); + MUST_MATCH_TOKEN_MOD(TOK_SEMI, modifier, JSMSG_SEMI_AFTER_FOR_INIT); TokenKind tt; if (!tokenStream.peekToken(&tt, TokenStream::Operand)) return null(); + modifier = TokenStream::Operand; if (tt != TOK_SEMI) { if (!expr(InAllowed, yieldHandling)) return null(); + modifier = TokenStream::None; } /* Parse the update expression or null. */ - MUST_MATCH_TOKEN(TOK_SEMI, JSMSG_SEMI_AFTER_FOR_COND); + MUST_MATCH_TOKEN_MOD(TOK_SEMI, modifier, JSMSG_SEMI_AFTER_FOR_COND); if (!tokenStream.peekToken(&tt, TokenStream::Operand)) return null(); + modifier = TokenStream::Operand; if (tt != TOK_RP) { if (!expr(InAllowed, yieldHandling)) return null(); - } - } - - MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FOR_CTRL); + modifier = TokenStream::None; + } + } + + MUST_MATCH_TOKEN_MOD(TOK_RP, modifier, JSMSG_PAREN_AFTER_FOR_CTRL); /* Parse the loop body. */ if (!statement(yieldHandling)) return null(); return SyntaxParseHandler::NodeGeneric; } @@ -5374,17 +5401,17 @@ Parser<ParseHandler>::switchStatement(Yi return null(); Node saveBlock = pc->blockNode; pc->blockNode = caseList; bool seenDefault = false; TokenKind tt; while (true) { - if (!tokenStream.getToken(&tt)) + if (!tokenStream.getToken(&tt, TokenStream::Operand)) return null(); if (tt == TOK_RC) break; uint32_t caseBegin = pos().begin; Node caseExpr; switch (tt) { case TOK_DEFAULT: @@ -5517,17 +5544,17 @@ Parser<ParseHandler>::continueStatement( report(ParseError, false, null(), JSMSG_BAD_CONTINUE); return null(); } if (stmt->isLoop()) break; } } - if (!MatchOrInsertSemicolon(tokenStream)) + if (!MatchOrInsertSemicolon(tokenStream, TokenStream::Operand)) return null(); return handler.newContinueStatement(label, TokenPos(begin, pos().end)); } template <typename ParseHandler> typename ParseHandler::Node Parser<ParseHandler>::breakStatement(YieldHandling yieldHandling) @@ -5554,17 +5581,17 @@ Parser<ParseHandler>::breakStatement(Yie report(ParseError, false, null(), JSMSG_TOUGH_BREAK); return null(); } if (stmt->isLoop() || stmt->type == StmtType::SWITCH) break; } } - if (!MatchOrInsertSemicolon(tokenStream)) + if (!MatchOrInsertSemicolon(tokenStream, TokenStream::Operand)) return null(); return handler.newBreakStatement(label, TokenPos(begin, pos().end)); } template <typename ParseHandler> typename ParseHandler::Node Parser<ParseHandler>::returnStatement(YieldHandling yieldHandling) @@ -5576,33 +5603,35 @@ Parser<ParseHandler>::returnStatement(Yi // Parse an optional operand. // // This is ugly, but we don't want to require a semicolon. Node exprNode; TokenKind tt; if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand)) return null(); + TokenStream::Modifier modifier = TokenStream::Operand; switch (tt) { case TOK_EOL: case TOK_EOF: case TOK_SEMI: case TOK_RC: exprNode = null(); pc->funHasReturnVoid = true; break; default: { exprNode = expr(InAllowed, yieldHandling); if (!exprNode) return null(); + modifier = TokenStream::None; pc->funHasReturnExpr = true; } } - if (!MatchOrInsertSemicolon(tokenStream)) + if (!MatchOrInsertSemicolon(tokenStream, modifier)) return null(); Node genrval = null(); if (pc->isStarGenerator()) { genrval = newName(context->names().dotGenRVal); if (!genrval) return null(); if (!noteNameUse(context->names().dotGenRVal, genrval)) @@ -5671,20 +5700,21 @@ Parser<ParseHandler>::yieldExpression(In case TOK_SEMI: case TOK_RC: case TOK_RB: case TOK_RP: case TOK_COLON: case TOK_COMMA: // No value. exprNode = null(); + tokenStream.addModifierException(TokenStream::NoneIsOperand); break; case TOK_MUL: kind = PNK_YIELD_STAR; - tokenStream.consumeKnownToken(TOK_MUL); + tokenStream.consumeKnownToken(TOK_MUL, TokenStream::Operand); // Fall through. default: exprNode = assignExpr(inHandling, YieldIsKeyword); if (!exprNode) return null(); } return newYieldExpression(begin, exprNode, kind == PNK_YIELD_STAR); } @@ -5733,16 +5763,17 @@ Parser<ParseHandler>::yieldExpression(In case TOK_SEMI: case TOK_RC: case TOK_RB: case TOK_RP: case TOK_COLON: case TOK_COMMA: // No value. exprNode = null(); + tokenStream.addModifierException(TokenStream::NoneIsOperand); break; default: exprNode = assignExpr(inHandling, YieldIsKeyword); if (!exprNode) return null(); } return newYieldExpression(begin, exprNode); @@ -5905,17 +5936,17 @@ Parser<ParseHandler>::tryStatement(Yield { MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_TRY); AutoPushStmtInfoPC stmtInfo(*this, StmtType::TRY); if (!stmtInfo.generateBlockId()) return null(); innerBlock = statements(yieldHandling); if (!innerBlock) return null(); - MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_TRY); + MUST_MATCH_TOKEN_MOD(TOK_RC, TokenStream::Operand, JSMSG_CURLY_AFTER_TRY); } bool hasUnconditionalCatch = false; Node catchList = null(); TokenKind tt; if (!tokenStream.getToken(&tt)) return null(); if (tt == TOK_CATCH) { @@ -6017,17 +6048,17 @@ Parser<ParseHandler>::tryStatement(Yield } #endif MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_CATCH); MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_CATCH); Node catchBody = statements(yieldHandling); if (!catchBody) return null(); - MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_CATCH); + MUST_MATCH_TOKEN_MOD(TOK_RC, TokenStream::Operand, JSMSG_CURLY_AFTER_CATCH); if (!catchGuard) hasUnconditionalCatch = true; if (!handler.addCatchBlock(catchList, pnblock, catchName, catchGuard, catchBody)) return null(); handler.setEndPosition(catchList, pos().end); handler.setEndPosition(pnblock, pos().end); @@ -6042,17 +6073,17 @@ Parser<ParseHandler>::tryStatement(Yield if (tt == TOK_FINALLY) { MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_FINALLY); AutoPushStmtInfoPC stmtInfo(*this, StmtType::TRY); if (!stmtInfo.generateBlockId()) return null(); finallyBlock = statements(yieldHandling); if (!finallyBlock) return null(); - MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_FINALLY); + MUST_MATCH_TOKEN_MOD(TOK_RC, TokenStream::Operand, JSMSG_CURLY_AFTER_FINALLY); } else { tokenStream.ungetToken(); } if (!catchList && !finallyBlock) { report(ParseError, false, null(), JSMSG_CATCH_OR_FINALLY); return null(); } @@ -6060,17 +6091,17 @@ Parser<ParseHandler>::tryStatement(Yield } template <typename ParseHandler> typename ParseHandler::Node Parser<ParseHandler>::debuggerStatement() { TokenPos p; p.begin = pos().begin; - if (!MatchOrInsertSemicolon(tokenStream)) + if (!MatchOrInsertSemicolon(tokenStream, TokenStream::Operand)) return null(); p.end = pos().end; pc->sc->setBindingsAccessedDynamically(); pc->sc->setHasDebuggerStatement(); return handler.newDebuggerStatement(p); } @@ -6705,17 +6736,17 @@ Parser<ParseHandler>::assignExpr(InHandl return null(); } tokenStream.seek(start); if (!abortIfSyntaxParser()) return null(); TokenKind ignored; - if (!tokenStream.peekToken(&ignored)) + if (!tokenStream.peekToken(&ignored, TokenStream::Operand)) return null(); if (pc->sc->isFunctionBox() && pc->sc->asFunctionBox()->isDerivedClassConstructor()) { report(ParseError, false, null(), JSMSG_DISABLED_DERIVED_CLASS, "arrow functions"); return null(); } return functionDef(inHandling, yieldHandling, nullptr, Arrow, NotGenerator); @@ -6948,17 +6979,17 @@ Parser<ParseHandler>::unaryExpr(YieldHan } default: { Node pn = memberExpr(yieldHandling, tt, /* allowCallSyntax = */ true, invoked); if (!pn) return null(); /* Don't look across a newline boundary for a postfix incop. */ - if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand)) + if (!tokenStream.peekTokenSameLine(&tt)) return null(); if (tt == TOK_INC || tt == TOK_DEC) { tokenStream.consumeKnownToken(tt); AssignmentFlavor flavor = (tt == TOK_INC) ? IncrementAssignment : DecrementAssignment; if (!checkAndMarkAsIncOperand(pn, flavor)) return null(); return handler.newUnary((tt == TOK_INC) ? PNK_POSTINCREMENT : PNK_POSTDECREMENT, JSOP_NOP, @@ -8267,35 +8298,36 @@ Parser<ParseHandler>::arrayInitializer(Y * determine their type. */ handler.setListFlag(literal, PNX_NONCONST); } else { tokenStream.ungetToken(); bool spread = false, missingTrailingComma = false; uint32_t index = 0; + TokenStream::Modifier modifier = TokenStream::Operand; for (; ; index++) { if (index == NativeObject::NELEMENTS_LIMIT) { report(ParseError, false, null(), JSMSG_ARRAY_INIT_TOO_BIG); return null(); } TokenKind tt; if (!tokenStream.peekToken(&tt, TokenStream::Operand)) return null(); if (tt == TOK_RB) break; if (tt == TOK_COMMA) { - tokenStream.consumeKnownToken(TOK_COMMA); + tokenStream.consumeKnownToken(TOK_COMMA, TokenStream::Operand); if (!handler.addElision(literal, pos())) return null(); } else if (tt == TOK_TRIPLEDOT) { spread = true; - tokenStream.consumeKnownToken(TOK_TRIPLEDOT); + tokenStream.consumeKnownToken(TOK_TRIPLEDOT, TokenStream::Operand); uint32_t begin = pos().begin; Node inner = assignExpr(InAllowed, yieldHandling); if (!inner) return null(); if (!handler.addSpreadElement(literal, begin, inner)) return null(); } else { Node element = assignExpr(InAllowed, yieldHandling); @@ -8308,16 +8340,17 @@ Parser<ParseHandler>::arrayInitializer(Y if (tt != TOK_COMMA) { /* If we didn't already match TOK_COMMA in above case. */ bool matched; if (!tokenStream.matchToken(&matched, TOK_COMMA)) return null(); if (!matched) { missingTrailingComma = true; + modifier = TokenStream::None; break; } } } /* * At this point, (index == 0 && missingTrailingComma) implies one * element initialiser was parsed. @@ -8362,23 +8395,24 @@ Parser<ParseHandler>::arrayInitializer(Y * slot's stack index from fp->spbase. * * The legacy array comprehension iteration step, array.push(i * j) in * the example above, is done by <i * j>; JSOP_ARRAYPUSH <array>, where * <array> is the index of array's stack slot. */ if (index == 0 && !spread) { bool matched; - if (!tokenStream.matchToken(&matched, TOK_FOR)) + if (!tokenStream.matchToken(&matched, TOK_FOR, modifier)) return null(); if (matched && missingTrailingComma) return legacyArrayComprehension(literal); - } - - MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_LIST); + if (matched) + modifier = TokenStream::None; + } + MUST_MATCH_TOKEN_MOD(TOK_RB, modifier, JSMSG_BRACKET_AFTER_LIST); } handler.setEndPosition(literal, pos().end); return literal; } static JSAtom* DoubleToAtom(ExclusiveContext* cx, double value) { @@ -8540,16 +8574,17 @@ Parser<ParseHandler>::propertyList(Yield if (!propname) return null(); } else { // Not an accessor property after all. tokenStream.ungetToken(); propname = handler.newObjectLiteralPropertyName(atom, pos()); if (!propname) return null(); + tokenStream.addModifierException(TokenStream::NoneIsKeywordIsName); op = JSOP_INITPROP; break; } MOZ_ASSERT(op == JSOP_INITPROP_GETTER || op == JSOP_INITPROP_SETTER); break; } @@ -8567,18 +8602,20 @@ Parser<ParseHandler>::propertyList(Yield } break; } default: // There is never a case in which |static *(| can make a meaningful method definition. if (isStatic && !isGenerator) { // Turns out it wasn't static. Put it back and pretend it was a name all along. + tokenStream.ungetToken(); + if (isStatic) + tokenStream.addModifierException(TokenStream::NoneIsKeywordIsName); isStatic = false; - tokenStream.ungetToken(); atom = tokenStream.currentName(); propname = handler.newObjectLiteralPropertyName(atom->asPropertyName(), pos()); if (!propname) return null(); } else { report(ParseError, false, null(), JSMSG_BAD_PROP_ID); return null(); } @@ -8803,17 +8840,17 @@ Parser<ParseHandler>::primaryExpr(YieldH TokenKind next; if (!tokenStream.peekToken(&next, TokenStream::Operand)) return null(); if (next != TOK_RP) return parenExprOrGeneratorComprehension(yieldHandling); // Not valid expression syntax, but this is valid in an arrow function // with no params: `() => body`. - tokenStream.consumeKnownToken(next); + tokenStream.consumeKnownToken(next, TokenStream::Operand); if (!tokenStream.peekToken(&next)) return null(); if (next != TOK_ARROW) { report(ParseError, false, null(), JSMSG_UNEXPECTED_TOKEN, "expression", TokenKindToDesc(TOK_RP)); return null(); }
--- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -1640,16 +1640,23 @@ TokenStream::getTokenInternal(TokenKind* MOZ_CRASH("should have jumped to |out| or |error|"); out: if (flags.hitOOM) return reportError(JSMSG_OUT_OF_MEMORY); flags.isDirtyLine = true; tp->pos.end = userbuf.offset(); +#ifdef DEBUG + // Save the modifier used to get this token, so that if an ungetToken() + // occurs and then the token is re-gotten (or peeked, etc.), we can assert + // that both gets have used the same modifiers. + tp->modifier = modifier; + tp->modifierExceptions = NoException; +#endif MOZ_ASSERT(IsTokenSane(tp)); *ttp = tp->type; return true; error: if (flags.hitOOM) return reportError(JSMSG_OUT_OF_MEMORY);
--- a/js/src/frontend/TokenStream.h +++ b/js/src/frontend/TokenStream.h @@ -5,16 +5,18 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef frontend_TokenStream_h #define frontend_TokenStream_h // JS lexical scanner interface. #include "mozilla/ArrayUtils.h" +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" #include "mozilla/DebugOnly.h" #include "mozilla/PodOperations.h" #include "mozilla/UniquePtr.h" #include <stdarg.h> #include <stddef.h> #include <stdio.h> @@ -71,32 +73,76 @@ struct TokenPos { bool encloses(const TokenPos& pos) const { return begin <= pos.begin && pos.end <= end; } }; enum DecimalPoint { NoDecimal = false, HasDecimal = true }; +class TokenStream; + struct Token { + private: + // Sometimes the parser needs to inform the tokenizer to interpret + // subsequent text in a particular manner: for example, to tokenize a + // keyword as an identifier, not as the actual keyword, on the right-hand + // side of a dotted property access. Such information is communicated to + // the tokenizer as a Modifier when getting the next token. + // + // Ideally this definition would reside in TokenStream as that's the real + // user, but the debugging-use of it here causes a cyclic dependency (and + // C++ provides no way to forward-declare an enum inside a class). So + // define it here, then typedef it into TokenStream with static consts to + // bring the initializers into scope. + enum Modifier + { + // Normal operation. + None, + + // Looking for an operand, not an operator. In practice, this means + // that when '/' is seen, we look for a regexp instead of just returning + // TOK_DIV. + Operand, + + // Treat keywords as names by returning TOK_NAME. + KeywordIsName, + + // Treat subsequent characters as the tail of a template literal, after + // a template substitution, beginning with a "}", continuing with zero + // or more template literal characters, and ending with either "${" or + // the end of the template literal. For example: + // + // var entity = "world"; + // var s = `Hello ${entity}!`; + // ^ TemplateTail context + TemplateTail, + }; + friend class TokenStream; + + public: TokenKind type; // char value or above enumerator TokenPos pos; // token position in file union { private: friend struct Token; PropertyName* name; // non-numeric atom JSAtom* atom; // potentially-numeric atom struct { double value; // floating point number DecimalPoint decimalPoint; // literal contains '.' } number; RegExpFlag reflags; // regexp flags; use tokenbuf to access // regexp chars } u; +#ifdef DEBUG + Modifier modifier; // Modifier used to get this token + uint8_t modifierExceptions; // Bitwise OR of modifier exceptions +#endif // This constructor is necessary only for MSVC 2013 and how it compiles the // initialization of TokenStream::tokens. That field is initialized as // tokens() in the constructor init-list. This *should* zero the entire // array, then (because Token has a non-trivial constructor, because // TokenPos has a user-provided constructor) call the implicit Token // constructor on each element, which would call the TokenPos constructor // for Token::pos and do nothing. (All of which is equivalent to just @@ -354,38 +400,119 @@ class MOZ_STACK_CLASS TokenStream bool hitOOM:1; // Hit OOM. Flags() : isEOF(), isDirtyLine(), sawOctalEscape(), hadError(), hitOOM() {} }; public: - // Sometimes the parser needs to modify how tokens are created. - enum Modifier + typedef Token::Modifier Modifier; + static MOZ_CONSTEXPR_VAR Modifier None = Token::None; + static MOZ_CONSTEXPR_VAR Modifier Operand = Token::Operand; + static MOZ_CONSTEXPR_VAR Modifier KeywordIsName = Token::KeywordIsName; + static MOZ_CONSTEXPR_VAR Modifier TemplateTail = Token::TemplateTail; + + enum ModifierException { - None, // Normal operation. - Operand, // Looking for an operand, not an operator. In - // practice, this means that when '/' is seen, - // we look for a regexp instead of just returning - // TOK_DIV. - KeywordIsName, // Treat keywords as names by returning TOK_NAME. - TemplateTail, // Treat next characters as part of a template string + NoException = 0x00, + + // If a semicolon is inserted automatically, the next token is already + // gotten with None, but we expect Operand. + NoneIsOperand = 0x01, + + // If an yield expression operand is omitted, the next token is already + // gotten with Operand, but we expect operator (None). + OperandIsNone = 0x02, + + // If name of method definition is `get` or `set`, the next token is + // already gotten with KeywordIsName, but we expect None. + NoneIsKeywordIsName = 0x04, }; + void addModifierException(ModifierException modifierException) { +#ifdef DEBUG + const Token& next = nextToken(); + switch (modifierException) { + case NoneIsOperand: + MOZ_ASSERT(next.modifier == Operand); + MOZ_ASSERT(next.type != TOK_DIV && next.type != TOK_REGEXP, + "next token requires contextual specifier to be parsed unambiguously"); + break; + case OperandIsNone: + // Non-Operand token after yield/continue/break already has + // NoneIsOperand exception. + MOZ_ASSERT(next.modifier == None || + ((next.modifierExceptions & NoneIsOperand) && next.modifier == Operand)); + MOZ_ASSERT(next.type != TOK_DIV && next.type != TOK_REGEXP, + "next token requires contextual specifier to be parsed unambiguously"); + break; + case NoneIsKeywordIsName: + MOZ_ASSERT(next.modifier == KeywordIsName); + MOZ_ASSERT(next.type != TOK_NAME); + break; + default: + MOZ_CRASH("unexpected modifier exception"); + } + tokens[(cursor + 1) & ntokensMask].modifierExceptions |= modifierException; +#endif + } + + bool hasLookahead() { return lookahead > 0; } + + Modifier getLookaheadModifier() { +#ifdef DEBUG + return nextToken().modifier; +#else + return None; +#endif + } + + void + verifyConsistentModifier(Modifier modifier, Token lookaheadToken) { +#ifdef DEBUG + // Easy case: modifiers match. + if (modifier == lookaheadToken.modifier) + return; + + if (lookaheadToken.modifierExceptions & OperandIsNone) { + // getToken(Operand) permissibly following getToken(). + if (modifier == Operand && lookaheadToken.modifier == None) + return; + } + + if (lookaheadToken.modifierExceptions & NoneIsOperand) { + // getToken() permissibly following getToken(Operand). + if (modifier == None && lookaheadToken.modifier == Operand) + return; + } + + if (lookaheadToken.modifierExceptions & NoneIsKeywordIsName) { + // getToken() permissibly following getToken(KeywordIsName). + if (modifier == None && lookaheadToken.modifier == KeywordIsName) + return; + } + + MOZ_ASSERT_UNREACHABLE("this token was previously looked up with a " + "different modifier, potentially making " + "tokenization non-deterministic"); +#endif + } + // Advance to the next token. If the token stream encountered an error, // return false. Otherwise return true and store the token kind in |*ttp|. bool getToken(TokenKind* ttp, Modifier modifier = None) { // Check for a pushed-back token resulting from mismatching lookahead. if (lookahead != 0) { MOZ_ASSERT(!flags.hadError); lookahead--; cursor = (cursor + 1) & ntokensMask; TokenKind tt = currentToken().type; MOZ_ASSERT(tt != TOK_EOL); + verifyConsistentModifier(modifier, currentToken()); *ttp = tt; return true; } return getTokenInternal(ttp, modifier); } // Push the last scanned token back into the stream. @@ -393,36 +520,38 @@ class MOZ_STACK_CLASS TokenStream MOZ_ASSERT(lookahead < maxLookahead); lookahead++; cursor = (cursor - 1) & ntokensMask; } bool peekToken(TokenKind* ttp, Modifier modifier = None) { if (lookahead > 0) { MOZ_ASSERT(!flags.hadError); - *ttp = tokens[(cursor + 1) & ntokensMask].type; + verifyConsistentModifier(modifier, nextToken()); + *ttp = nextToken().type; return true; } if (!getTokenInternal(ttp, modifier)) return false; ungetToken(); return true; } bool peekTokenPos(TokenPos* posp, Modifier modifier = None) { if (lookahead == 0) { TokenKind tt; if (!getTokenInternal(&tt, modifier)) return false; ungetToken(); - MOZ_ASSERT(lookahead != 0); + MOZ_ASSERT(hasLookahead()); } else { MOZ_ASSERT(!flags.hadError); + verifyConsistentModifier(modifier, nextToken()); } - *posp = tokens[(cursor + 1) & ntokensMask].pos; + *posp = nextToken().pos; return true; } // This is like peekToken(), with one exception: if there is an EOL // between the end of the current token and the start of the next token, it // return true and store TOK_EOL in |*ttp|. In that case, no token with // TOK_EOL is actually created, just a TOK_EOL TokenKind is returned, and // currentToken() shouldn't be consulted. (This is the only place TOK_EOL @@ -437,17 +566,18 @@ class MOZ_STACK_CLASS TokenStream // stronger condition than what we are looking for, and we don't need // to return TOK_EOL. if (lookahead != 0) { bool onThisLine; if (!srcCoords.isOnThisLine(curr.pos.end, lineno, &onThisLine)) return reportError(JSMSG_OUT_OF_MEMORY); if (onThisLine) { MOZ_ASSERT(!flags.hadError); - *ttp = tokens[(cursor + 1) & ntokensMask].type; + verifyConsistentModifier(modifier, nextToken()); + *ttp = nextToken().type; return true; } } // The above check misses two cases where we don't have to return // TOK_EOL. // - The next token starts on the same line, but is a multi-line token. // - The next token starts on the same line, but lookahead==2 and there @@ -475,20 +605,20 @@ class MOZ_STACK_CLASS TokenStream *matchedp = true; } else { ungetToken(); *matchedp = false; } return true; } - void consumeKnownToken(TokenKind tt) { + void consumeKnownToken(TokenKind tt, Modifier modifier = None) { bool matched; - MOZ_ASSERT(lookahead != 0); - MOZ_ALWAYS_TRUE(matchToken(&matched, tt)); + MOZ_ASSERT(hasLookahead()); + MOZ_ALWAYS_TRUE(matchToken(&matched, tt, modifier)); MOZ_ALWAYS_TRUE(matched); } bool matchContextualKeyword(bool* matchedp, Handle<PropertyName*> keyword) { TokenKind token; if (!getToken(&token)) return false; if (token == TOK_NAME && currentToken().name() == keyword) { @@ -816,16 +946,21 @@ class MOZ_STACK_CLASS TokenStream void skipChars(int n) { while (--n >= 0) getChar(); } void updateLineInfoForEOL(); void updateFlagsForEOL(); + const Token& nextToken() { + MOZ_ASSERT(hasLookahead()); + return tokens[(cursor + 1) & ntokensMask]; + } + // Options used for parsing/tokenizing. const ReadOnlyCompileOptions& options_; Token tokens[ntokens]; // circular token buffer unsigned cursor; // index of last parsed token unsigned lookahead; // count of lookahead tokens unsigned lineno; // current line number Flags flags; // flags -- see above
--- a/js/src/irregexp/NativeRegExpMacroAssembler.cpp +++ b/js/src/irregexp/NativeRegExpMacroAssembler.cpp @@ -390,17 +390,17 @@ NativeRegExpMacroAssembler::GenerateCode Label grow_failed; masm.movePtr(ImmPtr(runtime), temp1); // Save registers before calling C function LiveGeneralRegisterSet volatileRegs(GeneralRegisterSet::Volatile()); #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) volatileRegs.add(Register::FromCode(Registers::lr)); -#elif defined(JS_CODEGEN_MIPS) +#elif defined(JS_CODEGEN_MIPS32) volatileRegs.add(Register::FromCode(Registers::ra)); #endif volatileRegs.takeUnchecked(temp0); volatileRegs.takeUnchecked(temp1); masm.PushRegsInMask(volatileRegs); masm.setupUnalignedABICall(1, temp0); masm.passABIArg(temp1); @@ -1319,17 +1319,17 @@ NativeRegExpMacroAssembler::CheckSpecial } }