mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 16:28:38 +09:00
Merge remote-tracking branch 'origin/master' into custom
This commit is contained in:
commit
5fda7c378f
282 changed files with 8990 additions and 3961 deletions
2
CLOBBER
2
CLOBBER
|
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Clobber for ICU update
|
||||
Clobber for SpiderMonkey Update
|
||||
|
|
|
|||
|
|
@ -75,22 +75,22 @@ MAC_BUNDLE_VERSION = $(shell $(PYTHON) $(srcdir)/macversion.py --version=$(MOZ_A
|
|||
|
||||
.PHONY: repackage
|
||||
tools repackage:: $(DIST)/bin/$(MOZ_APP_NAME)
|
||||
$(MKDIR) -p $(dist_dest)/Contents/MacOS
|
||||
$(MKDIR) -p $(dist_dest)/$(LPROJ)
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents $(dist_dest) --exclude English.lproj
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/$(LPROJ)
|
||||
sed -e 's/%APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' -e 's/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/' -e 's/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/' $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
|
||||
sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/$(LPROJ)/InfoPlist.strings
|
||||
rsync -a --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ $(dist_dest)/Contents/Resources
|
||||
rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ $(dist_dest)/Contents/MacOS
|
||||
$(RM) $(dist_dest)/Contents/MacOS/$(MOZ_APP_NAME)
|
||||
rsync -aL $(DIST)/bin/$(MOZ_APP_NAME) $(dist_dest)/Contents/MacOS
|
||||
cp -RL $(DIST)/branding/firefox.icns $(dist_dest)/Contents/Resources/firefox.icns
|
||||
cp -RL $(DIST)/branding/document.icns $(dist_dest)/Contents/Resources/document.icns
|
||||
$(MKDIR) -p '$(dist_dest)/Contents/MacOS'
|
||||
$(MKDIR) -p '$(dist_dest)/$(LPROJ)'
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents '$(dist_dest)' --exclude English.lproj
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ '$(dist_dest)/$(LPROJ)'
|
||||
sed -e 's/%APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' -e 's/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/' -e 's/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/' $(srcdir)/macbuild/Contents/Info.plist.in > '$(dist_dest)/Contents/Info.plist'
|
||||
sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > '$(dist_dest)/$(LPROJ)/InfoPlist.strings'
|
||||
rsync -a --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ '$(dist_dest)/Contents/Resources'
|
||||
rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ '$(dist_dest)/Contents/MacOS'
|
||||
$(RM) '$(dist_dest)/Contents/MacOS/$(MOZ_APP_NAME)'
|
||||
rsync -aL $(DIST)/bin/$(MOZ_APP_NAME) '$(dist_dest)/Contents/MacOS'
|
||||
cp -RL $(DIST)/branding/firefox.icns '$(dist_dest)/Contents/Resources/firefox.icns'
|
||||
cp -RL $(DIST)/branding/document.icns '$(dist_dest)/Contents/Resources/document.icns'
|
||||
ifdef MOZ_UPDATER
|
||||
$(MKDIR) -p $(dist_dest)/Contents/Library/LaunchServices
|
||||
mv -f $(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater $(dist_dest)/Contents/Library/LaunchServices
|
||||
ln -s ../../../../Library/LaunchServices/org.mozilla.updater $(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater
|
||||
$(MKDIR) -p '$(dist_dest)/Contents/Library/LaunchServices'
|
||||
mv -f '$(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater' '$(dist_dest)/Contents/Library/LaunchServices'
|
||||
ln -s ../../../../Library/LaunchServices/org.mozilla.updater '$(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater'
|
||||
endif
|
||||
printf APPLMOZB > $(dist_dest)/Contents/PkgInfo
|
||||
printf APPLMOZB > '$(dist_dest)/Contents/PkgInfo'
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -102,19 +102,19 @@ include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
|
|||
|
||||
ifeq (bundle, $(MOZ_FS_LAYOUT))
|
||||
BINPATH = $(_BINPATH)
|
||||
DEFINES += -DAPPNAME=$(_APPNAME)
|
||||
DEFINES += -DAPPNAME='$(_APPNAME)'
|
||||
else
|
||||
# Every other platform just winds up in dist/bin
|
||||
BINPATH = bin
|
||||
endif
|
||||
DEFINES += -DBINPATH=$(BINPATH)
|
||||
DEFINES += -DBINPATH='$(BINPATH)'
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
RESPATH = $(_APPNAME)/Contents/Resources
|
||||
else
|
||||
RESPATH = $(BINPATH)
|
||||
endif
|
||||
DEFINES += -DRESPATH=$(RESPATH)
|
||||
DEFINES += -DRESPATH='$(RESPATH)'
|
||||
|
||||
LPROJ_ROOT = $(firstword $(subst -, ,$(AB_CD)))
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
|
@ -167,7 +167,7 @@ FINDPATH=bin
|
|||
endif
|
||||
|
||||
package-compare::
|
||||
cd $(DIST); find $(PKGCOMP_FIND_OPTS) $(FINDPATH) -type f | sort > bin-list.txt
|
||||
cd $(DIST); find $(PKGCOMP_FIND_OPTS) '$(FINDPATH)' -type f | sort > bin-list.txt
|
||||
$(call py_action,preprocessor,$(DEFINES) $(ACDEFINES) $(MOZ_PKG_MANIFEST)) | grep '^$(BINPATH)' | sed -e 's/^\///' | sort > $(DIST)/pack-list.txt
|
||||
-diff -u $(DIST)/pack-list.txt $(DIST)/bin-list.txt
|
||||
rm -f $(DIST)/pack-list.txt $(DIST)/bin-list.txt
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@
|
|||
@RESPATH@/components/dom.xpt
|
||||
@RESPATH@/components/dom_apps.xpt
|
||||
@RESPATH@/components/dom_base.xpt
|
||||
@RESPATH@/components/dom_bindings.xpt
|
||||
@RESPATH@/components/dom_system.xpt
|
||||
@RESPATH@/components/dom_canvas.xpt
|
||||
@RESPATH@/components/dom_core.xpt
|
||||
|
|
|
|||
|
|
@ -170,10 +170,10 @@ endif
|
|||
ident:
|
||||
@printf 'fx_revision '
|
||||
@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py \
|
||||
$(STAGEDIST)/application.ini App SourceStamp
|
||||
'$(STAGEDIST)'/application.ini App SourceStamp
|
||||
@printf 'buildid '
|
||||
@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py \
|
||||
$(STAGEDIST)/application.ini App BuildID
|
||||
'$(STAGEDIST)'/application.ini App BuildID
|
||||
|
||||
merge-%:
|
||||
ifdef LOCALE_MERGEDIR
|
||||
|
|
|
|||
|
|
@ -80,26 +80,26 @@ MAC_BUNDLE_VERSION = $(shell $(PYTHON) $(srcdir)/macversion.py --version=$(MOZ_A
|
|||
|
||||
.PHONY: repackage
|
||||
tools repackage:: $(PROGRAM)
|
||||
$(MKDIR) -p $(dist_dest)/Contents/MacOS
|
||||
$(MKDIR) -p $(dist_dest)/Contents/Resources/$(AB).lproj
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents $(dist_dest) --exclude English.lproj
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/Contents/Resources/$(AB).lproj
|
||||
sed -e 's/%APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' -e 's/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/' -e 's/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/' $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
|
||||
sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/Contents/Resources/$(AB).lproj/InfoPlist.strings
|
||||
rsync -a --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ $(dist_dest)/Contents/Resources
|
||||
rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ $(dist_dest)/Contents/MacOS
|
||||
$(RM) $(dist_dest)/Contents/MacOS/$(PROGRAM)
|
||||
rsync -aL $(PROGRAM) $(dist_dest)/Contents/MacOS
|
||||
cp -RL $(DIST)/branding/firefox.icns $(dist_dest)/Contents/Resources/firefox.icns
|
||||
cp -RL $(DIST)/branding/document.icns $(dist_dest)/Contents/Resources/document.icns
|
||||
printf APPLMOZB > $(dist_dest)/Contents/PkgInfo
|
||||
$(MKDIR) -p '$(dist_dest)/Contents/MacOS'
|
||||
$(MKDIR) -p '$(dist_dest)/Contents/Resources/$(AB).lproj'
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents '$(dist_dest)' --exclude English.lproj
|
||||
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ '$(dist_dest)/Contents/Resources/$(AB).lproj'
|
||||
sed -e 's/%APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' -e 's/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/' -e 's/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/' $(srcdir)/macbuild/Contents/Info.plist.in > '$(dist_dest)/Contents/Info.plist'
|
||||
sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > '$(dist_dest)/Contents/Resources/$(AB).lproj/InfoPlist.strings'
|
||||
rsync -a --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ '$(dist_dest)/Contents/Resources'
|
||||
rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ '$(dist_dest)/Contents/MacOS'
|
||||
$(RM) '$(dist_dest)/Contents/MacOS/$(PROGRAM)'
|
||||
rsync -aL $(PROGRAM) '$(dist_dest)/Contents/MacOS'
|
||||
cp -RL $(DIST)/branding/firefox.icns '$(dist_dest)/Contents/Resources/firefox.icns'
|
||||
cp -RL $(DIST)/branding/document.icns '$(dist_dest)/Contents/Resources/document.icns'
|
||||
printf APPLMOZB > '$(dist_dest)/Contents/PkgInfo'
|
||||
endif
|
||||
|
||||
ifdef LIBXUL_SDK #{
|
||||
ifndef SKIP_COPY_XULRUNNER #{
|
||||
libs::
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) #{
|
||||
rsync -a --copy-unsafe-links $(LIBXUL_DIST)/XUL.framework $(dist_dest)/Contents/Frameworks
|
||||
rsync -a --copy-unsafe-links $(LIBXUL_DIST)/XUL.framework '$(dist_dest)/Contents/Frameworks'
|
||||
else
|
||||
$(NSINSTALL) -D $(DIST)/bin/xulrunner
|
||||
(cd $(LIBXUL_SDK)/bin && tar $(TAR_CREATE_FLAGS) - .) | (cd $(DIST)/bin/xulrunner && tar -xf -)
|
||||
|
|
|
|||
|
|
@ -113,19 +113,19 @@ include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
|
|||
|
||||
ifeq (bundle, $(MOZ_FS_LAYOUT))
|
||||
BINPATH = $(_BINPATH)
|
||||
DEFINES += -DAPPNAME=$(_APPNAME)
|
||||
DEFINES += -DAPPNAME='$(_APPNAME)'
|
||||
else
|
||||
# Every other platform just winds up in dist/bin
|
||||
BINPATH = bin
|
||||
endif
|
||||
DEFINES += -DBINPATH=$(BINPATH)
|
||||
DEFINES += -DBINPATH='$(BINPATH)'
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
RESPATH = $(_APPNAME)/Contents/Resources
|
||||
else
|
||||
RESPATH = $(BINPATH)
|
||||
endif
|
||||
DEFINES += -DRESPATH=$(RESPATH)
|
||||
DEFINES += -DRESPATH='$(RESPATH)'
|
||||
|
||||
AB = $(firstword $(subst -, ,$(AB_CD)))
|
||||
DEFINES += -DAB=$(AB)
|
||||
|
|
@ -173,7 +173,7 @@ endif
|
|||
|
||||
package-compare:: $(MOZ_PKG_MANIFEST)
|
||||
ifdef MOZ_PKG_MANIFEST_P
|
||||
cd $(DIST); find $(PKGCOMP_FIND_OPTS) $(FINDPATH) -type f | sort > bin-list.txt
|
||||
cd $(DIST); find $(PKGCOMP_FIND_OPTS) '$(FINDPATH)' -type f | sort > bin-list.txt
|
||||
grep '^$(BINPATH)' $(MOZ_PKG_MANIFEST) | sed -e 's/^\///' | sort > $(DIST)/pack-list.txt
|
||||
-diff -u $(DIST)/pack-list.txt $(DIST)/bin-list.txt
|
||||
rm -f $(DIST)/pack-list.txt $(DIST)/bin-list.txt
|
||||
|
|
|
|||
|
|
@ -198,10 +198,10 @@ endif
|
|||
ident:
|
||||
@printf "fx_revision "
|
||||
@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py \
|
||||
$(STAGEDIST)/application.ini App SourceStamp
|
||||
'$(STAGEDIST)'/application.ini App SourceStamp
|
||||
@printf "buildid "
|
||||
@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py \
|
||||
$(STAGEDIST)/application.ini App BuildID
|
||||
'$(STAGEDIST)'/application.ini App BuildID
|
||||
|
||||
merge-%:
|
||||
ifdef LOCALE_MERGEDIR
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ included_inclnames_to_ignore = set([
|
|||
'devtools/Instruments.h', # we ignore devtools/ in general
|
||||
'double-conversion.h', # strange MFBT case
|
||||
'javascript-trace.h', # generated in $OBJDIR if HAVE_DTRACE is defined
|
||||
'jsautokw.h', # generated in $OBJDIR
|
||||
'frontend/ReservedWordsGenerated.h', # generated in $OBJDIR
|
||||
'jscustomallocator.h', # provided by embedders; allowed to be missing
|
||||
'js-config.h', # generated in $OBJDIR
|
||||
'fdlibm.h', # fdlibm
|
||||
|
|
@ -99,7 +99,7 @@ included_inclnames_to_ignore = set([
|
|||
# ignore #includes of them when checking #include ordering.
|
||||
oddly_ordered_inclnames = set([
|
||||
'ctypes/typedefs.h', # Included multiple times in the body of ctypes/CTypes.h
|
||||
'jsautokw.h', # Included in the body of frontend/TokenStream.h
|
||||
'frontend/ReservedWordsGenerated.h', # Included in the body of frontend/TokenStream.h
|
||||
'jswin.h', # Must be #included before <psapi.h>
|
||||
'machine/endian.h', # Must be included after <sys/types.h> on BSD
|
||||
'winbase.h', # Must precede other system headers(?)
|
||||
|
|
|
|||
|
|
@ -10,4 +10,4 @@
|
|||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
4.3.0
|
||||
4.4.0
|
||||
|
|
@ -34,6 +34,7 @@ function EvaluationResult(props) {
|
|||
id: messageId,
|
||||
exceptionDocURL,
|
||||
frame,
|
||||
notes,
|
||||
} = message;
|
||||
|
||||
let messageBody;
|
||||
|
|
@ -57,6 +58,7 @@ function EvaluationResult(props) {
|
|||
serviceContainer,
|
||||
exceptionDocURL,
|
||||
frame,
|
||||
notes,
|
||||
};
|
||||
return Message(childProps);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ function PageError(props) {
|
|||
stacktrace,
|
||||
frame,
|
||||
exceptionDocURL,
|
||||
notes,
|
||||
} = message;
|
||||
|
||||
const childProps = {
|
||||
|
|
@ -62,6 +63,7 @@ function PageError(props) {
|
|||
stacktrace,
|
||||
serviceContainer,
|
||||
exceptionDocURL,
|
||||
notes,
|
||||
};
|
||||
return Message(childProps);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ const Message = createClass({
|
|||
onViewSourceInDebugger: PropTypes.func.isRequired,
|
||||
sourceMapService: PropTypes.any,
|
||||
}),
|
||||
notes: PropTypes.arrayOf(PropTypes.shape({
|
||||
messageBody: PropTypes.string.isRequired,
|
||||
frame: PropTypes.any,
|
||||
})),
|
||||
},
|
||||
|
||||
getDefaultProps: function () {
|
||||
|
|
@ -90,6 +94,7 @@ const Message = createClass({
|
|||
serviceContainer,
|
||||
dispatch,
|
||||
exceptionDocURL,
|
||||
notes,
|
||||
} = this.props;
|
||||
|
||||
topLevelClasses.push("message", source, type, level);
|
||||
|
|
@ -127,6 +132,29 @@ const Message = createClass({
|
|||
});
|
||||
}
|
||||
|
||||
let notesNodes;
|
||||
if (notes) {
|
||||
notesNodes = notes.map(note => dom.span(
|
||||
{ className: "message-flex-body error-note" },
|
||||
dom.span({ className: "message-body devtools-monospace" },
|
||||
"note: " + note.messageBody
|
||||
),
|
||||
dom.span({ className: "message-location devtools-monospace" },
|
||||
note.frame ? FrameView({
|
||||
frame: note.frame,
|
||||
onClick: serviceContainer
|
||||
? serviceContainer.onViewSourceInDebugger
|
||||
: undefined,
|
||||
showEmptyPathAsHost: true,
|
||||
sourceMapService: serviceContainer
|
||||
? serviceContainer.sourceMapService
|
||||
: undefined
|
||||
}) : null
|
||||
)));
|
||||
} else {
|
||||
notesNodes = [];
|
||||
}
|
||||
|
||||
const repeat = this.props.repeat ? MessageRepeat({repeat: this.props.repeat}) : null;
|
||||
|
||||
// Configure the location.
|
||||
|
|
@ -167,7 +195,8 @@ const Message = createClass({
|
|||
repeat,
|
||||
location
|
||||
),
|
||||
attachment
|
||||
attachment,
|
||||
...notesNodes
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,15 @@ function matchSearchFilters(message, filters) {
|
|||
|| (message.parameters !== null
|
||||
&& message.parameters.join("").toLocaleLowerCase()
|
||||
.includes(text.toLocaleLowerCase()))
|
||||
// Look for a match in notes.
|
||||
|| (Array.isArray(message.notes) && message.notes.some(note =>
|
||||
// Look for a match in location.
|
||||
isTextInFrame(text, note.frame)
|
||||
// Look for a match in messageBody.
|
||||
|| (note.messageBody !== null
|
||||
&& note.messageBody.toLocaleLowerCase()
|
||||
.includes(text.toLocaleLowerCase()))
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -123,4 +123,118 @@ describe("PageError component:", () => {
|
|||
wrapper = render(PageError({ message, serviceContainer}));
|
||||
expect(wrapper.find(".indent").prop("style").width).toBe(`0`);
|
||||
});
|
||||
|
||||
it("has empty error notes", () => {
|
||||
const message = stubPreparedMessages.get("ReferenceError: asdf is not defined");
|
||||
let wrapper = render(PageError({ message, serviceContainer }));
|
||||
|
||||
const notes = wrapper.find(".error-note");
|
||||
|
||||
expect(notes.length).toBe(0);
|
||||
});
|
||||
|
||||
it("can show an error note", () => {
|
||||
const origMessage = stubPreparedMessages.get("ReferenceError: asdf is not defined");
|
||||
const message = origMessage.set("notes", [
|
||||
{
|
||||
"messageBody": "test note",
|
||||
"frame": {
|
||||
"source": "http://example.com/test.js",
|
||||
"line": 2,
|
||||
"column": 6
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
let wrapper = render(PageError({ message, serviceContainer }));
|
||||
|
||||
const notes = wrapper.find(".error-note");
|
||||
expect(notes.length).toBe(1);
|
||||
|
||||
const note = notes.eq(0);
|
||||
expect(note.find(".message-body").text())
|
||||
.toBe("note: test note");
|
||||
|
||||
// There should be the location.
|
||||
const locationLink = note.find(`.message-location`);
|
||||
expect(locationLink.length).toBe(1);
|
||||
expect(locationLink.text()).toBe("test.js:2:6");
|
||||
});
|
||||
|
||||
it("can show multiple error notes", () => {
|
||||
const origMessage = stubPreparedMessages.get("ReferenceError: asdf is not defined");
|
||||
const message = origMessage.set("notes", [
|
||||
{
|
||||
"messageBody": "test note 1",
|
||||
"frame": {
|
||||
"source": "http://example.com/test1.js",
|
||||
"line": 2,
|
||||
"column": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"messageBody": "test note 2",
|
||||
"frame": {
|
||||
"source": "http://example.com/test2.js",
|
||||
"line": 10,
|
||||
"column": 18
|
||||
}
|
||||
},
|
||||
{
|
||||
"messageBody": "test note 3",
|
||||
"frame": {
|
||||
"source": "http://example.com/test3.js",
|
||||
"line": 9,
|
||||
"column": 4
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
let wrapper = render(PageError({ message, serviceContainer }));
|
||||
|
||||
const notes = wrapper.find(".error-note");
|
||||
expect(notes.length).toBe(3);
|
||||
|
||||
const note1 = notes.eq(0);
|
||||
expect(note1.find(".message-body").text())
|
||||
.toBe("note: test note 1");
|
||||
|
||||
const locationLink1 = note1.find(`.message-location`);
|
||||
expect(locationLink1.length).toBe(1);
|
||||
expect(locationLink1.text()).toBe("test1.js:2:6");
|
||||
|
||||
const note2 = notes.eq(1);
|
||||
expect(note2.find(".message-body").text())
|
||||
.toBe("note: test note 2");
|
||||
|
||||
const locationLink2 = note2.find(`.message-location`);
|
||||
expect(locationLink2.length).toBe(1);
|
||||
expect(locationLink2.text()).toBe("test2.js:10:18");
|
||||
|
||||
const note3 = notes.eq(2);
|
||||
expect(note3.find(".message-body").text())
|
||||
.toBe("note: test note 3");
|
||||
|
||||
const locationLink3 = note3.find(`.message-location`);
|
||||
expect(locationLink3.length).toBe(1);
|
||||
expect(locationLink3.text()).toBe("test3.js:9:4");
|
||||
});
|
||||
|
||||
it("displays error notes", () => {
|
||||
const message = stubPreparedMessages.get("SyntaxError: redeclaration of let a");
|
||||
|
||||
let wrapper = render(PageError({ message, serviceContainer }));
|
||||
|
||||
const notes = wrapper.find(".error-note");
|
||||
expect(notes.length).toBe(1);
|
||||
|
||||
const note = notes.eq(0);
|
||||
expect(note.find(".message-body").text())
|
||||
.toBe("note: Previously declared at line 2, column 6");
|
||||
|
||||
// There should be the location.
|
||||
const locationLink = note.find(`.message-location`);
|
||||
expect(locationLink.length).toBe(1);
|
||||
expect(locationLink.text()).toBe("test-console-api.html:2:6");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -140,6 +140,10 @@ pageError.set("Reference Error", `
|
|||
foo()
|
||||
`);
|
||||
|
||||
pageError.set("Redeclaration Error", `
|
||||
let a, a;
|
||||
`);
|
||||
|
||||
module.exports = {
|
||||
consoleApi,
|
||||
evaluationResult,
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ const { ConsoleMessage, NetworkEventMessage } = require("devtools/client/webcons
|
|||
|
||||
let stubPreparedMessages = new Map();
|
||||
let stubPackets = new Map();
|
||||
|
||||
|
||||
stubPreparedMessages.set("console.log('foobar', 'test')", new ConsoleMessage({
|
||||
"id": "1",
|
||||
"allowRepeating": true,
|
||||
|
|
@ -34,7 +32,8 @@ stubPreparedMessages.set("console.log('foobar', 'test')", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.log(undefined)", new ConsoleMessage({
|
||||
|
|
@ -50,7 +49,7 @@ stubPreparedMessages.set("console.log(undefined)", new ConsoleMessage({
|
|||
}
|
||||
],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"undefined\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"undefined\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(undefined)",
|
||||
|
|
@ -59,7 +58,8 @@ stubPreparedMessages.set("console.log(undefined)", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.warn('danger, will robinson!')", new ConsoleMessage({
|
||||
|
|
@ -73,7 +73,7 @@ stubPreparedMessages.set("console.warn('danger, will robinson!')", new ConsoleMe
|
|||
"danger, will robinson!"
|
||||
],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"warn\",\"level\":\"warn\",\"messageText\":null,\"parameters\":[\"danger, will robinson!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"warn\",\"level\":\"warn\",\"messageText\":null,\"parameters\":[\"danger, will robinson!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.warn(%27danger%2C%20will%20robinson!%27)",
|
||||
|
|
@ -82,7 +82,8 @@ stubPreparedMessages.set("console.warn('danger, will robinson!')", new ConsoleMe
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.log(NaN)", new ConsoleMessage({
|
||||
|
|
@ -98,7 +99,7 @@ stubPreparedMessages.set("console.log(NaN)", new ConsoleMessage({
|
|||
}
|
||||
],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"NaN\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"NaN\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(NaN)",
|
||||
|
|
@ -107,7 +108,8 @@ stubPreparedMessages.set("console.log(NaN)", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.log(null)", new ConsoleMessage({
|
||||
|
|
@ -123,7 +125,7 @@ stubPreparedMessages.set("console.log(null)", new ConsoleMessage({
|
|||
}
|
||||
],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"null\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"null\"}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(null)",
|
||||
|
|
@ -132,7 +134,8 @@ stubPreparedMessages.set("console.log(null)", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.log('鼬')", new ConsoleMessage({
|
||||
|
|
@ -146,7 +149,7 @@ stubPreparedMessages.set("console.log('鼬')", new ConsoleMessage({
|
|||
"鼬"
|
||||
],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"鼬\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"鼬\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%E9%BC%AC%27)",
|
||||
|
|
@ -155,7 +158,8 @@ stubPreparedMessages.set("console.log('鼬')", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.clear()", new ConsoleMessage({
|
||||
|
|
@ -169,8 +173,7 @@ stubPreparedMessages.set("console.clear()", new ConsoleMessage({
|
|||
"Console was cleared."
|
||||
],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"clear\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"Console was cleared.\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"stacktrace": null,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"clear\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"Console was cleared.\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.clear()",
|
||||
"line": 1,
|
||||
|
|
@ -178,7 +181,8 @@ stubPreparedMessages.set("console.clear()", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.count('bar')", new ConsoleMessage({
|
||||
|
|
@ -190,7 +194,7 @@ stubPreparedMessages.set("console.count('bar')", new ConsoleMessage({
|
|||
"messageText": "bar: 1",
|
||||
"parameters": null,
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"debug\",\"messageText\":\"bar: 1\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"debug\",\"messageText\":\"bar: 1\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.count(%27bar%27)",
|
||||
|
|
@ -199,7 +203,8 @@ stubPreparedMessages.set("console.count('bar')", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.assert(false, {message: 'foobar'})", new ConsoleMessage({
|
||||
|
|
@ -234,7 +239,7 @@ stubPreparedMessages.set("console.assert(false, {message: 'foobar'})", new Conso
|
|||
}
|
||||
],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"assert\",\"level\":\"error\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn8.child1/obj31\",\"class\":\"Object\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":1,\"preview\":{\"kind\":\"Object\",\"ownProperties\":{\"message\":{\"configurable\":true,\"enumerable\":true,\"writable\":true,\"value\":\"foobar\"}},\"ownPropertiesLength\":1,\"safeGetterValues\":{}}}],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":27,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":1}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"assert\",\"level\":\"error\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn8.child1/obj31\",\"class\":\"Object\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":1,\"preview\":{\"kind\":\"Object\",\"ownProperties\":{\"message\":{\"configurable\":true,\"enumerable\":true,\"writable\":true,\"value\":\"foobar\"}},\"ownPropertiesLength\":1,\"safeGetterValues\":{}}}],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":27,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":1}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.assert(false%2C%20%7Bmessage%3A%20%27foobar%27%7D)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": [
|
||||
{
|
||||
"columnNumber": 27,
|
||||
|
|
@ -251,7 +256,8 @@ stubPreparedMessages.set("console.assert(false, {message: 'foobar'})", new Conso
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.log('hello \nfrom \rthe \"string world!')", new ConsoleMessage({
|
||||
|
|
@ -265,7 +271,7 @@ stubPreparedMessages.set("console.log('hello \nfrom \rthe \"string world!')", ne
|
|||
"hello \nfrom \rthe \"string world!"
|
||||
],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"hello \\nfrom \\rthe \\\"string world!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"hello \\nfrom \\rthe \\\"string world!\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27hello%20%5Cnfrom%20%5Crthe%20%5C%22string%20world!%27)",
|
||||
|
|
@ -274,7 +280,8 @@ stubPreparedMessages.set("console.log('hello \nfrom \rthe \"string world!')", ne
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.log('úṇĩçödê țĕșť')", new ConsoleMessage({
|
||||
|
|
@ -288,7 +295,7 @@ stubPreparedMessages.set("console.log('úṇĩçödê țĕșť')", new ConsoleMe
|
|||
"úṇĩçödê țĕșť"
|
||||
],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"úṇĩçödê țĕșť\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"úṇĩçödê țĕșť\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%27%C3%BA%E1%B9%87%C4%A9%C3%A7%C3%B6d%C3%AA%20%C8%9B%C4%95%C8%99%C5%A5%27)",
|
||||
|
|
@ -297,7 +304,8 @@ stubPreparedMessages.set("console.log('úṇĩçödê țĕșť')", new ConsoleMe
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.dirxml(window)", new ConsoleMessage({
|
||||
|
|
@ -315,7 +323,7 @@ stubPreparedMessages.set("console.dirxml(window)", new ConsoleMessage({
|
|||
"extensible": true,
|
||||
"frozen": false,
|
||||
"sealed": false,
|
||||
"ownPropertyLength": 804,
|
||||
"ownPropertyLength": 815,
|
||||
"preview": {
|
||||
"kind": "ObjectWithURL",
|
||||
"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html"
|
||||
|
|
@ -323,7 +331,7 @@ stubPreparedMessages.set("console.dirxml(window)", new ConsoleMessage({
|
|||
}
|
||||
],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn11.child1/obj31\",\"class\":\"Window\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":804,\"preview\":{\"kind\":\"ObjectWithURL\",\"url\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html\"}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.dirxml(window)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn11.child1/obj31\",\"class\":\"Window\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":804,\"preview\":{\"kind\":\"ObjectWithURL\",\"url\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html\"}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.dirxml(window)\",\"line\":1,\"column\":27},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.dirxml(window)",
|
||||
|
|
@ -332,7 +340,8 @@ stubPreparedMessages.set("console.dirxml(window)", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.trace()", new ConsoleMessage({
|
||||
|
|
@ -344,7 +353,7 @@ stubPreparedMessages.set("console.trace()", new ConsoleMessage({
|
|||
"messageText": null,
|
||||
"parameters": [],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"trace\",\"level\":\"log\",\"messageText\":null,\"parameters\":[],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"testStacktraceFiltering\",\"language\":2,\"lineNumber\":3},{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"foo\",\"language\":2,\"lineNumber\":6},{\"columnNumber\":1,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":9}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"line\":3,\"column\":3},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"trace\",\"level\":\"log\",\"messageText\":null,\"parameters\":[],\"repeatId\":null,\"stacktrace\":[{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"testStacktraceFiltering\",\"language\":2,\"lineNumber\":3},{\"columnNumber\":3,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"foo\",\"language\":2,\"lineNumber\":6},{\"columnNumber\":1,\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"functionName\":\"triggerPacket\",\"language\":2,\"lineNumber\":9}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.trace()\",\"line\":3,\"column\":3},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": [
|
||||
{
|
||||
"columnNumber": 3,
|
||||
|
|
@ -375,7 +384,8 @@ stubPreparedMessages.set("console.trace()", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.time('bar')", new ConsoleMessage({
|
||||
|
|
@ -387,7 +397,7 @@ stubPreparedMessages.set("console.time('bar')", new ConsoleMessage({
|
|||
"messageText": null,
|
||||
"parameters": null,
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"nullMessage\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"nullMessage\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
|
||||
|
|
@ -396,7 +406,8 @@ stubPreparedMessages.set("console.time('bar')", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.timeEnd('bar')", new ConsoleMessage({
|
||||
|
|
@ -408,7 +419,7 @@ stubPreparedMessages.set("console.timeEnd('bar')", new ConsoleMessage({
|
|||
"messageText": "bar: 1.36ms",
|
||||
"parameters": null,
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"timeEnd\",\"level\":\"log\",\"messageText\":\"bar: 1.36ms\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"timeEnd\",\"level\":\"log\",\"messageText\":\"bar: 1.36ms\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.time(%27bar%27)",
|
||||
|
|
@ -417,7 +428,8 @@ stubPreparedMessages.set("console.timeEnd('bar')", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.table('bar')", new ConsoleMessage({
|
||||
|
|
@ -431,7 +443,7 @@ stubPreparedMessages.set("console.table('bar')", new ConsoleMessage({
|
|||
"bar"
|
||||
],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%27bar%27)",
|
||||
|
|
@ -440,7 +452,8 @@ stubPreparedMessages.set("console.table('bar')", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.table(['a', 'b', 'c'])", new ConsoleMessage({
|
||||
|
|
@ -471,7 +484,7 @@ stubPreparedMessages.set("console.table(['a', 'b', 'c'])", new ConsoleMessage({
|
|||
}
|
||||
],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"table\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn15.child1/obj31\",\"class\":\"Array\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":4,\"preview\":{\"kind\":\"ArrayLike\",\"length\":3,\"items\":[\"a\",\"b\",\"c\"]}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"table\",\"level\":\"log\",\"messageText\":null,\"parameters\":[{\"type\":\"object\",\"actor\":\"server1.conn15.child1/obj31\",\"class\":\"Array\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":4,\"preview\":{\"kind\":\"ArrayLike\",\"length\":3,\"items\":[\"a\",\"b\",\"c\"]}}],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.table(%5B%27a%27%2C%20%27b%27%2C%20%27c%27%5D)",
|
||||
|
|
@ -480,7 +493,8 @@ stubPreparedMessages.set("console.table(['a', 'b', 'c'])", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.group('bar')", new ConsoleMessage({
|
||||
|
|
@ -492,7 +506,7 @@ stubPreparedMessages.set("console.group('bar')", new ConsoleMessage({
|
|||
"messageText": "bar",
|
||||
"parameters": null,
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"bar\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"bar\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
|
||||
|
|
@ -501,7 +515,8 @@ stubPreparedMessages.set("console.group('bar')", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.groupEnd('bar')", new ConsoleMessage({
|
||||
|
|
@ -513,7 +528,7 @@ stubPreparedMessages.set("console.groupEnd('bar')", new ConsoleMessage({
|
|||
"messageText": null,
|
||||
"parameters": null,
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group(%27bar%27)",
|
||||
|
|
@ -522,7 +537,8 @@ stubPreparedMessages.set("console.groupEnd('bar')", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.groupCollapsed('foo')", new ConsoleMessage({
|
||||
|
|
@ -534,7 +550,7 @@ stubPreparedMessages.set("console.groupCollapsed('foo')", new ConsoleMessage({
|
|||
"messageText": "foo",
|
||||
"parameters": null,
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroupCollapsed\",\"level\":\"log\",\"messageText\":\"foo\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroupCollapsed\",\"level\":\"log\",\"messageText\":\"foo\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
|
||||
|
|
@ -543,7 +559,8 @@ stubPreparedMessages.set("console.groupCollapsed('foo')", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.groupEnd('foo')", new ConsoleMessage({
|
||||
|
|
@ -555,7 +572,7 @@ stubPreparedMessages.set("console.groupEnd('foo')", new ConsoleMessage({
|
|||
"messageText": null,
|
||||
"parameters": null,
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.groupCollapsed(%27foo%27)",
|
||||
|
|
@ -564,7 +581,8 @@ stubPreparedMessages.set("console.groupEnd('foo')", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.group()", new ConsoleMessage({
|
||||
|
|
@ -576,7 +594,7 @@ stubPreparedMessages.set("console.group()", new ConsoleMessage({
|
|||
"messageText": "<no group label>",
|
||||
"parameters": null,
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"<no group label>\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"startGroup\",\"level\":\"log\",\"messageText\":\"<no group label>\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
|
||||
|
|
@ -585,7 +603,8 @@ stubPreparedMessages.set("console.group()", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.groupEnd()", new ConsoleMessage({
|
||||
|
|
@ -597,7 +616,7 @@ stubPreparedMessages.set("console.groupEnd()", new ConsoleMessage({
|
|||
"messageText": null,
|
||||
"parameters": null,
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"endGroup\",\"level\":\"log\",\"messageText\":null,\"parameters\":null,\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()\",\"line\":3,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.group()",
|
||||
|
|
@ -606,7 +625,8 @@ stubPreparedMessages.set("console.groupEnd()", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": null,
|
||||
"userProvidedStyles": []
|
||||
"userProvidedStyles": [],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("console.log(%cfoobar)", new ConsoleMessage({
|
||||
|
|
@ -621,7 +641,7 @@ stubPreparedMessages.set("console.log(%cfoobar)", new ConsoleMessage({
|
|||
"bar"
|
||||
],
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"foo\",\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%25cfoobar)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[\"color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px\",\"color:red;background:url('http://example.com/test')\"]}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"console-api\",\"type\":\"log\",\"level\":\"log\",\"messageText\":null,\"parameters\":[\"foo\",\"bar\"],\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%25cfoobar)\",\"line\":2,\"column\":1},\"groupId\":null,\"exceptionDocURL\":null,\"userProvidedStyles\":[\"color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px\",\"color:red;background:url('http://example.com/test')\"],\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=console.log(%25cfoobar)",
|
||||
|
|
@ -633,10 +653,10 @@ stubPreparedMessages.set("console.log(%cfoobar)", new ConsoleMessage({
|
|||
"userProvidedStyles": [
|
||||
"color:blue;font-size:1.3em;background:url('http://example.com/test');position:absolute;top:10px",
|
||||
"color:red;background:url('http://example.com/test')"
|
||||
]
|
||||
],
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
|
||||
stubPackets.set("console.log('foobar', 'test')", {
|
||||
"from": "server1.conn0.child1/consoleActor2",
|
||||
"type": "consoleAPICall",
|
||||
|
|
@ -1028,7 +1048,7 @@ stubPackets.set("console.dirxml(window)", {
|
|||
"extensible": true,
|
||||
"frozen": false,
|
||||
"sealed": false,
|
||||
"ownPropertyLength": 804,
|
||||
"ownPropertyLength": 815,
|
||||
"preview": {
|
||||
"kind": "ObjectWithURL",
|
||||
"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html"
|
||||
|
|
@ -1475,8 +1495,7 @@ stubPackets.set("console.log(%cfoobar)", {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
module.exports = {
|
||||
stubPreparedMessages,
|
||||
stubPackets,
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ const { ConsoleMessage, NetworkEventMessage } = require("devtools/client/webcons
|
|||
|
||||
let stubPreparedMessages = new Map();
|
||||
let stubPackets = new Map();
|
||||
|
||||
|
||||
stubPreparedMessages.set("new Date(0)", new ConsoleMessage({
|
||||
"id": "1",
|
||||
"allowRepeating": true,
|
||||
|
|
@ -32,11 +30,12 @@ stubPreparedMessages.set("new Date(0)", new ConsoleMessage({
|
|||
}
|
||||
},
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"result\",\"level\":\"log\",\"parameters\":{\"type\":\"object\",\"actor\":\"server1.conn0.child1/obj30\",\"class\":\"Date\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":0,\"preview\":{\"timestamp\":0}},\"repeatId\":null,\"stacktrace\":null,\"frame\":null,\"groupId\":null,\"userProvidedStyles\":null}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"result\",\"level\":\"log\",\"parameters\":{\"type\":\"object\",\"actor\":\"server1.conn0.child1/obj30\",\"class\":\"Date\",\"extensible\":true,\"frozen\":false,\"sealed\":false,\"ownPropertyLength\":0,\"preview\":{\"timestamp\":0}},\"repeatId\":null,\"stacktrace\":null,\"frame\":null,\"groupId\":null,\"userProvidedStyles\":null,\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": null,
|
||||
"groupId": null,
|
||||
"userProvidedStyles": null
|
||||
"userProvidedStyles": null,
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("asdf()", new ConsoleMessage({
|
||||
|
|
@ -50,7 +49,7 @@ stubPreparedMessages.set("asdf()", new ConsoleMessage({
|
|||
"type": "undefined"
|
||||
},
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"result\",\"level\":\"error\",\"messageText\":\"ReferenceError: asdf is not defined\",\"parameters\":{\"type\":\"undefined\"},\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"debugger eval code\",\"line\":1,\"column\":1},\"groupId\":null,\"exceptionDocURL\":\"https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default\",\"userProvidedStyles\":null}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"result\",\"level\":\"error\",\"messageText\":\"ReferenceError: asdf is not defined\",\"parameters\":{\"type\":\"undefined\"},\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"debugger eval code\",\"line\":1,\"column\":1},\"groupId\":null,\"exceptionDocURL\":\"https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default\",\"userProvidedStyles\":null,\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "debugger eval code",
|
||||
|
|
@ -59,7 +58,8 @@ stubPreparedMessages.set("asdf()", new ConsoleMessage({
|
|||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
|
||||
"userProvidedStyles": null
|
||||
"userProvidedStyles": null,
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("1 + @", new ConsoleMessage({
|
||||
|
|
@ -73,7 +73,7 @@ stubPreparedMessages.set("1 + @", new ConsoleMessage({
|
|||
"type": "undefined"
|
||||
},
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"result\",\"level\":\"error\",\"messageText\":\"SyntaxError: illegal character\",\"parameters\":{\"type\":\"undefined\"},\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"debugger eval code\",\"line\":1,\"column\":4},\"groupId\":null,\"userProvidedStyles\":null}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"result\",\"level\":\"error\",\"messageText\":\"SyntaxError: illegal character\",\"parameters\":{\"type\":\"undefined\"},\"repeatId\":null,\"stacktrace\":null,\"frame\":{\"source\":\"debugger eval code\",\"line\":1,\"column\":4},\"groupId\":null,\"userProvidedStyles\":null,\"notes\":null}",
|
||||
"stacktrace": null,
|
||||
"frame": {
|
||||
"source": "debugger eval code",
|
||||
|
|
@ -81,10 +81,10 @@ stubPreparedMessages.set("1 + @", new ConsoleMessage({
|
|||
"column": 4
|
||||
},
|
||||
"groupId": null,
|
||||
"userProvidedStyles": null
|
||||
"userProvidedStyles": null,
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
|
||||
stubPackets.set("new Date(0)", {
|
||||
"from": "server1.conn0.child1/consoleActor2",
|
||||
"input": "new Date(0)",
|
||||
|
|
@ -103,7 +103,8 @@ stubPackets.set("new Date(0)", {
|
|||
"timestamp": 1476573073424,
|
||||
"exception": null,
|
||||
"frame": null,
|
||||
"helperResult": null
|
||||
"helperResult": null,
|
||||
"notes": null
|
||||
});
|
||||
|
||||
stubPackets.set("asdf()", {
|
||||
|
|
@ -138,7 +139,8 @@ stubPackets.set("asdf()", {
|
|||
"line": 1,
|
||||
"column": 1
|
||||
},
|
||||
"helperResult": null
|
||||
"helperResult": null,
|
||||
"notes": null
|
||||
});
|
||||
|
||||
stubPackets.set("1 + @", {
|
||||
|
|
@ -172,11 +174,11 @@ stubPackets.set("1 + @", {
|
|||
"line": 1,
|
||||
"column": 4
|
||||
},
|
||||
"helperResult": null
|
||||
"helperResult": null,
|
||||
"notes": null
|
||||
});
|
||||
|
||||
|
||||
module.exports = {
|
||||
stubPreparedMessages,
|
||||
stubPackets,
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ const { ConsoleMessage, NetworkEventMessage } = require("devtools/client/webcons
|
|||
|
||||
let stubPreparedMessages = new Map();
|
||||
let stubPackets = new Map();
|
||||
|
||||
|
||||
stubPreparedMessages.set("ReferenceError: asdf is not defined", new ConsoleMessage({
|
||||
"id": "1",
|
||||
"allowRepeating": true,
|
||||
|
|
@ -22,7 +20,7 @@ stubPreparedMessages.set("ReferenceError: asdf is not defined", new ConsoleMessa
|
|||
"messageText": "ReferenceError: asdf is not defined",
|
||||
"parameters": null,
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"log\",\"level\":\"error\",\"messageText\":\"ReferenceError: asdf is not defined\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":[{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":3,\"columnNumber\":5,\"functionName\":\"bar\"},{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":6,\"columnNumber\":5,\"functionName\":\"foo\"},{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":9,\"columnNumber\":3,\"functionName\":null}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"line\":3,\"column\":5},\"groupId\":null,\"exceptionDocURL\":\"https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default\"}",
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"log\",\"level\":\"error\",\"messageText\":\"ReferenceError: asdf is not defined\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":[{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":3,\"columnNumber\":5,\"functionName\":\"bar\"},{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":6,\"columnNumber\":5,\"functionName\":\"foo\"},{\"filename\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"lineNumber\":9,\"columnNumber\":3,\"functionName\":null}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error\",\"line\":3,\"column\":5},\"groupId\":null,\"exceptionDocURL\":\"https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default\",\"userProvidedStyles\":null,\"notes\":null}",
|
||||
"stacktrace": [
|
||||
{
|
||||
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-tempfile.js?key=Reference%20Error",
|
||||
|
|
@ -49,9 +47,53 @@ stubPreparedMessages.set("ReferenceError: asdf is not defined", new ConsoleMessa
|
|||
"column": 5
|
||||
},
|
||||
"groupId": null,
|
||||
"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default"
|
||||
"exceptionDocURL": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_defined?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default",
|
||||
"userProvidedStyles": null,
|
||||
"notes": null
|
||||
}));
|
||||
|
||||
stubPreparedMessages.set("SyntaxError: redeclaration of let a", new ConsoleMessage({
|
||||
"id": "1",
|
||||
"allowRepeating": true,
|
||||
"source": "javascript",
|
||||
"type": "log",
|
||||
"level": "error",
|
||||
"messageText": "SyntaxError: redeclaration of let a",
|
||||
"parameters": null,
|
||||
"repeat": 1,
|
||||
"repeatId": "{\"id\":null,\"allowRepeating\":true,\"source\":\"javascript\",\"type\":\"log\",\"level\":\"error\",\"messageText\":\"SyntaxError: redeclaration of let a\",\"parameters\":null,\"repeatId\":null,\"stacktrace\":[{\"filename\":\"chrome://mochikit/content/tests/BrowserTestUtils/content-task.js line 52 > eval\",\"lineNumber\":6,\"columnNumber\":9,\"functionName\":null},{\"filename\":\"chrome://mochikit/content/tests/BrowserTestUtils/content-task.js\",\"lineNumber\":53,\"columnNumber\":20,\"functionName\":null}],\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html\",\"line\":2,\"column\":9},\"groupId\":null,\"userProvidedStyles\":null,\"notes\":[{\"messageBody\":\"Previously declared at line 2, column 6\",\"frame\":{\"source\":\"http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html\",\"line\":2,\"column\":6}}]}",
|
||||
"stacktrace": [
|
||||
{
|
||||
"filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js line 52 > eval",
|
||||
"lineNumber": 6,
|
||||
"columnNumber": 9,
|
||||
"functionName": null
|
||||
},
|
||||
{
|
||||
"filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js",
|
||||
"lineNumber": 53,
|
||||
"columnNumber": 20,
|
||||
"functionName": null
|
||||
}
|
||||
],
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
|
||||
"line": 2,
|
||||
"column": 9
|
||||
},
|
||||
"groupId": null,
|
||||
"userProvidedStyles": null,
|
||||
"notes": [
|
||||
{
|
||||
"messageBody": "Previously declared at line 2, column 6",
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
|
||||
"line": 2,
|
||||
"column": 6
|
||||
}
|
||||
}
|
||||
]
|
||||
}));
|
||||
|
||||
stubPackets.set("ReferenceError: asdf is not defined", {
|
||||
"from": "server1.conn0.child1/consoleActor2",
|
||||
|
|
@ -91,12 +133,56 @@ stubPackets.set("ReferenceError: asdf is not defined", {
|
|||
"columnNumber": 3,
|
||||
"functionName": null
|
||||
}
|
||||
]
|
||||
],
|
||||
"notes": null
|
||||
}
|
||||
});
|
||||
|
||||
stubPackets.set("SyntaxError: redeclaration of let a", {
|
||||
"from": "server1.conn0.child1/consoleActor2",
|
||||
"type": "pageError",
|
||||
"pageError": {
|
||||
"errorMessage": "SyntaxError: redeclaration of let a",
|
||||
"errorMessageName": "JSMSG_REDECLARED_VAR",
|
||||
"sourceName": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
|
||||
"lineText": " let a, a;\n",
|
||||
"lineNumber": 2,
|
||||
"columnNumber": 9,
|
||||
"category": "content javascript",
|
||||
"warning": false,
|
||||
"error": false,
|
||||
"exception": true,
|
||||
"strict": false,
|
||||
"info": false,
|
||||
"private": false,
|
||||
"stacktrace": [
|
||||
{
|
||||
"filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js line 52 > eval",
|
||||
"lineNumber": 6,
|
||||
"columnNumber": 9,
|
||||
"functionName": null
|
||||
},
|
||||
{
|
||||
"filename": "chrome://mochikit/content/tests/BrowserTestUtils/content-task.js",
|
||||
"lineNumber": 53,
|
||||
"columnNumber": 20,
|
||||
"functionName": null
|
||||
}
|
||||
],
|
||||
"notes": [
|
||||
{
|
||||
"messageBody": "Previously declared at line 2, column 6",
|
||||
"frame": {
|
||||
"source": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-console-api.html",
|
||||
"line": 2,
|
||||
"column": 6
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
stubPreparedMessages,
|
||||
stubPackets,
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ exports.ConsoleMessage = Immutable.Record({
|
|||
groupId: null,
|
||||
exceptionDocURL: null,
|
||||
userProvidedStyles: null,
|
||||
notes: null,
|
||||
});
|
||||
|
||||
exports.NetworkEventMessage = Immutable.Record({
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ function transformPacket(packet) {
|
|||
stacktrace: pageError.stacktrace ? pageError.stacktrace : null,
|
||||
frame,
|
||||
exceptionDocURL: pageError.exceptionDocURL,
|
||||
notes: pageError.notes,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -185,7 +186,8 @@ function transformPacket(packet) {
|
|||
exceptionMessage: messageText,
|
||||
exceptionDocURL,
|
||||
frame,
|
||||
result: parameters
|
||||
result: parameters,
|
||||
notes,
|
||||
} = packet;
|
||||
|
||||
const level = messageText ? MESSAGE_LEVEL.ERROR : MESSAGE_LEVEL.LOG;
|
||||
|
|
@ -197,6 +199,7 @@ function transformPacket(packet) {
|
|||
parameters,
|
||||
exceptionDocURL,
|
||||
frame,
|
||||
notes,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -888,7 +888,8 @@ WebConsoleActor.prototype =
|
|||
let evalResult = evalInfo.result;
|
||||
let helperResult = evalInfo.helperResult;
|
||||
|
||||
let result, errorDocURL, errorMessage, errorGrip = null, frame = null;
|
||||
let result, errorDocURL, errorMessage, errorNotes = null, errorGrip = null,
|
||||
frame = null;
|
||||
if (evalResult) {
|
||||
if ("return" in evalResult) {
|
||||
result = evalResult.return;
|
||||
|
|
@ -943,6 +944,23 @@ WebConsoleActor.prototype =
|
|||
};
|
||||
}
|
||||
} catch (ex) {}
|
||||
|
||||
try {
|
||||
let notes = error.errorNotes;
|
||||
if (notes && notes.length) {
|
||||
errorNotes = [];
|
||||
for (let note of notes) {
|
||||
errorNotes.push({
|
||||
messageBody: this._createStringGrip(note.message),
|
||||
frame: {
|
||||
source: note.fileName,
|
||||
line: note.lineNumber,
|
||||
column: note.columnNumber,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (ex) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -967,6 +985,7 @@ WebConsoleActor.prototype =
|
|||
exceptionDocURL: errorDocURL,
|
||||
frame,
|
||||
helperResult: helperResult,
|
||||
notes: errorNotes,
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -1500,6 +1519,23 @@ WebConsoleActor.prototype =
|
|||
lineText = lineText.substr(0, DebuggerServer.LONG_STRING_INITIAL_LENGTH);
|
||||
}
|
||||
|
||||
let notesArray = null;
|
||||
let notes = aPageError.notes;
|
||||
if (notes && notes.length) {
|
||||
notesArray = [];
|
||||
for (let i = 0, len = notes.length; i < len; i++) {
|
||||
let note = notes.queryElementAt(i, Ci.nsIScriptErrorNote);
|
||||
notesArray.push({
|
||||
messageBody: this._createStringGrip(note.errorMessage),
|
||||
frame: {
|
||||
source: note.sourceName,
|
||||
line: note.lineNumber,
|
||||
column: note.columnNumber,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
errorMessage: this._createStringGrip(aPageError.errorMessage),
|
||||
errorMessageName: aPageError.errorMessageName,
|
||||
|
|
@ -1516,7 +1552,8 @@ WebConsoleActor.prototype =
|
|||
strict: !!(aPageError.flags & aPageError.strictFlag),
|
||||
info: !!(aPageError.flags & aPageError.infoFlag),
|
||||
private: aPageError.isFromPrivateWindow,
|
||||
stacktrace: stack
|
||||
stacktrace: stack,
|
||||
notes: notesArray,
|
||||
};
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -112,6 +112,24 @@ function doPageErrors()
|
|||
warning: true,
|
||||
exception: false,
|
||||
},
|
||||
"let a, a;": {
|
||||
errorMessage: /redeclaration of/,
|
||||
errorMessageName: "JSMSG_REDECLARED_VAR",
|
||||
sourceName: /test_page_errors/,
|
||||
category: "chrome javascript",
|
||||
timeStamp: /^\d+$/,
|
||||
error: false,
|
||||
warning: false,
|
||||
exception: true,
|
||||
notes: [
|
||||
{
|
||||
messageBody: /Previously declared at line/,
|
||||
frame: {
|
||||
source: /test_page_errors/,
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
};
|
||||
|
||||
let container = document.createElement("script");
|
||||
|
|
|
|||
|
|
@ -1183,14 +1183,6 @@ GetInterfaceImpl(JSContext* aCx, nsIInterfaceRequestor* aRequestor,
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
UnforgeableValueOf(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
args.rval().set(args.thisv());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2044,9 +2044,6 @@ GetInterface(JSContext* aCx, T* aThis, nsIJSID* aIID,
|
|||
GetInterfaceImpl(aCx, aThis, aThis, aIID, aRetval, aError);
|
||||
}
|
||||
|
||||
bool
|
||||
UnforgeableValueOf(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
|
|
|
|||
|
|
@ -2390,11 +2390,10 @@ class MethodDefiner(PropertyDefiner):
|
|||
# Synthesize our valueOf method
|
||||
self.regular.append({
|
||||
"name": 'valueOf',
|
||||
"nativeName": "UnforgeableValueOf",
|
||||
"selfHostedName": "Object_valueOf",
|
||||
"methodInfo": False,
|
||||
"length": 0,
|
||||
"flags": "JSPROP_ENUMERATE", # readonly/permanent added
|
||||
# automatically.
|
||||
"flags": "0", # readonly/permanent added automatically.
|
||||
"condition": MemberCondition()
|
||||
})
|
||||
|
||||
|
|
@ -3456,19 +3455,15 @@ def InitUnforgeablePropertiesOnHolder(descriptor, properties, failureCode,
|
|||
"nsContentUtils::ThreadsafeIsCallerChrome()"))
|
||||
|
||||
if descriptor.interface.getExtendedAttribute("Unforgeable"):
|
||||
# We do our undefined toJSON and toPrimitive here, not as a regular
|
||||
# property because we don't have a concept of value props anywhere in
|
||||
# IDL.
|
||||
# We do our undefined toPrimitive here, not as a regular property
|
||||
# because we don't have a concept of value props anywhere in IDL.
|
||||
unforgeables.append(CGGeneric(fill(
|
||||
"""
|
||||
JS::RootedId toPrimitive(aCx,
|
||||
SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::toPrimitive)));
|
||||
if (!JS_DefinePropertyById(aCx, ${holderName}, toPrimitive,
|
||||
JS::UndefinedHandleValue,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT) ||
|
||||
!JS_DefineProperty(aCx, ${holderName}, "toJSON",
|
||||
JS::UndefinedHandleValue,
|
||||
JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
|
||||
JSPROP_READONLY | JSPROP_PERMANENT)) {
|
||||
$*{failureCode}
|
||||
}
|
||||
""",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,12 @@
|
|||
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIScriptError.idl'
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom_bindings'
|
||||
|
||||
EXPORTS.ipc += [
|
||||
'ErrorIPCUtils.h',
|
||||
]
|
||||
|
|
@ -91,6 +97,8 @@ UNIFIED_SOURCES += [
|
|||
'DOMJSProxyHandler.cpp',
|
||||
'Exceptions.cpp',
|
||||
'IterableIterator.cpp',
|
||||
'nsScriptError.cpp',
|
||||
'nsScriptErrorWithStack.cpp',
|
||||
'SimpleGlobalObject.cpp',
|
||||
'ToJSValue.cpp',
|
||||
'WebIDLGlobalNameHash.cpp',
|
||||
|
|
|
|||
|
|
@ -9,13 +9,25 @@
|
|||
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIArray.idl"
|
||||
#include "nsIConsoleMessage.idl"
|
||||
|
||||
%{C++
|
||||
#include "nsStringGlue.h" // for nsDependentCString
|
||||
%}
|
||||
|
||||
[scriptable, uuid(361be358-76f0-47aa-b37b-6ad833599e8d)]
|
||||
[scriptable, uuid(e8933fc9-c302-4e12-a55b-4f88611d9c6c)]
|
||||
interface nsIScriptErrorNote : nsISupports
|
||||
{
|
||||
readonly attribute AString errorMessage;
|
||||
readonly attribute AString sourceName;
|
||||
readonly attribute uint32_t lineNumber;
|
||||
readonly attribute uint32_t columnNumber;
|
||||
|
||||
AUTF8String toString();
|
||||
};
|
||||
|
||||
[scriptable, uuid(63eb4d3e-7d99-4150-b4f3-11314f9d82a9)]
|
||||
interface nsIScriptError : nsIConsoleMessage
|
||||
{
|
||||
/** pseudo-flag for default case */
|
||||
|
|
@ -74,6 +86,7 @@ interface nsIScriptError : nsIConsoleMessage
|
|||
*/
|
||||
attribute AString errorMessageName;
|
||||
|
||||
readonly attribute nsIArray notes;
|
||||
|
||||
void init(in AString message,
|
||||
in AString sourceName,
|
||||
|
|
@ -5,18 +5,19 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* nsIScriptError implementation. Defined here, lacking a JS-specific
|
||||
* place to put XPCOM things.
|
||||
* nsIScriptError implementation.
|
||||
*/
|
||||
|
||||
#include "xpcprivate.h"
|
||||
#include "nsScriptError.h"
|
||||
#include "jsprf.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsILoadContext.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsISensitiveInfoHiddenURI.h"
|
||||
|
||||
|
|
@ -46,6 +47,12 @@ nsScriptErrorBase::nsScriptErrorBase()
|
|||
|
||||
nsScriptErrorBase::~nsScriptErrorBase() {}
|
||||
|
||||
void
|
||||
nsScriptErrorBase::AddNote(nsIScriptErrorNote* note)
|
||||
{
|
||||
mNotes.AppendObject(note);
|
||||
}
|
||||
|
||||
void
|
||||
nsScriptErrorBase::InitializeOnMainThread()
|
||||
{
|
||||
|
|
@ -189,6 +196,28 @@ nsScriptErrorBase::Init(const nsAString& message,
|
|||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
AssignSourceNameHelper(nsString& aSourceNameDest, const nsAString& aSourceNameSrc)
|
||||
{
|
||||
if (aSourceNameSrc.IsEmpty())
|
||||
return;
|
||||
|
||||
aSourceNameDest.Assign(aSourceNameSrc);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsAutoCString pass;
|
||||
if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), aSourceNameSrc)) &&
|
||||
NS_SUCCEEDED(uri->GetPassword(pass)) &&
|
||||
!pass.IsEmpty())
|
||||
{
|
||||
nsCOMPtr<nsISensitiveInfoHiddenURI> safeUri = do_QueryInterface(uri);
|
||||
|
||||
nsAutoCString loc;
|
||||
if (safeUri && NS_SUCCEEDED(safeUri->GetSensitiveInfoHiddenSpec(loc)))
|
||||
aSourceNameDest.Assign(NS_ConvertUTF8toUTF16(loc));
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::InitWithWindowID(const nsAString& message,
|
||||
const nsAString& sourceName,
|
||||
|
|
@ -200,26 +229,7 @@ nsScriptErrorBase::InitWithWindowID(const nsAString& message,
|
|||
uint64_t aInnerWindowID)
|
||||
{
|
||||
mMessage.Assign(message);
|
||||
|
||||
if (!sourceName.IsEmpty()) {
|
||||
mSourceName.Assign(sourceName);
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsAutoCString pass;
|
||||
if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), sourceName)) &&
|
||||
NS_SUCCEEDED(uri->GetPassword(pass)) &&
|
||||
!pass.IsEmpty()) {
|
||||
nsCOMPtr<nsISensitiveInfoHiddenURI> safeUri =
|
||||
do_QueryInterface(uri);
|
||||
|
||||
nsAutoCString loc;
|
||||
if (safeUri &&
|
||||
NS_SUCCEEDED(safeUri->GetSensitiveInfoHiddenSpec(loc))) {
|
||||
mSourceName.Assign(NS_ConvertUTF8toUTF16(loc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AssignSourceNameHelper(mSourceName, sourceName);
|
||||
mLineNumber = lineNumber;
|
||||
mSourceLine.Assign(sourceLine);
|
||||
mColumnNumber = columnNumber;
|
||||
|
|
@ -235,8 +245,11 @@ nsScriptErrorBase::InitWithWindowID(const nsAString& message,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult)
|
||||
static nsresult
|
||||
ToStringHelper(const char* aSeverity, const nsString& aMessage,
|
||||
const nsString& aSourceName, const nsString* aSourceLine,
|
||||
uint32_t aLineNumber, uint32_t aColumnNumber,
|
||||
nsACString& /*UTF8*/ aResult)
|
||||
{
|
||||
static const char format0[] =
|
||||
"[%s: \"%s\" {file: \"%s\" line: %d column: %d source: \"%s\"}]";
|
||||
|
|
@ -245,43 +258,39 @@ nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult)
|
|||
static const char format2[] =
|
||||
"[%s: \"%s\"]";
|
||||
|
||||
static const char error[] = "JavaScript Error";
|
||||
static const char warning[] = "JavaScript Warning";
|
||||
|
||||
const char* severity = !(mFlags & JSREPORT_WARNING) ? error : warning;
|
||||
|
||||
char* temp;
|
||||
char* tempMessage = nullptr;
|
||||
char* tempSourceName = nullptr;
|
||||
char* tempSourceLine = nullptr;
|
||||
|
||||
if (!mMessage.IsEmpty())
|
||||
tempMessage = ToNewUTF8String(mMessage);
|
||||
if (!mSourceName.IsEmpty())
|
||||
if (!aMessage.IsEmpty())
|
||||
tempMessage = ToNewUTF8String(aMessage);
|
||||
if (!aSourceName.IsEmpty())
|
||||
// Use at most 512 characters from mSourceName.
|
||||
tempSourceName = ToNewUTF8String(StringHead(mSourceName, 512));
|
||||
if (!mSourceLine.IsEmpty())
|
||||
tempSourceName = ToNewUTF8String(StringHead(aSourceName, 512));
|
||||
if (aSourceLine && !aSourceLine->IsEmpty())
|
||||
// Use at most 512 characters from mSourceLine.
|
||||
tempSourceLine = ToNewUTF8String(StringHead(mSourceLine, 512));
|
||||
tempSourceLine = ToNewUTF8String(StringHead(*aSourceLine, 512));
|
||||
|
||||
if (nullptr != tempSourceName && nullptr != tempSourceLine)
|
||||
if (nullptr != tempSourceName && nullptr != tempSourceLine) {
|
||||
temp = JS_smprintf(format0,
|
||||
severity,
|
||||
aSeverity,
|
||||
tempMessage,
|
||||
tempSourceName,
|
||||
mLineNumber,
|
||||
mColumnNumber,
|
||||
aLineNumber,
|
||||
aColumnNumber,
|
||||
tempSourceLine);
|
||||
else if (!mSourceName.IsEmpty())
|
||||
} else if (!aSourceName.IsEmpty()) {
|
||||
temp = JS_smprintf(format1,
|
||||
severity,
|
||||
aSeverity,
|
||||
tempMessage,
|
||||
tempSourceName,
|
||||
mLineNumber);
|
||||
else
|
||||
aLineNumber);
|
||||
} else {
|
||||
temp = JS_smprintf(format2,
|
||||
severity,
|
||||
aSeverity,
|
||||
tempMessage);
|
||||
}
|
||||
|
||||
if (nullptr != tempMessage)
|
||||
free(tempMessage);
|
||||
|
|
@ -298,6 +307,18 @@ nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::ToString(nsACString& /*UTF8*/ aResult)
|
||||
{
|
||||
static const char error[] = "JavaScript Error";
|
||||
static const char warning[] = "JavaScript Warning";
|
||||
|
||||
const char* severity = !(mFlags & JSREPORT_WARNING) ? error : warning;
|
||||
|
||||
return ToStringHelper(severity, mMessage, mSourceName, &mSourceLine,
|
||||
mLineNumber, mColumnNumber, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetOuterWindowID(uint64_t* aOuterWindowID)
|
||||
{
|
||||
|
|
@ -342,4 +363,76 @@ nsScriptErrorBase::GetIsFromPrivateWindow(bool* aIsFromPrivateWindow)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorBase::GetNotes(nsIArray** aNotes)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIMutableArray> array =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t len = mNotes.Length();
|
||||
for (uint32_t i = 0; i < len; i++)
|
||||
array->AppendElement(mNotes[i], false);
|
||||
array.forget(aNotes);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsScriptError, nsIConsoleMessage, nsIScriptError)
|
||||
|
||||
nsScriptErrorNote::nsScriptErrorNote()
|
||||
: mMessage(),
|
||||
mSourceName(),
|
||||
mLineNumber(0),
|
||||
mColumnNumber(0)
|
||||
{
|
||||
}
|
||||
|
||||
nsScriptErrorNote::~nsScriptErrorNote() {}
|
||||
|
||||
void
|
||||
nsScriptErrorNote::Init(const nsAString& message,
|
||||
const nsAString& sourceName,
|
||||
uint32_t lineNumber,
|
||||
uint32_t columnNumber)
|
||||
{
|
||||
mMessage.Assign(message);
|
||||
AssignSourceNameHelper(mSourceName, sourceName);
|
||||
mLineNumber = lineNumber;
|
||||
mColumnNumber = columnNumber;
|
||||
}
|
||||
|
||||
// nsIScriptErrorNote methods
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorNote::GetErrorMessage(nsAString& aResult) {
|
||||
aResult.Assign(mMessage);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorNote::GetSourceName(nsAString& aResult) {
|
||||
aResult.Assign(mSourceName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorNote::GetLineNumber(uint32_t* result) {
|
||||
*result = mLineNumber;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorNote::GetColumnNumber(uint32_t* result) {
|
||||
*result = mColumnNumber;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptErrorNote::ToString(nsACString& /*UTF8*/ aResult)
|
||||
{
|
||||
return ToStringHelper("JavaScript Note", mMessage, mSourceName, nullptr,
|
||||
mLineNumber, mColumnNumber, aResult);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsScriptErrorNote, nsIScriptErrorNote)
|
||||
109
dom/bindings/nsScriptError.h
Normal file
109
dom/bindings/nsScriptError.h
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef mozilla_dom_nsScriptError_h
|
||||
#define mozilla_dom_nsScriptError_h
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "js/RootingAPI.h"
|
||||
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsScriptErrorNote final : public nsIScriptErrorNote {
|
||||
public:
|
||||
nsScriptErrorNote();
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSISCRIPTERRORNOTE
|
||||
|
||||
void Init(const nsAString& message, const nsAString& sourceName,
|
||||
uint32_t lineNumber, uint32_t columnNumber);
|
||||
|
||||
private:
|
||||
virtual ~nsScriptErrorNote();
|
||||
|
||||
nsString mMessage;
|
||||
nsString mSourceName;
|
||||
nsString mSourceLine;
|
||||
uint32_t mLineNumber;
|
||||
uint32_t mColumnNumber;
|
||||
};
|
||||
|
||||
// Definition of nsScriptError..
|
||||
class nsScriptErrorBase : public nsIScriptError {
|
||||
public:
|
||||
nsScriptErrorBase();
|
||||
|
||||
NS_DECL_NSICONSOLEMESSAGE
|
||||
NS_DECL_NSISCRIPTERROR
|
||||
|
||||
void AddNote(nsIScriptErrorNote* note);
|
||||
|
||||
protected:
|
||||
virtual ~nsScriptErrorBase();
|
||||
|
||||
void
|
||||
InitializeOnMainThread();
|
||||
|
||||
nsCOMArray<nsIScriptErrorNote> mNotes;
|
||||
nsString mMessage;
|
||||
nsString mMessageName;
|
||||
nsString mSourceName;
|
||||
uint32_t mLineNumber;
|
||||
nsString mSourceLine;
|
||||
uint32_t mColumnNumber;
|
||||
uint32_t mFlags;
|
||||
nsCString mCategory;
|
||||
// mOuterWindowID is set on the main thread from InitializeOnMainThread().
|
||||
uint64_t mOuterWindowID;
|
||||
uint64_t mInnerWindowID;
|
||||
int64_t mTimeStamp;
|
||||
// mInitializedOnMainThread and mIsFromPrivateWindow are set on the main
|
||||
// thread from InitializeOnMainThread().
|
||||
mozilla::Atomic<bool> mInitializedOnMainThread;
|
||||
bool mIsFromPrivateWindow;
|
||||
};
|
||||
|
||||
class nsScriptError final : public nsScriptErrorBase {
|
||||
public:
|
||||
nsScriptError() {}
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
private:
|
||||
virtual ~nsScriptError() {}
|
||||
};
|
||||
|
||||
class nsScriptErrorWithStack : public nsScriptErrorBase {
|
||||
public:
|
||||
explicit nsScriptErrorWithStack(JS::HandleObject);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsScriptErrorWithStack)
|
||||
|
||||
NS_IMETHOD Init(const nsAString& message,
|
||||
const nsAString& sourceName,
|
||||
const nsAString& sourceLine,
|
||||
uint32_t lineNumber,
|
||||
uint32_t columnNumber,
|
||||
uint32_t flags,
|
||||
const char* category) override;
|
||||
|
||||
NS_IMETHOD GetStack(JS::MutableHandleValue) override;
|
||||
NS_IMETHOD ToString(nsACString& aResult) override;
|
||||
|
||||
private:
|
||||
virtual ~nsScriptErrorWithStack();
|
||||
// Complete stackframe where the error happened.
|
||||
// Must be SavedFrame object.
|
||||
JS::Heap<JSObject*> mStack;
|
||||
};
|
||||
|
||||
#endif /* mozilla_dom_nsScriptError_h */
|
||||
|
|
@ -10,12 +10,14 @@
|
|||
* that can store a SavedFrame stack trace object.
|
||||
*/
|
||||
|
||||
#include "xpcprivate.h"
|
||||
#include "nsScriptError.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
@ -29,7 +29,9 @@ WebGLExtensionDebugShaders::GetTranslatedShaderSource(const WebGLShader& shader,
|
|||
{
|
||||
retval.SetIsVoid(true);
|
||||
|
||||
if (mIsLost || !mContext) return;
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mContext->ValidateObject("getShaderTranslatedSource: shader", shader))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -40,8 +40,10 @@ void
|
|||
WebGLExtensionDisjointTimerQuery::DeleteQueryEXT(WebGLQuery* query) const
|
||||
{
|
||||
const char funcName[] = "deleteQueryEXT";
|
||||
if (mIsLost || !mContext)
|
||||
return;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->DeleteQuery(query, funcName);
|
||||
}
|
||||
|
|
@ -50,8 +52,10 @@ bool
|
|||
WebGLExtensionDisjointTimerQuery::IsQueryEXT(const WebGLQuery* query) const
|
||||
{
|
||||
const char funcName[] = "isQueryEXT";
|
||||
if (mIsLost || !mContext)
|
||||
return false;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mContext->IsQuery(query, funcName);
|
||||
}
|
||||
|
|
@ -60,8 +64,10 @@ void
|
|||
WebGLExtensionDisjointTimerQuery::BeginQueryEXT(GLenum target, WebGLQuery& query) const
|
||||
{
|
||||
const char funcName[] = "beginQueryEXT";
|
||||
if (mIsLost || !mContext)
|
||||
return;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->BeginQuery(target, query, funcName);
|
||||
}
|
||||
|
|
@ -70,8 +76,10 @@ void
|
|||
WebGLExtensionDisjointTimerQuery::EndQueryEXT(GLenum target) const
|
||||
{
|
||||
const char funcName[] = "endQueryEXT";
|
||||
if (mIsLost || !mContext)
|
||||
return;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->EndQuery(target, funcName);
|
||||
}
|
||||
|
|
@ -80,8 +88,10 @@ void
|
|||
WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLQuery& query, GLenum target) const
|
||||
{
|
||||
const char funcName[] = "queryCounterEXT";
|
||||
if (mIsLost || !mContext)
|
||||
return;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mContext->ValidateObject(funcName, query))
|
||||
return;
|
||||
|
|
@ -95,8 +105,10 @@ WebGLExtensionDisjointTimerQuery::GetQueryEXT(JSContext* cx, GLenum target, GLen
|
|||
{
|
||||
const char funcName[] = "getQueryEXT";
|
||||
retval.setNull();
|
||||
if (mIsLost || !mContext)
|
||||
return;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->GetQuery(cx, target, pname, retval, funcName);
|
||||
}
|
||||
|
|
@ -108,8 +120,10 @@ WebGLExtensionDisjointTimerQuery::GetQueryObjectEXT(JSContext* cx,
|
|||
{
|
||||
const char funcName[] = "getQueryObjectEXT";
|
||||
retval.setNull();
|
||||
if (mIsLost || !mContext)
|
||||
return;
|
||||
|
||||
if (mIsLost || !mContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->GetQueryParameter(cx, query, pname, retval, funcName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ WebGLExtensionInstancedArrays::DrawArraysInstancedANGLE(GLenum mode,
|
|||
if (mContext) {
|
||||
mContext->ErrorInvalidOperation("%s: Extension is lost.",
|
||||
"drawArraysInstancedANGLE");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->DrawArraysInstanced(mode, first, count, primcount);
|
||||
|
|
@ -49,8 +49,8 @@ WebGLExtensionInstancedArrays::DrawElementsInstancedANGLE(GLenum mode,
|
|||
if (mContext) {
|
||||
mContext->ErrorInvalidOperation("%s: Extension is lost.",
|
||||
"drawElementsInstancedANGLE");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->DrawElementsInstanced(mode, count, type, offset, primcount);
|
||||
|
|
@ -64,8 +64,8 @@ WebGLExtensionInstancedArrays::VertexAttribDivisorANGLE(GLuint index,
|
|||
if (mContext) {
|
||||
mContext->ErrorInvalidOperation("%s: Extension is lost.",
|
||||
"vertexAttribDivisorANGLE");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mContext->VertexAttribDivisor(index, divisor);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "nsCycleCollectionNoteChild.h"
|
||||
|
||||
#include "WebGLTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
|
|
|||
|
|
@ -1381,7 +1381,7 @@ nsPluginStreamListenerPeer::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsICh
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Don't allow cross-origin 307 POST redirects.
|
||||
// Don't allow cross-origin 307/308 POST redirects.
|
||||
nsCOMPtr<nsIHttpChannel> oldHttpChannel(do_QueryInterface(oldChannel));
|
||||
if (oldHttpChannel) {
|
||||
uint32_t responseStatus;
|
||||
|
|
@ -1389,7 +1389,7 @@ nsPluginStreamListenerPeer::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsICh
|
|||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (responseStatus == 307) {
|
||||
if (responseStatus == 307 || responseStatus == 308) {
|
||||
nsAutoCString method;
|
||||
rv = oldHttpChannel->GetRequestMethod(method);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
|
|
|||
|
|
@ -988,7 +988,7 @@ Wrap(JSContext *cx, JS::HandleObject existing, JS::HandleObject obj)
|
|||
}
|
||||
|
||||
if (existing) {
|
||||
js::Wrapper::Renew(cx, existing, obj, wrapper);
|
||||
js::Wrapper::Renew(existing, obj, wrapper);
|
||||
}
|
||||
return js::Wrapper::New(cx, obj, wrapper);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@
|
|||
#include "nsProxyRelease.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "nsScriptError.h"
|
||||
#include "nsUTF8Utils.h"
|
||||
#include "prthread.h"
|
||||
#include "xpcpublic.h"
|
||||
|
|
@ -281,27 +282,34 @@ struct WindowAction
|
|||
};
|
||||
|
||||
void
|
||||
LogErrorToConsole(const nsAString& aMessage,
|
||||
const nsAString& aFilename,
|
||||
const nsAString& aLine,
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber,
|
||||
uint32_t aFlags,
|
||||
uint64_t aInnerWindowId)
|
||||
LogErrorToConsole(const WorkerErrorReport& aReport, uint64_t aInnerWindowId)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsCOMPtr<nsIScriptError> scriptError =
|
||||
do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
|
||||
RefPtr<nsScriptErrorBase> scriptError = new nsScriptError();
|
||||
NS_WARNING_ASSERTION(scriptError, "Failed to create script error!");
|
||||
|
||||
if (scriptError) {
|
||||
if (NS_FAILED(scriptError->InitWithWindowID(aMessage, aFilename, aLine,
|
||||
aLineNumber, aColumnNumber,
|
||||
aFlags, "Web Worker",
|
||||
nsAutoCString category("Web Worker");
|
||||
if (NS_FAILED(scriptError->InitWithWindowID(aReport.mMessage,
|
||||
aReport.mFilename,
|
||||
aReport.mLine,
|
||||
aReport.mLineNumber,
|
||||
aReport.mColumnNumber,
|
||||
aReport.mFlags,
|
||||
category,
|
||||
aInnerWindowId))) {
|
||||
NS_WARNING("Failed to init script error!");
|
||||
scriptError = nullptr;
|
||||
|
||||
for (size_t i = 0, len = aReport.mNotes.Length(); i < len; i++) {
|
||||
const WorkerErrorNote& note = aReport.mNotes.ElementAt(i);
|
||||
|
||||
nsScriptErrorNote* noteObject = new nsScriptErrorNote();
|
||||
noteObject->Init(note.mMessage, note.mFilename,
|
||||
note.mLineNumber, note.mColumnNumber);
|
||||
scriptError->AddNote(noteObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -316,23 +324,23 @@ LogErrorToConsole(const nsAString& aMessage,
|
|||
}
|
||||
NS_WARNING("LogMessage failed!");
|
||||
} else if (NS_SUCCEEDED(consoleService->LogStringMessage(
|
||||
aMessage.BeginReading()))) {
|
||||
aReport.mMessage.BeginReading()))) {
|
||||
return;
|
||||
}
|
||||
NS_WARNING("LogStringMessage failed!");
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 msg(aMessage);
|
||||
NS_ConvertUTF16toUTF8 filename(aFilename);
|
||||
NS_ConvertUTF16toUTF8 msg(aReport.mMessage);
|
||||
NS_ConvertUTF16toUTF8 filename(aReport.mFilename);
|
||||
|
||||
static const char kErrorString[] = "JS error in Web Worker: %s [%s:%u]";
|
||||
|
||||
#ifdef ANDROID
|
||||
__android_log_print(ANDROID_LOG_INFO, "Gecko", kErrorString, msg.get(),
|
||||
filename.get(), aLineNumber);
|
||||
filename.get(), aReport.mLineNumber);
|
||||
#endif
|
||||
|
||||
fprintf(stderr, kErrorString, msg.get(), filename.get(), aLineNumber);
|
||||
fprintf(stderr, kErrorString, msg.get(), filename.get(), aReport.mLineNumber);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
|
|
@ -536,10 +544,7 @@ private:
|
|||
}
|
||||
|
||||
if (aWorkerPrivate->IsSharedWorker()) {
|
||||
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, EmptyString(),
|
||||
EmptyString(),
|
||||
EmptyString(), 0, 0,
|
||||
JSREPORT_ERROR,
|
||||
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, nullptr,
|
||||
/* isErrorEvent */ false);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1060,15 +1065,7 @@ private:
|
|||
|
||||
class ReportErrorRunnable final : public WorkerRunnable
|
||||
{
|
||||
nsString mMessage;
|
||||
nsString mFilename;
|
||||
nsString mLine;
|
||||
uint32_t mLineNumber;
|
||||
uint32_t mColumnNumber;
|
||||
uint32_t mFlags;
|
||||
uint32_t mErrorNumber;
|
||||
JSExnType mExnType;
|
||||
bool mMutedError;
|
||||
WorkerErrorReport mReport;
|
||||
|
||||
public:
|
||||
// aWorkerPrivate is the worker thread we're on (or the main thread, if null)
|
||||
|
|
@ -1077,11 +1074,7 @@ public:
|
|||
static void
|
||||
ReportError(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aFireAtScope, WorkerPrivate* aTarget,
|
||||
const nsString& aMessage, const nsString& aFilename,
|
||||
const nsString& aLine, uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber, uint32_t aFlags,
|
||||
uint32_t aErrorNumber, JSExnType aExnType,
|
||||
bool aMutedError, uint64_t aInnerWindowId,
|
||||
const WorkerErrorReport& aReport, uint64_t aInnerWindowId,
|
||||
JS::Handle<JS::Value> aException = JS::NullHandleValue)
|
||||
{
|
||||
if (aWorkerPrivate) {
|
||||
|
|
@ -1092,16 +1085,16 @@ public:
|
|||
|
||||
// We should not fire error events for warnings but instead make sure that
|
||||
// they show up in the error console.
|
||||
if (!JSREPORT_IS_WARNING(aFlags)) {
|
||||
if (!JSREPORT_IS_WARNING(aReport.mFlags)) {
|
||||
// First fire an ErrorEvent at the worker.
|
||||
RootedDictionary<ErrorEventInit> init(aCx);
|
||||
|
||||
if (aMutedError) {
|
||||
if (aReport.mMutedError) {
|
||||
init.mMessage.AssignLiteral("Script error.");
|
||||
} else {
|
||||
init.mMessage = aMessage;
|
||||
init.mFilename = aFilename;
|
||||
init.mLineno = aLineNumber;
|
||||
init.mMessage = aReport.mMessage;
|
||||
init.mFilename = aReport.mFilename;
|
||||
init.mLineno = aReport.mLineNumber;
|
||||
init.mError = aException;
|
||||
}
|
||||
|
||||
|
|
@ -1128,7 +1121,8 @@ public:
|
|||
// into an error event on our parent worker!
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1271441 tracks making this
|
||||
// better.
|
||||
if (aFireAtScope && (aTarget || aErrorNumber != JSMSG_OVER_RECURSED)) {
|
||||
if (aFireAtScope &&
|
||||
(aTarget || aReport.mErrorNumber != JSMSG_OVER_RECURSED)) {
|
||||
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
|
||||
NS_ASSERTION(global, "This should never be null!");
|
||||
|
||||
|
|
@ -1145,8 +1139,8 @@ public:
|
|||
|
||||
MOZ_ASSERT_IF(globalScope, globalScope->GetWrapperPreserveColor() == global);
|
||||
if (globalScope || IsDebuggerSandbox(global)) {
|
||||
aWorkerPrivate->ReportErrorToDebugger(aFilename, aLineNumber,
|
||||
aMessage);
|
||||
aWorkerPrivate->ReportErrorToDebugger(aReport.mFilename, aReport.mLineNumber,
|
||||
aReport.mMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1193,28 +1187,20 @@ public:
|
|||
// Now fire a runnable to do the same on the parent's thread if we can.
|
||||
if (aWorkerPrivate) {
|
||||
RefPtr<ReportErrorRunnable> runnable =
|
||||
new ReportErrorRunnable(aWorkerPrivate, aMessage, aFilename, aLine,
|
||||
aLineNumber, aColumnNumber, aFlags,
|
||||
aErrorNumber, aExnType, aMutedError);
|
||||
new ReportErrorRunnable(aWorkerPrivate, aReport);
|
||||
runnable->Dispatch();
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise log an error to the error console.
|
||||
LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
|
||||
aFlags, aInnerWindowId);
|
||||
LogErrorToConsole(aReport, aInnerWindowId);
|
||||
}
|
||||
|
||||
private:
|
||||
ReportErrorRunnable(WorkerPrivate* aWorkerPrivate, const nsString& aMessage,
|
||||
const nsString& aFilename, const nsString& aLine,
|
||||
uint32_t aLineNumber, uint32_t aColumnNumber,
|
||||
uint32_t aFlags, uint32_t aErrorNumber,
|
||||
JSExnType aExnType, bool aMutedError)
|
||||
ReportErrorRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const WorkerErrorReport& aReport)
|
||||
: WorkerRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount),
|
||||
mMessage(aMessage), mFilename(aFilename), mLine(aLine),
|
||||
mLineNumber(aLineNumber), mColumnNumber(aColumnNumber), mFlags(aFlags),
|
||||
mErrorNumber(aErrorNumber), mExnType(aExnType), mMutedError(aMutedError)
|
||||
mReport(aReport)
|
||||
{ }
|
||||
|
||||
virtual void
|
||||
|
|
@ -1251,9 +1237,7 @@ private:
|
|||
}
|
||||
|
||||
if (aWorkerPrivate->IsSharedWorker()) {
|
||||
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, mMessage, mFilename,
|
||||
mLine, mLineNumber,
|
||||
mColumnNumber, mFlags,
|
||||
aWorkerPrivate->BroadcastErrorToSharedWorkers(aCx, &mReport,
|
||||
/* isErrorEvent */ true);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1267,9 +1251,10 @@ private:
|
|||
swm->HandleError(aCx, aWorkerPrivate->GetPrincipal(),
|
||||
aWorkerPrivate->WorkerName(),
|
||||
aWorkerPrivate->ScriptURL(),
|
||||
mMessage,
|
||||
mFilename, mLine, mLineNumber,
|
||||
mColumnNumber, mFlags, mExnType);
|
||||
mReport.mMessage,
|
||||
mReport.mFilename, mReport.mLine, mReport.mLineNumber,
|
||||
mReport.mColumnNumber, mReport.mFlags,
|
||||
mReport.mExnType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1289,9 +1274,8 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
ReportError(aCx, parent, fireAtScope, aWorkerPrivate, mMessage,
|
||||
mFilename, mLine, mLineNumber, mColumnNumber, mFlags,
|
||||
mErrorNumber, mExnType, mMutedError, innerWindowId);
|
||||
ReportError(aCx, parent, fireAtScope, aWorkerPrivate, mReport,
|
||||
innerWindowId);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
@ -3314,21 +3298,16 @@ template <class Derived>
|
|||
void
|
||||
WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
|
||||
JSContext* aCx,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aFilename,
|
||||
const nsAString& aLine,
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber,
|
||||
uint32_t aFlags,
|
||||
const WorkerErrorReport* aReport,
|
||||
bool aIsErrorEvent)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
if (JSREPORT_IS_WARNING(aFlags)) {
|
||||
if (aIsErrorEvent && JSREPORT_IS_WARNING(aReport->mFlags)) {
|
||||
// Don't fire any events anywhere. Just log to console.
|
||||
// XXXbz should we log to all the consoles of all the relevant windows?
|
||||
LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
|
||||
aFlags, 0);
|
||||
MOZ_ASSERT(aReport);
|
||||
LogErrorToConsole(*aReport, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -3357,10 +3336,10 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
|
|||
RootedDictionary<ErrorEventInit> errorInit(aCx);
|
||||
errorInit.mBubbles = false;
|
||||
errorInit.mCancelable = true;
|
||||
errorInit.mMessage = aMessage;
|
||||
errorInit.mFilename = aFilename;
|
||||
errorInit.mLineno = aLineNumber;
|
||||
errorInit.mColno = aColumnNumber;
|
||||
errorInit.mMessage = aReport->mMessage;
|
||||
errorInit.mFilename = aReport->mFilename;
|
||||
errorInit.mLineno = aReport->mLineNumber;
|
||||
errorInit.mColno = aReport->mColumnNumber;
|
||||
|
||||
event = ErrorEvent::Constructor(sharedWorker, NS_LITERAL_STRING("error"),
|
||||
errorInit);
|
||||
|
|
@ -3426,9 +3405,9 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
|
|||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
RootedDictionary<ErrorEventInit> init(aCx);
|
||||
init.mLineno = aLineNumber;
|
||||
init.mFilename = aFilename;
|
||||
init.mMessage = aMessage;
|
||||
init.mLineno = aReport->mLineNumber;
|
||||
init.mFilename = aReport->mFilename;
|
||||
init.mMessage = aReport->mMessage;
|
||||
init.mCancelable = true;
|
||||
init.mBubbles = true;
|
||||
|
||||
|
|
@ -3446,8 +3425,8 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
|
|||
|
||||
// Finally log a warning in the console if no window tried to prevent it.
|
||||
if (shouldLogErrorToConsole) {
|
||||
LogErrorToConsole(aMessage, aFilename, aLine, aLineNumber, aColumnNumber,
|
||||
aFlags, 0);
|
||||
MOZ_ASSERT(aReport);
|
||||
LogErrorToConsole(*aReport, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4120,7 +4099,10 @@ WorkerDebugger::ReportErrorToDebuggerOnMainThread(const nsAString& aFilename,
|
|||
listeners[index]->OnError(aFilename, aLineno, aMessage);
|
||||
}
|
||||
|
||||
LogErrorToConsole(aMessage, aFilename, nsString(), aLineno, 0, 0, 0);
|
||||
WorkerErrorReport report;
|
||||
report.mMessage = aMessage;
|
||||
report.mFilename = aFilename;
|
||||
LogErrorToConsole(report, 0);
|
||||
}
|
||||
|
||||
WorkerPrivate::WorkerPrivate(WorkerPrivate* aParent,
|
||||
|
|
@ -5925,6 +5907,47 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
WorkerErrorBase::AssignErrorBase(JSErrorBase* aReport)
|
||||
{
|
||||
mFilename = NS_ConvertUTF8toUTF16(aReport->filename);
|
||||
mLineNumber = aReport->lineno;
|
||||
mColumnNumber = aReport->column;
|
||||
mErrorNumber = aReport->errorNumber;
|
||||
}
|
||||
|
||||
void
|
||||
WorkerErrorNote::AssignErrorNote(JSErrorNotes::Note* aNote)
|
||||
{
|
||||
WorkerErrorBase::AssignErrorBase(aNote);
|
||||
xpc::ErrorNote::ErrorNoteToMessageString(aNote, mMessage);
|
||||
}
|
||||
|
||||
void
|
||||
WorkerErrorReport::AssignErrorReport(JSErrorReport* aReport)
|
||||
{
|
||||
WorkerErrorBase::AssignErrorBase(aReport);
|
||||
xpc::ErrorReport::ErrorReportToMessageString(aReport, mMessage);
|
||||
|
||||
mLine.Assign(aReport->linebuf(), aReport->linebufLength());
|
||||
mFlags = aReport->flags;
|
||||
MOZ_ASSERT(aReport->exnType >= JSEXN_FIRST && aReport->exnType < JSEXN_LIMIT);
|
||||
mExnType = JSExnType(aReport->exnType);
|
||||
mMutedError = aReport->isMuted;
|
||||
|
||||
if (aReport->notes) {
|
||||
if (!mNotes.SetLength(aReport->notes->length(), fallible)) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for (auto&& note : *aReport->notes) {
|
||||
mNotes.ElementAt(i).AssignErrorNote(note.get());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
|
||||
JSErrorReport* aReport)
|
||||
|
|
@ -5947,32 +5970,17 @@ WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
|
|||
}
|
||||
JS_ClearPendingException(aCx);
|
||||
|
||||
nsString message, filename, line;
|
||||
uint32_t lineNumber, columnNumber, flags, errorNumber;
|
||||
JSExnType exnType = JSEXN_ERR;
|
||||
bool mutedError = aReport && aReport->isMuted;
|
||||
|
||||
WorkerErrorReport report;
|
||||
if (aReport) {
|
||||
// We want the same behavior here as xpc::ErrorReport::init here.
|
||||
xpc::ErrorReport::ErrorReportToMessageString(aReport, message);
|
||||
|
||||
filename = NS_ConvertUTF8toUTF16(aReport->filename);
|
||||
line.Assign(aReport->linebuf(), aReport->linebufLength());
|
||||
lineNumber = aReport->lineno;
|
||||
columnNumber = aReport->tokenOffset();
|
||||
flags = aReport->flags;
|
||||
errorNumber = aReport->errorNumber;
|
||||
MOZ_ASSERT(aReport->exnType >= JSEXN_FIRST && aReport->exnType < JSEXN_LIMIT);
|
||||
exnType = JSExnType(aReport->exnType);
|
||||
report.AssignErrorReport(aReport);
|
||||
}
|
||||
else {
|
||||
lineNumber = columnNumber = errorNumber = 0;
|
||||
flags = nsIScriptError::errorFlag | nsIScriptError::exceptionFlag;
|
||||
report.mFlags = nsIScriptError::errorFlag | nsIScriptError::exceptionFlag;
|
||||
}
|
||||
|
||||
if (message.IsEmpty() && aToStringResult) {
|
||||
if (report.mMessage.IsEmpty() && aToStringResult) {
|
||||
nsDependentCString toStringResult(aToStringResult.c_str());
|
||||
if (!AppendUTF8toUTF16(toStringResult, message, mozilla::fallible)) {
|
||||
if (!AppendUTF8toUTF16(toStringResult, report.mMessage, mozilla::fallible)) {
|
||||
// Try again, with only a 1 KB string. Do this infallibly this time.
|
||||
// If the user doesn't have 1 KB to spare we're done anyways.
|
||||
uint32_t index = std::min(uint32_t(1024), toStringResult.Length());
|
||||
|
|
@ -5982,7 +5990,7 @@ WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
|
|||
|
||||
nsDependentCString truncatedToStringResult(aToStringResult.c_str(),
|
||||
index);
|
||||
AppendUTF8toUTF16(truncatedToStringResult, message);
|
||||
AppendUTF8toUTF16(truncatedToStringResult, report.mMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5991,13 +5999,11 @@ WorkerPrivate::ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
|
|||
// Don't want to run the scope's error handler if this is a recursive error or
|
||||
// if we ran out of memory.
|
||||
bool fireAtScope = mErrorHandlerRecursionCount == 1 &&
|
||||
errorNumber != JSMSG_OUT_OF_MEMORY &&
|
||||
report.mErrorNumber != JSMSG_OUT_OF_MEMORY &&
|
||||
JS::CurrentGlobalOrNull(aCx);
|
||||
|
||||
ReportErrorRunnable::ReportError(aCx, this, fireAtScope, nullptr, message,
|
||||
filename, line, lineNumber,
|
||||
columnNumber, flags, errorNumber, exnType,
|
||||
mutedError, 0, exn);
|
||||
ReportErrorRunnable::ReportError(aCx, this, fireAtScope, nullptr, report, 0,
|
||||
exn);
|
||||
|
||||
mErrorHandlerRecursionCount--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,6 +140,45 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class WorkerErrorBase {
|
||||
public:
|
||||
nsString mMessage;
|
||||
nsString mFilename;
|
||||
uint32_t mLineNumber;
|
||||
uint32_t mColumnNumber;
|
||||
uint32_t mErrorNumber;
|
||||
|
||||
WorkerErrorBase()
|
||||
: mLineNumber(0),
|
||||
mColumnNumber(0),
|
||||
mErrorNumber(0)
|
||||
{ }
|
||||
|
||||
void AssignErrorBase(JSErrorBase* aReport);
|
||||
};
|
||||
|
||||
class WorkerErrorNote : public WorkerErrorBase {
|
||||
public:
|
||||
void AssignErrorNote(JSErrorNotes::Note* aNote);
|
||||
};
|
||||
|
||||
class WorkerErrorReport : public WorkerErrorBase {
|
||||
public:
|
||||
nsString mLine;
|
||||
uint32_t mFlags;
|
||||
JSExnType mExnType;
|
||||
bool mMutedError;
|
||||
nsTArray<WorkerErrorNote> mNotes;
|
||||
|
||||
WorkerErrorReport()
|
||||
: mFlags(0),
|
||||
mExnType(JSEXN_ERR),
|
||||
mMutedError(false)
|
||||
{ }
|
||||
|
||||
void AssignErrorReport(JSErrorReport* aReport);
|
||||
};
|
||||
|
||||
template <class Derived>
|
||||
class WorkerPrivateParent : public DOMEventTargetHelper
|
||||
{
|
||||
|
|
@ -401,12 +440,7 @@ public:
|
|||
|
||||
void
|
||||
BroadcastErrorToSharedWorkers(JSContext* aCx,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aFilename,
|
||||
const nsAString& aLine,
|
||||
uint32_t aLineNumber,
|
||||
uint32_t aColumnNumber,
|
||||
uint32_t aFlags,
|
||||
const WorkerErrorReport* aReport,
|
||||
bool aIsErrorEvent);
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ LOCAL_INCLUDES += [
|
|||
'../base',
|
||||
'../system',
|
||||
'/dom/base',
|
||||
'/dom/bindings',
|
||||
'/xpcom/build',
|
||||
'/xpcom/threads',
|
||||
]
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
const errorFilename = href.substring(0, href.lastIndexOf("/") + 1) +
|
||||
filename;
|
||||
const errorLine = 91;
|
||||
const errorColumn = 0;
|
||||
const errorColumn = 11;
|
||||
|
||||
var worker = new SharedWorker(filename);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jswrapper.h"
|
||||
#include "js/Proxy.h"
|
||||
|
|
|
|||
|
|
@ -128,7 +128,10 @@ class MOZ_STACK_CLASS CallArgsBase : public WantUsedRval
|
|||
protected:
|
||||
Value* argv_;
|
||||
unsigned argc_;
|
||||
bool constructing_;
|
||||
bool constructing_:1;
|
||||
|
||||
// True if the caller does not use the return value.
|
||||
bool ignoresReturnValue_:1;
|
||||
|
||||
public:
|
||||
// CALLEE ACCESS
|
||||
|
|
@ -164,6 +167,10 @@ class MOZ_STACK_CLASS CallArgsBase : public WantUsedRval
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ignoresReturnValue() const {
|
||||
return ignoresReturnValue_;
|
||||
}
|
||||
|
||||
MutableHandleValue newTarget() const {
|
||||
MOZ_ASSERT(constructing_);
|
||||
return MutableHandleValue::fromMarkedLocation(&this->argv_[argc_]);
|
||||
|
|
@ -280,14 +287,17 @@ class MOZ_STACK_CLASS CallArgs : public detail::CallArgsBase<detail::IncludeUsed
|
|||
{
|
||||
private:
|
||||
friend CallArgs CallArgsFromVp(unsigned argc, Value* vp);
|
||||
friend CallArgs CallArgsFromSp(unsigned stackSlots, Value* sp, bool constructing);
|
||||
friend CallArgs CallArgsFromSp(unsigned stackSlots, Value* sp, bool constructing,
|
||||
bool ignoresReturnValue);
|
||||
|
||||
static CallArgs create(unsigned argc, Value* argv, bool constructing) {
|
||||
static CallArgs create(unsigned argc, Value* argv, bool constructing,
|
||||
bool ignoresReturnValue = false) {
|
||||
CallArgs args;
|
||||
args.clearUsedRval();
|
||||
args.argv_ = argv;
|
||||
args.argc_ = argc;
|
||||
args.constructing_ = constructing;
|
||||
args.ignoresReturnValue_ = ignoresReturnValue;
|
||||
#ifdef DEBUG
|
||||
for (unsigned i = 0; i < argc; ++i)
|
||||
MOZ_ASSERT_IF(argv[i].isGCThing(), !GCThingIsMarkedGray(GCCellPtr(argv[i])));
|
||||
|
|
@ -314,9 +324,11 @@ CallArgsFromVp(unsigned argc, Value* vp)
|
|||
// eventually move it to an internal header. Embedders should use
|
||||
// JS::CallArgsFromVp!
|
||||
MOZ_ALWAYS_INLINE CallArgs
|
||||
CallArgsFromSp(unsigned stackSlots, Value* sp, bool constructing = false)
|
||||
CallArgsFromSp(unsigned stackSlots, Value* sp, bool constructing = false,
|
||||
bool ignoresReturnValue = false)
|
||||
{
|
||||
return CallArgs::create(stackSlots - constructing, sp - stackSlots, constructing);
|
||||
return CallArgs::create(stackSlots - constructing, sp - stackSlots, constructing,
|
||||
ignoresReturnValue);
|
||||
}
|
||||
|
||||
} // namespace JS
|
||||
|
|
|
|||
|
|
@ -1117,7 +1117,7 @@ JSObject*
|
|||
AtomicsObject::initClass(JSContext* cx, Handle<GlobalObject*> global)
|
||||
{
|
||||
// Create Atomics Object.
|
||||
RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
|
||||
RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
|
||||
if (!objProto)
|
||||
return nullptr;
|
||||
RootedObject Atomics(cx, NewObjectWithGivenProto(cx, &AtomicsObject::class_, objProto,
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ Collator(JSContext* cx, const CallArgs& args, bool construct)
|
|||
// See https://github.com/tc39/ecma402/issues/57
|
||||
if (!construct) {
|
||||
// ES Intl 1st ed., 10.1.2.1 step 3
|
||||
JSObject* intl = cx->global()->getOrCreateIntlObject(cx);
|
||||
JSObject* intl = GlobalObject::getOrCreateIntlObject(cx, cx->global());
|
||||
if (!intl)
|
||||
return false;
|
||||
RootedValue self(cx, args.thisv());
|
||||
|
|
@ -298,7 +298,7 @@ Collator(JSContext* cx, const CallArgs& args, bool construct)
|
|||
return false;
|
||||
|
||||
if (!proto) {
|
||||
proto = cx->global()->getOrCreateCollatorPrototype(cx);
|
||||
proto = GlobalObject::getOrCreateCollatorPrototype(cx, cx->global());
|
||||
if (!proto)
|
||||
return false;
|
||||
}
|
||||
|
|
@ -358,11 +358,12 @@ collator_finalize(FreeOp* fop, JSObject* obj)
|
|||
static JSObject*
|
||||
CreateCollatorPrototype(JSContext* cx, HandleObject Intl, Handle<GlobalObject*> global)
|
||||
{
|
||||
RootedFunction ctor(cx, global->createConstructor(cx, &Collator, cx->names().Collator, 0));
|
||||
RootedFunction ctor(cx, GlobalObject::createConstructor(cx, &Collator, cx->names().Collator,
|
||||
0));
|
||||
if (!ctor)
|
||||
return nullptr;
|
||||
|
||||
RootedNativeObject proto(cx, global->createBlankPrototype(cx, &CollatorClass));
|
||||
RootedNativeObject proto(cx, GlobalObject::createBlankPrototype(cx, global, &CollatorClass));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
proto->setReservedSlot(UCOLLATOR_SLOT, PrivateValue(nullptr));
|
||||
|
|
@ -772,7 +773,7 @@ NumberFormat(JSContext* cx, const CallArgs& args, bool construct)
|
|||
// See https://github.com/tc39/ecma402/issues/57
|
||||
if (!construct) {
|
||||
// ES Intl 1st ed., 11.1.2.1 step 3
|
||||
JSObject* intl = cx->global()->getOrCreateIntlObject(cx);
|
||||
JSObject* intl = GlobalObject::getOrCreateIntlObject(cx, cx->global());
|
||||
if (!intl)
|
||||
return false;
|
||||
RootedValue self(cx, args.thisv());
|
||||
|
|
@ -800,7 +801,7 @@ NumberFormat(JSContext* cx, const CallArgs& args, bool construct)
|
|||
return false;
|
||||
|
||||
if (!proto) {
|
||||
proto = cx->global()->getOrCreateNumberFormatPrototype(cx);
|
||||
proto = GlobalObject::getOrCreateNumberFormatPrototype(cx, cx->global());
|
||||
if (!proto)
|
||||
return false;
|
||||
}
|
||||
|
|
@ -862,11 +863,12 @@ static JSObject*
|
|||
CreateNumberFormatPrototype(JSContext* cx, HandleObject Intl, Handle<GlobalObject*> global)
|
||||
{
|
||||
RootedFunction ctor(cx);
|
||||
ctor = global->createConstructor(cx, &NumberFormat, cx->names().NumberFormat, 0);
|
||||
ctor = GlobalObject::createConstructor(cx, &NumberFormat, cx->names().NumberFormat, 0);
|
||||
if (!ctor)
|
||||
return nullptr;
|
||||
|
||||
RootedNativeObject proto(cx, global->createBlankPrototype(cx, &NumberFormatClass));
|
||||
RootedNativeObject proto(cx, GlobalObject::createBlankPrototype(cx, global,
|
||||
&NumberFormatClass));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
proto->setReservedSlot(UNUMBER_FORMAT_SLOT, PrivateValue(nullptr));
|
||||
|
|
@ -1250,7 +1252,7 @@ DateTimeFormat(JSContext* cx, const CallArgs& args, bool construct)
|
|||
// See https://github.com/tc39/ecma402/issues/57
|
||||
if (!construct) {
|
||||
// ES Intl 1st ed., 12.1.2.1 step 3
|
||||
JSObject* intl = cx->global()->getOrCreateIntlObject(cx);
|
||||
JSObject* intl = GlobalObject::getOrCreateIntlObject(cx, cx->global());
|
||||
if (!intl)
|
||||
return false;
|
||||
RootedValue self(cx, args.thisv());
|
||||
|
|
@ -1278,7 +1280,7 @@ DateTimeFormat(JSContext* cx, const CallArgs& args, bool construct)
|
|||
return false;
|
||||
|
||||
if (!proto) {
|
||||
proto = cx->global()->getOrCreateDateTimeFormatPrototype(cx);
|
||||
proto = GlobalObject::getOrCreateDateTimeFormatPrototype(cx, cx->global());
|
||||
if (!proto)
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1340,11 +1342,12 @@ static JSObject*
|
|||
CreateDateTimeFormatPrototype(JSContext* cx, HandleObject Intl, Handle<GlobalObject*> global)
|
||||
{
|
||||
RootedFunction ctor(cx);
|
||||
ctor = global->createConstructor(cx, &DateTimeFormat, cx->names().DateTimeFormat, 0);
|
||||
ctor = GlobalObject::createConstructor(cx, &DateTimeFormat, cx->names().DateTimeFormat, 0);
|
||||
if (!ctor)
|
||||
return nullptr;
|
||||
|
||||
RootedNativeObject proto(cx, global->createBlankPrototype(cx, &DateTimeFormatClass));
|
||||
RootedNativeObject proto(cx, GlobalObject::createBlankPrototype(cx, global,
|
||||
&DateTimeFormatClass));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
proto->setReservedSlot(UDATE_FORMAT_SLOT, PrivateValue(nullptr));
|
||||
|
|
@ -2731,10 +2734,10 @@ static const JSFunctionSpec intl_static_methods[] = {
|
|||
* Initializes the Intl Object and its standard built-in properties.
|
||||
* Spec: ECMAScript Internationalization API Specification, 8.0, 8.1
|
||||
*/
|
||||
bool
|
||||
/* static */ bool
|
||||
GlobalObject::initIntlObject(JSContext* cx, Handle<GlobalObject*> global)
|
||||
{
|
||||
RootedObject proto(cx, global->getOrCreateObjectPrototype(cx));
|
||||
RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
|
||||
if (!proto)
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ MapIteratorObject::kind() const
|
|||
return MapObject::IteratorKind(i);
|
||||
}
|
||||
|
||||
bool
|
||||
/* static */ bool
|
||||
GlobalObject::initMapIteratorProto(JSContext* cx, Handle<GlobalObject*> global)
|
||||
{
|
||||
Rooted<JSObject*> base(cx, GlobalObject::getOrCreateIteratorPrototype(cx, global));
|
||||
|
|
@ -924,7 +924,7 @@ SetIteratorObject::kind() const
|
|||
return SetObject::IteratorKind(i);
|
||||
}
|
||||
|
||||
bool
|
||||
/* static */ bool
|
||||
GlobalObject::initSetIteratorProto(JSContext* cx, Handle<GlobalObject*> global)
|
||||
{
|
||||
Rooted<JSObject*> base(cx, GlobalObject::getOrCreateIteratorPrototype(cx, global));
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ GlobalObject::initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global)
|
|||
JS_PS_END
|
||||
};
|
||||
|
||||
RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
|
||||
RootedObject proto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
|
||||
if (!proto)
|
||||
return false;
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ GlobalObject::initExportEntryProto(JSContext* cx, Handle<GlobalObject*> global)
|
|||
JS_PS_END
|
||||
};
|
||||
|
||||
RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
|
||||
RootedObject proto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
|
||||
if (!proto)
|
||||
return false;
|
||||
|
||||
|
|
@ -788,7 +788,7 @@ AssertModuleScopesMatch(ModuleObject* module)
|
|||
}
|
||||
|
||||
void
|
||||
ModuleObject::fixEnvironmentsAfterCompartmentMerge(JSContext* cx)
|
||||
ModuleObject::fixEnvironmentsAfterCompartmentMerge()
|
||||
{
|
||||
AssertModuleScopesMatch(this);
|
||||
initialEnvironment().fixEnclosingEnvironmentAfterCompartmentMerge(script()->global());
|
||||
|
|
@ -1020,7 +1020,7 @@ GlobalObject::initModuleProto(JSContext* cx, Handle<GlobalObject*> global)
|
|||
JS_FS_END
|
||||
};
|
||||
|
||||
RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
|
||||
RootedObject proto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
|
||||
if (!proto)
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ class ModuleObject : public NativeObject
|
|||
#ifdef DEBUG
|
||||
static bool IsFrozen(JSContext* cx, HandleModuleObject self);
|
||||
#endif
|
||||
void fixEnvironmentsAfterCompartmentMerge(JSContext* cx);
|
||||
void fixEnvironmentsAfterCompartmentMerge();
|
||||
|
||||
JSScript* script() const;
|
||||
Scope* enclosingScope() const;
|
||||
|
|
|
|||
|
|
@ -525,18 +525,6 @@ js::obj_toString(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
js::obj_valueOf(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RootedObject obj(cx, ToObject(cx, args.thisv()));
|
||||
if (!obj)
|
||||
return false;
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
obj_setPrototypeOf(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
|
@ -1301,7 +1289,7 @@ static const JSFunctionSpec object_methods[] = {
|
|||
#endif
|
||||
JS_FN(js_toString_str, obj_toString, 0,0),
|
||||
JS_SELF_HOSTED_FN(js_toLocaleString_str, "Object_toLocaleString", 0, 0),
|
||||
JS_FN(js_valueOf_str, obj_valueOf, 0,0),
|
||||
JS_SELF_HOSTED_FN(js_valueOf_str, "Object_valueOf", 0,0),
|
||||
#if JS_HAS_OBJ_WATCHPOINT
|
||||
JS_FN(js_watch_str, obj_watch, 2,0),
|
||||
JS_FN(js_unwatch_str, obj_unwatch, 1,0),
|
||||
|
|
@ -1420,8 +1408,8 @@ FinishObjectClassInit(JSContext* cx, JS::HandleObject ctor, JS::HandleObject pro
|
|||
* only set the [[Prototype]] if it hasn't already been set.
|
||||
*/
|
||||
Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
|
||||
if (global->shouldSplicePrototype(cx)) {
|
||||
if (!global->splicePrototype(cx, global->getClass(), tagged))
|
||||
if (global->shouldSplicePrototype()) {
|
||||
if (!JSObject::splicePrototype(cx, global, global->getClass(), tagged))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -25,9 +25,6 @@ obj_construct(JSContext* cx, unsigned argc, JS::Value* vp);
|
|||
MOZ_MUST_USE bool
|
||||
obj_propertyIsEnumerable(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
obj_valueOf(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
PlainObject*
|
||||
ObjectCreateImpl(JSContext* cx, HandleObject proto, NewObjectKind newKind = GenericObject,
|
||||
HandleObjectGroup group = nullptr);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,12 @@ function Object_toLocaleString() {
|
|||
return callContentFunction(O.toString, O);
|
||||
}
|
||||
|
||||
// ES 2017 draft bb96899bb0d9ef9be08164a26efae2ee5f25e875 19.1.3.7
|
||||
function Object_valueOf() {
|
||||
// Step 1.
|
||||
return ToObject(this);
|
||||
}
|
||||
|
||||
// ES7 draft (2016 March 8) B.2.2.3
|
||||
function ObjectDefineSetter(name, setter) {
|
||||
// Step 1.
|
||||
|
|
|
|||
|
|
@ -603,7 +603,7 @@ ResolvePromise(JSContext* cx, Handle<PromiseObject*> promise, HandleValue valueO
|
|||
|
||||
// Now that everything else is done, do the things the debugger needs.
|
||||
// Step 7 of RejectPromise implemented in onSettled.
|
||||
promise->onSettled(cx);
|
||||
PromiseObject::onSettled(cx, promise);
|
||||
|
||||
// Step 7 of FulfillPromise.
|
||||
// Step 8 of RejectPromise.
|
||||
|
|
@ -1947,26 +1947,23 @@ PerformPromiseRace(JSContext *cx, JS::ForOfIterator& iterator, HandleObject C,
|
|||
}
|
||||
|
||||
// ES2016, Sub-steps of 25.4.4.4 and 25.4.4.5.
|
||||
static MOZ_MUST_USE bool
|
||||
CommonStaticResolveRejectImpl(JSContext* cx, unsigned argc, Value* vp, ResolutionMode mode)
|
||||
static MOZ_MUST_USE JSObject*
|
||||
CommonStaticResolveRejectImpl(JSContext* cx, HandleValue thisVal, HandleValue argVal,
|
||||
ResolutionMode mode)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RootedValue x(cx, args.get(0));
|
||||
|
||||
// Steps 1-2.
|
||||
if (!args.thisv().isObject()) {
|
||||
if (!thisVal.isObject()) {
|
||||
const char* msg = mode == ResolveMode
|
||||
? "Receiver of Promise.resolve call"
|
||||
: "Receiver of Promise.reject call";
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, msg);
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
RootedValue cVal(cx, args.thisv());
|
||||
RootedObject C(cx, &cVal.toObject());
|
||||
RootedObject C(cx, &thisVal.toObject());
|
||||
|
||||
// Step 3 of Resolve.
|
||||
if (mode == ResolveMode && x.isObject()) {
|
||||
RootedObject xObj(cx, &x.toObject());
|
||||
if (mode == ResolveMode && argVal.isObject()) {
|
||||
RootedObject xObj(cx, &argVal.toObject());
|
||||
bool isPromise = false;
|
||||
if (xObj->is<PromiseObject>()) {
|
||||
isPromise = true;
|
||||
|
|
@ -1985,11 +1982,9 @@ CommonStaticResolveRejectImpl(JSContext* cx, unsigned argc, Value* vp, Resolutio
|
|||
if (isPromise) {
|
||||
RootedValue ctorVal(cx);
|
||||
if (!GetProperty(cx, xObj, xObj, cx->names().constructor, &ctorVal))
|
||||
return false;
|
||||
if (ctorVal == cVal) {
|
||||
args.rval().set(x);
|
||||
return true;
|
||||
}
|
||||
return nullptr;
|
||||
if (ctorVal == thisVal)
|
||||
return xObj;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1998,15 +1993,17 @@ CommonStaticResolveRejectImpl(JSContext* cx, unsigned argc, Value* vp, Resolutio
|
|||
RootedObject resolveFun(cx);
|
||||
RootedObject rejectFun(cx);
|
||||
if (!NewPromiseCapability(cx, C, &promise, &resolveFun, &rejectFun, true))
|
||||
return false;
|
||||
return nullptr;
|
||||
|
||||
// Step 5 of Resolve, 4 of Reject.
|
||||
if (!RunResolutionFunction(cx, mode == ResolveMode ? resolveFun : rejectFun, x, mode, promise))
|
||||
return false;
|
||||
if (!RunResolutionFunction(cx, mode == ResolveMode ? resolveFun : rejectFun, argVal, mode,
|
||||
promise))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Step 6 of Resolve, 4 of Reject.
|
||||
args.rval().setObject(*promise);
|
||||
return true;
|
||||
return promise;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2015,7 +2012,14 @@ CommonStaticResolveRejectImpl(JSContext* cx, unsigned argc, Value* vp, Resolutio
|
|||
bool
|
||||
js::Promise_reject(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
return CommonStaticResolveRejectImpl(cx, argc, vp, RejectMode);
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RootedValue thisVal(cx, args.thisv());
|
||||
RootedValue argVal(cx, args.get(0));
|
||||
JSObject* result = CommonStaticResolveRejectImpl(cx, thisVal, argVal, RejectMode);
|
||||
if (!result)
|
||||
return false;
|
||||
args.rval().setObject(*result);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2024,19 +2028,11 @@ js::Promise_reject(JSContext* cx, unsigned argc, Value* vp)
|
|||
/* static */ JSObject*
|
||||
PromiseObject::unforgeableReject(JSContext* cx, HandleValue value)
|
||||
{
|
||||
// Steps 1-2 (omitted).
|
||||
|
||||
// Roughly step 3.
|
||||
Rooted<PromiseObject*> promise(cx, CreatePromiseObjectInternal(cx));
|
||||
if (!promise)
|
||||
RootedObject promiseCtor(cx, JS::GetPromiseConstructor(cx));
|
||||
if (!promiseCtor)
|
||||
return nullptr;
|
||||
|
||||
// Roughly step 4.
|
||||
if (!ResolvePromise(cx, promise, value, JS::PromiseState::Rejected))
|
||||
return nullptr;
|
||||
|
||||
// Step 5.
|
||||
return promise;
|
||||
RootedValue cVal(cx, ObjectValue(*promiseCtor));
|
||||
return CommonStaticResolveRejectImpl(cx, cVal, value, RejectMode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2045,7 +2041,14 @@ PromiseObject::unforgeableReject(JSContext* cx, HandleValue value)
|
|||
bool
|
||||
js::Promise_static_resolve(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
return CommonStaticResolveRejectImpl(cx, argc, vp, ResolveMode);
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RootedValue thisVal(cx, args.thisv());
|
||||
RootedValue argVal(cx, args.get(0));
|
||||
JSObject* result = CommonStaticResolveRejectImpl(cx, thisVal, argVal, ResolveMode);
|
||||
if (!result)
|
||||
return false;
|
||||
args.rval().setObject(*result);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2054,30 +2057,11 @@ js::Promise_static_resolve(JSContext* cx, unsigned argc, Value* vp)
|
|||
/* static */ JSObject*
|
||||
PromiseObject::unforgeableResolve(JSContext* cx, HandleValue value)
|
||||
{
|
||||
// Steps 1-2 (omitted).
|
||||
|
||||
// Step 3.
|
||||
if (value.isObject()) {
|
||||
JSObject* obj = &value.toObject();
|
||||
if (IsWrapper(obj))
|
||||
obj = CheckedUnwrap(obj);
|
||||
// Instead of getting the `constructor` property, do an unforgeable
|
||||
// check.
|
||||
if (obj && obj->is<PromiseObject>())
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Step 4.
|
||||
Rooted<PromiseObject*> promise(cx, CreatePromiseObjectInternal(cx));
|
||||
if (!promise)
|
||||
RootedObject promiseCtor(cx, JS::GetPromiseConstructor(cx));
|
||||
if (!promiseCtor)
|
||||
return nullptr;
|
||||
|
||||
// Steps 5.
|
||||
if (!ResolvePromiseInternal(cx, promise, value))
|
||||
return nullptr;
|
||||
|
||||
// Step 6.
|
||||
return promise;
|
||||
RootedValue cVal(cx, ObjectValue(*promiseCtor));
|
||||
return CommonStaticResolveRejectImpl(cx, cVal, value, ResolveMode);
|
||||
}
|
||||
|
||||
// ES2016, 25.4.4.6, implemented in Promise.js.
|
||||
|
|
@ -2647,14 +2631,14 @@ PromiseObject::dependentPromises(JSContext* cx, MutableHandle<GCVector<Value>> v
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PromiseObject::resolve(JSContext* cx, HandleValue resolutionValue)
|
||||
/* static */ bool
|
||||
PromiseObject::resolve(JSContext* cx, Handle<PromiseObject*> promise, HandleValue resolutionValue)
|
||||
{
|
||||
MOZ_ASSERT(!PromiseHasAnyFlag(*this, PROMISE_FLAG_ASYNC));
|
||||
if (state() != JS::PromiseState::Pending)
|
||||
MOZ_ASSERT(!PromiseHasAnyFlag(*promise, PROMISE_FLAG_ASYNC));
|
||||
if (promise->state() != JS::PromiseState::Pending)
|
||||
return true;
|
||||
|
||||
RootedObject resolveFun(cx, GetResolveFunctionFromPromise(this));
|
||||
RootedObject resolveFun(cx, GetResolveFunctionFromPromise(promise));
|
||||
RootedValue funVal(cx, ObjectValue(*resolveFun));
|
||||
|
||||
// For xray'd Promises, the resolve fun may have been created in another
|
||||
|
|
@ -2670,14 +2654,14 @@ PromiseObject::resolve(JSContext* cx, HandleValue resolutionValue)
|
|||
return Call(cx, funVal, UndefinedHandleValue, args, &dummy);
|
||||
}
|
||||
|
||||
bool
|
||||
PromiseObject::reject(JSContext* cx, HandleValue rejectionValue)
|
||||
/* static */ bool
|
||||
PromiseObject::reject(JSContext* cx, Handle<PromiseObject*> promise, HandleValue rejectionValue)
|
||||
{
|
||||
MOZ_ASSERT(!PromiseHasAnyFlag(*this, PROMISE_FLAG_ASYNC));
|
||||
if (state() != JS::PromiseState::Pending)
|
||||
MOZ_ASSERT(!PromiseHasAnyFlag(*promise, PROMISE_FLAG_ASYNC));
|
||||
if (promise->state() != JS::PromiseState::Pending)
|
||||
return true;
|
||||
|
||||
RootedValue funVal(cx, this->getFixedSlot(PromiseSlot_RejectFunction));
|
||||
RootedValue funVal(cx, promise->getFixedSlot(PromiseSlot_RejectFunction));
|
||||
MOZ_ASSERT(IsCallable(funVal));
|
||||
|
||||
FixedInvokeArgs<1> args(cx);
|
||||
|
|
@ -2687,10 +2671,9 @@ PromiseObject::reject(JSContext* cx, HandleValue rejectionValue)
|
|||
return Call(cx, funVal, UndefinedHandleValue, args, &dummy);
|
||||
}
|
||||
|
||||
void
|
||||
PromiseObject::onSettled(JSContext* cx)
|
||||
/* static */ void
|
||||
PromiseObject::onSettled(JSContext* cx, Handle<PromiseObject*> promise)
|
||||
{
|
||||
Rooted<PromiseObject*> promise(cx, this);
|
||||
RootedObject stack(cx);
|
||||
if (cx->options().asyncStack() || cx->compartment()->isDebuggee()) {
|
||||
if (!JS::CaptureCurrentStack(cx, &stack, JS::StackCapture(JS::AllFrames()))) {
|
||||
|
|
@ -2750,7 +2733,7 @@ PromiseTask::executeAndFinish(JSContext* cx)
|
|||
static JSObject*
|
||||
CreatePromisePrototype(JSContext* cx, JSProtoKey key)
|
||||
{
|
||||
return cx->global()->createBlankPrototype(cx, &PromiseObject::protoClass_);
|
||||
return GlobalObject::createBlankPrototype(cx, cx->global(), &PromiseObject::protoClass_);
|
||||
}
|
||||
|
||||
static const JSFunctionSpec promise_methods[] = {
|
||||
|
|
|
|||
|
|
@ -66,10 +66,12 @@ class PromiseObject : public NativeObject
|
|||
return getFixedSlot(PromiseSlot_ReactionsOrResult);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool resolve(JSContext* cx, HandleValue resolutionValue);
|
||||
MOZ_MUST_USE bool reject(JSContext* cx, HandleValue rejectionValue);
|
||||
static MOZ_MUST_USE bool resolve(JSContext* cx, Handle<PromiseObject*> promise,
|
||||
HandleValue resolutionValue);
|
||||
static MOZ_MUST_USE bool reject(JSContext* cx, Handle<PromiseObject*> promise,
|
||||
HandleValue rejectionValue);
|
||||
|
||||
void onSettled(JSContext* cx);
|
||||
static void onSettled(JSContext* cx, Handle<PromiseObject*> promise);
|
||||
|
||||
double allocationTime() { return getFixedSlot(PromiseSlot_AllocationTime).toNumber(); }
|
||||
double resolutionTime() { return getFixedSlot(PromiseSlot_ResolutionTime).toNumber(); }
|
||||
|
|
|
|||
|
|
@ -268,7 +268,8 @@ static const JSFunctionSpec methods[] = {
|
|||
JSObject*
|
||||
js::InitReflect(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
RootedObject proto(cx, obj->as<GlobalObject>().getOrCreateObjectPrototype(cx));
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -3044,7 +3044,12 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
MOZ_ASSERT(pn->pn_pos.encloses(next->pn_pos));
|
||||
|
||||
RootedValue expr(cx);
|
||||
expr.setString(next->pn_atom);
|
||||
if (next->isKind(PNK_RAW_UNDEFINED)) {
|
||||
expr.setUndefined();
|
||||
} else {
|
||||
MOZ_ASSERT(next->isKind(PNK_TEMPLATE_STRING));
|
||||
expr.setString(next->pn_atom);
|
||||
}
|
||||
cooked.infallibleAppend(expr);
|
||||
}
|
||||
|
||||
|
|
@ -3136,6 +3141,7 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
|
|||
case PNK_TRUE:
|
||||
case PNK_FALSE:
|
||||
case PNK_NULL:
|
||||
case PNK_RAW_UNDEFINED:
|
||||
return literal(pn, dst);
|
||||
|
||||
case PNK_YIELD_STAR:
|
||||
|
|
@ -3216,6 +3222,8 @@ ASTSerializer::property(ParseNode* pn, MutableHandleValue dst)
|
|||
return expression(pn->pn_kid, &val) &&
|
||||
builder.prototypeMutation(val, &pn->pn_pos, dst);
|
||||
}
|
||||
if (pn->isKind(PNK_SPREAD))
|
||||
return expression(pn, dst);
|
||||
|
||||
PropKind kind;
|
||||
switch (pn->getOp()) {
|
||||
|
|
@ -3276,6 +3284,10 @@ ASTSerializer::literal(ParseNode* pn, MutableHandleValue dst)
|
|||
val.setNull();
|
||||
break;
|
||||
|
||||
case PNK_RAW_UNDEFINED:
|
||||
val.setUndefined();
|
||||
break;
|
||||
|
||||
case PNK_TRUE:
|
||||
val.setBoolean(true);
|
||||
break;
|
||||
|
|
@ -3332,6 +3344,16 @@ ASTSerializer::objectPattern(ParseNode* pn, MutableHandleValue dst)
|
|||
return false;
|
||||
|
||||
for (ParseNode* propdef = pn->pn_head; propdef; propdef = propdef->pn_next) {
|
||||
if (propdef->isKind(PNK_SPREAD)) {
|
||||
RootedValue target(cx);
|
||||
RootedValue spread(cx);
|
||||
if (!pattern(propdef->pn_kid, &target))
|
||||
return false;
|
||||
if(!builder.spreadExpression(target, &propdef->pn_pos, &spread))
|
||||
return false;
|
||||
elts.infallibleAppend(spread);
|
||||
continue;
|
||||
}
|
||||
LOCAL_ASSERT(propdef->isKind(PNK_MUTATEPROTO) != propdef->isOp(JSOP_INITPROP));
|
||||
|
||||
RootedValue key(cx);
|
||||
|
|
@ -3407,12 +3429,7 @@ ASTSerializer::function(ParseNode* pn, ASTType type, MutableHandleValue dst)
|
|||
: GeneratorStyle::None;
|
||||
|
||||
bool isAsync = pn->pn_funbox->isAsync();
|
||||
bool isExpression =
|
||||
#if JS_HAS_EXPR_CLOSURES
|
||||
func->isExprBody();
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
bool isExpression = pn->pn_funbox->isExprBody();
|
||||
|
||||
RootedValue id(cx);
|
||||
RootedAtom funcAtom(cx, func->explicitName());
|
||||
|
|
|
|||
|
|
@ -140,12 +140,12 @@ ExecuteRegExpImpl(JSContext* cx, RegExpStatics* res, RegExpShared& re, HandleLin
|
|||
|
||||
/* Legacy ExecuteRegExp behavior is baked into the JSAPI. */
|
||||
bool
|
||||
js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, RegExpObject& reobj,
|
||||
js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, Handle<RegExpObject*> reobj,
|
||||
HandleLinearString input, size_t* lastIndex, bool test,
|
||||
MutableHandleValue rval)
|
||||
{
|
||||
RegExpGuard shared(cx);
|
||||
if (!reobj.getShared(cx, &shared))
|
||||
if (!RegExpObject::getShared(cx, reobj, &shared))
|
||||
return false;
|
||||
|
||||
ScopedMatchPairs matches(&cx->tempLifoAlloc());
|
||||
|
|
@ -801,7 +801,7 @@ const JSFunctionSpec js::regexp_methods[] = {
|
|||
name(JSContext* cx, unsigned argc, Value* vp) \
|
||||
{ \
|
||||
CallArgs args = CallArgsFromVp(argc, vp); \
|
||||
RegExpStatics* res = cx->global()->getRegExpStatics(cx); \
|
||||
RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global()); \
|
||||
if (!res) \
|
||||
return false; \
|
||||
code; \
|
||||
|
|
@ -827,7 +827,7 @@ DEFINE_STATIC_GETTER(static_paren9_getter, STATIC_PAREN_GETTER_CODE(9))
|
|||
static bool \
|
||||
name(JSContext* cx, unsigned argc, Value* vp) \
|
||||
{ \
|
||||
RegExpStatics* res = cx->global()->getRegExpStatics(cx); \
|
||||
RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global()); \
|
||||
if (!res) \
|
||||
return false; \
|
||||
code; \
|
||||
|
|
@ -838,7 +838,7 @@ static bool
|
|||
static_input_setter(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RegExpStatics* res = cx->global()->getRegExpStatics(cx);
|
||||
RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global());
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
|
|
@ -918,12 +918,12 @@ ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string,
|
|||
Rooted<RegExpObject*> reobj(cx, ®exp->as<RegExpObject>());
|
||||
|
||||
RegExpGuard re(cx);
|
||||
if (!reobj->getShared(cx, &re))
|
||||
if (!RegExpObject::getShared(cx, reobj, &re))
|
||||
return RegExpRunStatus_Error;
|
||||
|
||||
RegExpStatics* res;
|
||||
if (staticsUpdate == UpdateRegExpStatics) {
|
||||
res = cx->global()->getRegExpStatics(cx);
|
||||
res = GlobalObject::getRegExpStatics(cx, cx->global());
|
||||
if (!res)
|
||||
return RegExpRunStatus_Error;
|
||||
} else {
|
||||
|
|
@ -1725,7 +1725,7 @@ js::intrinsic_GetElemBaseForLambda(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (!fun->isInterpreted() || fun->isClassConstructor())
|
||||
return true;
|
||||
|
||||
JSScript* script = fun->getOrCreateScript(cx);
|
||||
JSScript* script = JSFunction::getOrCreateScript(cx, fun);
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
|
|
@ -1800,7 +1800,7 @@ js::intrinsic_GetStringDataProperty(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
|
||||
RootedValue v(cx);
|
||||
if (HasDataProperty(cx, nobj, AtomToId(atom), v.address()) && v.isString())
|
||||
if (GetPropertyPure(cx, nobj, AtomToId(atom), v.address()) && v.isString())
|
||||
args.rval().set(v);
|
||||
else
|
||||
args.rval().setUndefined();
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ enum RegExpStaticsUpdate { UpdateRegExpStatics, DontUpdateRegExpStatics };
|
|||
* |chars| and |length|.
|
||||
*/
|
||||
MOZ_MUST_USE bool
|
||||
ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, RegExpObject& reobj,
|
||||
ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, Handle<RegExpObject*> reobj,
|
||||
HandleLinearString input, size_t* lastIndex, bool test,
|
||||
MutableHandleValue rval);
|
||||
|
||||
|
|
|
|||
|
|
@ -475,7 +475,7 @@ const Class SimdObject::class_ = {
|
|||
&SimdObjectClassOps
|
||||
};
|
||||
|
||||
bool
|
||||
/* static */ bool
|
||||
GlobalObject::initSimdObject(JSContext* cx, Handle<GlobalObject*> global)
|
||||
{
|
||||
// SIMD relies on the TypedObject module being initialized.
|
||||
|
|
@ -483,11 +483,11 @@ GlobalObject::initSimdObject(JSContext* cx, Handle<GlobalObject*> global)
|
|||
// to be able to call GetTypedObjectModule(). It is NOT necessary
|
||||
// to install the TypedObjectModule global, but at the moment
|
||||
// those two things are not separable.
|
||||
if (!global->getOrCreateTypedObjectModule(cx))
|
||||
if (!GlobalObject::getOrCreateTypedObjectModule(cx, global))
|
||||
return false;
|
||||
|
||||
RootedObject globalSimdObject(cx);
|
||||
RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
|
||||
RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
|
||||
if (!objProto)
|
||||
return false;
|
||||
|
||||
|
|
@ -510,7 +510,7 @@ static bool
|
|||
CreateSimdType(JSContext* cx, Handle<GlobalObject*> global, HandlePropertyName stringRepr,
|
||||
SimdType simdType, const JSFunctionSpec* methods)
|
||||
{
|
||||
RootedObject funcProto(cx, global->getOrCreateFunctionPrototype(cx));
|
||||
RootedObject funcProto(cx, GlobalObject::getOrCreateFunctionPrototype(cx, global));
|
||||
if (!funcProto)
|
||||
return false;
|
||||
|
||||
|
|
@ -531,7 +531,7 @@ CreateSimdType(JSContext* cx, Handle<GlobalObject*> global, HandlePropertyName s
|
|||
return false;
|
||||
|
||||
// Create prototype property, which inherits from Object.prototype.
|
||||
RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
|
||||
RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
|
||||
if (!objProto)
|
||||
return false;
|
||||
Rooted<TypedProto*> proto(cx);
|
||||
|
|
@ -551,7 +551,7 @@ CreateSimdType(JSContext* cx, Handle<GlobalObject*> global, HandlePropertyName s
|
|||
}
|
||||
|
||||
// Bind type descriptor to the global SIMD object
|
||||
RootedObject globalSimdObject(cx, global->getOrCreateSimdGlobalObject(cx));
|
||||
RootedObject globalSimdObject(cx, GlobalObject::getOrCreateSimdGlobalObject(cx, global));
|
||||
MOZ_ASSERT(globalSimdObject);
|
||||
|
||||
RootedValue typeValue(cx, ObjectValue(*typeDescr));
|
||||
|
|
@ -568,7 +568,7 @@ CreateSimdType(JSContext* cx, Handle<GlobalObject*> global, HandlePropertyName s
|
|||
return !!typeDescr;
|
||||
}
|
||||
|
||||
bool
|
||||
/* static */ bool
|
||||
GlobalObject::initSimdType(JSContext* cx, Handle<GlobalObject*> global, SimdType simdType)
|
||||
{
|
||||
#define CREATE_(Type) \
|
||||
|
|
@ -584,13 +584,13 @@ GlobalObject::initSimdType(JSContext* cx, Handle<GlobalObject*> global, SimdType
|
|||
#undef CREATE_
|
||||
}
|
||||
|
||||
SimdTypeDescr*
|
||||
/* static */ SimdTypeDescr*
|
||||
GlobalObject::getOrCreateSimdTypeDescr(JSContext* cx, Handle<GlobalObject*> global,
|
||||
SimdType simdType)
|
||||
{
|
||||
MOZ_ASSERT(unsigned(simdType) < unsigned(SimdType::Count), "Invalid SIMD type");
|
||||
|
||||
RootedObject globalSimdObject(cx, global->getOrCreateSimdGlobalObject(cx));
|
||||
RootedObject globalSimdObject(cx, GlobalObject::getOrCreateSimdGlobalObject(cx, global));
|
||||
if (!globalSimdObject)
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -628,8 +628,8 @@ SimdObject::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool*
|
|||
JSObject*
|
||||
js::InitSimdClass(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
||||
return global->getOrCreateSimdGlobalObject(cx);
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
return GlobalObject::getOrCreateSimdGlobalObject(cx, global);
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
|
|
|
|||
|
|
@ -53,17 +53,17 @@ const JSFunctionSpec SymbolObject::staticMethods[] = {
|
|||
JSObject*
|
||||
SymbolObject::initClass(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
|
||||
// This uses &JSObject::class_ because: "The Symbol prototype object is an
|
||||
// ordinary object. It is not a Symbol instance and does not have a
|
||||
// [[SymbolData]] internal slot." (ES6 rev 24, 19.4.3)
|
||||
RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
|
||||
RootedObject proto(cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
RootedFunction ctor(cx, global->createConstructor(cx, construct,
|
||||
ClassName(JSProto_Symbol, cx), 0));
|
||||
RootedFunction ctor(cx, GlobalObject::createConstructor(cx, construct,
|
||||
ClassName(JSProto_Symbol, cx), 0));
|
||||
if (!ctor)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -3218,13 +3218,13 @@ ByteSizeOfScript(JSContext*cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
JSFunction* fun = &args[0].toObject().as<JSFunction>();
|
||||
RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
|
||||
if (fun->isNative()) {
|
||||
JS_ReportErrorASCII(cx, "Argument must be a scripted function");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedScript script(cx, fun->getOrCreateScript(cx));
|
||||
RootedScript script(cx, JSFunction::getOrCreateScript(cx, fun));
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
|
|
@ -3319,7 +3319,8 @@ GetConstructorName(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
|
||||
RootedAtom name(cx);
|
||||
if (!args[0].toObject().constructorDisplayAtom(cx, &name))
|
||||
RootedObject obj(cx, &args[0].toObject());
|
||||
if (!JSObject::constructorDisplayAtom(cx, obj, &name))
|
||||
return false;
|
||||
|
||||
if (name) {
|
||||
|
|
@ -4023,7 +4024,7 @@ DisRegExp(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!reobj->dumpBytecode(cx, match_only, input))
|
||||
if (!RegExpObject::dumpBytecode(cx, reobj, match_only, input))
|
||||
return false;
|
||||
|
||||
args.rval().setUndefined();
|
||||
|
|
@ -4042,6 +4043,32 @@ IsConstructor(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetErrorNotes(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (!args.requireAtLeast(cx, "getErrorNotes", 1))
|
||||
return false;
|
||||
|
||||
if (!args[0].isObject() || !args[0].toObject().is<ErrorObject>()) {
|
||||
args.rval().setNull();
|
||||
return true;
|
||||
}
|
||||
|
||||
JSErrorReport* report = args[0].toObject().as<ErrorObject>().getErrorReport();
|
||||
if (!report) {
|
||||
args.rval().setNull();
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedObject notesArray(cx, CreateErrorNotesArray(cx, report));
|
||||
if (!notesArray)
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*notesArray);
|
||||
return true;
|
||||
}
|
||||
|
||||
static const JSFunctionSpecWithHelp TestingFunctions[] = {
|
||||
JS_FN_HELP("gc", ::GC, 0, 0,
|
||||
"gc([obj] | 'zone' [, 'shrinking'])",
|
||||
|
|
@ -4576,6 +4603,10 @@ static const JSFunctionSpecWithHelp FuzzingUnsafeTestingFunctions[] = {
|
|||
" Dumps RegExp bytecode."),
|
||||
#endif
|
||||
|
||||
JS_FN_HELP("getErrorNotes", GetErrorNotes, 1, 0,
|
||||
"getErrorNotes(error)",
|
||||
" Returns an array of error notes."),
|
||||
|
||||
JS_FS_HELP_END
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1124,11 +1124,11 @@ DefineSimpleTypeDescr(JSContext* cx,
|
|||
typename T::Type type,
|
||||
HandlePropertyName className)
|
||||
{
|
||||
RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
|
||||
RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
|
||||
if (!objProto)
|
||||
return false;
|
||||
|
||||
RootedObject funcProto(cx, global->getOrCreateFunctionPrototype(cx));
|
||||
RootedObject funcProto(cx, GlobalObject::getOrCreateFunctionPrototype(cx, global));
|
||||
if (!funcProto)
|
||||
return false;
|
||||
|
||||
|
|
@ -1185,7 +1185,7 @@ DefineMetaTypeDescr(JSContext* cx,
|
|||
if (!className)
|
||||
return nullptr;
|
||||
|
||||
RootedObject funcProto(cx, global->getOrCreateFunctionPrototype(cx));
|
||||
RootedObject funcProto(cx, GlobalObject::getOrCreateFunctionPrototype(cx, global));
|
||||
if (!funcProto)
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -1197,7 +1197,7 @@ DefineMetaTypeDescr(JSContext* cx,
|
|||
|
||||
// Create ctor.prototype.prototype, which inherits from Object.__proto__
|
||||
|
||||
RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
|
||||
RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
|
||||
if (!objProto)
|
||||
return nullptr;
|
||||
RootedObject protoProto(cx);
|
||||
|
|
@ -1216,7 +1216,7 @@ DefineMetaTypeDescr(JSContext* cx,
|
|||
|
||||
const int constructorLength = 2;
|
||||
RootedFunction ctor(cx);
|
||||
ctor = global->createConstructor(cx, T::construct, className, constructorLength);
|
||||
ctor = GlobalObject::createConstructor(cx, T::construct, className, constructorLength);
|
||||
if (!ctor ||
|
||||
!LinkConstructorAndPrototype(cx, ctor, proto) ||
|
||||
!DefinePropertiesAndFunctions(cx, proto,
|
||||
|
|
@ -1240,10 +1240,10 @@ DefineMetaTypeDescr(JSContext* cx,
|
|||
* initializer for the `TypedObject` class populate the
|
||||
* `TypedObject` global (which is referred to as "module" herein).
|
||||
*/
|
||||
bool
|
||||
/* static */ bool
|
||||
GlobalObject::initTypedObjectModule(JSContext* cx, Handle<GlobalObject*> global)
|
||||
{
|
||||
RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
|
||||
RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
|
||||
if (!objProto)
|
||||
return false;
|
||||
|
||||
|
|
@ -1317,9 +1317,8 @@ GlobalObject::initTypedObjectModule(JSContext* cx, Handle<GlobalObject*> global)
|
|||
JSObject*
|
||||
js::InitTypedObjectModuleObject(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
MOZ_ASSERT(obj->is<GlobalObject>());
|
||||
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
||||
return global->getOrCreateTypedObjectModule(cx);
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
return GlobalObject::getOrCreateTypedObjectModule(cx, global);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
|
|||
|
|
@ -229,6 +229,69 @@ function GetInternalError(msg) {
|
|||
// To be used when a function is required but calling it shouldn't do anything.
|
||||
function NullFunction() {}
|
||||
|
||||
// Object Rest/Spread Properties proposal
|
||||
// Abstract operation: CopyDataProperties (target, source, excluded)
|
||||
function CopyDataProperties(target, source, excluded) {
|
||||
// Step 1.
|
||||
assert(IsObject(target), "target is an object");
|
||||
|
||||
// Step 2.
|
||||
assert(IsObject(excluded), "excluded is an object");
|
||||
|
||||
// Steps 3, 6.
|
||||
if (source === undefined || source === null)
|
||||
return;
|
||||
|
||||
// Step 4.a.
|
||||
source = ToObject(source);
|
||||
|
||||
// Step 4.b.
|
||||
var keys = OwnPropertyKeys(source, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS);
|
||||
|
||||
// Step 5.
|
||||
for (var index = 0; index < keys.length; index++) {
|
||||
var key = keys[index];
|
||||
|
||||
// We abbreviate this by calling propertyIsEnumerable which is faster
|
||||
// and returns false for not defined properties.
|
||||
if (!callFunction(std_Object_hasOwnProperty, excluded, key) && callFunction(std_Object_propertyIsEnumerable, source, key))
|
||||
_DefineDataProperty(target, key, source[key]);
|
||||
}
|
||||
|
||||
// Step 6 (Return).
|
||||
}
|
||||
|
||||
// Object Rest/Spread Properties proposal
|
||||
// Abstract operation: CopyDataProperties (target, source, excluded)
|
||||
function CopyDataPropertiesUnfiltered(target, source) {
|
||||
// Step 1.
|
||||
assert(IsObject(target), "target is an object");
|
||||
|
||||
// Step 2 (Not applicable).
|
||||
|
||||
// Steps 3, 6.
|
||||
if (source === undefined || source === null)
|
||||
return;
|
||||
|
||||
// Step 4.a.
|
||||
source = ToObject(source);
|
||||
|
||||
// Step 4.b.
|
||||
var keys = OwnPropertyKeys(source, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS);
|
||||
|
||||
// Step 5.
|
||||
for (var index = 0; index < keys.length; index++) {
|
||||
var key = keys[index];
|
||||
|
||||
// We abbreviate this by calling propertyIsEnumerable which is faster
|
||||
// and returns false for not defined properties.
|
||||
if (callFunction(std_Object_propertyIsEnumerable, source, key))
|
||||
_DefineDataProperty(target, key, source[key]);
|
||||
}
|
||||
|
||||
// Step 6 (Return).
|
||||
}
|
||||
|
||||
/*************************************** Testing functions ***************************************/
|
||||
function outer() {
|
||||
return function inner() {
|
||||
|
|
|
|||
|
|
@ -350,14 +350,14 @@ InitWeakMapClass(JSContext* cx, HandleObject obj, bool defineMembers)
|
|||
{
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
|
||||
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
|
||||
RootedPlainObject proto(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
RootedFunction ctor(cx, global->createConstructor(cx, WeakMap_construct,
|
||||
cx->names().WeakMap, 0));
|
||||
RootedFunction ctor(cx, GlobalObject::createConstructor(cx, WeakMap_construct,
|
||||
cx->names().WeakMap, 0));
|
||||
if (!ctor)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -41,14 +41,15 @@ const JSFunctionSpec WeakSetObject::methods[] = {
|
|||
};
|
||||
|
||||
JSObject*
|
||||
WeakSetObject::initClass(JSContext* cx, JSObject* obj)
|
||||
WeakSetObject::initClass(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
RootedPlainObject proto(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
Rooted<JSFunction*> ctor(cx, global->createConstructor(cx, construct, ClassName(JSProto_WeakSet, cx), 0));
|
||||
Rooted<JSFunction*> ctor(cx, GlobalObject::createConstructor(cx, construct,
|
||||
ClassName(JSProto_WeakSet, cx), 0));
|
||||
if (!ctor ||
|
||||
!LinkConstructorAndPrototype(cx, ctor, proto) ||
|
||||
!DefinePropertiesAndFunctions(cx, proto, properties, methods) ||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class WeakSetObject : public NativeObject
|
|||
public:
|
||||
static const unsigned RESERVED_SLOTS = 1;
|
||||
|
||||
static JSObject* initClass(JSContext* cx, JSObject* obj);
|
||||
static JSObject* initClass(JSContext* cx, HandleObject obj);
|
||||
static const Class class_;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -77,7 +77,13 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
bool canLazilyParse();
|
||||
bool createParser();
|
||||
bool createSourceAndParser(Maybe<uint32_t> parameterListEnd = Nothing());
|
||||
bool createScript(uint32_t preludeStart = 0);
|
||||
|
||||
// If toString{Start,End} are not explicitly passed, assume the script's
|
||||
// offsets in the source used to parse it are the same as what should be
|
||||
// used to compute its Function.prototype.toString() value.
|
||||
bool createScript();
|
||||
bool createScript(uint32_t toStringStart, uint32_t toStringEnd);
|
||||
|
||||
bool emplaceEmitter(Maybe<BytecodeEmitter>& emitter, SharedContext* sharedContext);
|
||||
bool handleParseFailure(const Directives& newDirectives);
|
||||
bool deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObject environment);
|
||||
|
|
@ -242,11 +248,17 @@ BytecodeCompiler::createSourceAndParser(Maybe<uint32_t> parameterListEnd /* = No
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::createScript(uint32_t preludeStart /* = 0 */)
|
||||
BytecodeCompiler::createScript()
|
||||
{
|
||||
return createScript(0, sourceBuffer.length());
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::createScript(uint32_t toStringStart, uint32_t toStringEnd)
|
||||
{
|
||||
script = JSScript::Create(cx, options,
|
||||
sourceObject, /* sourceStart = */ 0, sourceBuffer.length(),
|
||||
preludeStart);
|
||||
toStringStart, toStringEnd);
|
||||
return script != nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -287,7 +299,8 @@ BytecodeCompiler::deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObj
|
|||
RootedObject env(cx, environment);
|
||||
while (env->is<EnvironmentObject>() || env->is<DebugEnvironmentProxy>()) {
|
||||
if (env->is<CallObject>()) {
|
||||
RootedScript script(cx, env->as<CallObject>().callee().getOrCreateScript(cx));
|
||||
RootedFunction fun(cx, &env->as<CallObject>().callee());
|
||||
RootedScript script(cx, JSFunction::getOrCreateScript(cx, fun));
|
||||
if (!script)
|
||||
return false;
|
||||
if (script->argumentsHasVarBinding()) {
|
||||
|
|
@ -457,7 +470,7 @@ BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
|
|||
if (fn->pn_funbox->function()->isInterpreted()) {
|
||||
MOZ_ASSERT(fun == fn->pn_funbox->function());
|
||||
|
||||
if (!createScript(fn->pn_funbox->preludeStart))
|
||||
if (!createScript(fn->pn_funbox->toStringStart, fn->pn_funbox->toStringEnd))
|
||||
return false;
|
||||
|
||||
Maybe<BytecodeEmitter> emitter;
|
||||
|
|
@ -652,7 +665,7 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
|
|||
|
||||
Rooted<JSScript*> script(cx, JSScript::Create(cx, options, sourceObject,
|
||||
lazy->begin(), lazy->end(),
|
||||
lazy->preludeStart()));
|
||||
lazy->toStringStart(), lazy->toStringEnd()));
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -3069,6 +3069,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
|||
case PNK_TRUE:
|
||||
case PNK_FALSE:
|
||||
case PNK_NULL:
|
||||
case PNK_RAW_UNDEFINED:
|
||||
case PNK_ELISION:
|
||||
case PNK_GENERATOR:
|
||||
case PNK_NUMBER:
|
||||
|
|
@ -3538,9 +3539,10 @@ BytecodeEmitter::needsImplicitThis()
|
|||
bool
|
||||
BytecodeEmitter::maybeSetDisplayURL()
|
||||
{
|
||||
if (tokenStream()->hasDisplayURL()) {
|
||||
if (!parser->ss->setDisplayURL(cx, tokenStream()->displayURL()))
|
||||
if (tokenStream().hasDisplayURL()) {
|
||||
if (!parser->ss->setDisplayURL(cx, tokenStream().displayURL())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3548,10 +3550,11 @@ BytecodeEmitter::maybeSetDisplayURL()
|
|||
bool
|
||||
BytecodeEmitter::maybeSetSourceMap()
|
||||
{
|
||||
if (tokenStream()->hasSourceMapURL()) {
|
||||
if (tokenStream().hasSourceMapURL()) {
|
||||
MOZ_ASSERT(!parser->ss->hasSourceMapURL());
|
||||
if (!parser->ss->setSourceMapURL(cx, tokenStream()->sourceMapURL()))
|
||||
if (!parser->ss->setSourceMapURL(cx, tokenStream().sourceMapURL())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3590,21 +3593,21 @@ BytecodeEmitter::tellDebuggerAboutCompiledScript(ExclusiveContext* cx)
|
|||
}
|
||||
}
|
||||
|
||||
inline TokenStream*
|
||||
inline TokenStream&
|
||||
BytecodeEmitter::tokenStream()
|
||||
{
|
||||
return &parser->tokenStream;
|
||||
return parser->tokenStream;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...)
|
||||
{
|
||||
TokenPos pos = pn ? pn->pn_pos : tokenStream()->currentToken().pos;
|
||||
TokenPos pos = pn ? pn->pn_pos : tokenStream().currentToken().pos;
|
||||
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
bool result = tokenStream()->reportCompileErrorNumberVA(pos.begin, JSREPORT_ERROR,
|
||||
errorNumber, args);
|
||||
bool result = tokenStream().reportCompileErrorNumberVA(nullptr, pos.begin, JSREPORT_ERROR,
|
||||
errorNumber, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -3612,11 +3615,12 @@ BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...)
|
|||
bool
|
||||
BytecodeEmitter::reportExtraWarning(ParseNode* pn, unsigned errorNumber, ...)
|
||||
{
|
||||
TokenPos pos = pn ? pn->pn_pos : tokenStream()->currentToken().pos;
|
||||
TokenPos pos = pn ? pn->pn_pos : tokenStream().currentToken().pos;
|
||||
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
bool result = tokenStream()->reportExtraWarningErrorNumberVA(pos.begin, errorNumber, args);
|
||||
bool result = tokenStream().reportExtraWarningErrorNumberVA(nullptr, pos.begin,
|
||||
errorNumber, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -3624,12 +3628,12 @@ BytecodeEmitter::reportExtraWarning(ParseNode* pn, unsigned errorNumber, ...)
|
|||
bool
|
||||
BytecodeEmitter::reportStrictModeError(ParseNode* pn, unsigned errorNumber, ...)
|
||||
{
|
||||
TokenPos pos = pn ? pn->pn_pos : tokenStream()->currentToken().pos;
|
||||
TokenPos pos = pn ? pn->pn_pos : tokenStream().currentToken().pos;
|
||||
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
bool result = tokenStream()->reportStrictModeErrorNumberVA(pos.begin, sc->strict(),
|
||||
errorNumber, args);
|
||||
bool result = tokenStream().reportStrictModeErrorNumberVA(nullptr, pos.begin, sc->strict(),
|
||||
errorNumber, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -4599,7 +4603,7 @@ BytecodeEmitter::emitSwitch(ParseNode* pn)
|
|||
// If the expression is a literal, suppress line number emission so
|
||||
// that debugging works more naturally.
|
||||
if (caseValue) {
|
||||
if (!emitTree(caseValue,
|
||||
if (!emitTree(caseValue, ValueUsage::WantValue,
|
||||
caseValue->isLiteral() ? SUPPRESS_LINENOTE : EMIT_LINENOTE))
|
||||
{
|
||||
return false;
|
||||
|
|
@ -5810,36 +5814,78 @@ BytecodeEmitter::emitDestructuringOpsObject(ParseNode* pattern, DestructuringFla
|
|||
if (!emitRequireObjectCoercible()) // ... RHS
|
||||
return false;
|
||||
|
||||
bool needsRestPropertyExcludedSet = pattern->pn_count > 1 &&
|
||||
pattern->last()->isKind(PNK_SPREAD);
|
||||
if (needsRestPropertyExcludedSet) {
|
||||
if (!emitDestructuringObjRestExclusionSet(pattern)) // ... RHS SET
|
||||
return false;
|
||||
|
||||
if (!emit1(JSOP_SWAP)) // ... SET RHS
|
||||
return false;
|
||||
}
|
||||
|
||||
for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
|
||||
ParseNode* subpattern;
|
||||
if (member->isKind(PNK_MUTATEPROTO))
|
||||
if (member->isKind(PNK_MUTATEPROTO) || member->isKind(PNK_SPREAD))
|
||||
subpattern = member->pn_kid;
|
||||
else
|
||||
subpattern = member->pn_right;
|
||||
|
||||
ParseNode* lhs = subpattern;
|
||||
MOZ_ASSERT_IF(member->isKind(PNK_SPREAD), !lhs->isKind(PNK_ASSIGN));
|
||||
if (lhs->isKind(PNK_ASSIGN))
|
||||
lhs = lhs->pn_left;
|
||||
|
||||
size_t emitted;
|
||||
if (!emitDestructuringLHSRef(lhs, &emitted)) // ... RHS *LREF
|
||||
if (!emitDestructuringLHSRef(lhs, &emitted)) // ... *SET RHS *LREF
|
||||
return false;
|
||||
|
||||
// Duplicate the value being destructured to use as a reference base.
|
||||
if (emitted) {
|
||||
if (!emitDupAt(emitted)) // ... RHS *LREF RHS
|
||||
if (!emitDupAt(emitted)) // ... *SET RHS *LREF RHS
|
||||
return false;
|
||||
} else {
|
||||
if (!emit1(JSOP_DUP)) // ... RHS RHS
|
||||
if (!emit1(JSOP_DUP)) // ... *SET RHS RHS
|
||||
return false;
|
||||
}
|
||||
|
||||
if (member->isKind(PNK_SPREAD)) {
|
||||
if (!updateSourceCoordNotes(member->pn_pos.begin))
|
||||
return false;
|
||||
|
||||
if (!emitNewInit(JSProto_Object)) // ... *SET RHS *LREF RHS TARGET
|
||||
return false;
|
||||
if (!emit1(JSOP_DUP)) // ... *SET RHS *LREF RHS TARGET TARGET
|
||||
return false;
|
||||
if (!emit2(JSOP_PICK, 2)) // ... *SET RHS *LREF TARGET TARGET RHS
|
||||
return false;
|
||||
|
||||
if (needsRestPropertyExcludedSet) {
|
||||
if (!emit2(JSOP_PICK, emitted + 4)) // ... RHS *LREF TARGET TARGET RHS SET
|
||||
return false;
|
||||
}
|
||||
|
||||
CopyOption option = needsRestPropertyExcludedSet
|
||||
? CopyOption::Filtered
|
||||
: CopyOption::Unfiltered;
|
||||
if (!emitCopyDataProperties(option)) // ... RHS *LREF TARGET
|
||||
return false;
|
||||
|
||||
// Destructure TARGET per this member's lhs.
|
||||
if (!emitSetOrInitializeDestructuring(lhs, flav)) // ... RHS
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(member == pattern->last(), "Rest property is always last");
|
||||
break;
|
||||
}
|
||||
|
||||
// Now push the property name currently being matched, which is the
|
||||
// current property name "label" on the left of a colon in the object
|
||||
// initialiser.
|
||||
bool needsGetElem = true;
|
||||
|
||||
if (member->isKind(PNK_MUTATEPROTO)) {
|
||||
if (!emitAtomOp(cx->names().proto, JSOP_GETPROP)) // ... RHS *LREF PROP
|
||||
if (!emitAtomOp(cx->names().proto, JSOP_GETPROP)) // ... *SET RHS *LREF PROP
|
||||
return false;
|
||||
needsGetElem = false;
|
||||
} else {
|
||||
|
|
@ -5847,40 +5893,131 @@ BytecodeEmitter::emitDestructuringOpsObject(ParseNode* pattern, DestructuringFla
|
|||
|
||||
ParseNode* key = member->pn_left;
|
||||
if (key->isKind(PNK_NUMBER)) {
|
||||
if (!emitNumberOp(key->pn_dval)) // ... RHS *LREF RHS KEY
|
||||
if (!emitNumberOp(key->pn_dval)) // ... *SET RHS *LREF RHS KEY
|
||||
return false;
|
||||
} else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
|
||||
PropertyName* name = key->pn_atom->asPropertyName();
|
||||
|
||||
// The parser already checked for atoms representing indexes and
|
||||
// used PNK_NUMBER instead, but also watch for ids which TI treats
|
||||
// as indexes for simplification of downstream analysis.
|
||||
jsid id = NameToId(name);
|
||||
if (id != IdToTypeId(id)) {
|
||||
if (!emitTree(key)) // ... RHS *LREF RHS KEY
|
||||
return false;
|
||||
} else {
|
||||
if (!emitAtomOp(name, JSOP_GETPROP)) // ... RHS *LREF PROP
|
||||
return false;
|
||||
needsGetElem = false;
|
||||
}
|
||||
} else {
|
||||
if (!emitComputedPropertyName(key)) // ... RHS *LREF RHS KEY
|
||||
if (!emitAtomOp(key->pn_atom, JSOP_GETPROP)) // ... *SET RHS *LREF PROP
|
||||
return false;
|
||||
needsGetElem = false;
|
||||
} else {
|
||||
if (!emitComputedPropertyName(key)) // ... *SET RHS *LREF RHS KEY
|
||||
return false;
|
||||
|
||||
// Add the computed property key to the exclusion set.
|
||||
if (needsRestPropertyExcludedSet) {
|
||||
if (!emitDupAt(emitted + 3)) // ... SET RHS *LREF RHS KEY SET
|
||||
return false;
|
||||
if (!emitDupAt(1)) // ... SET RHS *LREF RHS KEY SET KEY
|
||||
return false;
|
||||
if (!emit1(JSOP_UNDEFINED)) // ... SET RHS *LREF RHS KEY SET KEY UNDEFINED
|
||||
return false;
|
||||
if (!emit1(JSOP_INITELEM)) // ... SET RHS *LREF RHS KEY SET
|
||||
return false;
|
||||
if (!emit1(JSOP_POP)) // ... SET RHS *LREF RHS KEY
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the property value if not done already.
|
||||
if (needsGetElem && !emitElemOpBase(JSOP_GETELEM)) // ... RHS *LREF PROP
|
||||
if (needsGetElem && !emitElemOpBase(JSOP_GETELEM)) // ... *SET RHS *LREF PROP
|
||||
return false;
|
||||
|
||||
if (subpattern->isKind(PNK_ASSIGN)) {
|
||||
if (!emitDefault(subpattern->pn_right, lhs)) // ... RHS *LREF VALUE
|
||||
if (!emitDefault(subpattern->pn_right, lhs)) // ... *SET RHS *LREF VALUE
|
||||
return false;
|
||||
}
|
||||
|
||||
// Destructure PROP per this member's lhs.
|
||||
if (!emitSetOrInitializeDestructuring(subpattern, flav)) // ... RHS
|
||||
if (!emitSetOrInitializeDestructuring(subpattern, flav)) // ... *SET RHS
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitDestructuringObjRestExclusionSet(ParseNode* pattern)
|
||||
{
|
||||
MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(pattern->isArity(PN_LIST));
|
||||
MOZ_ASSERT(pattern->last()->isKind(PNK_SPREAD));
|
||||
|
||||
ptrdiff_t offset = this->offset();
|
||||
if (!emitNewInit(JSProto_Object))
|
||||
return false;
|
||||
|
||||
// Try to construct the shape of the object as we go, so we can emit a
|
||||
// JSOP_NEWOBJECT with the final shape instead.
|
||||
// In the case of computed property names and indices, we cannot fix the
|
||||
// shape at bytecode compile time. When the shape cannot be determined,
|
||||
// |obj| is nulled out.
|
||||
|
||||
// No need to do any guessing for the object kind, since we know the upper
|
||||
// bound of how many properties we plan to have.
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(pattern->pn_count - 1);
|
||||
RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
RootedAtom pnatom(cx);
|
||||
for (ParseNode* member = pattern->pn_head; member; member = member->pn_next) {
|
||||
if (member->isKind(PNK_SPREAD))
|
||||
break;
|
||||
|
||||
bool isIndex = false;
|
||||
if (member->isKind(PNK_MUTATEPROTO)) {
|
||||
pnatom.set(cx->names().proto);
|
||||
} else {
|
||||
ParseNode* key = member->pn_left;
|
||||
if (key->isKind(PNK_NUMBER)) {
|
||||
if (!emitNumberOp(key->pn_dval))
|
||||
return false;
|
||||
isIndex = true;
|
||||
} else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
|
||||
pnatom.set(key->pn_atom);
|
||||
} else {
|
||||
// Otherwise this is a computed property name which needs to
|
||||
// be added dynamically.
|
||||
obj.set(nullptr);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize elements with |undefined|.
|
||||
if (!emit1(JSOP_UNDEFINED))
|
||||
return false;
|
||||
|
||||
if (isIndex) {
|
||||
obj.set(nullptr);
|
||||
if (!emit1(JSOP_INITELEM))
|
||||
return false;
|
||||
} else {
|
||||
uint32_t index;
|
||||
if (!makeAtomIndex(pnatom, &index))
|
||||
return false;
|
||||
|
||||
if (obj) {
|
||||
MOZ_ASSERT(!obj->inDictionaryMode());
|
||||
Rooted<jsid> id(cx, AtomToId(pnatom));
|
||||
if (!NativeDefineProperty(cx, obj, id, UndefinedHandleValue, nullptr, nullptr,
|
||||
JSPROP_ENUMERATE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (obj->inDictionaryMode())
|
||||
obj.set(nullptr);
|
||||
}
|
||||
|
||||
if (!emitIndex32(JSOP_INITPROP, index))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (obj) {
|
||||
// The object survived and has a predictable shape: update the
|
||||
// original bytecode.
|
||||
if (!replaceNewInitWithNewObject(obj, offset))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -6242,6 +6379,9 @@ ParseNode::getConstantValue(ExclusiveContext* cx, AllowConstantObjects allowObje
|
|||
case PNK_NULL:
|
||||
vp.setNull();
|
||||
return true;
|
||||
case PNK_RAW_UNDEFINED:
|
||||
vp.setUndefined();
|
||||
return true;
|
||||
case PNK_CALLSITEOBJ:
|
||||
case PNK_ARRAY: {
|
||||
unsigned count;
|
||||
|
|
@ -6645,7 +6785,7 @@ BytecodeEmitter::emitLexicalScopeBody(ParseNode* body, EmitLineNumberNote emitLi
|
|||
}
|
||||
|
||||
// Line notes were updated by emitLexicalScope.
|
||||
return emitTree(body, emitLineNote);
|
||||
return emitTree(body, ValueUsage::WantValue, emitLineNote);
|
||||
}
|
||||
|
||||
// Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
|
||||
|
|
@ -6747,9 +6887,9 @@ BytecodeEmitter::emitRequireObjectCoercible()
|
|||
return false;
|
||||
if (!emit2(JSOP_PICK, 2)) // VAL REQUIREOBJECTCOERCIBLE UNDEFINED VAL
|
||||
return false;
|
||||
if (!emitCall(JSOP_CALL, 1)) // VAL IGNORED
|
||||
if (!emitCall(JSOP_CALL_IGNORES_RV, 1))// VAL IGNORED
|
||||
return false;
|
||||
checkTypeSet(JSOP_CALL);
|
||||
checkTypeSet(JSOP_CALL_IGNORES_RV);
|
||||
|
||||
if (!emit1(JSOP_POP)) // VAL
|
||||
return false;
|
||||
|
|
@ -6758,6 +6898,53 @@ BytecodeEmitter::emitRequireObjectCoercible()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitCopyDataProperties(CopyOption option)
|
||||
{
|
||||
DebugOnly<int32_t> depth = this->stackDepth;
|
||||
|
||||
uint32_t argc;
|
||||
if (option == CopyOption::Filtered) {
|
||||
MOZ_ASSERT(depth > 2); // TARGET SOURCE SET
|
||||
argc = 3;
|
||||
|
||||
if (!emitAtomOp(cx->names().CopyDataProperties,
|
||||
JSOP_GETINTRINSIC)) // TARGET SOURCE SET COPYDATAPROPERTIES
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(depth > 1); // TARGET SOURCE
|
||||
argc = 2;
|
||||
|
||||
if (!emitAtomOp(cx->names().CopyDataPropertiesUnfiltered,
|
||||
JSOP_GETINTRINSIC)) // TARGET SOURCE COPYDATAPROPERTIES
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!emit1(JSOP_UNDEFINED)) // TARGET SOURCE *SET COPYDATAPROPERTIES UNDEFINED
|
||||
return false;
|
||||
if (!emit2(JSOP_PICK, argc + 1)) // SOURCE *SET COPYDATAPROPERTIES UNDEFINED TARGET
|
||||
return false;
|
||||
if (!emit2(JSOP_PICK, argc + 1)) // *SET COPYDATAPROPERTIES UNDEFINED TARGET SOURCE
|
||||
return false;
|
||||
if (option == CopyOption::Filtered) {
|
||||
if (!emit2(JSOP_PICK, argc + 1)) // COPYDATAPROPERTIES UNDEFINED TARGET SOURCE SET
|
||||
return false;
|
||||
}
|
||||
if (!emitCall(JSOP_CALL_IGNORES_RV, argc)) // IGNORED
|
||||
return false;
|
||||
checkTypeSet(JSOP_CALL_IGNORES_RV);
|
||||
|
||||
if (!emit1(JSOP_POP)) // -
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(depth - int(argc) == this->stackDepth);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitIterator()
|
||||
{
|
||||
|
|
@ -7269,12 +7456,14 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
|
|||
// scope, but we still need to emit code for the initializers.)
|
||||
if (!updateSourceCoordNotes(init->pn_pos.begin))
|
||||
return false;
|
||||
if (!emitTree(init))
|
||||
return false;
|
||||
|
||||
if (!init->isForLoopDeclaration()) {
|
||||
if (init->isForLoopDeclaration()) {
|
||||
if (!emitTree(init))
|
||||
return false;
|
||||
} else {
|
||||
// 'init' is an expression, not a declaration. emitTree left its
|
||||
// value on the stack.
|
||||
if (!emitTree(init, ValueUsage::IgnoreValue))
|
||||
return false;
|
||||
if (!emit1(JSOP_POP))
|
||||
return false;
|
||||
}
|
||||
|
|
@ -7356,7 +7545,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc
|
|||
|
||||
if (!updateSourceCoordNotes(update->pn_pos.begin))
|
||||
return false;
|
||||
if (!emitTree(update))
|
||||
if (!emitTree(update, ValueUsage::IgnoreValue))
|
||||
return false;
|
||||
if (!emit1(JSOP_POP))
|
||||
return false;
|
||||
|
|
@ -7839,7 +8028,8 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
|||
Rooted<JSObject*> sourceObject(cx, script->sourceObject());
|
||||
Rooted<JSScript*> script(cx, JSScript::Create(cx, options, sourceObject,
|
||||
funbox->bufStart, funbox->bufEnd,
|
||||
funbox->preludeStart));
|
||||
funbox->toStringStart,
|
||||
funbox->toStringEnd));
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
|
|
@ -8682,8 +8872,9 @@ BytecodeEmitter::emitStatement(ParseNode* pn)
|
|||
|
||||
if (useful) {
|
||||
JSOp op = wantval ? JSOP_SETRVAL : JSOP_POP;
|
||||
ValueUsage valueUsage = wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue;
|
||||
MOZ_ASSERT_IF(pn2->isKind(PNK_ASSIGN), pn2->isOp(JSOP_NOP));
|
||||
if (!emitTree(pn2))
|
||||
if (!emitTree(pn2, valueUsage))
|
||||
return false;
|
||||
if (!emit1(op))
|
||||
return false;
|
||||
|
|
@ -9033,7 +9224,7 @@ BytecodeEmitter::emitOptimizeSpread(ParseNode* arg0, JumpList* jmp, bool* emitte
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitCallOrNew(ParseNode* pn)
|
||||
BytecodeEmitter::emitCallOrNew(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */)
|
||||
{
|
||||
bool callop = pn->isKind(PNK_CALL) || pn->isKind(PNK_TAGGED_TEMPLATE);
|
||||
/*
|
||||
|
|
@ -9212,13 +9403,20 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
|
|||
}
|
||||
|
||||
if (!spread) {
|
||||
if (!emitCall(pn->getOp(), argc, pn))
|
||||
return false;
|
||||
if (pn->getOp() == JSOP_CALL && valueUsage == ValueUsage::IgnoreValue) {
|
||||
if (!emitCall(JSOP_CALL_IGNORES_RV, argc, pn))
|
||||
return false;
|
||||
checkTypeSet(JSOP_CALL_IGNORES_RV);
|
||||
} else {
|
||||
if (!emitCall(pn->getOp(), argc, pn))
|
||||
return false;
|
||||
checkTypeSet(pn->getOp());
|
||||
}
|
||||
} else {
|
||||
if (!emit1(pn->getOp()))
|
||||
return false;
|
||||
checkTypeSet(pn->getOp());
|
||||
}
|
||||
checkTypeSet(pn->getOp());
|
||||
if (pn->isOp(JSOP_EVAL) ||
|
||||
pn->isOp(JSOP_STRICTEVAL) ||
|
||||
pn->isOp(JSOP_SPREADEVAL) ||
|
||||
|
|
@ -9316,12 +9514,13 @@ BytecodeEmitter::emitLogical(ParseNode* pn)
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitSequenceExpr(ParseNode* pn)
|
||||
BytecodeEmitter::emitSequenceExpr(ParseNode* pn,
|
||||
ValueUsage valueUsage /* = ValueUsage::WantValue */)
|
||||
{
|
||||
for (ParseNode* child = pn->pn_head; ; child = child->pn_next) {
|
||||
if (!updateSourceCoordNotes(child->pn_pos.begin))
|
||||
return false;
|
||||
if (!emitTree(child))
|
||||
if (!emitTree(child, child->pn_next ? ValueUsage::IgnoreValue : valueUsage))
|
||||
return false;
|
||||
if (!child->pn_next)
|
||||
break;
|
||||
|
|
@ -9384,7 +9583,8 @@ BytecodeEmitter::emitLabeledStatement(const LabeledStatement* pn)
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitConditionalExpression(ConditionalExpression& conditional)
|
||||
BytecodeEmitter::emitConditionalExpression(ConditionalExpression& conditional,
|
||||
ValueUsage valueUsage /* = ValueUsage::WantValue */)
|
||||
{
|
||||
/* Emit the condition, then branch if false to the else part. */
|
||||
if (!emitTree(&conditional.condition()))
|
||||
|
|
@ -9394,13 +9594,13 @@ BytecodeEmitter::emitConditionalExpression(ConditionalExpression& conditional)
|
|||
if (!ifThenElse.emitCond())
|
||||
return false;
|
||||
|
||||
if (!emitTreeInBranch(&conditional.thenExpression()))
|
||||
if (!emitTreeInBranch(&conditional.thenExpression(), valueUsage))
|
||||
return false;
|
||||
|
||||
if (!ifThenElse.emitElse())
|
||||
return false;
|
||||
|
||||
if (!emitTreeInBranch(&conditional.elseExpression()))
|
||||
if (!emitTreeInBranch(&conditional.elseExpression(), valueUsage))
|
||||
return false;
|
||||
|
||||
if (!ifThenElse.emitEnd())
|
||||
|
|
@ -9429,6 +9629,22 @@ BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (propdef->isKind(PNK_SPREAD)) {
|
||||
MOZ_ASSERT(type == ObjectLiteral);
|
||||
|
||||
if (!emit1(JSOP_DUP))
|
||||
return false;
|
||||
|
||||
if (!emitTree(propdef->pn_kid))
|
||||
return false;
|
||||
|
||||
if (!emitCopyDataProperties(CopyOption::Unfiltered))
|
||||
return false;
|
||||
|
||||
objp.set(nullptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool extraPop = false;
|
||||
if (type == ClassBody && propdef->as<ClassMethod>().isStatic()) {
|
||||
extraPop = true;
|
||||
|
|
@ -9452,16 +9668,6 @@ BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
|
|||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// The parser already checked for atoms representing indexes and
|
||||
// used PNK_NUMBER instead, but also watch for ids which TI treats
|
||||
// as indexes for simpliciation of downstream analysis.
|
||||
jsid id = NameToId(key->pn_atom->asPropertyName());
|
||||
if (id != IdToTypeId(id)) {
|
||||
if (!emitTree(key))
|
||||
return false;
|
||||
isIndex = true;
|
||||
}
|
||||
} else {
|
||||
if (!emitComputedPropertyName(key))
|
||||
return false;
|
||||
|
|
@ -9542,8 +9748,7 @@ BytecodeEmitter::emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
|
|||
MOZ_ASSERT(!IsHiddenInitOp(op));
|
||||
MOZ_ASSERT(!objp->inDictionaryMode());
|
||||
Rooted<jsid> id(cx, AtomToId(key->pn_atom));
|
||||
RootedValue undefinedValue(cx, UndefinedValue());
|
||||
if (!NativeDefineProperty(cx, objp, id, undefinedValue, nullptr, nullptr,
|
||||
if (!NativeDefineProperty(cx, objp, id, UndefinedHandleValue, nullptr, nullptr,
|
||||
JSPROP_ENUMERATE))
|
||||
{
|
||||
return false;
|
||||
|
|
@ -9586,15 +9791,16 @@ BytecodeEmitter::emitObject(ParseNode* pn)
|
|||
if (!emitNewInit(JSProto_Object))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Try to construct the shape of the object as we go, so we can emit a
|
||||
* JSOP_NEWOBJECT with the final shape instead.
|
||||
*/
|
||||
RootedPlainObject obj(cx);
|
||||
// No need to do any guessing for the object kind, since we know exactly
|
||||
// how many properties we plan to have.
|
||||
// Try to construct the shape of the object as we go, so we can emit a
|
||||
// JSOP_NEWOBJECT with the final shape instead.
|
||||
// In the case of computed property names and indices, we cannot fix the
|
||||
// shape at bytecode compile time. When the shape cannot be determined,
|
||||
// |obj| is nulled out.
|
||||
|
||||
// No need to do any guessing for the object kind, since we know the upper
|
||||
// bound of how many properties we plan to have.
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(pn->pn_count);
|
||||
obj = NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject);
|
||||
RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx, kind, TenuredObject));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
|
|
@ -9602,29 +9808,38 @@ BytecodeEmitter::emitObject(ParseNode* pn)
|
|||
return false;
|
||||
|
||||
if (obj) {
|
||||
/*
|
||||
* The object survived and has a predictable shape: update the original
|
||||
* bytecode.
|
||||
*/
|
||||
ObjectBox* objbox = parser->newObjectBox(obj);
|
||||
if (!objbox)
|
||||
// The object survived and has a predictable shape: update the original
|
||||
// bytecode.
|
||||
if (!replaceNewInitWithNewObject(obj, offset))
|
||||
return false;
|
||||
|
||||
static_assert(JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
|
||||
"newinit and newobject must have equal length to edit in-place");
|
||||
|
||||
uint32_t index = objectList.add(objbox);
|
||||
jsbytecode* code = this->code(offset);
|
||||
code[0] = JSOP_NEWOBJECT;
|
||||
code[1] = jsbytecode(index >> 24);
|
||||
code[2] = jsbytecode(index >> 16);
|
||||
code[3] = jsbytecode(index >> 8);
|
||||
code[4] = jsbytecode(index);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::replaceNewInitWithNewObject(JSObject* obj, ptrdiff_t offset)
|
||||
{
|
||||
ObjectBox* objbox = parser->newObjectBox(obj);
|
||||
if (!objbox)
|
||||
return false;
|
||||
|
||||
static_assert(JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
|
||||
"newinit and newobject must have equal length to edit in-place");
|
||||
|
||||
uint32_t index = objectList.add(objbox);
|
||||
jsbytecode* code = this->code(offset);
|
||||
|
||||
MOZ_ASSERT(code[0] == JSOP_NEWINIT);
|
||||
code[0] = JSOP_NEWOBJECT;
|
||||
code[1] = jsbytecode(index >> 24);
|
||||
code[2] = jsbytecode(index >> 16);
|
||||
code[3] = jsbytecode(index >> 8);
|
||||
code[4] = jsbytecode(index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitArrayComp(ParseNode* pn)
|
||||
{
|
||||
|
|
@ -10220,6 +10435,13 @@ BytecodeEmitter::emitClass(ParseNode* pn)
|
|||
return false;
|
||||
}
|
||||
} else {
|
||||
// In the case of default class constructors, emit the start and end
|
||||
// offsets in the source buffer as source notes so that when we
|
||||
// actually make the constructor during execution, we can give it the
|
||||
// correct toString output.
|
||||
if (!newSrcNote3(SRC_CLASS_SPAN, ptrdiff_t(pn->pn_pos.begin), ptrdiff_t(pn->pn_pos.end)))
|
||||
return false;
|
||||
|
||||
JSAtom *name = names ? names->innerBinding()->pn_atom : cx->names().empty;
|
||||
if (heritageExpression) {
|
||||
if (!emitAtomOp(name, JSOP_DERIVEDCONSTRUCTOR))
|
||||
|
|
@ -10274,7 +10496,8 @@ BytecodeEmitter::emitClass(ParseNode* pn)
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
|
||||
BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::WantValue */,
|
||||
EmitLineNumberNote emitLineNote /* = EMIT_LINENOTE */)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
|
||||
|
|
@ -10396,7 +10619,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
|
|||
break;
|
||||
|
||||
case PNK_COMMA:
|
||||
if (!emitSequenceExpr(pn))
|
||||
if (!emitSequenceExpr(pn, valueUsage))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
|
@ -10418,7 +10641,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
|
|||
break;
|
||||
|
||||
case PNK_CONDITIONAL:
|
||||
if (!emitConditionalExpression(pn->as<ConditionalExpression>()))
|
||||
if (!emitConditionalExpression(pn->as<ConditionalExpression>(), valueUsage))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
|
@ -10531,7 +10754,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
|
|||
case PNK_CALL:
|
||||
case PNK_GENEXP:
|
||||
case PNK_SUPERCALL:
|
||||
if (!emitCallOrNew(pn))
|
||||
if (!emitCallOrNew(pn, valueUsage))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
|
@ -10637,6 +10860,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
|
|||
case PNK_TRUE:
|
||||
case PNK_FALSE:
|
||||
case PNK_NULL:
|
||||
case PNK_RAW_UNDEFINED:
|
||||
if (!emit1(pn->getOp()))
|
||||
return false;
|
||||
break;
|
||||
|
|
@ -10688,12 +10912,13 @@ BytecodeEmitter::emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote)
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitTreeInBranch(ParseNode* pn)
|
||||
BytecodeEmitter::emitTreeInBranch(ParseNode* pn,
|
||||
ValueUsage valueUsage /* = ValueUsage::WantValue */)
|
||||
{
|
||||
// Code that may be conditionally executed always need their own TDZ
|
||||
// cache.
|
||||
TDZCheckCache tdzCache(this);
|
||||
return emitTree(pn);
|
||||
return emitTree(pn, valueUsage);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
|||
|
|
@ -171,6 +171,11 @@ struct JumpList {
|
|||
void patchAll(jsbytecode* code, JumpTarget target);
|
||||
};
|
||||
|
||||
enum class ValueUsage {
|
||||
WantValue,
|
||||
IgnoreValue
|
||||
};
|
||||
|
||||
struct MOZ_STACK_CLASS BytecodeEmitter
|
||||
{
|
||||
class TDZCheckCache;
|
||||
|
|
@ -356,7 +361,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool maybeSetSourceMap();
|
||||
void tellDebuggerAboutCompiledScript(ExclusiveContext* cx);
|
||||
|
||||
inline TokenStream* tokenStream();
|
||||
inline TokenStream& tokenStream();
|
||||
|
||||
BytecodeVector& code() const { return current->code; }
|
||||
jsbytecode* code(ptrdiff_t offset) const { return current->code.begin() + offset; }
|
||||
|
|
@ -434,10 +439,12 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
};
|
||||
|
||||
// Emit code for the tree rooted at pn.
|
||||
MOZ_MUST_USE bool emitTree(ParseNode* pn, EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
|
||||
MOZ_MUST_USE bool emitTree(ParseNode* pn, ValueUsage valueUsage = ValueUsage::WantValue,
|
||||
EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
|
||||
|
||||
// Emit code for the tree rooted at pn with its own TDZ cache.
|
||||
MOZ_MUST_USE bool emitTreeInBranch(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitTreeInBranch(ParseNode* pn,
|
||||
ValueUsage valueUsage = ValueUsage::WantValue);
|
||||
|
||||
// Emit global, eval, or module code for tree rooted at body. Always
|
||||
// encompasses the entire source.
|
||||
|
|
@ -533,6 +540,8 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitFunction(ParseNode* pn, bool needsProto = false);
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitObject(ParseNode* pn);
|
||||
|
||||
MOZ_MUST_USE bool replaceNewInitWithNewObject(JSObject* obj, ptrdiff_t offset);
|
||||
|
||||
MOZ_MUST_USE bool emitHoistedFunctionsInList(ParseNode* pn);
|
||||
|
||||
MOZ_MUST_USE bool emitPropertyList(ParseNode* pn, MutableHandlePlainObject objp,
|
||||
|
|
@ -660,6 +669,10 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
// []/{} expression).
|
||||
MOZ_MUST_USE bool emitSetOrInitializeDestructuring(ParseNode* target, DestructuringFlavor flav);
|
||||
|
||||
// emitDestructuringObjRestExclusionSet emits the property exclusion set
|
||||
// for the rest-property in an object pattern.
|
||||
MOZ_MUST_USE bool emitDestructuringObjRestExclusionSet(ParseNode* pattern);
|
||||
|
||||
// emitDestructuringOps assumes the to-be-destructured value has been
|
||||
// pushed on the stack and emits code to destructure each part of a [] or
|
||||
// {} lhs expression.
|
||||
|
|
@ -677,6 +690,15 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
// object, with no overall effect on the stack.
|
||||
MOZ_MUST_USE bool emitRequireObjectCoercible();
|
||||
|
||||
enum class CopyOption {
|
||||
Filtered, Unfiltered
|
||||
};
|
||||
|
||||
// Calls either the |CopyDataProperties| or the
|
||||
// |CopyDataPropertiesUnfiltered| intrinsic function, consumes three (or
|
||||
// two in the latter case) elements from the stack.
|
||||
MOZ_MUST_USE bool emitCopyDataProperties(CopyOption option);
|
||||
|
||||
// emitIterator expects the iterable to already be on the stack.
|
||||
// It will replace that stack value with the corresponding iterator
|
||||
MOZ_MUST_USE bool emitIterator();
|
||||
|
|
@ -724,16 +746,18 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool emitRightAssociative(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitLeftAssociative(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitLogical(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSequenceExpr(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSequenceExpr(ParseNode* pn,
|
||||
ValueUsage valueUsage = ValueUsage::WantValue);
|
||||
|
||||
MOZ_NEVER_INLINE MOZ_MUST_USE bool emitIncOrDec(ParseNode* pn);
|
||||
|
||||
MOZ_MUST_USE bool emitConditionalExpression(ConditionalExpression& conditional);
|
||||
MOZ_MUST_USE bool emitConditionalExpression(ConditionalExpression& conditional,
|
||||
ValueUsage valueUsage = ValueUsage::WantValue);
|
||||
|
||||
MOZ_MUST_USE bool isRestParameter(ParseNode* pn, bool* result);
|
||||
MOZ_MUST_USE bool emitOptimizeSpread(ParseNode* arg0, JumpList* jmp, bool* emitted);
|
||||
|
||||
MOZ_MUST_USE bool emitCallOrNew(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitCallOrNew(ParseNode* pn, ValueUsage valueUsage = ValueUsage::WantValue);
|
||||
MOZ_MUST_USE bool emitSelfHostedCallFunction(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSelfHostedResumeGenerator(ParseNode* pn);
|
||||
MOZ_MUST_USE bool emitSelfHostedForceInterpreter(ParseNode* pn);
|
||||
|
|
|
|||
|
|
@ -378,6 +378,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
|||
case PNK_TRUE:
|
||||
case PNK_FALSE:
|
||||
case PNK_NULL:
|
||||
case PNK_RAW_UNDEFINED:
|
||||
case PNK_THIS:
|
||||
case PNK_ELISION:
|
||||
case PNK_NUMBER:
|
||||
|
|
@ -468,6 +469,7 @@ IsEffectless(ParseNode* node)
|
|||
node->isKind(PNK_TEMPLATE_STRING) ||
|
||||
node->isKind(PNK_NUMBER) ||
|
||||
node->isKind(PNK_NULL) ||
|
||||
node->isKind(PNK_RAW_UNDEFINED) ||
|
||||
node->isKind(PNK_FUNCTION) ||
|
||||
node->isKind(PNK_GENEXP);
|
||||
}
|
||||
|
|
@ -492,6 +494,7 @@ Boolish(ParseNode* pn)
|
|||
|
||||
case PNK_FALSE:
|
||||
case PNK_NULL:
|
||||
case PNK_RAW_UNDEFINED:
|
||||
return Falsy;
|
||||
|
||||
case PNK_VOID: {
|
||||
|
|
@ -1342,15 +1345,8 @@ FoldElement(ExclusiveContext* cx, ParseNode** nodePtr, Parser<FullParseHandler>&
|
|||
if (!name)
|
||||
return true;
|
||||
|
||||
// Also don't optimize if the name doesn't map directly to its id for TI's
|
||||
// purposes.
|
||||
if (NameToId(name) != IdToTypeId(NameToId(name)))
|
||||
return true;
|
||||
|
||||
// Optimization 3: We have expr["foo"] where foo is not an index. Convert
|
||||
// to a property access (like expr.foo) that optimizes better downstream.
|
||||
// Don't bother with this for names that TI considers to be indexes, to
|
||||
// simplify downstream analysis.
|
||||
ParseNode* dottedAccess = parser.handler.newPropertyAccess(expr, name, node->pn_pos.end);
|
||||
if (!dottedAccess)
|
||||
return false;
|
||||
|
|
@ -1643,6 +1639,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
|||
case PNK_TRUE:
|
||||
case PNK_FALSE:
|
||||
case PNK_NULL:
|
||||
case PNK_RAW_UNDEFINED:
|
||||
case PNK_ELISION:
|
||||
case PNK_NUMBER:
|
||||
case PNK_DEBUGGER:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "frontend/ParseNode.h"
|
||||
#include "frontend/SharedContext.h"
|
||||
|
||||
|
|
@ -181,6 +183,10 @@ class FullParseHandler
|
|||
return new_<NullLiteral>(pos);
|
||||
}
|
||||
|
||||
ParseNode* newRawUndefinedLiteral(const TokenPos& pos) {
|
||||
return new_<RawUndefinedLiteral>(pos);
|
||||
}
|
||||
|
||||
// The Boxer object here is any object that can allocate ObjectBoxes.
|
||||
// Specifically, a Boxer has a .newObjectBox(T) method that accepts a
|
||||
// Rooted<RegExpObject*> argument and returns an ObjectBox*.
|
||||
|
|
@ -296,10 +302,9 @@ class FullParseHandler
|
|||
}
|
||||
|
||||
MOZ_MUST_USE bool addSpreadElement(ParseNode* literal, uint32_t begin, ParseNode* inner) {
|
||||
TokenPos pos(begin, inner->pn_pos.end);
|
||||
ParseNode* spread = new_<UnaryNode>(PNK_SPREAD, JSOP_NOP, pos, inner);
|
||||
ParseNode* spread = newSpread(begin, inner);
|
||||
if (!spread)
|
||||
return null();
|
||||
return false;
|
||||
literal->append(spread);
|
||||
literal->pn_xflags |= PNX_ARRAYHOLESPREAD | PNX_NONCONST;
|
||||
return true;
|
||||
|
|
@ -327,8 +332,10 @@ class FullParseHandler
|
|||
return literal;
|
||||
}
|
||||
|
||||
ParseNode* newClass(ParseNode* name, ParseNode* heritage, ParseNode* methodBlock) {
|
||||
return new_<ClassNode>(name, heritage, methodBlock);
|
||||
ParseNode* newClass(ParseNode* name, ParseNode* heritage, ParseNode* methodBlock,
|
||||
const TokenPos& pos)
|
||||
{
|
||||
return new_<ClassNode>(name, heritage, methodBlock, pos);
|
||||
}
|
||||
ParseNode* newClassMethodList(uint32_t begin) {
|
||||
return new_<ListNode>(PNK_CLASSMETHODLIST, TokenPos(begin, begin + 1));
|
||||
|
|
@ -388,6 +395,18 @@ class FullParseHandler
|
|||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool addSpreadProperty(ParseNode* literal, uint32_t begin, ParseNode* inner) {
|
||||
MOZ_ASSERT(literal->isKind(PNK_OBJECT));
|
||||
MOZ_ASSERT(literal->isArity(PN_LIST));
|
||||
|
||||
setListFlag(literal, PNX_NONCONST);
|
||||
ParseNode* spread = newSpread(begin, inner);
|
||||
if (!spread)
|
||||
return false;
|
||||
literal->append(spread);
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool addObjectMethodDefinition(ParseNode* literal, ParseNode* key, ParseNode* fn,
|
||||
JSOp op)
|
||||
{
|
||||
|
|
@ -870,29 +889,29 @@ class FullParseHandler
|
|||
return node->isKind(PNK_NAME);
|
||||
}
|
||||
|
||||
bool nameIsEvalAnyParentheses(ParseNode* node, ExclusiveContext* cx) {
|
||||
MOZ_ASSERT(isNameAnyParentheses(node),
|
||||
"must only call this function on known names");
|
||||
bool isArgumentsAnyParentheses(ParseNode* node, ExclusiveContext* cx) {
|
||||
return node->isKind(PNK_NAME) && node->pn_atom == cx->names().arguments;
|
||||
}
|
||||
|
||||
return node->pn_atom == cx->names().eval;
|
||||
bool isEvalAnyParentheses(ParseNode* node, ExclusiveContext* cx) {
|
||||
return node->isKind(PNK_NAME) && node->pn_atom == cx->names().eval;
|
||||
}
|
||||
|
||||
const char* nameIsArgumentsEvalAnyParentheses(ParseNode* node, ExclusiveContext* cx) {
|
||||
MOZ_ASSERT(isNameAnyParentheses(node),
|
||||
"must only call this function on known names");
|
||||
|
||||
if (nameIsEvalAnyParentheses(node, cx))
|
||||
if (isEvalAnyParentheses(node, cx))
|
||||
return js_eval_str;
|
||||
if (node->pn_atom == cx->names().arguments)
|
||||
if (isArgumentsAnyParentheses(node, cx))
|
||||
return js_arguments_str;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool nameIsUnparenthesizedAsync(ParseNode* node, ExclusiveContext* cx) {
|
||||
MOZ_ASSERT(isNameAnyParentheses(node),
|
||||
"must only call this function on known names");
|
||||
|
||||
return node->pn_atom == cx->names().async;
|
||||
bool isAsyncKeyword(ParseNode* node, ExclusiveContext* cx) {
|
||||
return node->isKind(PNK_NAME) &&
|
||||
node->pn_pos.begin + strlen("async") == node->pn_pos.end &&
|
||||
node->pn_atom == cx->names().async;
|
||||
}
|
||||
|
||||
bool isCall(ParseNode* pn) {
|
||||
|
|
|
|||
213
js/src/frontend/GenerateReservedWords.py
Normal file
213
js/src/frontend/GenerateReservedWords.py
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
# 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/.
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
def read_reserved_word_list(filename):
|
||||
macro_pat = re.compile(r"^\s*macro\(([^,]+), *[^,]+, *[^\)]+\)\s*\\?$")
|
||||
|
||||
reserved_word_list = []
|
||||
index = 0
|
||||
with open(filename, 'r') as f:
|
||||
for line in f:
|
||||
m = macro_pat.search(line)
|
||||
if m:
|
||||
reserved_word_list.append((index, m.group(1)))
|
||||
index += 1
|
||||
|
||||
assert(len(reserved_word_list) != 0)
|
||||
|
||||
return reserved_word_list
|
||||
|
||||
def line(opt, s):
|
||||
opt['output'].write('{}{}\n'.format(' ' * opt['indent_level'], s))
|
||||
|
||||
def indent(opt):
|
||||
opt['indent_level'] += 1
|
||||
|
||||
def dedent(opt):
|
||||
opt['indent_level'] -= 1
|
||||
|
||||
def span_and_count_at(reserved_word_list, column):
|
||||
assert(len(reserved_word_list) != 0);
|
||||
|
||||
chars_dict = {}
|
||||
for index, word in reserved_word_list:
|
||||
chars_dict[ord(word[column])] = True
|
||||
|
||||
chars = sorted(chars_dict.keys())
|
||||
return chars[-1] - chars[0] + 1, len(chars)
|
||||
|
||||
def optimal_switch_column(opt, reserved_word_list, columns, unprocessed_columns):
|
||||
assert(len(reserved_word_list) != 0);
|
||||
assert(unprocessed_columns != 0);
|
||||
|
||||
min_count = 0
|
||||
min_span = 0
|
||||
min_count_index = 0
|
||||
min_span_index = 0
|
||||
|
||||
for index in range(0, unprocessed_columns):
|
||||
span, count = span_and_count_at(reserved_word_list, columns[index])
|
||||
assert(span != 0)
|
||||
|
||||
if span == 1:
|
||||
assert(count == 1)
|
||||
return 1, True
|
||||
|
||||
assert(count != 1)
|
||||
if index == 0 or min_span > span:
|
||||
min_span = span
|
||||
min_span_index = index
|
||||
|
||||
if index == 0 or min_count > count:
|
||||
min_count = count
|
||||
min_count_index = index
|
||||
|
||||
if min_count <= opt['use_if_threshold']:
|
||||
return min_count_index, True
|
||||
|
||||
return min_span_index, False
|
||||
|
||||
def split_list_per_column(reserved_word_list, column):
|
||||
assert(len(reserved_word_list) != 0);
|
||||
|
||||
column_dict = {}
|
||||
for item in reserved_word_list:
|
||||
index, word = item
|
||||
per_column = column_dict.setdefault(word[column], [])
|
||||
per_column.append(item)
|
||||
|
||||
return sorted(column_dict.items(), key=lambda (char, word): ord(char))
|
||||
|
||||
def generate_letter_switch(opt, unprocessed_columns, reserved_word_list,
|
||||
columns=None):
|
||||
assert(len(reserved_word_list) != 0);
|
||||
|
||||
if not columns:
|
||||
columns = range(0, unprocessed_columns)
|
||||
|
||||
if len(reserved_word_list) == 1:
|
||||
index, word = reserved_word_list[0]
|
||||
|
||||
if unprocessed_columns == 0:
|
||||
line(opt, 'JSRW_GOT_MATCH({}) /* {} */'.format(index, word))
|
||||
return
|
||||
|
||||
if unprocessed_columns > opt['char_tail_test_threshold']:
|
||||
line(opt, 'JSRW_TEST_GUESS({}) /* {} */'.format(index, word))
|
||||
return
|
||||
|
||||
conds = []
|
||||
for column in columns[0:unprocessed_columns]:
|
||||
quoted = repr(word[column])
|
||||
conds.append('JSRW_AT({})=={}'.format(column, quoted))
|
||||
|
||||
line(opt, 'if ({}) {{'.format(' && '.join(conds)))
|
||||
|
||||
indent(opt)
|
||||
line(opt, 'JSRW_GOT_MATCH({}) /* {} */'.format(index, word))
|
||||
dedent(opt)
|
||||
|
||||
line(opt, '}')
|
||||
line(opt, 'JSRW_NO_MATCH()')
|
||||
return
|
||||
|
||||
assert(unprocessed_columns != 0);
|
||||
|
||||
optimal_column_index, use_if = optimal_switch_column(opt, reserved_word_list,
|
||||
columns,
|
||||
unprocessed_columns)
|
||||
optimal_column = columns[optimal_column_index]
|
||||
|
||||
# Make a copy to avoid breaking passed list.
|
||||
columns = columns[:]
|
||||
columns[optimal_column_index] = columns[unprocessed_columns - 1]
|
||||
|
||||
list_per_column = split_list_per_column(reserved_word_list, optimal_column)
|
||||
|
||||
if not use_if:
|
||||
line(opt, 'switch (JSRW_AT({})) {{'.format(optimal_column))
|
||||
|
||||
for char, reserved_word_list_per_column in list_per_column:
|
||||
quoted = repr(char)
|
||||
if use_if:
|
||||
line(opt, 'if (JSRW_AT({}) == {}) {{'.format(optimal_column,
|
||||
quoted))
|
||||
else:
|
||||
line(opt, ' case {}:'.format(quoted))
|
||||
|
||||
indent(opt)
|
||||
generate_letter_switch(opt, unprocessed_columns - 1,
|
||||
reserved_word_list_per_column, columns)
|
||||
dedent(opt)
|
||||
|
||||
if use_if:
|
||||
line(opt, '}')
|
||||
|
||||
if not use_if:
|
||||
line(opt, '}')
|
||||
|
||||
line(opt, 'JSRW_NO_MATCH()')
|
||||
|
||||
def split_list_per_length(reserved_word_list):
|
||||
assert(len(reserved_word_list) != 0);
|
||||
|
||||
length_dict = {}
|
||||
for item in reserved_word_list:
|
||||
index, word = item
|
||||
per_length = length_dict.setdefault(len(word), [])
|
||||
per_length.append(item)
|
||||
|
||||
return sorted(length_dict.items(), key=lambda (length, word): length)
|
||||
|
||||
def generate_switch(opt, reserved_word_list):
|
||||
assert(len(reserved_word_list) != 0);
|
||||
|
||||
line(opt, '/*')
|
||||
line(opt, ' * Generating switch for the list of {} entries:'.format(len(reserved_word_list)))
|
||||
for index, word in reserved_word_list:
|
||||
line(opt, ' * {}'.format(word))
|
||||
line(opt, ' */')
|
||||
|
||||
list_per_length = split_list_per_length(reserved_word_list)
|
||||
|
||||
use_if = False
|
||||
if len(list_per_length) < opt['use_if_threshold']:
|
||||
use_if = True
|
||||
|
||||
if not use_if:
|
||||
line(opt, 'switch (JSRW_LENGTH()) {')
|
||||
|
||||
for length, reserved_word_list_per_length in list_per_length:
|
||||
if use_if:
|
||||
line(opt, 'if (JSRW_LENGTH() == {}) {{'.format(length))
|
||||
else:
|
||||
line(opt, ' case {}:'.format(length))
|
||||
|
||||
indent(opt)
|
||||
generate_letter_switch(opt, length, reserved_word_list_per_length)
|
||||
dedent(opt)
|
||||
|
||||
if use_if:
|
||||
line(opt, '}')
|
||||
|
||||
if not use_if:
|
||||
line(opt, '}')
|
||||
line(opt, 'JSRW_NO_MATCH()')
|
||||
|
||||
def main(output, reserved_words_h):
|
||||
reserved_word_list = read_reserved_word_list(reserved_words_h)
|
||||
|
||||
opt = {
|
||||
'indent_level': 1,
|
||||
'use_if_threshold': 3,
|
||||
'char_tail_test_threshold': 4,
|
||||
'output': output
|
||||
}
|
||||
generate_switch(opt, reserved_word_list)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.stdout, *sys.argv[1:])
|
||||
|
|
@ -78,6 +78,7 @@ enum class DeclarationKind : uint8_t
|
|||
Const,
|
||||
Import,
|
||||
BodyLevelFunction,
|
||||
ModuleBodyLevelFunction,
|
||||
LexicalFunction,
|
||||
VarForAnnexBLexicalFunction,
|
||||
SimpleCatchParameter,
|
||||
|
|
@ -95,6 +96,7 @@ DeclarationKindToBindingKind(DeclarationKind kind)
|
|||
|
||||
case DeclarationKind::Var:
|
||||
case DeclarationKind::BodyLevelFunction:
|
||||
case DeclarationKind::ModuleBodyLevelFunction:
|
||||
case DeclarationKind::VarForAnnexBLexicalFunction:
|
||||
case DeclarationKind::ForOfVar:
|
||||
return BindingKind::Var;
|
||||
|
|
@ -124,6 +126,7 @@ DeclarationKindIsLexical(DeclarationKind kind)
|
|||
// Used in Parser to track declared names.
|
||||
class DeclaredNameInfo
|
||||
{
|
||||
uint32_t pos_;
|
||||
DeclarationKind kind_;
|
||||
|
||||
// If the declared name is a binding, whether the binding is closed
|
||||
|
|
@ -132,8 +135,9 @@ class DeclaredNameInfo
|
|||
bool closedOver_;
|
||||
|
||||
public:
|
||||
explicit DeclaredNameInfo(DeclarationKind kind)
|
||||
: kind_(kind),
|
||||
explicit DeclaredNameInfo(DeclarationKind kind, uint32_t pos)
|
||||
: pos_(pos),
|
||||
kind_(kind),
|
||||
closedOver_(false)
|
||||
{ }
|
||||
|
||||
|
|
@ -144,6 +148,12 @@ class DeclaredNameInfo
|
|||
return kind_;
|
||||
}
|
||||
|
||||
static const uint32_t npos = uint32_t(-1);
|
||||
|
||||
uint32_t pos() const {
|
||||
return pos_;
|
||||
}
|
||||
|
||||
void alterKind(DeclarationKind kind) {
|
||||
kind_ = kind;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -316,7 +316,8 @@ class NameResolver
|
|||
return false;
|
||||
|
||||
// Next is the callsite object node. This node only contains
|
||||
// internal strings and an array -- no user-controlled expressions.
|
||||
// internal strings or undefined and an array -- no user-controlled
|
||||
// expressions.
|
||||
element = element->pn_next;
|
||||
#ifdef DEBUG
|
||||
{
|
||||
|
|
@ -326,7 +327,7 @@ class NameResolver
|
|||
for (ParseNode* kid = array->pn_head; kid; kid = kid->pn_next)
|
||||
MOZ_ASSERT(kid->isKind(PNK_TEMPLATE_STRING));
|
||||
for (ParseNode* next = array->pn_next; next; next = next->pn_next)
|
||||
MOZ_ASSERT(next->isKind(PNK_TEMPLATE_STRING));
|
||||
MOZ_ASSERT(next->isKind(PNK_TEMPLATE_STRING) || next->isKind(PNK_RAW_UNDEFINED));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -382,6 +383,7 @@ class NameResolver
|
|||
case PNK_TRUE:
|
||||
case PNK_FALSE:
|
||||
case PNK_NULL:
|
||||
case PNK_RAW_UNDEFINED:
|
||||
case PNK_ELISION:
|
||||
case PNK_GENERATOR:
|
||||
case PNK_NUMBER:
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
|||
case PNK_TRUE:
|
||||
case PNK_FALSE:
|
||||
case PNK_NULL:
|
||||
case PNK_RAW_UNDEFINED:
|
||||
case PNK_ELISION:
|
||||
case PNK_GENERATOR:
|
||||
case PNK_NUMBER:
|
||||
|
|
@ -685,6 +686,7 @@ NullaryNode::dump()
|
|||
case PNK_TRUE: fprintf(stderr, "#true"); break;
|
||||
case PNK_FALSE: fprintf(stderr, "#false"); break;
|
||||
case PNK_NULL: fprintf(stderr, "#null"); break;
|
||||
case PNK_RAW_UNDEFINED: fprintf(stderr, "#undefined"); break;
|
||||
|
||||
case PNK_NUMBER: {
|
||||
ToCStringBuf cbuf;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ class ObjectBox;
|
|||
F(TRUE) \
|
||||
F(FALSE) \
|
||||
F(NULL) \
|
||||
F(RAW_UNDEFINED) \
|
||||
F(THIS) \
|
||||
F(FUNCTION) \
|
||||
F(MODULE) \
|
||||
|
|
@ -406,7 +407,8 @@ IsTypeofKind(ParseNodeKind kind)
|
|||
* PNK_NUMBER dval pn_dval: double value of numeric literal
|
||||
* PNK_TRUE, nullary pn_op: JSOp bytecode
|
||||
* PNK_FALSE,
|
||||
* PNK_NULL
|
||||
* PNK_NULL,
|
||||
* PNK_RAW_UNDEFINED
|
||||
*
|
||||
* PNK_THIS, unary pn_kid: '.this' Name if function `this`, else nullptr
|
||||
* PNK_SUPERBASE unary pn_kid: '.this' Name
|
||||
|
|
@ -686,7 +688,8 @@ class ParseNode
|
|||
isKind(PNK_STRING) ||
|
||||
isKind(PNK_TRUE) ||
|
||||
isKind(PNK_FALSE) ||
|
||||
isKind(PNK_NULL);
|
||||
isKind(PNK_NULL) ||
|
||||
isKind(PNK_RAW_UNDEFINED);
|
||||
}
|
||||
|
||||
/* Return true if this node appears in a Directive Prologue. */
|
||||
|
|
@ -1141,6 +1144,16 @@ class NullLiteral : public ParseNode
|
|||
explicit NullLiteral(const TokenPos& pos) : ParseNode(PNK_NULL, JSOP_NULL, PN_NULLARY, pos) { }
|
||||
};
|
||||
|
||||
// This is only used internally, currently just for tagged templates.
|
||||
// It represents the value 'undefined' (aka `void 0`), like NullLiteral
|
||||
// represents the value 'null'.
|
||||
class RawUndefinedLiteral : public ParseNode
|
||||
{
|
||||
public:
|
||||
explicit RawUndefinedLiteral(const TokenPos& pos)
|
||||
: ParseNode(PNK_RAW_UNDEFINED, JSOP_UNDEFINED, PN_NULLARY, pos) { }
|
||||
};
|
||||
|
||||
class BooleanLiteral : public ParseNode
|
||||
{
|
||||
public:
|
||||
|
|
@ -1296,8 +1309,9 @@ struct ClassNames : public BinaryNode {
|
|||
};
|
||||
|
||||
struct ClassNode : public TernaryNode {
|
||||
ClassNode(ParseNode* names, ParseNode* heritage, ParseNode* methodsOrBlock)
|
||||
: TernaryNode(PNK_CLASS, JSOP_NOP, names, heritage, methodsOrBlock)
|
||||
ClassNode(ParseNode* names, ParseNode* heritage, ParseNode* methodsOrBlock,
|
||||
const TokenPos& pos)
|
||||
: TernaryNode(PNK_CLASS, JSOP_NOP, names, heritage, methodsOrBlock, pos)
|
||||
{
|
||||
MOZ_ASSERT_IF(names, names->is<ClassNames>());
|
||||
MOZ_ASSERT(methodsOrBlock->is<LexicalScopeNode>() ||
|
||||
|
|
@ -1361,6 +1375,7 @@ ParseNode::isConstant()
|
|||
case PNK_STRING:
|
||||
case PNK_TEMPLATE_STRING:
|
||||
case PNK_NULL:
|
||||
case PNK_RAW_UNDEFINED:
|
||||
case PNK_FALSE:
|
||||
case PNK_TRUE:
|
||||
return true;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -85,6 +85,16 @@ class ParseContext : public Nestable<ParseContext>
|
|||
}
|
||||
};
|
||||
|
||||
struct ClassStatement : public Statement
|
||||
{
|
||||
FunctionBox* constructorBox;
|
||||
|
||||
explicit ClassStatement(ParseContext* pc)
|
||||
: Statement(pc, StatementKind::Class),
|
||||
constructorBox(nullptr)
|
||||
{ }
|
||||
};
|
||||
|
||||
// The intra-function scope stack.
|
||||
//
|
||||
// Tracks declared and used names within a scope.
|
||||
|
|
@ -146,9 +156,9 @@ class ParseContext : public Nestable<ParseContext>
|
|||
}
|
||||
|
||||
MOZ_MUST_USE bool addDeclaredName(ParseContext* pc, AddDeclaredNamePtr& p, JSAtom* name,
|
||||
DeclarationKind kind)
|
||||
DeclarationKind kind, uint32_t pos)
|
||||
{
|
||||
return maybeReportOOM(pc, declared_->add(p, name, DeclaredNameInfo(kind)));
|
||||
return maybeReportOOM(pc, declared_->add(p, name, DeclaredNameInfo(kind, pos)));
|
||||
}
|
||||
|
||||
// Remove all VarForAnnexBLexicalFunction declarations of a certain
|
||||
|
|
@ -330,17 +340,6 @@ class ParseContext : public Nestable<ParseContext>
|
|||
// pointer may be nullptr.
|
||||
Directives* newDirectives;
|
||||
|
||||
// Set when parsing a declaration-like destructuring pattern. This flag
|
||||
// causes PrimaryExpr to create PN_NAME parse nodes for variable references
|
||||
// which are not hooked into any definition's use chain, added to any tree
|
||||
// context's AtomList, etc. etc. checkDestructuring will do that work
|
||||
// later.
|
||||
//
|
||||
// The comments atop checkDestructuring explain the distinction between
|
||||
// assignment-like and declaration-like destructuring patterns, and why
|
||||
// they need to be treated differently.
|
||||
mozilla::Maybe<DeclarationKind> inDestructuringDecl;
|
||||
|
||||
// Set when parsing a function and it has 'return <expr>;'
|
||||
bool funHasReturnExpr;
|
||||
|
||||
|
|
@ -432,6 +431,11 @@ class ParseContext : public Nestable<ParseContext>
|
|||
return Statement::findNearest<T>(innermostStatement_, predicate);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* findInnermostStatement() {
|
||||
return Statement::findNearest<T>(innermostStatement_);
|
||||
}
|
||||
|
||||
AtomVector& positionalFormalParameterNames() {
|
||||
return *positionalFormalParameterNames_;
|
||||
}
|
||||
|
|
@ -532,6 +536,13 @@ ParseContext::Statement::is<ParseContext::LabelStatement>() const
|
|||
return kind_ == StatementKind::Label;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool
|
||||
ParseContext::Statement::is<ParseContext::ClassStatement>() const
|
||||
{
|
||||
return kind_ == StatementKind::Class;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T&
|
||||
ParseContext::Statement::as()
|
||||
|
|
@ -735,7 +746,155 @@ class UsedNameTracker
|
|||
};
|
||||
|
||||
template <typename ParseHandler>
|
||||
class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
||||
class AutoAwaitIsKeyword;
|
||||
|
||||
class ParserBase : public StrictModeGetter
|
||||
{
|
||||
private:
|
||||
ParserBase* thisForCtor() { return this; }
|
||||
|
||||
public:
|
||||
ExclusiveContext* const context;
|
||||
|
||||
LifoAlloc& alloc;
|
||||
|
||||
TokenStream tokenStream;
|
||||
LifoAlloc::Mark tempPoolMark;
|
||||
|
||||
/* list of parsed objects for GC tracing */
|
||||
ObjectBox* traceListHead;
|
||||
|
||||
/* innermost parse context (stack-allocated) */
|
||||
ParseContext* pc;
|
||||
|
||||
// For tracking used names in this parsing session.
|
||||
UsedNameTracker& usedNames;
|
||||
|
||||
/* Compression token for aborting. */
|
||||
SourceCompressionTask* sct;
|
||||
|
||||
ScriptSource* ss;
|
||||
|
||||
/* Root atoms and objects allocated for the parsed tree. */
|
||||
AutoKeepAtoms keepAtoms;
|
||||
|
||||
/* Perform constant-folding; must be true when interfacing with the emitter. */
|
||||
const bool foldConstants:1;
|
||||
|
||||
protected:
|
||||
#if DEBUG
|
||||
/* Our fallible 'checkOptions' member function has been called. */
|
||||
bool checkOptionsCalled:1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Not all language constructs can be handled during syntax parsing. If it
|
||||
* is not known whether the parse succeeds or fails, this bit is set and
|
||||
* the parse will return false.
|
||||
*/
|
||||
bool abortedSyntaxParse:1;
|
||||
|
||||
/* Unexpected end of input, i.e. TOK_EOF not at top-level. */
|
||||
bool isUnexpectedEOF_:1;
|
||||
|
||||
bool awaitIsKeyword_:1;
|
||||
|
||||
public:
|
||||
bool awaitIsKeyword() const {
|
||||
return awaitIsKeyword_;
|
||||
}
|
||||
|
||||
ParserBase(ExclusiveContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
|
||||
const char16_t* chars, size_t length, bool foldConstants,
|
||||
UsedNameTracker& usedNames, Parser<SyntaxParseHandler>* syntaxParser,
|
||||
LazyScript* lazyOuterFunction);
|
||||
~ParserBase();
|
||||
|
||||
const char* getFilename() const { return tokenStream.getFilename(); }
|
||||
JSVersion versionNumber() const { return tokenStream.versionNumber(); }
|
||||
TokenPos pos() const { return tokenStream.currentToken().pos; }
|
||||
|
||||
// Determine whether |yield| is a valid name in the current context, or
|
||||
// whether it's prohibited due to strictness, JS version, or occurrence
|
||||
// inside a star generator.
|
||||
bool yieldExpressionsSupported() {
|
||||
return (versionNumber() >= JSVERSION_1_7 || pc->isGenerator()) && !pc->isAsync();
|
||||
}
|
||||
|
||||
virtual bool strictMode() { return pc->sc()->strict(); }
|
||||
bool setLocalStrictMode(bool strict) {
|
||||
MOZ_ASSERT(tokenStream.debugHasNoLookahead());
|
||||
return pc->sc()->setLocalStrictMode(strict);
|
||||
}
|
||||
|
||||
const ReadOnlyCompileOptions& options() const {
|
||||
return tokenStream.options();
|
||||
}
|
||||
|
||||
bool hadAbortedSyntaxParse() {
|
||||
return abortedSyntaxParse;
|
||||
}
|
||||
void clearAbortedSyntaxParse() {
|
||||
abortedSyntaxParse = false;
|
||||
}
|
||||
|
||||
bool isUnexpectedEOF() const { return isUnexpectedEOF_; }
|
||||
|
||||
bool reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...);
|
||||
|
||||
/* Report the given error at the current offset. */
|
||||
void error(unsigned errorNumber, ...);
|
||||
void errorWithNotes(UniquePtr<JSErrorNotes> notes, unsigned errorNumber, ...);
|
||||
|
||||
/* Report the given error at the given offset. */
|
||||
void errorAt(uint32_t offset, unsigned errorNumber, ...);
|
||||
void errorWithNotesAt(UniquePtr<JSErrorNotes> notes, uint32_t offset,
|
||||
unsigned errorNumber, ...);
|
||||
|
||||
/*
|
||||
* Handle a strict mode error at the current offset. Report an error if in
|
||||
* strict mode code, or warn if not, using the given error number and
|
||||
* arguments.
|
||||
*/
|
||||
MOZ_MUST_USE bool strictModeError(unsigned errorNumber, ...);
|
||||
|
||||
/*
|
||||
* Handle a strict mode error at the given offset. Report an error if in
|
||||
* strict mode code, or warn if not, using the given error number and
|
||||
* arguments.
|
||||
*/
|
||||
MOZ_MUST_USE bool strictModeErrorAt(uint32_t offset, unsigned errorNumber, ...);
|
||||
|
||||
/* Report the given warning at the current offset. */
|
||||
MOZ_MUST_USE bool warning(unsigned errorNumber, ...);
|
||||
|
||||
/* Report the given warning at the given offset. */
|
||||
MOZ_MUST_USE bool warningAt(uint32_t offset, unsigned errorNumber, ...);
|
||||
|
||||
/*
|
||||
* If extra warnings are enabled, report the given warning at the current
|
||||
* offset.
|
||||
*/
|
||||
MOZ_MUST_USE bool extraWarning(unsigned errorNumber, ...);
|
||||
|
||||
/*
|
||||
* If extra warnings are enabled, report the given warning at the given
|
||||
* offset.
|
||||
*/
|
||||
MOZ_MUST_USE bool extraWarningAt(uint32_t offset, unsigned errorNumber, ...);
|
||||
|
||||
bool isValidStrictBinding(PropertyName* name);
|
||||
|
||||
bool warnOnceAboutExprClosure();
|
||||
bool warnOnceAboutForEach();
|
||||
|
||||
protected:
|
||||
enum InvokedPrediction { PredictUninvoked = false, PredictInvoked = true };
|
||||
enum ForInitLocation { InForInit, NotInForInit };
|
||||
};
|
||||
|
||||
template <typename ParseHandler>
|
||||
class Parser final : public ParserBase, private JS::AutoGCRooter
|
||||
{
|
||||
private:
|
||||
using Node = typename ParseHandler::Node;
|
||||
|
|
@ -788,7 +947,7 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
class MOZ_STACK_CLASS PossibleError
|
||||
{
|
||||
private:
|
||||
enum class ErrorKind { Expression, Destructuring };
|
||||
enum class ErrorKind { Expression, Destructuring, DestructuringWarning };
|
||||
|
||||
enum class ErrorState { None, Pending };
|
||||
|
||||
|
|
@ -803,11 +962,12 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
Parser<ParseHandler>& parser_;
|
||||
Error exprError_;
|
||||
Error destructuringError_;
|
||||
Error destructuringWarning_;
|
||||
|
||||
// Returns the error report.
|
||||
Error& error(ErrorKind kind);
|
||||
|
||||
// Return true if an error is pending without reporting
|
||||
// Return true if an error is pending without reporting.
|
||||
bool hasError(ErrorKind kind);
|
||||
|
||||
// Resolve any pending error.
|
||||
|
|
@ -819,7 +979,11 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
|
||||
// If there is a pending error, report it and return false, otherwise
|
||||
// return true.
|
||||
bool checkForError(ErrorKind kind);
|
||||
MOZ_MUST_USE bool checkForError(ErrorKind kind);
|
||||
|
||||
// If there is a pending warning, report it and return either false or
|
||||
// true depending on the werror option, otherwise return true.
|
||||
MOZ_MUST_USE bool checkForWarning(ErrorKind kind);
|
||||
|
||||
// Transfer an existing error to another instance.
|
||||
void transferErrorTo(ErrorKind kind, PossibleError* other);
|
||||
|
|
@ -827,23 +991,33 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
public:
|
||||
explicit PossibleError(Parser<ParseHandler>& parser);
|
||||
|
||||
// Return true if a pending destructuring error is present.
|
||||
bool hasPendingDestructuringError();
|
||||
|
||||
// Set a pending destructuring error. Only a single error may be set
|
||||
// per instance, i.e. subsequent calls to this method are ignored and
|
||||
// won't overwrite the existing pending error.
|
||||
void setPendingDestructuringErrorAt(const TokenPos& pos, unsigned errorNumber);
|
||||
|
||||
// Set a pending destructuring warning. Only a single warning may be
|
||||
// set per instance, i.e. subsequent calls to this method are ignored
|
||||
// and won't overwrite the existing pending warning.
|
||||
void setPendingDestructuringWarningAt(const TokenPos& pos, unsigned errorNumber);
|
||||
|
||||
// Set a pending expression error. Only a single error may be set per
|
||||
// instance, i.e. subsequent calls to this method are ignored and won't
|
||||
// overwrite the existing pending error.
|
||||
void setPendingExpressionErrorAt(const TokenPos& pos, unsigned errorNumber);
|
||||
|
||||
// If there is a pending destructuring error, report it and return
|
||||
// false, otherwise return true. Clears any pending expression error.
|
||||
bool checkForDestructuringError();
|
||||
// If there is a pending destructuring error or warning, report it and
|
||||
// return false, otherwise return true. Clears any pending expression
|
||||
// error.
|
||||
MOZ_MUST_USE bool checkForDestructuringErrorOrWarning();
|
||||
|
||||
// If there is a pending expression error, report it and return false,
|
||||
// otherwise return true. Clears any pending destructuring error.
|
||||
bool checkForExpressionError();
|
||||
// otherwise return true. Clears any pending destructuring error or
|
||||
// warning.
|
||||
MOZ_MUST_USE bool checkForExpressionError();
|
||||
|
||||
// Pass pending errors between possible error instances. This is useful
|
||||
// for extending the lifetime of a pending error beyond the scope of
|
||||
|
|
@ -852,50 +1026,6 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
void transferErrorsTo(PossibleError* other);
|
||||
};
|
||||
|
||||
public:
|
||||
ExclusiveContext* const context;
|
||||
|
||||
LifoAlloc& alloc;
|
||||
|
||||
TokenStream tokenStream;
|
||||
LifoAlloc::Mark tempPoolMark;
|
||||
|
||||
/* list of parsed objects for GC tracing */
|
||||
ObjectBox* traceListHead;
|
||||
|
||||
/* innermost parse context (stack-allocated) */
|
||||
ParseContext* pc;
|
||||
|
||||
// For tracking used names in this parsing session.
|
||||
UsedNameTracker& usedNames;
|
||||
|
||||
/* Compression token for aborting. */
|
||||
SourceCompressionTask* sct;
|
||||
|
||||
ScriptSource* ss;
|
||||
|
||||
/* Root atoms and objects allocated for the parsed tree. */
|
||||
AutoKeepAtoms keepAtoms;
|
||||
|
||||
/* Perform constant-folding; must be true when interfacing with the emitter. */
|
||||
const bool foldConstants:1;
|
||||
|
||||
private:
|
||||
#if DEBUG
|
||||
/* Our fallible 'checkOptions' member function has been called. */
|
||||
bool checkOptionsCalled:1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Not all language constructs can be handled during syntax parsing. If it
|
||||
* is not known whether the parse succeeds or fails, this bit is set and
|
||||
* the parse will return false.
|
||||
*/
|
||||
bool abortedSyntaxParse:1;
|
||||
|
||||
/* Unexpected end of input, i.e. TOK_EOF not at top-level. */
|
||||
bool isUnexpectedEOF_:1;
|
||||
|
||||
public:
|
||||
/* State specific to the kind of parse being performed. */
|
||||
ParseHandler handler;
|
||||
|
|
@ -904,45 +1034,14 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
void freeTree(Node node) { handler.freeTree(node); }
|
||||
|
||||
public:
|
||||
bool reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...);
|
||||
|
||||
/* Report the given error at the current offset. */
|
||||
void error(unsigned errorNumber, ...);
|
||||
|
||||
/* Report the given error at the given offset. */
|
||||
void errorAt(uint32_t offset, unsigned errorNumber, ...);
|
||||
|
||||
/*
|
||||
* Handle a strict mode error at the current offset. Report an error if in
|
||||
* strict mode code, or warn if not, using the given error number and
|
||||
* arguments.
|
||||
*/
|
||||
MOZ_MUST_USE bool strictModeError(unsigned errorNumber, ...);
|
||||
|
||||
/*
|
||||
* Handle a strict mode error at the given offset. Report an error if in
|
||||
* strict mode code, or warn if not, using the given error number and
|
||||
* arguments.
|
||||
*/
|
||||
MOZ_MUST_USE bool strictModeErrorAt(uint32_t offset, unsigned errorNumber, ...);
|
||||
|
||||
/* Report the given warning at the current offset. */
|
||||
MOZ_MUST_USE bool warning(unsigned errorNumber, ...);
|
||||
|
||||
/* Report the given warning at the given offset. */
|
||||
MOZ_MUST_USE bool warningAt(uint32_t offset, unsigned errorNumber, ...);
|
||||
|
||||
/*
|
||||
* If extra warnings are enabled, report the given warning at the current
|
||||
* offset.
|
||||
*/
|
||||
MOZ_MUST_USE bool extraWarning(unsigned errorNumber, ...);
|
||||
|
||||
Parser(ExclusiveContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
|
||||
const char16_t* chars, size_t length, bool foldConstants, UsedNameTracker& usedNames,
|
||||
Parser<SyntaxParseHandler>* syntaxParser, LazyScript* lazyOuterFunction);
|
||||
~Parser();
|
||||
|
||||
friend class AutoAwaitIsKeyword<ParseHandler>;
|
||||
void setAwaitIsKeyword(bool isKeyword);
|
||||
|
||||
bool checkOptions();
|
||||
|
||||
// A Parser::Mark is the extension of the LifoAlloc::Mark to the entire
|
||||
|
|
@ -967,9 +1066,6 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
|
||||
friend void js::frontend::MarkParser(JSTracer* trc, JS::AutoGCRooter* parser);
|
||||
|
||||
const char* getFilename() const { return tokenStream.getFilename(); }
|
||||
JSVersion versionNumber() const { return tokenStream.versionNumber(); }
|
||||
|
||||
/*
|
||||
* Parse a top-level JS script.
|
||||
*/
|
||||
|
|
@ -980,7 +1076,7 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
* cx->tempLifoAlloc.
|
||||
*/
|
||||
ObjectBox* newObjectBox(JSObject* obj);
|
||||
FunctionBox* newFunctionBox(Node fn, JSFunction* fun, uint32_t preludeStart,
|
||||
FunctionBox* newFunctionBox(Node fn, JSFunction* fun, uint32_t toStringStart,
|
||||
Directives directives,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
bool tryAnnexB);
|
||||
|
|
@ -995,24 +1091,14 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
|
||||
void trace(JSTracer* trc);
|
||||
|
||||
bool hadAbortedSyntaxParse() {
|
||||
return abortedSyntaxParse;
|
||||
}
|
||||
void clearAbortedSyntaxParse() {
|
||||
abortedSyntaxParse = false;
|
||||
}
|
||||
|
||||
bool isUnexpectedEOF() const { return isUnexpectedEOF_; }
|
||||
|
||||
bool checkUnescapedName();
|
||||
|
||||
private:
|
||||
Parser* thisForCtor() { return this; }
|
||||
|
||||
JSAtom* stopStringCompression();
|
||||
|
||||
Node stringLiteral();
|
||||
Node noSubstitutionTemplate();
|
||||
Node noSubstitutionTaggedTemplate();
|
||||
Node noSubstitutionUntaggedTemplate();
|
||||
Node templateLiteral(YieldHandling yieldHandling);
|
||||
bool taggedTemplate(YieldHandling yieldHandling, Node nodeList, TokenKind tt);
|
||||
bool appendToCallSiteObj(Node callSiteObj);
|
||||
|
|
@ -1061,7 +1147,7 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
|
||||
// Parse an inner function given an enclosing ParseContext and a
|
||||
// FunctionBox for the inner function.
|
||||
bool innerFunction(Node pn, ParseContext* outerpc, FunctionBox* funbox, uint32_t preludeStart,
|
||||
bool innerFunction(Node pn, ParseContext* outerpc, FunctionBox* funbox, uint32_t toStringStart,
|
||||
InHandling inHandling, YieldHandling yieldHandling,
|
||||
FunctionSyntaxKind kind,
|
||||
Directives inheritedDirectives, Directives* newDirectives);
|
||||
|
|
@ -1070,35 +1156,14 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
// ParseContext is already on the stack.
|
||||
bool functionFormalParametersAndBody(InHandling inHandling, YieldHandling yieldHandling,
|
||||
Node pn, FunctionSyntaxKind kind,
|
||||
mozilla::Maybe<uint32_t> parameterListEnd = mozilla::Nothing());
|
||||
|
||||
|
||||
// Determine whether |yield| is a valid name in the current context, or
|
||||
// whether it's prohibited due to strictness, JS version, or occurrence
|
||||
// inside a star generator.
|
||||
bool yieldExpressionsSupported() {
|
||||
return (versionNumber() >= JSVERSION_1_7 || pc->isGenerator()) && !pc->isAsync();
|
||||
}
|
||||
mozilla::Maybe<uint32_t> parameterListEnd = mozilla::Nothing(),
|
||||
bool isStandaloneFunction = false);
|
||||
|
||||
// Match the current token against the BindingIdentifier production with
|
||||
// the given Yield parameter. If there is no match, report a syntax
|
||||
// error.
|
||||
PropertyName* bindingIdentifier(YieldHandling yieldHandling);
|
||||
|
||||
virtual bool strictMode() { return pc->sc()->strict(); }
|
||||
bool setLocalStrictMode(bool strict) {
|
||||
MOZ_ASSERT(tokenStream.debugHasNoLookahead());
|
||||
return pc->sc()->setLocalStrictMode(strict);
|
||||
}
|
||||
|
||||
const ReadOnlyCompileOptions& options() const {
|
||||
return tokenStream.options();
|
||||
}
|
||||
|
||||
private:
|
||||
enum InvokedPrediction { PredictUninvoked = false, PredictInvoked = true };
|
||||
enum ForInitLocation { InForInit, NotInForInit };
|
||||
|
||||
private:
|
||||
/*
|
||||
* JS parsers, from lowest to highest precedence.
|
||||
|
|
@ -1116,10 +1181,10 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
* Some parsers have two versions: an always-inlined version (with an 'i'
|
||||
* suffix) and a never-inlined version (with an 'n' suffix).
|
||||
*/
|
||||
Node functionStmt(uint32_t preludeStart,
|
||||
Node functionStmt(uint32_t toStringStart,
|
||||
YieldHandling yieldHandling, DefaultHandling defaultHandling,
|
||||
FunctionAsyncKind asyncKind = SyncFunction);
|
||||
Node functionExpr(uint32_t preludeStart, InvokedPrediction invoked = PredictUninvoked,
|
||||
Node functionExpr(uint32_t toStringStart, InvokedPrediction invoked = PredictUninvoked,
|
||||
FunctionAsyncKind asyncKind = SyncFunction);
|
||||
|
||||
Node statementList(YieldHandling yieldHandling);
|
||||
|
|
@ -1160,9 +1225,27 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
// continues a LexicalDeclaration.
|
||||
bool nextTokenContinuesLetDeclaration(TokenKind next, YieldHandling yieldHandling);
|
||||
|
||||
Node lexicalDeclaration(YieldHandling yieldHandling, bool isConst);
|
||||
Node lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind);
|
||||
|
||||
Node importDeclaration();
|
||||
|
||||
bool processExport(Node node);
|
||||
bool processExportFrom(Node node);
|
||||
|
||||
Node exportFrom(uint32_t begin, Node specList);
|
||||
Node exportBatch(uint32_t begin);
|
||||
bool checkLocalExportNames(Node node);
|
||||
Node exportClause(uint32_t begin);
|
||||
Node exportFunctionDeclaration(uint32_t begin);
|
||||
Node exportVariableStatement(uint32_t begin);
|
||||
Node exportClassDeclaration(uint32_t begin);
|
||||
Node exportLexicalDeclaration(uint32_t begin, DeclarationKind kind);
|
||||
Node exportDefaultFunctionDeclaration(uint32_t begin,
|
||||
FunctionAsyncKind asyncKind = SyncFunction);
|
||||
Node exportDefaultClassDeclaration(uint32_t begin);
|
||||
Node exportDefaultAssignExpr(uint32_t begin);
|
||||
Node exportDefault(uint32_t begin);
|
||||
|
||||
Node exportDeclaration();
|
||||
Node expressionStatement(YieldHandling yieldHandling,
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
|
|
@ -1250,7 +1333,7 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
bool tryNewTarget(Node& newTarget);
|
||||
bool checkAndMarkSuperScope();
|
||||
|
||||
Node methodDefinition(uint32_t preludeStart, PropertyType propType, HandleAtom funName);
|
||||
Node methodDefinition(uint32_t toStringStart, PropertyType propType, HandleAtom funName);
|
||||
|
||||
/*
|
||||
* Additional JS parsers.
|
||||
|
|
@ -1258,7 +1341,7 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
bool functionArguments(YieldHandling yieldHandling, FunctionSyntaxKind kind,
|
||||
Node funcpn);
|
||||
|
||||
Node functionDefinition(uint32_t preludeStart, Node pn,
|
||||
Node functionDefinition(uint32_t toStringStart, Node pn,
|
||||
InHandling inHandling, YieldHandling yieldHandling, HandleAtom name,
|
||||
FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
|
|
@ -1294,21 +1377,34 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
bool checkExportedName(JSAtom* exportName);
|
||||
bool checkExportedNamesForDeclaration(Node node);
|
||||
|
||||
bool checkExportedNameForClause(Node node);
|
||||
bool checkExportedNameForFunction(Node node);
|
||||
bool checkExportedNameForClass(Node node);
|
||||
|
||||
enum ClassContext { ClassStatement, ClassExpression };
|
||||
Node classDefinition(YieldHandling yieldHandling, ClassContext classContext,
|
||||
DefaultHandling defaultHandling);
|
||||
|
||||
PropertyName* labelOrIdentifierReference(YieldHandling yieldHandling,
|
||||
bool yieldTokenizedAsName);
|
||||
bool checkLabelOrIdentifierReference(HandlePropertyName ident,
|
||||
uint32_t offset,
|
||||
YieldHandling yieldHandling);
|
||||
|
||||
PropertyName* labelIdentifier(YieldHandling yieldHandling) {
|
||||
return labelOrIdentifierReference(yieldHandling, false);
|
||||
bool checkLocalExportName(HandlePropertyName ident, uint32_t offset) {
|
||||
return checkLabelOrIdentifierReference(ident, offset, YieldIsName);
|
||||
}
|
||||
|
||||
PropertyName* identifierReference(YieldHandling yieldHandling,
|
||||
bool yieldTokenizedAsName = false)
|
||||
{
|
||||
return labelOrIdentifierReference(yieldHandling, yieldTokenizedAsName);
|
||||
bool checkBindingIdentifier(HandlePropertyName ident,
|
||||
uint32_t offset,
|
||||
YieldHandling yieldHandling);
|
||||
|
||||
PropertyName* labelOrIdentifierReference(YieldHandling yieldHandling);
|
||||
|
||||
PropertyName* labelIdentifier(YieldHandling yieldHandling) {
|
||||
return labelOrIdentifierReference(yieldHandling);
|
||||
}
|
||||
|
||||
PropertyName* identifierReference(YieldHandling yieldHandling) {
|
||||
return labelOrIdentifierReference(yieldHandling);
|
||||
}
|
||||
|
||||
PropertyName* importedBinding() {
|
||||
|
|
@ -1337,23 +1433,27 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
Node newDotGeneratorName();
|
||||
bool declareDotGeneratorName();
|
||||
|
||||
bool skipLazyInnerFunction(Node pn, uint32_t preludeStart, FunctionSyntaxKind kind,
|
||||
bool skipLazyInnerFunction(Node pn, uint32_t toStringStart, FunctionSyntaxKind kind,
|
||||
bool tryAnnexB);
|
||||
bool innerFunction(Node pn, ParseContext* outerpc, HandleFunction fun, uint32_t preludeStart,
|
||||
bool innerFunction(Node pn, ParseContext* outerpc, HandleFunction fun, uint32_t toStringStart,
|
||||
InHandling inHandling, YieldHandling yieldHandling,
|
||||
FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
|
||||
Directives inheritedDirectives, Directives* newDirectives);
|
||||
bool trySyntaxParseInnerFunction(Node pn, HandleFunction fun, uint32_t preludeStart,
|
||||
bool trySyntaxParseInnerFunction(Node pn, HandleFunction fun, uint32_t toStringStart,
|
||||
InHandling inHandling, YieldHandling yieldHandling,
|
||||
FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
bool tryAnnexB,
|
||||
Directives inheritedDirectives, Directives* newDirectives);
|
||||
bool finishFunctionScopes();
|
||||
bool finishFunction();
|
||||
bool finishFunctionScopes(bool isStandaloneFunction);
|
||||
bool finishFunction(bool isStandaloneFunction = false);
|
||||
bool leaveInnerFunction(ParseContext* outerpc);
|
||||
|
||||
bool matchOrInsertSemicolonHelper(TokenStream::Modifier modifier);
|
||||
bool matchOrInsertSemicolonAfterExpression();
|
||||
bool matchOrInsertSemicolonAfterNonExpression();
|
||||
|
||||
public:
|
||||
enum FunctionCallBehavior {
|
||||
PermitAssignmentToFunctionCalls,
|
||||
|
|
@ -1366,21 +1466,22 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
private:
|
||||
bool checkIncDecOperand(Node operand, uint32_t operandOffset);
|
||||
bool checkStrictAssignment(Node lhs);
|
||||
bool checkStrictBinding(PropertyName* name, TokenPos pos);
|
||||
|
||||
bool hasValidSimpleStrictParameterNames();
|
||||
|
||||
bool isValidStrictBinding(PropertyName* name);
|
||||
void reportMissingClosing(unsigned errorNumber, unsigned noteNumber, uint32_t openedPos);
|
||||
|
||||
void reportRedeclaration(HandlePropertyName name, DeclarationKind kind, TokenPos pos);
|
||||
bool notePositionalFormalParameter(Node fn, HandlePropertyName name,
|
||||
void reportRedeclaration(HandlePropertyName name, DeclarationKind prevKind, TokenPos pos,
|
||||
uint32_t prevPos);
|
||||
bool notePositionalFormalParameter(Node fn, HandlePropertyName name, uint32_t beginPos,
|
||||
bool disallowDuplicateParams, bool* duplicatedParam);
|
||||
bool noteDestructuredPositionalFormalParameter(Node fn, Node destruct);
|
||||
mozilla::Maybe<DeclarationKind> isVarRedeclaredInEval(HandlePropertyName name,
|
||||
DeclarationKind kind);
|
||||
bool tryDeclareVar(HandlePropertyName name, DeclarationKind kind,
|
||||
mozilla::Maybe<DeclarationKind>* redeclaredKind);
|
||||
bool tryDeclareVarForAnnexBLexicalFunction(HandlePropertyName name, bool* tryAnnexB);
|
||||
bool tryDeclareVar(HandlePropertyName name, DeclarationKind kind, uint32_t beginPos,
|
||||
mozilla::Maybe<DeclarationKind>* redeclaredKind, uint32_t* prevPos);
|
||||
bool tryDeclareVarForAnnexBLexicalFunction(HandlePropertyName name, uint32_t beginPos,
|
||||
bool* tryAnnexB);
|
||||
bool checkLexicalDeclarationDirectlyWithinBlock(ParseContext::Statement& stmt,
|
||||
DeclarationKind kind, TokenPos pos);
|
||||
bool noteDeclaredName(HandlePropertyName name, DeclarationKind kind, TokenPos pos);
|
||||
|
|
@ -1399,25 +1500,27 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
mozilla::Maybe<LexicalScope::Data*> newLexicalScopeData(ParseContext::Scope& scope);
|
||||
Node finishLexicalScope(ParseContext::Scope& scope, Node body);
|
||||
|
||||
Node propertyName(YieldHandling yieldHandling, Node propList,
|
||||
Node propertyName(YieldHandling yieldHandling,
|
||||
const mozilla::Maybe<DeclarationKind>& maybeDecl, Node propList,
|
||||
PropertyType* propType, MutableHandleAtom propAtom);
|
||||
Node computedPropertyName(YieldHandling yieldHandling, Node literal);
|
||||
Node computedPropertyName(YieldHandling yieldHandling,
|
||||
const mozilla::Maybe<DeclarationKind>& maybeDecl, Node literal);
|
||||
Node arrayInitializer(YieldHandling yieldHandling, PossibleError* possibleError);
|
||||
Node newRegExp();
|
||||
|
||||
Node objectLiteral(YieldHandling yieldHandling, PossibleError* possibleError);
|
||||
|
||||
// Top-level entrypoint into destructuring pattern checking/name-analyzing.
|
||||
bool checkDestructuringPattern(Node pattern, mozilla::Maybe<DeclarationKind> maybeDecl,
|
||||
PossibleError* possibleError = nullptr);
|
||||
Node bindingInitializer(Node lhs, DeclarationKind kind, YieldHandling yieldHandling);
|
||||
Node bindingIdentifier(DeclarationKind kind, YieldHandling yieldHandling);
|
||||
Node bindingIdentifierOrPattern(DeclarationKind kind, YieldHandling yieldHandling,
|
||||
TokenKind tt);
|
||||
Node objectBindingPattern(DeclarationKind kind, YieldHandling yieldHandling);
|
||||
Node arrayBindingPattern(DeclarationKind kind, YieldHandling yieldHandling);
|
||||
|
||||
// Recursive methods for checking/name-analyzing subcomponents of a
|
||||
// destructuring pattern. The array/object methods *must* be passed arrays
|
||||
// or objects. The name method may be passed anything but will report an
|
||||
// error if not passed a name.
|
||||
bool checkDestructuringArray(Node arrayPattern, mozilla::Maybe<DeclarationKind> maybeDecl);
|
||||
bool checkDestructuringObject(Node objectPattern, mozilla::Maybe<DeclarationKind> maybeDecl);
|
||||
bool checkDestructuringName(Node expr, mozilla::Maybe<DeclarationKind> maybeDecl);
|
||||
void checkDestructuringAssignmentTarget(Node expr, TokenPos exprPos,
|
||||
PossibleError* possibleError);
|
||||
void checkDestructuringAssignmentElement(Node expr, TokenPos exprPos,
|
||||
PossibleError* possibleError);
|
||||
|
||||
Node newNumber(const Token& tok) {
|
||||
return handler.newNumber(tok.number(), tok.decimalPoint(), tok.pos);
|
||||
|
|
@ -1427,12 +1530,26 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
|
||||
JSAtom* prefixAccessorName(PropertyType propType, HandleAtom propAtom);
|
||||
|
||||
TokenPos pos() const { return tokenStream.currentToken().pos; }
|
||||
|
||||
bool asmJS(Node list);
|
||||
};
|
||||
|
||||
bool warnOnceAboutExprClosure();
|
||||
bool warnOnceAboutForEach();
|
||||
template <typename ParseHandler>
|
||||
class MOZ_STACK_CLASS AutoAwaitIsKeyword
|
||||
{
|
||||
private:
|
||||
Parser<ParseHandler>* parser_;
|
||||
bool oldAwaitIsKeyword_;
|
||||
|
||||
public:
|
||||
AutoAwaitIsKeyword(Parser<ParseHandler>* parser, bool awaitIsKeyword) {
|
||||
parser_ = parser;
|
||||
oldAwaitIsKeyword_ = parser_->awaitIsKeyword_;
|
||||
parser_->setAwaitIsKeyword(awaitIsKeyword);
|
||||
}
|
||||
|
||||
~AutoAwaitIsKeyword() {
|
||||
parser_->setAwaitIsKeyword(oldAwaitIsKeyword_);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace frontend */
|
||||
|
|
|
|||
|
|
@ -4,15 +4,16 @@
|
|||
* 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/. */
|
||||
|
||||
/* A higher-order macro for enumerating keyword tokens. */
|
||||
/* A higher-order macro for enumerating reserved word tokens. */
|
||||
|
||||
#ifndef vm_Keywords_h
|
||||
#define vm_Keywords_h
|
||||
#ifndef vm_ReservedWords_h
|
||||
#define vm_ReservedWords_h
|
||||
|
||||
#define FOR_EACH_JAVASCRIPT_KEYWORD(macro) \
|
||||
#define FOR_EACH_JAVASCRIPT_RESERVED_WORD(macro) \
|
||||
macro(false, false_, TOK_FALSE) \
|
||||
macro(true, true_, TOK_TRUE) \
|
||||
macro(null, null, TOK_NULL) \
|
||||
\
|
||||
/* Keywords. */ \
|
||||
macro(break, break_, TOK_BREAK) \
|
||||
macro(case, case_, TOK_CASE) \
|
||||
|
|
@ -36,31 +37,45 @@
|
|||
macro(this, this_, TOK_THIS) \
|
||||
macro(throw, throw_, TOK_THROW) \
|
||||
macro(try, try_, TOK_TRY) \
|
||||
macro(typeof, typeof, TOK_TYPEOF) \
|
||||
macro(typeof, typeof_, TOK_TYPEOF) \
|
||||
macro(var, var, TOK_VAR) \
|
||||
macro(void, void_, TOK_VOID) \
|
||||
macro(while, while_, TOK_WHILE) \
|
||||
macro(with, with, TOK_WITH) \
|
||||
macro(import, import, TOK_IMPORT) \
|
||||
macro(export, export, TOK_EXPORT) \
|
||||
macro(export, export_, TOK_EXPORT) \
|
||||
macro(class, class_, TOK_CLASS) \
|
||||
macro(extends, extends, TOK_EXTENDS) \
|
||||
macro(super, super, TOK_SUPER) \
|
||||
/* Reserved keywords. */ \
|
||||
macro(enum, enum_, TOK_RESERVED) \
|
||||
/* Future reserved keywords, but only in strict mode. */ \
|
||||
macro(implements, implements, TOK_STRICT_RESERVED) \
|
||||
macro(interface, interface, TOK_STRICT_RESERVED) \
|
||||
macro(package, package, TOK_STRICT_RESERVED) \
|
||||
macro(private, private_, TOK_STRICT_RESERVED) \
|
||||
macro(protected, protected_, TOK_STRICT_RESERVED) \
|
||||
macro(public, public_, TOK_STRICT_RESERVED) \
|
||||
\
|
||||
/* Future reserved words. */ \
|
||||
macro(enum, enum_, TOK_ENUM) \
|
||||
\
|
||||
/* Future reserved words, but only in strict mode. */ \
|
||||
macro(implements, implements, TOK_IMPLEMENTS) \
|
||||
macro(interface, interface, TOK_INTERFACE) \
|
||||
macro(package, package, TOK_PACKAGE) \
|
||||
macro(private, private_, TOK_PRIVATE) \
|
||||
macro(protected, protected_, TOK_PROTECTED) \
|
||||
macro(public, public_, TOK_PUBLIC) \
|
||||
\
|
||||
/* Contextual keywords. */ \
|
||||
macro(as, as, TOK_AS) \
|
||||
macro(async, async, TOK_ASYNC) \
|
||||
macro(await, await, TOK_AWAIT) \
|
||||
macro(each, each, TOK_EACH) \
|
||||
macro(from, from, TOK_FROM) \
|
||||
macro(get, get, TOK_GET) \
|
||||
macro(let, let, TOK_LET) \
|
||||
macro(of, of, TOK_OF) \
|
||||
macro(set, set, TOK_SET) \
|
||||
macro(static, static_, TOK_STATIC) \
|
||||
macro(target, target, TOK_TARGET) \
|
||||
/* \
|
||||
* Yield is a token inside function*. Outside of a function*, it is a \
|
||||
* future reserved keyword in strict mode, but a keyword in JS1.7 even \
|
||||
* future reserved word in strict mode, but a keyword in JS1.7 even \
|
||||
* when strict. Punt logic to parser. \
|
||||
*/ \
|
||||
macro(yield, yield, TOK_YIELD)
|
||||
|
||||
#endif /* vm_Keywords_h */
|
||||
#endif /* vm_ReservedWords_h */
|
||||
|
|
@ -38,6 +38,7 @@ enum class StatementKind : uint8_t
|
|||
ForOfLoop,
|
||||
DoLoop,
|
||||
WhileLoop,
|
||||
Class,
|
||||
|
||||
// Used only by BytecodeEmitter.
|
||||
Spread
|
||||
|
|
@ -450,7 +451,8 @@ class FunctionBox : public ObjectBox, public SharedContext
|
|||
uint32_t bufEnd;
|
||||
uint32_t startLine;
|
||||
uint32_t startColumn;
|
||||
uint32_t preludeStart;
|
||||
uint32_t toStringStart;
|
||||
uint32_t toStringEnd;
|
||||
uint16_t length;
|
||||
|
||||
uint8_t generatorKindBits_; /* The GeneratorKind of this function. */
|
||||
|
|
@ -473,11 +475,14 @@ class FunctionBox : public ObjectBox, public SharedContext
|
|||
bool usesThis:1; /* contains 'this' */
|
||||
bool usesReturn:1; /* contains a 'return' statement */
|
||||
bool hasRest_:1; /* has rest parameter */
|
||||
bool isExprBody_:1; /* arrow function with expression
|
||||
* body or expression closure:
|
||||
* function(x) x*x */
|
||||
|
||||
FunctionContextFlags funCxFlags;
|
||||
|
||||
FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, ObjectBox* traceListHead, JSFunction* fun,
|
||||
uint32_t preludeStart, Directives directives, bool extraWarnings,
|
||||
uint32_t toStringStart, Directives directives, bool extraWarnings,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind);
|
||||
|
||||
MutableHandle<LexicalScope::Data*> namedLambdaBindings() {
|
||||
|
|
@ -546,6 +551,11 @@ class FunctionBox : public ObjectBox, public SharedContext
|
|||
hasRest_ = true;
|
||||
}
|
||||
|
||||
bool isExprBody() const { return isExprBody_; }
|
||||
void setIsExprBody() {
|
||||
isExprBody_ = true;
|
||||
}
|
||||
|
||||
void setGeneratorKind(GeneratorKind kind) {
|
||||
// A generator kind can be set at initialization, or when "yield" is
|
||||
// first seen. In both cases the transition can only happen from
|
||||
|
|
@ -595,6 +605,14 @@ class FunctionBox : public ObjectBox, public SharedContext
|
|||
tokenStream.srcCoords.lineNumAndColumnIndex(bufStart, &startLine, &startColumn);
|
||||
}
|
||||
|
||||
void setEnd(uint32_t end) {
|
||||
// For all functions except class constructors, the buffer and
|
||||
// toString ending positions are the same. Class constructors override
|
||||
// the toString ending position with the end of the class definition.
|
||||
bufEnd = end;
|
||||
toStringEnd = end;
|
||||
}
|
||||
|
||||
void trace(JSTracer* trc) override;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -56,13 +56,14 @@ namespace js {
|
|||
M(SRC_NEXTCASE, "nextcase", 1) /* Distance forward from one CASE in a CONDSWITCH to \
|
||||
the next. */ \
|
||||
M(SRC_ASSIGNOP, "assignop", 0) /* += or another assign-op follows. */ \
|
||||
M(SRC_CLASS_SPAN, "class", 2) /* The starting and ending offsets for the class, used \
|
||||
for toString correctness for default ctors. */ \
|
||||
M(SRC_TRY, "try", 1) /* JSOP_TRY, offset points to goto at the end of the \
|
||||
try block. */ \
|
||||
/* All notes above here are "gettable". See SN_IS_GETTABLE below. */ \
|
||||
M(SRC_COLSPAN, "colspan", 1) /* Number of columns this opcode spans. */ \
|
||||
M(SRC_NEWLINE, "newline", 0) /* Bytecode follows a source newline. */ \
|
||||
M(SRC_SETLINE, "setline", 1) /* A file-absolute source line number note. */ \
|
||||
M(SRC_UNUSED20, "unused20", 0) /* Unused. */ \
|
||||
M(SRC_UNUSED21, "unused21", 0) /* Unused. */ \
|
||||
M(SRC_UNUSED22, "unused22", 0) /* Unused. */ \
|
||||
M(SRC_UNUSED23, "unused23", 0) /* Unused. */ \
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "frontend/ParseNode.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
|
||||
|
|
@ -94,10 +96,13 @@ class SyntaxParseHandler
|
|||
|
||||
// Nodes representing unparenthesized names.
|
||||
NodeUnparenthesizedArgumentsName,
|
||||
NodeUnparenthesizedAsyncName,
|
||||
NodeUnparenthesizedEvalName,
|
||||
NodeUnparenthesizedName,
|
||||
|
||||
// Node representing the "async" name, which may actually be a
|
||||
// contextual keyword.
|
||||
NodePotentialAsyncKeyword,
|
||||
|
||||
// Valuable for recognizing potential destructuring patterns.
|
||||
NodeUnparenthesizedArray,
|
||||
NodeUnparenthesizedObject,
|
||||
|
|
@ -183,8 +188,8 @@ class SyntaxParseHandler
|
|||
lastAtom = name;
|
||||
if (name == cx->names().arguments)
|
||||
return NodeUnparenthesizedArgumentsName;
|
||||
if (name == cx->names().async)
|
||||
return NodeUnparenthesizedAsyncName;
|
||||
if (pos.begin + strlen("async") == pos.end && name == cx->names().async)
|
||||
return NodePotentialAsyncKeyword;
|
||||
if (name == cx->names().eval)
|
||||
return NodeUnparenthesizedEvalName;
|
||||
return NodeUnparenthesizedName;
|
||||
|
|
@ -219,6 +224,7 @@ class SyntaxParseHandler
|
|||
|
||||
Node newThisLiteral(const TokenPos& pos, Node thisName) { return NodeGeneric; }
|
||||
Node newNullLiteral(const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newRawUndefinedLiteral(const TokenPos& pos) { return NodeGeneric; }
|
||||
|
||||
template <class Boxer>
|
||||
Node newRegExp(RegExpObject* reobj, const TokenPos& pos, Boxer& boxer) { return NodeGeneric; }
|
||||
|
|
@ -235,6 +241,10 @@ class SyntaxParseHandler
|
|||
return NodeUnparenthesizedUnary;
|
||||
}
|
||||
|
||||
Node newNullary(ParseNodeKind kind, JSOp op, const TokenPos& pos) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
Node newUnary(ParseNodeKind kind, JSOp op, uint32_t begin, Node kid) {
|
||||
return NodeUnparenthesizedUnary;
|
||||
}
|
||||
|
|
@ -279,7 +289,7 @@ class SyntaxParseHandler
|
|||
Node newObjectLiteral(uint32_t begin) { return NodeUnparenthesizedObject; }
|
||||
Node newClassMethodList(uint32_t begin) { return NodeGeneric; }
|
||||
Node newClassNames(Node outer, Node inner, const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newClass(Node name, Node heritage, Node methodBlock) { return NodeGeneric; }
|
||||
Node newClass(Node name, Node heritage, Node methodBlock, const TokenPos& pos) { return NodeGeneric; }
|
||||
|
||||
Node newNewTarget(Node newHolder, Node targetHolder) { return NodeGeneric; }
|
||||
Node newPosHolder(const TokenPos& pos) { return NodeGeneric; }
|
||||
|
|
@ -288,6 +298,7 @@ class SyntaxParseHandler
|
|||
MOZ_MUST_USE bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
|
||||
MOZ_MUST_USE bool addPropertyDefinition(Node literal, Node name, Node expr) { return true; }
|
||||
MOZ_MUST_USE bool addShorthand(Node literal, Node name, Node expr) { return true; }
|
||||
MOZ_MUST_USE bool addSpreadProperty(Node literal, uint32_t begin, Node inner) { return true; }
|
||||
MOZ_MUST_USE bool addObjectMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
|
||||
MOZ_MUST_USE bool addClassMethodDefinition(Node literal, Node name, Node fn, JSOp op, bool isStatic) { return true; }
|
||||
Node newYieldExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; }
|
||||
|
|
@ -302,6 +313,16 @@ class SyntaxParseHandler
|
|||
MOZ_MUST_USE bool prependInitialYield(Node stmtList, Node gen) { return true; }
|
||||
Node newEmptyStatement(const TokenPos& pos) { return NodeEmptyStatement; }
|
||||
|
||||
Node newExportDeclaration(Node kid, const TokenPos& pos) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
Node newExportFromDeclaration(uint32_t begin, Node exportSpecSet, Node moduleSpec) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
Node newExportDefaultDeclaration(Node kid, Node maybeBinding, const TokenPos& pos) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
Node newSetThis(Node thisName, Node value) { return value; }
|
||||
|
||||
Node newExprStatement(Node expr, uint32_t end) {
|
||||
|
|
@ -497,7 +518,7 @@ class SyntaxParseHandler
|
|||
return NodeParenthesizedArgumentsName;
|
||||
if (node == NodeUnparenthesizedEvalName)
|
||||
return NodeParenthesizedEvalName;
|
||||
if (node == NodeUnparenthesizedName || node == NodeUnparenthesizedAsyncName)
|
||||
if (node == NodeUnparenthesizedName || node == NodePotentialAsyncKeyword)
|
||||
return NodeParenthesizedName;
|
||||
|
||||
if (node == NodeUnparenthesizedArray)
|
||||
|
|
@ -528,9 +549,9 @@ class SyntaxParseHandler
|
|||
|
||||
bool isUnparenthesizedName(Node node) {
|
||||
return node == NodeUnparenthesizedArgumentsName ||
|
||||
node == NodeUnparenthesizedAsyncName ||
|
||||
node == NodeUnparenthesizedEvalName ||
|
||||
node == NodeUnparenthesizedName;
|
||||
node == NodeUnparenthesizedName ||
|
||||
node == NodePotentialAsyncKeyword;
|
||||
}
|
||||
|
||||
bool isNameAnyParentheses(Node node) {
|
||||
|
|
@ -541,9 +562,11 @@ class SyntaxParseHandler
|
|||
node == NodeParenthesizedName;
|
||||
}
|
||||
|
||||
bool nameIsEvalAnyParentheses(Node node, ExclusiveContext* cx) {
|
||||
MOZ_ASSERT(isNameAnyParentheses(node),
|
||||
"must only call this function on known names");
|
||||
bool isArgumentsAnyParentheses(Node node, ExclusiveContext* cx) {
|
||||
return node == NodeUnparenthesizedArgumentsName || node == NodeParenthesizedArgumentsName;
|
||||
}
|
||||
|
||||
bool isEvalAnyParentheses(Node node, ExclusiveContext* cx) {
|
||||
return node == NodeUnparenthesizedEvalName || node == NodeParenthesizedEvalName;
|
||||
}
|
||||
|
||||
|
|
@ -551,17 +574,15 @@ class SyntaxParseHandler
|
|||
MOZ_ASSERT(isNameAnyParentheses(node),
|
||||
"must only call this method on known names");
|
||||
|
||||
if (nameIsEvalAnyParentheses(node, cx))
|
||||
if (isEvalAnyParentheses(node, cx))
|
||||
return js_eval_str;
|
||||
if (node == NodeUnparenthesizedArgumentsName || node == NodeParenthesizedArgumentsName)
|
||||
if (isArgumentsAnyParentheses(node, cx))
|
||||
return js_arguments_str;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool nameIsUnparenthesizedAsync(Node node, ExclusiveContext* cx) {
|
||||
MOZ_ASSERT(isNameAnyParentheses(node),
|
||||
"must only call this function on known names");
|
||||
return node == NodeUnparenthesizedAsyncName;
|
||||
bool isAsyncKeyword(Node node, ExclusiveContext* cx) {
|
||||
return node == NodePotentialAsyncKeyword;
|
||||
}
|
||||
|
||||
PropertyName* maybeDottedProperty(Node node) {
|
||||
|
|
|
|||
|
|
@ -81,9 +81,12 @@
|
|||
\
|
||||
macro(REGEXP, "regular expression literal") \
|
||||
macro(TRUE, "boolean literal 'true'") \
|
||||
range(RESERVED_WORD_LITERAL_FIRST, TRUE) \
|
||||
macro(FALSE, "boolean literal 'false'") \
|
||||
macro(NULL, "null literal") \
|
||||
range(RESERVED_WORD_LITERAL_LAST, NULL) \
|
||||
macro(THIS, "keyword 'this'") \
|
||||
range(KEYWORD_FIRST, THIS) \
|
||||
macro(FUNCTION, "keyword 'function'") \
|
||||
macro(IF, "keyword 'if'") \
|
||||
macro(ELSE, "keyword 'else'") \
|
||||
|
|
@ -106,16 +109,43 @@
|
|||
macro(FINALLY, "keyword 'finally'") \
|
||||
macro(THROW, "keyword 'throw'") \
|
||||
macro(DEBUGGER, "keyword 'debugger'") \
|
||||
macro(YIELD, "keyword 'yield'") \
|
||||
macro(AWAIT, "keyword 'await'") \
|
||||
macro(EXPORT, "keyword 'export'") \
|
||||
macro(IMPORT, "keyword 'import'") \
|
||||
macro(CLASS, "keyword 'class'") \
|
||||
macro(EXTENDS, "keyword 'extends'") \
|
||||
macro(SUPER, "keyword 'super'") \
|
||||
macro(RESERVED, "reserved keyword") \
|
||||
/* reserved keywords in strict mode */ \
|
||||
macro(STRICT_RESERVED, "reserved keyword") \
|
||||
range(KEYWORD_LAST, SUPER) \
|
||||
\
|
||||
/* contextual keywords */ \
|
||||
macro(AS, "'as'") \
|
||||
range(CONTEXTUAL_KEYWORD_FIRST, AS) \
|
||||
macro(ASYNC, "'async'") \
|
||||
macro(AWAIT, "'await'") \
|
||||
macro(EACH, "'each'") \
|
||||
macro(FROM, "'from'") \
|
||||
macro(GET, "'get'") \
|
||||
macro(LET, "'let'") \
|
||||
macro(OF, "'of'") \
|
||||
macro(SET, "'set'") \
|
||||
macro(STATIC, "'static'") \
|
||||
macro(TARGET, "'target'") \
|
||||
macro(YIELD, "'yield'") \
|
||||
range(CONTEXTUAL_KEYWORD_LAST, YIELD) \
|
||||
\
|
||||
/* future reserved words */ \
|
||||
macro(ENUM, "reserved word 'enum'") \
|
||||
range(FUTURE_RESERVED_KEYWORD_FIRST, ENUM) \
|
||||
range(FUTURE_RESERVED_KEYWORD_LAST, ENUM) \
|
||||
\
|
||||
/* reserved words in strict mode */ \
|
||||
macro(IMPLEMENTS, "reserved word 'implements'") \
|
||||
range(STRICT_RESERVED_KEYWORD_FIRST, IMPLEMENTS) \
|
||||
macro(INTERFACE, "reserved word 'interface'") \
|
||||
macro(PACKAGE, "reserved word 'package'") \
|
||||
macro(PRIVATE, "reserved word 'private'") \
|
||||
macro(PROTECTED, "reserved word 'protected'") \
|
||||
macro(PUBLIC, "reserved word 'public'") \
|
||||
range(STRICT_RESERVED_KEYWORD_LAST, PUBLIC) \
|
||||
\
|
||||
/* \
|
||||
* The following token types occupy contiguous ranges to enable easy \
|
||||
|
|
@ -149,7 +179,9 @@
|
|||
range(RELOP_LAST, GE) \
|
||||
\
|
||||
macro(INSTANCEOF, "keyword 'instanceof'") \
|
||||
range(KEYWORD_BINOP_FIRST, INSTANCEOF) \
|
||||
macro(IN, "keyword 'in'") \
|
||||
range(KEYWORD_BINOP_LAST, IN) \
|
||||
\
|
||||
/* Shift ops, per TokenKindIsShift. */ \
|
||||
macro(LSH, "'<<'") \
|
||||
|
|
@ -168,7 +200,9 @@
|
|||
\
|
||||
/* Unary operation tokens. */ \
|
||||
macro(TYPEOF, "keyword 'typeof'") \
|
||||
range(KEYWORD_UNOP_FIRST, TYPEOF) \
|
||||
macro(VOID, "keyword 'void'") \
|
||||
range(KEYWORD_UNOP_LAST, VOID) \
|
||||
macro(NOT, "'!'") \
|
||||
macro(BITNOT, "'~'") \
|
||||
\
|
||||
|
|
@ -239,6 +273,61 @@ TokenKindIsAssignment(TokenKind tt)
|
|||
return TOK_ASSIGNMENT_START <= tt && tt <= TOK_ASSIGNMENT_LAST;
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsKeyword(TokenKind tt)
|
||||
{
|
||||
return (TOK_KEYWORD_FIRST <= tt && tt <= TOK_KEYWORD_LAST) ||
|
||||
(TOK_KEYWORD_BINOP_FIRST <= tt && tt <= TOK_KEYWORD_BINOP_LAST) ||
|
||||
(TOK_KEYWORD_UNOP_FIRST <= tt && tt <= TOK_KEYWORD_UNOP_LAST);
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsContextualKeyword(TokenKind tt)
|
||||
{
|
||||
return TOK_CONTEXTUAL_KEYWORD_FIRST <= tt && tt <= TOK_CONTEXTUAL_KEYWORD_LAST;
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsFutureReservedWord(TokenKind tt)
|
||||
{
|
||||
return TOK_FUTURE_RESERVED_KEYWORD_FIRST <= tt && tt <= TOK_FUTURE_RESERVED_KEYWORD_LAST;
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsStrictReservedWord(TokenKind tt)
|
||||
{
|
||||
return TOK_STRICT_RESERVED_KEYWORD_FIRST <= tt && tt <= TOK_STRICT_RESERVED_KEYWORD_LAST;
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsReservedWordLiteral(TokenKind tt)
|
||||
{
|
||||
return TOK_RESERVED_WORD_LITERAL_FIRST <= tt && tt <= TOK_RESERVED_WORD_LITERAL_LAST;
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsReservedWord(TokenKind tt)
|
||||
{
|
||||
return TokenKindIsKeyword(tt) ||
|
||||
TokenKindIsFutureReservedWord(tt) ||
|
||||
TokenKindIsReservedWordLiteral(tt);
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsPossibleIdentifier(TokenKind tt)
|
||||
{
|
||||
return tt == TOK_NAME ||
|
||||
TokenKindIsContextualKeyword(tt) ||
|
||||
TokenKindIsStrictReservedWord(tt);
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsPossibleIdentifierName(TokenKind tt)
|
||||
{
|
||||
return TokenKindIsPossibleIdentifier(tt) ||
|
||||
TokenKindIsReservedWord(tt);
|
||||
}
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace js
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "frontend/TokenStream.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/IntegerTypeTraits.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
|
||||
|
|
@ -23,80 +24,81 @@
|
|||
#include "jsnum.h"
|
||||
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "frontend/ReservedWords.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "vm/HelperThreads.h"
|
||||
#include "vm/Keywords.h"
|
||||
#include "vm/StringBuffer.h"
|
||||
#include "vm/Unicode.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::frontend;
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
using mozilla::Maybe;
|
||||
using mozilla::PodAssign;
|
||||
using mozilla::PodCopy;
|
||||
using mozilla::PodZero;
|
||||
|
||||
struct KeywordInfo {
|
||||
const char* chars; // C string with keyword text
|
||||
struct ReservedWordInfo {
|
||||
const char* chars; // C string with reserved word text
|
||||
TokenKind tokentype;
|
||||
};
|
||||
|
||||
static const KeywordInfo keywords[] = {
|
||||
#define KEYWORD_INFO(keyword, name, type) \
|
||||
{js_##keyword##_str, type},
|
||||
FOR_EACH_JAVASCRIPT_KEYWORD(KEYWORD_INFO)
|
||||
#undef KEYWORD_INFO
|
||||
static const ReservedWordInfo reservedWords[] = {
|
||||
#define RESERVED_WORD_INFO(word, name, type) \
|
||||
{js_##word##_str, type},
|
||||
FOR_EACH_JAVASCRIPT_RESERVED_WORD(RESERVED_WORD_INFO)
|
||||
#undef RESERVED_WORD_INFO
|
||||
};
|
||||
|
||||
// Returns a KeywordInfo for the specified characters, or nullptr if the string
|
||||
// is not a keyword.
|
||||
// Returns a ReservedWordInfo for the specified characters, or nullptr if the
|
||||
// string is not a reserved word.
|
||||
template <typename CharT>
|
||||
static const KeywordInfo*
|
||||
FindKeyword(const CharT* s, size_t length)
|
||||
static const ReservedWordInfo*
|
||||
FindReservedWord(const CharT* s, size_t length)
|
||||
{
|
||||
MOZ_ASSERT(length != 0);
|
||||
|
||||
size_t i;
|
||||
const KeywordInfo* kw;
|
||||
const ReservedWordInfo* rw;
|
||||
const char* chars;
|
||||
|
||||
#define JSKW_LENGTH() length
|
||||
#define JSKW_AT(column) s[column]
|
||||
#define JSKW_GOT_MATCH(index) i = (index); goto got_match;
|
||||
#define JSKW_TEST_GUESS(index) i = (index); goto test_guess;
|
||||
#define JSKW_NO_MATCH() goto no_match;
|
||||
#include "jsautokw.h"
|
||||
#undef JSKW_NO_MATCH
|
||||
#undef JSKW_TEST_GUESS
|
||||
#undef JSKW_GOT_MATCH
|
||||
#undef JSKW_AT
|
||||
#undef JSKW_LENGTH
|
||||
#define JSRW_LENGTH() length
|
||||
#define JSRW_AT(column) s[column]
|
||||
#define JSRW_GOT_MATCH(index) i = (index); goto got_match;
|
||||
#define JSRW_TEST_GUESS(index) i = (index); goto test_guess;
|
||||
#define JSRW_NO_MATCH() goto no_match;
|
||||
#include "frontend/ReservedWordsGenerated.h"
|
||||
#undef JSRW_NO_MATCH
|
||||
#undef JSRW_TEST_GUESS
|
||||
#undef JSRW_GOT_MATCH
|
||||
#undef JSRW_AT
|
||||
#undef JSRW_LENGTH
|
||||
|
||||
got_match:
|
||||
return &keywords[i];
|
||||
return &reservedWords[i];
|
||||
|
||||
test_guess:
|
||||
kw = &keywords[i];
|
||||
chars = kw->chars;
|
||||
rw = &reservedWords[i];
|
||||
chars = rw->chars;
|
||||
do {
|
||||
if (*s++ != (unsigned char)(*chars++))
|
||||
goto no_match;
|
||||
} while (--length != 0);
|
||||
return kw;
|
||||
return rw;
|
||||
|
||||
no_match:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const KeywordInfo*
|
||||
FindKeyword(JSLinearString* str)
|
||||
static const ReservedWordInfo*
|
||||
FindReservedWord(JSLinearString* str)
|
||||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
return str->hasLatin1Chars()
|
||||
? FindKeyword(str->latin1Chars(nogc), str->length())
|
||||
: FindKeyword(str->twoByteChars(nogc), str->length());
|
||||
? FindReservedWord(str->latin1Chars(nogc), str->length())
|
||||
: FindReservedWord(str->twoByteChars(nogc), str->length());
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
|
|
@ -186,7 +188,68 @@ frontend::IsIdentifier(const char16_t* chars, size_t length)
|
|||
bool
|
||||
frontend::IsKeyword(JSLinearString* str)
|
||||
{
|
||||
return FindKeyword(str) != nullptr;
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str))
|
||||
return TokenKindIsKeyword(rw->tokentype);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::IsFutureReservedWord(JSLinearString* str)
|
||||
{
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str))
|
||||
return TokenKindIsFutureReservedWord(rw->tokentype);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::IsStrictReservedWord(JSLinearString* str)
|
||||
{
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str))
|
||||
return TokenKindIsStrictReservedWord(rw->tokentype);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::IsReservedWordLiteral(JSLinearString* str)
|
||||
{
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str))
|
||||
return TokenKindIsReservedWordLiteral(rw->tokentype);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char*
|
||||
frontend::ReservedWordToCharZ(PropertyName* str)
|
||||
{
|
||||
const ReservedWordInfo* rw = FindReservedWord(str);
|
||||
if (rw == nullptr)
|
||||
return nullptr;
|
||||
|
||||
switch (rw->tokentype) {
|
||||
#define EMIT_CASE(word, name, type) case type: return js_##word##_str;
|
||||
FOR_EACH_JAVASCRIPT_RESERVED_WORD(EMIT_CASE)
|
||||
#undef EMIT_CASE
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Not a reserved word PropertyName.");
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PropertyName*
|
||||
TokenStream::reservedWordToPropertyName(TokenKind tt) const
|
||||
{
|
||||
MOZ_ASSERT(tt != TOK_NAME);
|
||||
switch (tt) {
|
||||
#define EMIT_CASE(word, name, type) case type: return cx->names().name;
|
||||
FOR_EACH_JAVASCRIPT_RESERVED_WORD(EMIT_CASE)
|
||||
#undef EMIT_CASE
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Not a reserved word TokenKind.");
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TokenStream::SourceCoords::SourceCoords(ExclusiveContext* cx, uint32_t ln)
|
||||
|
|
@ -223,8 +286,13 @@ TokenStream::SourceCoords::add(uint32_t lineNum, uint32_t lineStartOffset)
|
|||
// only if lineStartOffsets_.append succeeds, to keep sentinel.
|
||||
// Otherwise return false to tell TokenStream about OOM.
|
||||
uint32_t maxPtr = MAX_PTR;
|
||||
if (!lineStartOffsets_.append(maxPtr))
|
||||
if (!lineStartOffsets_.append(maxPtr)) {
|
||||
static_assert(mozilla::IsSame<decltype(lineStartOffsets_.allocPolicy()),
|
||||
TempAllocPolicy&>::value,
|
||||
"this function's caller depends on it reporting an "
|
||||
"error on failure, as TempAllocPolicy ensures");
|
||||
return false;
|
||||
}
|
||||
|
||||
lineStartOffsets_[lineIndex] = lineStartOffset;
|
||||
} else {
|
||||
|
|
@ -554,8 +622,9 @@ TokenStream::advance(size_t position)
|
|||
MOZ_MAKE_MEM_UNDEFINED(&cur->type, sizeof(cur->type));
|
||||
lookahead = 0;
|
||||
|
||||
if (flags.hitOOM)
|
||||
return reportError(JSMSG_OUT_OF_MEMORY);
|
||||
if (flags.hitOOM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -599,8 +668,8 @@ TokenStream::seek(const Position& pos, const TokenStream& other)
|
|||
}
|
||||
|
||||
bool
|
||||
TokenStream::reportStrictModeErrorNumberVA(uint32_t offset, bool strictMode, unsigned errorNumber,
|
||||
va_list args)
|
||||
TokenStream::reportStrictModeErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset,
|
||||
bool strictMode, unsigned errorNumber, va_list args)
|
||||
{
|
||||
// In strict mode code, this is an error, not merely a warning.
|
||||
unsigned flags;
|
||||
|
|
@ -611,7 +680,7 @@ TokenStream::reportStrictModeErrorNumberVA(uint32_t offset, bool strictMode, uns
|
|||
else
|
||||
return true;
|
||||
|
||||
return reportCompileErrorNumberVA(offset, flags, errorNumber, args);
|
||||
return reportCompileErrorNumberVA(Move(notes), offset, flags, errorNumber, args);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -637,8 +706,8 @@ CompileError::throwError(JSContext* cx)
|
|||
}
|
||||
|
||||
bool
|
||||
TokenStream::reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigned errorNumber,
|
||||
va_list args)
|
||||
TokenStream::reportCompileErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset,
|
||||
unsigned flags, unsigned errorNumber, va_list args)
|
||||
{
|
||||
bool warning = JSREPORT_IS_WARNING(flags);
|
||||
|
||||
|
|
@ -655,6 +724,7 @@ TokenStream::reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigne
|
|||
return false;
|
||||
CompileError& err = *tempErrPtr;
|
||||
|
||||
err.notes = Move(notes);
|
||||
err.flags = flags;
|
||||
err.errorNumber = errorNumber;
|
||||
err.filename = filename;
|
||||
|
|
@ -746,7 +816,7 @@ TokenStream::reportStrictModeError(unsigned errorNumber, ...)
|
|||
{
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
bool result = reportStrictModeErrorNumberVA(currentToken().pos.begin, strictMode(),
|
||||
bool result = reportStrictModeErrorNumberVA(nullptr, currentToken().pos.begin, strictMode(),
|
||||
errorNumber, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
|
|
@ -757,8 +827,8 @@ TokenStream::reportError(unsigned errorNumber, ...)
|
|||
{
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
bool result = reportCompileErrorNumberVA(currentToken().pos.begin, JSREPORT_ERROR, errorNumber,
|
||||
args);
|
||||
bool result = reportCompileErrorNumberVA(nullptr, currentToken().pos.begin, JSREPORT_ERROR,
|
||||
errorNumber, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -768,30 +838,32 @@ TokenStream::reportErrorNoOffset(unsigned errorNumber, ...)
|
|||
{
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
bool result = reportCompileErrorNumberVA(NoOffset, JSREPORT_ERROR, errorNumber,
|
||||
args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
TokenStream::reportWarning(unsigned errorNumber, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
bool result = reportCompileErrorNumberVA(currentToken().pos.begin, JSREPORT_WARNING,
|
||||
bool result = reportCompileErrorNumberVA(nullptr, NoOffset, JSREPORT_ERROR,
|
||||
errorNumber, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
TokenStream::reportExtraWarningErrorNumberVA(uint32_t offset, unsigned errorNumber, va_list args)
|
||||
TokenStream::warning(unsigned errorNumber, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
bool result = reportCompileErrorNumberVA(nullptr, currentToken().pos.begin, JSREPORT_WARNING,
|
||||
errorNumber, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
TokenStream::reportExtraWarningErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset,
|
||||
unsigned errorNumber, va_list args)
|
||||
{
|
||||
if (!options().extraWarningsOption)
|
||||
return true;
|
||||
|
||||
return reportCompileErrorNumberVA(offset, JSREPORT_STRICT|JSREPORT_WARNING, errorNumber, args);
|
||||
return reportCompileErrorNumberVA(Move(notes), offset, JSREPORT_STRICT|JSREPORT_WARNING,
|
||||
errorNumber, args);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -802,7 +874,34 @@ TokenStream::reportAsmJSError(uint32_t offset, unsigned errorNumber, ...)
|
|||
unsigned flags = options().throwOnAsmJSValidationFailureOption
|
||||
? JSREPORT_ERROR
|
||||
: JSREPORT_WARNING;
|
||||
reportCompileErrorNumberVA(offset, flags, errorNumber, args);
|
||||
reportCompileErrorNumberVA(nullptr, offset, flags, errorNumber, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
TokenStream::error(unsigned errorNumber, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
#ifdef DEBUG
|
||||
bool result =
|
||||
#endif
|
||||
reportCompileErrorNumberVA(nullptr, currentToken().pos.begin, JSREPORT_ERROR,
|
||||
errorNumber, args);
|
||||
MOZ_ASSERT(!result, "reporting an error returned true?");
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
TokenStream::errorAt(uint32_t offset, unsigned errorNumber, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
#ifdef DEBUG
|
||||
bool result =
|
||||
#endif
|
||||
reportCompileErrorNumberVA(nullptr, offset, JSREPORT_ERROR, errorNumber, args);
|
||||
MOZ_ASSERT(!result, "reporting an error returned true?");
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
|
@ -934,34 +1033,49 @@ TokenStream::getDirectives(bool isMultiline, bool shouldWarnDeprecated)
|
|||
|
||||
bool
|
||||
TokenStream::getDirective(bool isMultiline, bool shouldWarnDeprecated,
|
||||
const char* directive, int directiveLength,
|
||||
const char* directive, uint8_t directiveLength,
|
||||
const char* errorMsgPragma,
|
||||
UniqueTwoByteChars* destination)
|
||||
{
|
||||
MOZ_ASSERT(directiveLength <= 18);
|
||||
char16_t peeked[18];
|
||||
int32_t c;
|
||||
|
||||
if (peekChars(directiveLength, peeked) && CharsMatch(peeked, directive)) {
|
||||
if (shouldWarnDeprecated &&
|
||||
!reportWarning(JSMSG_DEPRECATED_PRAGMA, errorMsgPragma))
|
||||
return false;
|
||||
if (shouldWarnDeprecated) {
|
||||
if (!warning(JSMSG_DEPRECATED_PRAGMA, errorMsgPragma))
|
||||
return false;
|
||||
}
|
||||
|
||||
skipChars(directiveLength);
|
||||
tokenbuf.clear();
|
||||
|
||||
while ((c = peekChar()) && c != EOF && !unicode::IsSpaceOrBOM2(c)) {
|
||||
getChar();
|
||||
do {
|
||||
int32_t c;
|
||||
if (!peekChar(&c))
|
||||
return false;
|
||||
|
||||
if (c == EOF || unicode::IsSpaceOrBOM2(c))
|
||||
break;
|
||||
|
||||
consumeKnownChar(c);
|
||||
|
||||
// Debugging directives can occur in both single- and multi-line
|
||||
// comments. If we're currently inside a multi-line comment, we also
|
||||
// need to recognize multi-line comment terminators.
|
||||
if (isMultiline && c == '*' && peekChar() == '/') {
|
||||
ungetChar('*');
|
||||
break;
|
||||
if (isMultiline && c == '*') {
|
||||
int32_t c2;
|
||||
if (!peekChar(&c2))
|
||||
return false;
|
||||
|
||||
if (c2 == '/') {
|
||||
ungetChar('*');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tokenbuf.append(c))
|
||||
return false;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
if (tokenbuf.empty()) {
|
||||
// The directive's URL was missing, but this is not quite an
|
||||
|
|
@ -993,7 +1107,10 @@ TokenStream::getDisplayURL(bool isMultiline, bool shouldWarnDeprecated)
|
|||
// developer would like to refer to the source as from the source's actual
|
||||
// URL.
|
||||
|
||||
return getDirective(isMultiline, shouldWarnDeprecated, " sourceURL=", 11,
|
||||
static const char sourceURLDirective[] = " sourceURL=";
|
||||
constexpr uint8_t sourceURLDirectiveLength = ArrayLength(sourceURLDirective) - 1;
|
||||
return getDirective(isMultiline, shouldWarnDeprecated,
|
||||
sourceURLDirective, sourceURLDirectiveLength,
|
||||
"sourceURL", &displayURL_);
|
||||
}
|
||||
|
||||
|
|
@ -1003,7 +1120,10 @@ TokenStream::getSourceMappingURL(bool isMultiline, bool shouldWarnDeprecated)
|
|||
// Match comments of the form "//# sourceMappingURL=<url>" or
|
||||
// "/\* //# sourceMappingURL=<url> *\/"
|
||||
|
||||
return getDirective(isMultiline, shouldWarnDeprecated, " sourceMappingURL=", 18,
|
||||
static const char sourceMappingURLDirective[] = " sourceMappingURL=";
|
||||
constexpr uint8_t sourceMappingURLDirectiveLength = ArrayLength(sourceMappingURLDirective) - 1;
|
||||
return getDirective(isMultiline, shouldWarnDeprecated,
|
||||
sourceMappingURLDirective, sourceMappingURLDirectiveLength,
|
||||
"sourceMappingURL", &sourceMapURL_);
|
||||
}
|
||||
|
||||
|
|
@ -1110,36 +1230,6 @@ TokenStream::putIdentInTokenbuf(const char16_t* identStart)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TokenStream::checkForKeyword(const KeywordInfo* kw, TokenKind* ttp)
|
||||
{
|
||||
if (!awaitIsKeyword && kw->tokentype == TOK_AWAIT) {
|
||||
if (ttp)
|
||||
*ttp = TOK_NAME;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (kw->tokentype == TOK_RESERVED)
|
||||
return reportError(JSMSG_RESERVED_ID, kw->chars);
|
||||
|
||||
if (kw->tokentype == TOK_STRICT_RESERVED)
|
||||
return reportStrictModeError(JSMSG_RESERVED_ID, kw->chars);
|
||||
|
||||
// Working keyword.
|
||||
*ttp = kw->tokentype;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TokenStream::checkForKeyword(JSAtom* atom, TokenKind* ttp)
|
||||
{
|
||||
const KeywordInfo* kw = FindKeyword(atom);
|
||||
if (!kw)
|
||||
return true;
|
||||
|
||||
return checkForKeyword(kw, ttp);
|
||||
}
|
||||
|
||||
enum FirstCharKind {
|
||||
// A char16_t has the 'OneChar' kind if it, by itself, constitutes a valid
|
||||
// token that cannot also be a prefix of a longer token. E.g. ';' has the
|
||||
|
|
@ -1363,36 +1453,18 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
length = userbuf.addressOfNextRawChar() - identStart;
|
||||
}
|
||||
|
||||
// Represent keywords as keyword tokens unless told otherwise.
|
||||
if (modifier != KeywordIsName) {
|
||||
if (const KeywordInfo* kw = FindKeyword(chars, length)) {
|
||||
// That said, keywords can't contain escapes. (Contexts where
|
||||
// keywords are treated as names, that also sometimes treat
|
||||
// keywords as keywords, must manually check this requirement.)
|
||||
// There are two exceptions
|
||||
// 1) StrictReservedWords: These keywords need to be treated as
|
||||
// names in non-strict mode.
|
||||
// 2) yield is also treated as a name if it contains an escape
|
||||
// sequence. The parser must handle this case separately.
|
||||
if (hadUnicodeEscape && !(
|
||||
(kw->tokentype == TOK_STRICT_RESERVED && !strictMode()) ||
|
||||
kw->tokentype == TOK_YIELD))
|
||||
{
|
||||
reportError(JSMSG_ESCAPED_KEYWORD);
|
||||
goto error;
|
||||
}
|
||||
|
||||
tp->type = TOK_NAME;
|
||||
if (!checkForKeyword(kw, &tp->type))
|
||||
goto error;
|
||||
if (tp->type != TOK_NAME && !hadUnicodeEscape)
|
||||
goto out;
|
||||
// Represent reserved words as reserved word tokens.
|
||||
if (!hadUnicodeEscape) {
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(chars, length)) {
|
||||
tp->type = rw->tokentype;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
JSAtom* atom = AtomizeChars(cx, chars, length);
|
||||
if (!atom)
|
||||
if (!atom) {
|
||||
goto error;
|
||||
}
|
||||
tp->type = TOK_NAME;
|
||||
tp->setName(atom->asPropertyName());
|
||||
goto out;
|
||||
|
|
@ -1538,10 +1610,11 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
// grammar. We might not always be so permissive, so we warn
|
||||
// about it.
|
||||
if (c >= '8') {
|
||||
if (!reportWarning(JSMSG_BAD_OCTAL, c == '8' ? "08" : "09")) {
|
||||
if (!warning(JSMSG_BAD_OCTAL, c == '8' ? "08" : "09"))
|
||||
goto error;
|
||||
}
|
||||
goto decimal; // use the decimal scanner for the rest of the number
|
||||
|
||||
// Use the decimal scanner for the rest of the number.
|
||||
goto decimal;
|
||||
}
|
||||
c = getCharIgnoreEOL();
|
||||
}
|
||||
|
|
@ -1690,7 +1763,8 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
case '/':
|
||||
// Look for a single-line comment.
|
||||
if (matchChar('/')) {
|
||||
c = peekChar();
|
||||
if (!peekChar(&c))
|
||||
goto error;
|
||||
if (c == '@' || c == '#') {
|
||||
bool shouldWarn = getChar() == '@';
|
||||
if (!getDirectives(false, shouldWarn))
|
||||
|
|
@ -1757,7 +1831,8 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
RegExpFlag reflags = NoFlags;
|
||||
unsigned length = tokenbuf.length() + 1;
|
||||
while (true) {
|
||||
c = peekChar();
|
||||
if (!peekChar(&c))
|
||||
goto error;
|
||||
if (c == 'g' && !(reflags & GlobalFlag))
|
||||
reflags = RegExpFlag(reflags | GlobalFlag);
|
||||
else if (c == 'i' && !(reflags & IgnoreCaseFlag))
|
||||
|
|
@ -1774,7 +1849,8 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
length++;
|
||||
}
|
||||
|
||||
c = peekChar();
|
||||
if (!peekChar(&c))
|
||||
goto error;
|
||||
if (JS7_ISLET(c)) {
|
||||
char buf[2] = { '\0', '\0' };
|
||||
tp->pos.begin += length + 1;
|
||||
|
|
@ -1797,8 +1873,13 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
|
||||
case '-':
|
||||
if (matchChar('-')) {
|
||||
if (peekChar() == '>' && !flags.isDirtyLine)
|
||||
int32_t c2;
|
||||
if (!peekChar(&c2))
|
||||
goto error;
|
||||
|
||||
if (c2 == '>' && !flags.isDirtyLine)
|
||||
goto skipline;
|
||||
|
||||
tp->type = TOK_DEC;
|
||||
} else {
|
||||
tp->type = matchChar('=') ? TOK_SUBASSIGN : TOK_SUB;
|
||||
|
|
@ -1814,8 +1895,9 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
MOZ_CRASH("should have jumped to |out| or |error|");
|
||||
|
||||
out:
|
||||
if (flags.hitOOM)
|
||||
return reportError(JSMSG_OUT_OF_MEMORY);
|
||||
if (flags.hitOOM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
flags.isDirtyLine = true;
|
||||
tp->pos.end = userbuf.offset();
|
||||
|
|
@ -1831,8 +1913,9 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
return true;
|
||||
|
||||
error:
|
||||
if (flags.hitOOM)
|
||||
return reportError(JSMSG_OUT_OF_MEMORY);
|
||||
if (flags.hitOOM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
flags.isDirtyLine = true;
|
||||
tp->pos.end = userbuf.offset();
|
||||
|
|
@ -1849,37 +1932,6 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
TokenStream::getBracedUnicode(uint32_t* cp)
|
||||
{
|
||||
consumeKnownChar('{');
|
||||
|
||||
bool first = true;
|
||||
int32_t c;
|
||||
uint32_t code = 0;
|
||||
while (true) {
|
||||
c = getCharIgnoreEOL();
|
||||
if (c == EOF)
|
||||
return false;
|
||||
if (c == '}') {
|
||||
if (first)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!JS7_ISHEX(c))
|
||||
return false;
|
||||
|
||||
code = (code << 4) | JS7_UNHEX(c);
|
||||
if (code > unicode::NonBMPMax)
|
||||
return false;
|
||||
first = false;
|
||||
}
|
||||
|
||||
*cp = code;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
|
||||
{
|
||||
|
|
@ -1897,11 +1949,15 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
|
|||
while ((c = getCharIgnoreEOL()) != untilChar) {
|
||||
if (c == EOF) {
|
||||
ungetCharIgnoreEOL(c);
|
||||
reportError(JSMSG_UNTERMINATED_STRING);
|
||||
error(JSMSG_UNTERMINATED_STRING);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c == '\\') {
|
||||
// When parsing templates, we don't immediately report errors for
|
||||
// invalid escapes; these are handled by the parser.
|
||||
// In those cases we don't append to tokenbuf, since it won't be
|
||||
// read.
|
||||
switch (c = getChar()) {
|
||||
case 'b': c = '\b'; break;
|
||||
case 'f': c = '\f'; break;
|
||||
|
|
@ -1917,12 +1973,73 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
|
|||
|
||||
// Unicode character specification.
|
||||
case 'u': {
|
||||
if (peekChar() == '{') {
|
||||
uint32_t code;
|
||||
if (!getBracedUnicode(&code)) {
|
||||
reportError(JSMSG_MALFORMED_ESCAPE, "Unicode");
|
||||
return false;
|
||||
}
|
||||
uint32_t code = 0;
|
||||
|
||||
int32_t c2;
|
||||
if (!peekChar(&c2))
|
||||
return false;
|
||||
|
||||
uint32_t start = userbuf.offset() - 2;
|
||||
|
||||
if (c2 == '{') {
|
||||
consumeKnownChar('{');
|
||||
|
||||
bool first = true;
|
||||
bool valid = true;
|
||||
do {
|
||||
int32_t c = getCharIgnoreEOL();
|
||||
if (c == EOF) {
|
||||
if (parsingTemplate) {
|
||||
setInvalidTemplateEscape(start, InvalidEscapeType::Unicode);
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
reportInvalidEscapeError(start, InvalidEscapeType::Unicode);
|
||||
return false;
|
||||
}
|
||||
if (c == '}') {
|
||||
if (first) {
|
||||
if (parsingTemplate) {
|
||||
setInvalidTemplateEscape(start, InvalidEscapeType::Unicode);
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
reportInvalidEscapeError(start, InvalidEscapeType::Unicode);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!JS7_ISHEX(c)) {
|
||||
if (parsingTemplate) {
|
||||
// We put the character back so that we read
|
||||
// it on the next pass, which matters if it
|
||||
// was '`' or '\'.
|
||||
ungetCharIgnoreEOL(c);
|
||||
setInvalidTemplateEscape(start, InvalidEscapeType::Unicode);
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
reportInvalidEscapeError(start, InvalidEscapeType::Unicode);
|
||||
return false;
|
||||
}
|
||||
|
||||
code = (code << 4) | JS7_UNHEX(c);
|
||||
if (code > unicode::NonBMPMax) {
|
||||
if (parsingTemplate) {
|
||||
setInvalidTemplateEscape(start + 3, InvalidEscapeType::UnicodeOverflow);
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
reportInvalidEscapeError(start + 3, InvalidEscapeType::UnicodeOverflow);
|
||||
return false;
|
||||
}
|
||||
|
||||
first = false;
|
||||
} while (true);
|
||||
|
||||
if (!valid)
|
||||
continue;
|
||||
|
||||
MOZ_ASSERT(code <= unicode::NonBMPMax);
|
||||
if (code < unicode::NonBMPMin) {
|
||||
|
|
@ -1945,7 +2062,11 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
|
|||
c = (c << 4) + JS7_UNHEX(cp[3]);
|
||||
skipChars(4);
|
||||
} else {
|
||||
reportError(JSMSG_MALFORMED_ESCAPE, "Unicode");
|
||||
if (parsingTemplate) {
|
||||
setInvalidTemplateEscape(start, InvalidEscapeType::Unicode);
|
||||
continue;
|
||||
}
|
||||
reportInvalidEscapeError(start, InvalidEscapeType::Unicode);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1958,7 +2079,12 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
|
|||
c = (JS7_UNHEX(cp[0]) << 4) + JS7_UNHEX(cp[1]);
|
||||
skipChars(2);
|
||||
} else {
|
||||
reportError(JSMSG_MALFORMED_ESCAPE, "hexadecimal");
|
||||
uint32_t start = userbuf.offset() - 2;
|
||||
if (parsingTemplate) {
|
||||
setInvalidTemplateEscape(start, InvalidEscapeType::Hexadecimal);
|
||||
continue;
|
||||
}
|
||||
reportInvalidEscapeError(start, InvalidEscapeType::Hexadecimal);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1969,13 +2095,14 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
|
|||
if (JS7_ISOCT(c)) {
|
||||
int32_t val = JS7_UNOCT(c);
|
||||
|
||||
c = peekChar();
|
||||
if (!peekChar(&c))
|
||||
return false;
|
||||
|
||||
// Strict mode code allows only \0, then a non-digit.
|
||||
if (val != 0 || JS7_ISDEC(c)) {
|
||||
if (parsingTemplate) {
|
||||
reportError(JSMSG_DEPRECATED_OCTAL);
|
||||
return false;
|
||||
setInvalidTemplateEscape(userbuf.offset() - 2, InvalidEscapeType::Octal);
|
||||
continue;
|
||||
}
|
||||
if (!reportStrictModeError(JSMSG_DEPRECATED_OCTAL))
|
||||
return false;
|
||||
|
|
@ -1985,7 +2112,8 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
|
|||
if (JS7_ISOCT(c)) {
|
||||
val = 8 * val + JS7_UNOCT(c);
|
||||
getChar();
|
||||
c = peekChar();
|
||||
if (!peekChar(&c))
|
||||
return false;
|
||||
if (JS7_ISOCT(c)) {
|
||||
int32_t save = val;
|
||||
val = 8 * val + JS7_UNOCT(c);
|
||||
|
|
@ -2003,7 +2131,7 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
|
|||
} else if (TokenBuf::isRawEOLChar(c)) {
|
||||
if (!parsingTemplate) {
|
||||
ungetCharIgnoreEOL(c);
|
||||
reportError(JSMSG_UNTERMINATED_STRING);
|
||||
error(JSMSG_UNTERMINATED_STRING);
|
||||
return false;
|
||||
}
|
||||
if (c == '\r') {
|
||||
|
|
|
|||
|
|
@ -26,14 +26,13 @@
|
|||
#include "js/UniquePtr.h"
|
||||
#include "js/Vector.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
#include "vm/String.h"
|
||||
|
||||
struct KeywordInfo;
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
class AutoAwaitIsKeyword;
|
||||
|
||||
struct TokenPos {
|
||||
uint32_t begin; // Offset of the token's first char.
|
||||
uint32_t end; // Offset of 1 past the token's last char.
|
||||
|
|
@ -80,6 +79,20 @@ struct TokenPos {
|
|||
|
||||
enum DecimalPoint { NoDecimal = false, HasDecimal = true };
|
||||
|
||||
enum class InvalidEscapeType {
|
||||
// No invalid character escapes.
|
||||
None,
|
||||
// A malformed \x escape.
|
||||
Hexadecimal,
|
||||
// A malformed \u escape.
|
||||
Unicode,
|
||||
// An otherwise well-formed \u escape which represents a
|
||||
// codepoint > 10FFFF.
|
||||
UnicodeOverflow,
|
||||
// An octal escape in a template token.
|
||||
Octal
|
||||
};
|
||||
|
||||
class TokenStream;
|
||||
|
||||
struct Token
|
||||
|
|
@ -106,9 +119,6 @@ struct Token
|
|||
// 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
|
||||
|
|
@ -150,10 +160,6 @@ struct Token
|
|||
// If a semicolon is inserted automatically, the next token is already
|
||||
// gotten with None, but we expect Operand.
|
||||
OperandIsNone,
|
||||
|
||||
// If name of method definition is `get` or `set`, the next token is
|
||||
// already gotten with KeywordIsName, but we expect None.
|
||||
NoneIsKeywordIsName,
|
||||
};
|
||||
friend class TokenStream;
|
||||
|
||||
|
|
@ -210,11 +216,6 @@ struct Token
|
|||
return u.name->JSAtom::asPropertyName(); // poor-man's type verification
|
||||
}
|
||||
|
||||
bool nameContainsEscape() const {
|
||||
PropertyName* n = name();
|
||||
return pos.begin + n->length() != pos.end;
|
||||
}
|
||||
|
||||
JSAtom* atom() const {
|
||||
MOZ_ASSERT(type == TOK_STRING ||
|
||||
type == TOK_TEMPLATE_HEAD ||
|
||||
|
|
@ -240,10 +241,22 @@ struct Token
|
|||
};
|
||||
|
||||
class CompileError : public JSErrorReport {
|
||||
public:
|
||||
public:
|
||||
void throwError(JSContext* cx);
|
||||
};
|
||||
|
||||
extern const char*
|
||||
ReservedWordToCharZ(PropertyName* str);
|
||||
|
||||
extern MOZ_MUST_USE bool
|
||||
IsFutureReservedWord(JSLinearString* str);
|
||||
|
||||
extern MOZ_MUST_USE bool
|
||||
IsReservedWordLiteral(JSLinearString* str);
|
||||
|
||||
extern MOZ_MUST_USE bool
|
||||
IsStrictReservedWord(JSLinearString* str);
|
||||
|
||||
// Ideally, tokenizing would be entirely independent of context. But the
|
||||
// strict mode flag, which is in SharedContext, affects tokenizing, and
|
||||
// TokenStream needs to see it.
|
||||
|
|
@ -330,25 +343,26 @@ class MOZ_STACK_CLASS TokenStream
|
|||
JSVersion versionNumber() const { return VersionNumber(options().version); }
|
||||
JSVersion versionWithFlags() const { return options().version; }
|
||||
|
||||
private:
|
||||
PropertyName* reservedWordToPropertyName(TokenKind tt) const;
|
||||
|
||||
public:
|
||||
PropertyName* currentName() const {
|
||||
if (isCurrentTokenType(TOK_YIELD))
|
||||
return cx->names().yield;
|
||||
MOZ_ASSERT(isCurrentTokenType(TOK_NAME));
|
||||
return currentToken().name();
|
||||
if (isCurrentTokenType(TOK_NAME)) {
|
||||
return currentToken().name();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(TokenKindIsPossibleIdentifierName(currentToken().type));
|
||||
return reservedWordToPropertyName(currentToken().type);
|
||||
}
|
||||
|
||||
PropertyName* nextName() const {
|
||||
if (nextToken().type == TOK_YIELD)
|
||||
return cx->names().yield;
|
||||
MOZ_ASSERT(nextToken().type == TOK_NAME);
|
||||
return nextToken().name();
|
||||
}
|
||||
if (nextToken().type != TOK_NAME) {
|
||||
return nextToken().name();
|
||||
}
|
||||
|
||||
bool nextNameContainsEscape() const {
|
||||
if (nextToken().type == TOK_YIELD)
|
||||
return false;
|
||||
MOZ_ASSERT(nextToken().type == TOK_NAME);
|
||||
return nextToken().nameContainsEscape();
|
||||
MOZ_ASSERT(TokenKindIsPossibleIdentifierName(nextToken().type));
|
||||
return reservedWordToPropertyName(nextToken().type);
|
||||
}
|
||||
|
||||
bool isCurrentTokenAssignment() const {
|
||||
|
|
@ -361,21 +375,47 @@ class MOZ_STACK_CLASS TokenStream
|
|||
bool hadError() const { return flags.hadError; }
|
||||
void clearSawOctalEscape() { flags.sawOctalEscape = false; }
|
||||
|
||||
bool hasInvalidTemplateEscape() const {
|
||||
return invalidTemplateEscapeType != InvalidEscapeType::None;
|
||||
}
|
||||
void clearInvalidTemplateEscape() {
|
||||
invalidTemplateEscapeType = InvalidEscapeType::None;
|
||||
}
|
||||
|
||||
// If there is an invalid escape in a template, report it and return false,
|
||||
// otherwise return true.
|
||||
bool checkForInvalidTemplateEscapeError() {
|
||||
if (invalidTemplateEscapeType == InvalidEscapeType::None)
|
||||
return true;
|
||||
|
||||
reportInvalidEscapeError(invalidTemplateEscapeOffset, invalidTemplateEscapeType);
|
||||
return false;
|
||||
}
|
||||
|
||||
// TokenStream-specific error reporters.
|
||||
bool reportError(unsigned errorNumber, ...);
|
||||
bool reportErrorNoOffset(unsigned errorNumber, ...);
|
||||
bool reportWarning(unsigned errorNumber, ...);
|
||||
|
||||
// Report the given error at the current offset.
|
||||
void error(unsigned errorNumber, ...);
|
||||
|
||||
// Report the given error at the given offset.
|
||||
void errorAt(uint32_t offset, unsigned errorNumber, ...);
|
||||
|
||||
// Warn at the current offset.
|
||||
MOZ_MUST_USE bool warning(unsigned errorNumber, ...);
|
||||
|
||||
static const uint32_t NoOffset = UINT32_MAX;
|
||||
|
||||
// General-purpose error reporters. You should avoid calling these
|
||||
// directly, and instead use the more succinct alternatives (e.g.
|
||||
// reportError()) in TokenStream, Parser, and BytecodeEmitter.
|
||||
bool reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigned errorNumber,
|
||||
va_list args);
|
||||
bool reportStrictModeErrorNumberVA(uint32_t offset, bool strictMode, unsigned errorNumber,
|
||||
va_list args);
|
||||
bool reportExtraWarningErrorNumberVA(uint32_t offset, unsigned errorNumber, va_list args);
|
||||
// directly, and instead use the more succinct alternatives (error(),
|
||||
// warning(), &c.) in TokenStream, Parser, and BytecodeEmitter.
|
||||
bool reportCompileErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset, unsigned flags,
|
||||
unsigned errorNumber, va_list args);
|
||||
bool reportStrictModeErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset,
|
||||
bool strictMode, unsigned errorNumber, va_list args);
|
||||
bool reportExtraWarningErrorNumberVA(UniquePtr<JSErrorNotes> notes, uint32_t offset,
|
||||
unsigned errorNumber, va_list args);
|
||||
|
||||
// asm.js reporter
|
||||
void reportAsmJSError(uint32_t offset, unsigned errorNumber, ...);
|
||||
|
|
@ -414,6 +454,33 @@ class MOZ_STACK_CLASS TokenStream
|
|||
bool reportStrictModeError(unsigned errorNumber, ...);
|
||||
bool strictMode() const { return strictModeGetter && strictModeGetter->strictMode(); }
|
||||
|
||||
void setInvalidTemplateEscape(uint32_t offset, InvalidEscapeType type) {
|
||||
MOZ_ASSERT(type != InvalidEscapeType::None);
|
||||
if (invalidTemplateEscapeType != InvalidEscapeType::None)
|
||||
return;
|
||||
invalidTemplateEscapeOffset = offset;
|
||||
invalidTemplateEscapeType = type;
|
||||
}
|
||||
void reportInvalidEscapeError(uint32_t offset, InvalidEscapeType type) {
|
||||
switch (type) {
|
||||
case InvalidEscapeType::None:
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected InvalidEscapeType");
|
||||
return;
|
||||
case InvalidEscapeType::Hexadecimal:
|
||||
errorAt(offset, JSMSG_MALFORMED_ESCAPE, "hexadecimal");
|
||||
return;
|
||||
case InvalidEscapeType::Unicode:
|
||||
errorAt(offset, JSMSG_MALFORMED_ESCAPE, "Unicode");
|
||||
return;
|
||||
case InvalidEscapeType::UnicodeOverflow:
|
||||
errorAt(offset, JSMSG_UNICODE_OVERFLOW, "escape sequence");
|
||||
return;
|
||||
case InvalidEscapeType::Octal:
|
||||
errorAt(offset, JSMSG_DEPRECATED_OCTAL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static JSAtom* atomize(ExclusiveContext* cx, CharBuffer& cb);
|
||||
MOZ_MUST_USE bool putIdentInTokenbuf(const char16_t* identStart);
|
||||
|
||||
|
|
@ -431,21 +498,19 @@ class MOZ_STACK_CLASS TokenStream
|
|||
{}
|
||||
};
|
||||
|
||||
bool awaitIsKeyword = false;
|
||||
friend class AutoAwaitIsKeyword;
|
||||
uint32_t invalidTemplateEscapeOffset = 0;
|
||||
InvalidEscapeType invalidTemplateEscapeType = InvalidEscapeType::None;
|
||||
|
||||
public:
|
||||
typedef Token::Modifier Modifier;
|
||||
static constexpr Modifier None = Token::None;
|
||||
static constexpr Modifier Operand = Token::Operand;
|
||||
static constexpr Modifier KeywordIsName = Token::KeywordIsName;
|
||||
static constexpr Modifier TemplateTail = Token::TemplateTail;
|
||||
|
||||
typedef Token::ModifierException ModifierException;
|
||||
static constexpr ModifierException NoException = Token::NoException;
|
||||
static constexpr ModifierException NoneIsOperand = Token::NoneIsOperand;
|
||||
static constexpr ModifierException OperandIsNone = Token::OperandIsNone;
|
||||
static constexpr ModifierException NoneIsKeywordIsName = Token::NoneIsKeywordIsName;
|
||||
|
||||
void addModifierException(ModifierException modifierException) {
|
||||
#ifdef DEBUG
|
||||
|
|
@ -474,10 +539,6 @@ class MOZ_STACK_CLASS TokenStream
|
|||
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");
|
||||
}
|
||||
|
|
@ -504,18 +565,17 @@ class MOZ_STACK_CLASS TokenStream
|
|||
return;
|
||||
}
|
||||
|
||||
if (lookaheadToken.modifierException == 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
|
||||
}
|
||||
|
||||
const Token& nextToken() const {
|
||||
MOZ_ASSERT(hasLookahead());
|
||||
return tokens[(cursor + 1) & ntokensMask];
|
||||
}
|
||||
|
||||
// Advance to the next token. If the token stream encountered an error,
|
||||
// return false. Otherwise return true and store the token kind in |*ttp|.
|
||||
MOZ_MUST_USE bool getToken(TokenKind* ttp, Modifier modifier = None) {
|
||||
|
|
@ -644,36 +704,6 @@ class MOZ_STACK_CLASS TokenStream
|
|||
MOZ_ALWAYS_TRUE(matched);
|
||||
}
|
||||
|
||||
// Like matchToken(..., TOK_NAME) but further matching the name token only
|
||||
// if it has the given characters, without containing escape sequences.
|
||||
// If the name token has the given characters yet *does* contain an escape,
|
||||
// a syntax error will be reported.
|
||||
//
|
||||
// This latter behavior makes this method unsuitable for use in any context
|
||||
// where ASI might occur. In such places, an escaped "contextual keyword"
|
||||
// on a new line is the start of an ExpressionStatement, not a continuation
|
||||
// of a StatementListItem (or ImportDeclaration or ExportDeclaration, in
|
||||
// modules).
|
||||
MOZ_MUST_USE bool matchContextualKeyword(bool* matchedp, Handle<PropertyName*> keyword,
|
||||
Modifier modifier = None)
|
||||
{
|
||||
TokenKind token;
|
||||
if (!getToken(&token, modifier))
|
||||
return false;
|
||||
if (token == TOK_NAME && currentToken().name() == keyword) {
|
||||
if (currentToken().nameContainsEscape()) {
|
||||
reportError(JSMSG_ESCAPED_KEYWORD);
|
||||
return false;
|
||||
}
|
||||
|
||||
*matchedp = true;
|
||||
} else {
|
||||
*matchedp = false;
|
||||
ungetToken();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool nextTokenEndsExpr(bool* endsExpr) {
|
||||
TokenKind tt;
|
||||
if (!peekToken(&tt))
|
||||
|
|
@ -739,19 +769,6 @@ class MOZ_STACK_CLASS TokenStream
|
|||
return sourceMapURL_.get();
|
||||
}
|
||||
|
||||
// If |atom| is not a keyword in this version, return true with *ttp
|
||||
// unchanged.
|
||||
//
|
||||
// If it is a reserved word in this version and strictness mode, and thus
|
||||
// can't be present in correct code, report a SyntaxError and return false.
|
||||
//
|
||||
// If it is a keyword, like "if", return true with the keyword's TokenKind
|
||||
// in *ttp.
|
||||
MOZ_MUST_USE bool checkForKeyword(JSAtom* atom, TokenKind* ttp);
|
||||
|
||||
// Same semantics as above, but for the provided keyword.
|
||||
MOZ_MUST_USE bool checkForKeyword(const KeywordInfo* kw, TokenKind* ttp);
|
||||
|
||||
// This class maps a userbuf offset (which is 0-indexed) to a line number
|
||||
// (which is 1-indexed) and a column index (which is 0-indexed).
|
||||
class SourceCoords
|
||||
|
|
@ -947,7 +964,6 @@ class MOZ_STACK_CLASS TokenStream
|
|||
|
||||
MOZ_MUST_USE bool getTokenInternal(TokenKind* ttp, Modifier modifier);
|
||||
|
||||
MOZ_MUST_USE bool getBracedUnicode(uint32_t* code);
|
||||
MOZ_MUST_USE bool getStringOrTemplateToken(int untilChar, Token** tp);
|
||||
|
||||
int32_t getChar();
|
||||
|
|
@ -964,7 +980,7 @@ class MOZ_STACK_CLASS TokenStream
|
|||
|
||||
MOZ_MUST_USE bool getDirectives(bool isMultiline, bool shouldWarnDeprecated);
|
||||
MOZ_MUST_USE bool getDirective(bool isMultiline, bool shouldWarnDeprecated,
|
||||
const char* directive, int directiveLength,
|
||||
const char* directive, uint8_t directiveLength,
|
||||
const char* errorMsgPragma,
|
||||
UniquePtr<char16_t[], JS::FreePolicy>* destination);
|
||||
MOZ_MUST_USE bool getDisplayURL(bool isMultiline, bool shouldWarnDeprecated);
|
||||
|
|
@ -982,29 +998,30 @@ class MOZ_STACK_CLASS TokenStream
|
|||
MOZ_ASSERT(c == expect);
|
||||
}
|
||||
|
||||
int32_t peekChar() {
|
||||
int32_t c = getChar();
|
||||
ungetChar(c);
|
||||
return c;
|
||||
MOZ_MUST_USE bool peekChar(int32_t* c) {
|
||||
*c = getChar();
|
||||
ungetChar(*c);
|
||||
return true;
|
||||
}
|
||||
|
||||
void skipChars(int n) {
|
||||
while (--n >= 0)
|
||||
getChar();
|
||||
void skipChars(uint8_t n) {
|
||||
while (n-- > 0) {
|
||||
MOZ_ASSERT(userbuf.hasRawChars());
|
||||
mozilla::DebugOnly<int32_t> c = getCharIgnoreEOL();
|
||||
MOZ_ASSERT(c != '\n');
|
||||
}
|
||||
}
|
||||
|
||||
void skipCharsIgnoreEOL(int n) {
|
||||
while (--n >= 0)
|
||||
void skipCharsIgnoreEOL(uint8_t n) {
|
||||
while (n-- > 0) {
|
||||
MOZ_ASSERT(userbuf.hasRawChars());
|
||||
getCharIgnoreEOL();
|
||||
}
|
||||
}
|
||||
|
||||
void updateLineInfoForEOL();
|
||||
void updateFlagsForEOL();
|
||||
|
||||
const Token& nextToken() const {
|
||||
MOZ_ASSERT(hasLookahead());
|
||||
return tokens[(cursor + 1) & ntokensMask];
|
||||
}
|
||||
|
||||
bool hasLookahead() const { return lookahead > 0; }
|
||||
|
||||
|
|
@ -1029,25 +1046,6 @@ class MOZ_STACK_CLASS TokenStream
|
|||
StrictModeGetter* strictModeGetter; // used to test for strict mode
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS AutoAwaitIsKeyword
|
||||
{
|
||||
private:
|
||||
TokenStream* ts_;
|
||||
bool oldAwaitIsKeyword_;
|
||||
|
||||
public:
|
||||
AutoAwaitIsKeyword(TokenStream* ts, bool awaitIsKeyword) {
|
||||
ts_ = ts;
|
||||
oldAwaitIsKeyword_ = ts_->awaitIsKeyword;
|
||||
ts_->awaitIsKeyword = awaitIsKeyword;
|
||||
}
|
||||
|
||||
~AutoAwaitIsKeyword() {
|
||||
ts_->awaitIsKeyword = oldAwaitIsKeyword_;
|
||||
ts_ = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
extern const char*
|
||||
TokenKindToDesc(TokenKind tt);
|
||||
|
||||
|
|
|
|||
|
|
@ -243,10 +243,10 @@ RegExpParser<CharT>::RegExpParser(frontend::TokenStream& ts, LifoAlloc* alloc,
|
|||
|
||||
template <typename CharT>
|
||||
RegExpTree*
|
||||
RegExpParser<CharT>::ReportError(unsigned errorNumber)
|
||||
RegExpParser<CharT>::ReportError(unsigned errorNumber, const char* param /* = nullptr */)
|
||||
{
|
||||
gc::AutoSuppressGC suppressGC(ts.context());
|
||||
ts.reportError(errorNumber);
|
||||
ts.reportError(errorNumber, param);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -350,7 +350,7 @@ RegExpParser<CharT>::ParseBracedHexEscape(widechar* value)
|
|||
}
|
||||
code = (code << 4) | d;
|
||||
if (code > unicode::NonBMPMax) {
|
||||
ReportError(JSMSG_UNICODE_OVERFLOW);
|
||||
ReportError(JSMSG_UNICODE_OVERFLOW, "regular expression");
|
||||
return false;
|
||||
}
|
||||
Advance();
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ class RegExpParser
|
|||
bool ParseBackReferenceIndex(int* index_out);
|
||||
|
||||
bool ParseClassAtom(char16_t* char_class, widechar *value);
|
||||
RegExpTree* ReportError(unsigned errorNumber);
|
||||
RegExpTree* ReportError(unsigned errorNumber, const char* param = nullptr);
|
||||
void Advance();
|
||||
void Advance(int dist) {
|
||||
next_pos_ += dist - 1;
|
||||
|
|
|
|||
2
js/src/jit-test/modules/export-default-async-asi.js
Normal file
2
js/src/jit-test/modules/export-default-async-asi.js
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export default async // ASI occurs here due to the [no LineTerminator here] restriction on default-exporting an async function
|
||||
function async() { return 17; }
|
||||
26
js/src/jit-test/tests/asm.js/import-function-toPrimitive.js
Normal file
26
js/src/jit-test/tests/asm.js/import-function-toPrimitive.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
var counter = 0;
|
||||
|
||||
function f(stdlib, foreign)
|
||||
{
|
||||
"use asm";
|
||||
var a = +foreign.a;
|
||||
var b = +foreign.b;
|
||||
function g() {}
|
||||
return g;
|
||||
}
|
||||
|
||||
var foreign =
|
||||
{
|
||||
a: function() {},
|
||||
b: /value that doesn't coerce purely/,
|
||||
};
|
||||
|
||||
foreign.a[Symbol.toPrimitive] =
|
||||
function()
|
||||
{
|
||||
counter++;
|
||||
return 0;
|
||||
};
|
||||
|
||||
f(null, foreign);
|
||||
assertEq(counter, 1);
|
||||
14
js/src/jit-test/tests/baseline/bug1344334.js
Normal file
14
js/src/jit-test/tests/baseline/bug1344334.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
function f(s) {
|
||||
s + "x";
|
||||
s.indexOf("y") === 0;
|
||||
oomTest(new Function(s));
|
||||
}
|
||||
var s = `
|
||||
class TestClass { constructor() {} }
|
||||
for (var fun of hasPrototype) {}
|
||||
`;
|
||||
if (s.length)
|
||||
f(s);
|
||||
|
|
@ -8,7 +8,7 @@ function addDebug(g, id) {\
|
|||
var debuggerGlobal = newGlobal();\
|
||||
debuggerGlobal.debuggee = g;\
|
||||
debuggerGlobal.id = id;\
|
||||
debuggerGlobal.print = function (s) { (g) += s; };\
|
||||
debuggerGlobal.print = function (s) { print(s); };\
|
||||
debuggerGlobal.eval('var dbg = new Debugger(debuggee);dbg.onDebuggerStatement = function () { print(id); debugger; };');\
|
||||
return debuggerGlobal;\
|
||||
}\
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
load(libdir + "asserts.js");
|
||||
|
||||
let string = Object.defineProperty(new String("123"), "valueOf", {
|
||||
get: function() { throw "get-valueOf"; }
|
||||
});
|
||||
assertThrowsValue(() => "" + string, "get-valueOf");
|
||||
|
||||
string = Object.defineProperty(new String("123"), "toString", {
|
||||
get: function() { throw "get-toString"; }
|
||||
});
|
||||
assertThrowsValue(() => string.toLowerCase(), "get-toString");
|
||||
|
||||
string = Object.defineProperty(new String("123"), Symbol.toPrimitive, {
|
||||
get: function() { throw "get-toPrimitive"; }
|
||||
});
|
||||
assertThrowsValue(() => string.toLowerCase(), "get-toPrimitive");
|
||||
|
||||
let number = Object.defineProperty(new Number(123), "valueOf", {
|
||||
get: function() { throw "get-valueOf"; }
|
||||
});
|
||||
assertThrowsValue(() => +number, "get-valueOf");
|
||||
|
|
@ -8,9 +8,11 @@ assertEq(typeof f1(true), "function");
|
|||
assertEq(f1(false), 3);
|
||||
|
||||
function f2(b, w) {
|
||||
// Annex B doesn't apply to functions in blocks with the same name as a
|
||||
// parameter.
|
||||
if (b)
|
||||
function w() {}
|
||||
return w;
|
||||
}
|
||||
assertEq(typeof f2(true, 3), "function");
|
||||
assertEq(typeof f2(true, 3), "number");
|
||||
assertEq(f2(false, 3), 3);
|
||||
|
|
|
|||
8
js/src/jit-test/tests/class/bug1357506.js
Normal file
8
js/src/jit-test/tests/class/bug1357506.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// Test that constructors that abort due to asm.js do not assert due to the
|
||||
// parser keeping track of the FunctionBox corresponding to the constructor.
|
||||
|
||||
class a {
|
||||
constructor() {
|
||||
"use asm";
|
||||
}
|
||||
}
|
||||
4
js/src/jit-test/tests/class/bug1359622.js
Normal file
4
js/src/jit-test/tests/class/bug1359622.js
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
setDiscardSource(true)
|
||||
evaluate(`
|
||||
unescape(class get { static staticMethod() {} });
|
||||
`);
|
||||
26
js/src/jit-test/tests/debug/wasm-12.js
Normal file
26
js/src/jit-test/tests/debug/wasm-12.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Tests that wasm module scripts have special URLs.
|
||||
|
||||
if (!wasmIsSupported())
|
||||
quit();
|
||||
|
||||
var g = newGlobal();
|
||||
g.eval(`
|
||||
function initWasm(s) { return new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(s))); }
|
||||
o = initWasm('(module (func) (export "" 0))');
|
||||
o2 = initWasm('(module (func) (func) (export "" 1))');
|
||||
`);
|
||||
|
||||
function isWasm(script) { return script.format === "wasm"; }
|
||||
|
||||
function isValidWasmURL(url) {
|
||||
// The URLs will have the following format:
|
||||
// wasm: [<uri-econded-filename-of-host> ":"] <64-bit-hash>
|
||||
return /^wasm:(?:[^:]*:)*?[0-9a-f]{16}$/.test(url);
|
||||
}
|
||||
|
||||
var dbg = new Debugger(g);
|
||||
var foundScripts = dbg.findScripts().filter(isWasm);
|
||||
assertEq(foundScripts.length, 2);
|
||||
assertEq(isValidWasmURL(foundScripts[0].source.url), true);
|
||||
assertEq(isValidWasmURL(foundScripts[1].source.url), true);
|
||||
assertEq(foundScripts[0].source.url != foundScripts[1].source.url, true);
|
||||
|
|
@ -403,12 +403,52 @@ assertThrowsInstanceOf(function() {
|
|||
parseAsModule("export {,} from 'a'");
|
||||
}, SyntaxError);
|
||||
|
||||
program([
|
||||
exportDeclaration(
|
||||
null,
|
||||
[
|
||||
exportSpecifier(
|
||||
ident("true"),
|
||||
ident("true")
|
||||
),
|
||||
],
|
||||
lit("b"),
|
||||
false
|
||||
)
|
||||
]).assert(parseAsModule("export { true } from 'b'"));
|
||||
|
||||
program([
|
||||
exportDeclaration(
|
||||
null,
|
||||
[
|
||||
exportSpecifier(
|
||||
ident("true"),
|
||||
ident("name")
|
||||
),
|
||||
],
|
||||
lit("b"),
|
||||
false
|
||||
)
|
||||
]).assert(parseAsModule("export { true as name } from 'b'"));
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
parseAsModule("export { true as a } from 'b'");
|
||||
parseAsModule("export { true }");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
parseAsModule("export { true as name }");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
parseAsModule("export { static }");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
parseAsModule("export { static as name }");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function () {
|
||||
parseAsModule("export { a } from 'b' f();");
|
||||
parseAsModule("export { name } from 'b' f();");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function () {
|
||||
|
|
|
|||
94
js/src/jit-test/tests/modules/function-redeclaration.js
Normal file
94
js/src/jit-test/tests/modules/function-redeclaration.js
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
load(libdir + "asserts.js");
|
||||
|
||||
var functionDeclarations = [
|
||||
"function f(){}",
|
||||
"function* f(){}",
|
||||
"async function f(){}",
|
||||
];
|
||||
|
||||
var varDeclarations = [
|
||||
"var f",
|
||||
"{ var f; }",
|
||||
"for (var f in null);",
|
||||
"for (var f of null);",
|
||||
"for (var f; ;);",
|
||||
];
|
||||
|
||||
var lexicalDeclarations = [
|
||||
"let f;",
|
||||
"const f = 0;",
|
||||
"class f {};",
|
||||
];
|
||||
|
||||
var imports = [
|
||||
"import f from '';",
|
||||
"import f, {} from '';",
|
||||
"import d, {f} from '';",
|
||||
"import d, {f as f} from '';",
|
||||
"import d, {foo as f} from '';",
|
||||
"import f, * as d from '';",
|
||||
"import d, * as f from '';",
|
||||
"import {f} from '';",
|
||||
"import {f as f} from '';",
|
||||
"import {foo as f} from '';",
|
||||
"import* as f from '';",
|
||||
];
|
||||
|
||||
var exports = [
|
||||
"export var f;",
|
||||
...functionDeclarations.map(fn => `export ${fn};`),
|
||||
...lexicalDeclarations.map(ld => `export ${ld};`),
|
||||
...functionDeclarations.map(fn => `export default ${fn};`),
|
||||
"export default class f {};",
|
||||
];
|
||||
|
||||
var redeclarations = [
|
||||
...functionDeclarations,
|
||||
...varDeclarations,
|
||||
...lexicalDeclarations,
|
||||
...imports,
|
||||
...exports,
|
||||
];
|
||||
|
||||
var noredeclarations = [
|
||||
...functionDeclarations.map(fn => `{ ${fn} }`),
|
||||
...lexicalDeclarations.map(ld => `{ ${ld} }`),
|
||||
...["let", "const"].map(ld => `for (${ld} f in null);`),
|
||||
...["let", "const"].map(ld => `for (${ld} f of null);`),
|
||||
...["let", "const"].map(ld => `for (${ld} f = 0; ;);`),
|
||||
"export {f};",
|
||||
"export {f as f};",
|
||||
"export {foo as f}; var foo;",
|
||||
"export {f} from '';",
|
||||
"export {f as f} from '';",
|
||||
"export {foo as f} from '';",
|
||||
];
|
||||
|
||||
for (var decl of functionDeclarations) {
|
||||
for (var redecl of redeclarations) {
|
||||
assertThrowsInstanceOf(() => {
|
||||
parseModule(`
|
||||
${decl}
|
||||
${redecl}
|
||||
`);
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(() => {
|
||||
parseModule(`
|
||||
${redecl}
|
||||
${decl}
|
||||
`);
|
||||
}, SyntaxError);
|
||||
}
|
||||
|
||||
for (var redecl of noredeclarations) {
|
||||
parseModule(`
|
||||
${decl}
|
||||
${redecl}
|
||||
`);
|
||||
parseModule(`
|
||||
${redecl}
|
||||
${decl}
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
|
@ -39,7 +39,7 @@ testThrow(`
|
|||
|
||||
testThrow(`
|
||||
({...a)=>
|
||||
`, 2);
|
||||
`, 6);
|
||||
|
||||
testThrow(`
|
||||
function f([... ...a)=>
|
||||
|
|
@ -47,7 +47,7 @@ function f([... ...a)=>
|
|||
|
||||
testThrow(`
|
||||
function f({...a)=>
|
||||
`, 12);
|
||||
`, 16);
|
||||
|
||||
// arrow
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ var [... ...a)=>
|
|||
|
||||
testThrow(`
|
||||
var {...a)=>
|
||||
`, 5);
|
||||
`, 9);
|
||||
|
||||
// initializer
|
||||
|
||||
|
|
|
|||
90
js/src/jit-test/tests/parser/missing-closing-brace.js
Normal file
90
js/src/jit-test/tests/parser/missing-closing-brace.js
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
function test(source, [lineNumber, columnNumber], openType = "{", closeType = "}") {
|
||||
let caught = false;
|
||||
try {
|
||||
Reflect.parse(source, { source: "foo.js" });
|
||||
} catch (e) {
|
||||
assertEq(e.message.includes("missing " + closeType + " "), true);
|
||||
let notes = getErrorNotes(e);
|
||||
assertEq(notes.length, 1);
|
||||
let note = notes[0];
|
||||
assertEq(note.message, openType + " opened at line " + lineNumber + ", column " + columnNumber);
|
||||
assertEq(note.fileName, "foo.js");
|
||||
assertEq(note.lineNumber, lineNumber);
|
||||
assertEq(note.columnNumber, columnNumber);
|
||||
caught = true;
|
||||
}
|
||||
assertEq(caught, true);
|
||||
}
|
||||
|
||||
// Function
|
||||
|
||||
test(`
|
||||
function test1() {
|
||||
}
|
||||
function test2() {
|
||||
if (true) {
|
||||
//}
|
||||
}
|
||||
function test3() {
|
||||
}
|
||||
`, [4, 17]);
|
||||
|
||||
// Block statement.
|
||||
test(`
|
||||
{
|
||||
if (true) {
|
||||
}
|
||||
`, [2, 0]);
|
||||
test(`
|
||||
if (true) {
|
||||
if (true) {
|
||||
}
|
||||
`, [2, 10]);
|
||||
test(`
|
||||
for (;;) {
|
||||
if (true) {
|
||||
}
|
||||
`, [2, 9]);
|
||||
test(`
|
||||
while (true) {
|
||||
if (true) {
|
||||
}
|
||||
`, [2, 13]);
|
||||
test(`
|
||||
do {
|
||||
do {
|
||||
} while(true);
|
||||
`, [2, 3]);
|
||||
|
||||
// try-catch-finally.
|
||||
test(`
|
||||
try {
|
||||
if (true) {
|
||||
}
|
||||
`, [2, 4]);
|
||||
test(`
|
||||
try {
|
||||
} catch (e) {
|
||||
if (true) {
|
||||
}
|
||||
`, [3, 12]);
|
||||
test(`
|
||||
try {
|
||||
} finally {
|
||||
if (true) {
|
||||
}
|
||||
`, [3, 10]);
|
||||
|
||||
// Object literal.
|
||||
test(`
|
||||
var x = {
|
||||
foo: {
|
||||
};
|
||||
`, [2, 8]);
|
||||
|
||||
// Array literal.
|
||||
test(`
|
||||
var x = [
|
||||
[
|
||||
];
|
||||
`, [2, 8], "[", "]");
|
||||
230
js/src/jit-test/tests/parser/redeclaration.js
Normal file
230
js/src/jit-test/tests/parser/redeclaration.js
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
// Error message for redeclaration should show the position where the variable
|
||||
// was declared.
|
||||
|
||||
const npos = -1;
|
||||
|
||||
function test_one(fun, filename, name,
|
||||
[prevLineNumber, prevColumnNumber],
|
||||
[lineNumber, columnNumber]) {
|
||||
let caught = false;
|
||||
try {
|
||||
fun();
|
||||
} catch (e) {
|
||||
assertEq(e.message.includes("redeclaration"), true);
|
||||
assertEq(e.lineNumber, lineNumber);
|
||||
assertEq(e.columnNumber, columnNumber);
|
||||
let notes = getErrorNotes(e);
|
||||
if (prevLineNumber == npos) {
|
||||
assertEq(notes.length, 0);
|
||||
} else {
|
||||
assertEq(notes.length, 1);
|
||||
let note = notes[0];
|
||||
assertEq(note.message,
|
||||
`Previously declared at line ${prevLineNumber}, column ${prevColumnNumber}`);
|
||||
assertEq(note.lineNumber, prevLineNumber);
|
||||
assertEq(note.columnNumber, prevColumnNumber);
|
||||
if (filename)
|
||||
assertEq(note.fileName, filename);
|
||||
}
|
||||
caught = true;
|
||||
}
|
||||
assertEq(caught, true);
|
||||
}
|
||||
|
||||
function test_parse(source, ...args) {
|
||||
test_one(() => {
|
||||
Reflect.parse(source, { source: "foo.js" });
|
||||
}, "foo.js", ...args);
|
||||
}
|
||||
|
||||
function test_eval(source, ...args) {
|
||||
test_one(() => {
|
||||
eval(source);
|
||||
}, undefined, ...args);
|
||||
}
|
||||
|
||||
function test(...args) {
|
||||
test_parse(...args);
|
||||
test_eval(...args);
|
||||
}
|
||||
|
||||
// let
|
||||
|
||||
test(`
|
||||
let a, a;
|
||||
`, "a", [2, 4], [2, 7]);
|
||||
|
||||
test(`
|
||||
let a;
|
||||
let a;
|
||||
`, "a", [2, 4], [3, 4]);
|
||||
|
||||
test(`
|
||||
let a;
|
||||
const a = 1;
|
||||
`, "a", [2, 4], [3, 6]);
|
||||
|
||||
test(`
|
||||
let a;
|
||||
var a;
|
||||
`, "a", [2, 4], [3, 4]);
|
||||
|
||||
test(`
|
||||
let a;
|
||||
function a() {
|
||||
}
|
||||
`, "a", [2, 4], [3, 9]);
|
||||
|
||||
test(`
|
||||
{
|
||||
let a;
|
||||
function a() {
|
||||
}
|
||||
}
|
||||
`, "a", [3, 6], [4, 11]);
|
||||
|
||||
// const
|
||||
|
||||
test(`
|
||||
const a = 1, a = 2;
|
||||
`, "a", [2, 6], [2, 13]);
|
||||
|
||||
test(`
|
||||
const a = 1;
|
||||
const a = 2;
|
||||
`, "a", [2, 6], [3, 6]);
|
||||
|
||||
test(`
|
||||
const a = 1;
|
||||
let a;
|
||||
`, "a", [2, 6], [3, 4]);
|
||||
|
||||
test(`
|
||||
const a = 1;
|
||||
var a;
|
||||
`, "a", [2, 6], [3, 4]);
|
||||
|
||||
test(`
|
||||
const a = 1;
|
||||
function a() {
|
||||
}
|
||||
`, "a", [2, 6], [3, 9]);
|
||||
|
||||
test(`
|
||||
{
|
||||
const a = 1;
|
||||
function a() {
|
||||
}
|
||||
}
|
||||
`, "a", [3, 8], [4, 11]);
|
||||
|
||||
// var
|
||||
|
||||
test(`
|
||||
var a;
|
||||
let a;
|
||||
`, "a", [2, 4], [3, 4]);
|
||||
|
||||
test(`
|
||||
var a;
|
||||
const a = 1;
|
||||
`, "a", [2, 4], [3, 6]);
|
||||
|
||||
// function
|
||||
|
||||
test(`
|
||||
function a() {};
|
||||
let a;
|
||||
`, "a", [2, 9], [3, 4]);
|
||||
|
||||
test(`
|
||||
function a() {};
|
||||
const a = 1;
|
||||
`, "a", [2, 9], [3, 6]);
|
||||
|
||||
// Annex B lexical function
|
||||
|
||||
test(`
|
||||
{
|
||||
function a() {};
|
||||
let a;
|
||||
}
|
||||
`, "a", [3, 11], [4, 6]);
|
||||
|
||||
test(`
|
||||
{
|
||||
function a() {};
|
||||
const a = 1;
|
||||
}
|
||||
`, "a", [3, 11], [4, 8]);
|
||||
|
||||
// catch parameter
|
||||
|
||||
test(`
|
||||
try {
|
||||
} catch (a) {
|
||||
let a;
|
||||
}
|
||||
`, "a", [3, 9], [4, 6]);
|
||||
|
||||
test(`
|
||||
try {
|
||||
} catch (a) {
|
||||
const a = 1;
|
||||
}
|
||||
`, "a", [3, 9], [4, 8]);
|
||||
|
||||
test(`
|
||||
try {
|
||||
} catch (a) {
|
||||
function a() {
|
||||
}
|
||||
}
|
||||
`, "a", [3, 9], [4, 11]);
|
||||
|
||||
// parameter
|
||||
|
||||
test(`
|
||||
function f(a) {
|
||||
let a;
|
||||
}
|
||||
`, "a", [2, 11], [3, 6]);
|
||||
|
||||
test(`
|
||||
function f(a) {
|
||||
const a = 1;
|
||||
}
|
||||
`, "a", [2, 11], [3, 8]);
|
||||
|
||||
test(`
|
||||
function f([a]) {
|
||||
let a;
|
||||
}
|
||||
`, "a", [2, 12], [3, 6]);
|
||||
|
||||
test(`
|
||||
function f({a}) {
|
||||
let a;
|
||||
}
|
||||
`, "a", [2, 12], [3, 6]);
|
||||
|
||||
test(`
|
||||
function f(...a) {
|
||||
let a;
|
||||
}
|
||||
`, "a", [2, 14], [3, 6]);
|
||||
|
||||
test(`
|
||||
function f(a=1) {
|
||||
let a;
|
||||
}
|
||||
`, "a", [2, 11], [3, 6]);
|
||||
|
||||
// eval
|
||||
// We don't have position information at runtime.
|
||||
// No note should be shown.
|
||||
|
||||
test_eval(`
|
||||
let a;
|
||||
eval("var a");
|
||||
`, "a", [npos, npos], [1, 4]);
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue