Reviewed by Oliver Hunt.
Source/JavaScriptCore:
From chapter 16 the spec:
An implementation must report most errors at the time the relevant ECMAScript language construct is
evaluated. An early error is an error that can be detected and reported prior to the evaluation of
any construct in the Program containing the error. An implementation must report early errors in a
Program prior to the first evaluation of that Program. Early errors in eval code are reported at
the time eval is called but prior to evaluation of any construct within the eval code. All errors
that are not early errors are runtime errors.
An implementation must treat any instance of the following kinds of errors as an early error:
* Any syntax error."
* JavaScriptCore.xcodeproj/project.pbxproj:
Added new files.
* bytecode/CodeBlock.cpp:
Removed op_throw_syntax_error.
* bytecode/Opcode.h:
Removed op_throw_syntax_error.
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::generate):
If m_expressionTooDeep then throw a runtime error.
(JSC::BytecodeGenerator::BytecodeGenerator):
Initialize m_expressionTooDeep.
(JSC::BytecodeGenerator::emitThrowExpressionTooDeepException):
Sets m_expressionTooDeep.
* bytecompiler/BytecodeGenerator.h:
Added m_expressionTooDeep, removed emitThrowSyntaxError.
* bytecompiler/NodesCodegen.cpp:
(JSC::RegExpNode::emitBytecode):
(JSC::ContinueNode::emitBytecode):
(JSC::BreakNode::emitBytecode):
(JSC::ReturnNode::emitBytecode):
(JSC::LabelNode::emitBytecode):
Conditions that threw syntax error are now handled during parsing;
during bytecompilation these are now just ASSERTs.
* interpreter/Interpreter.cpp:
(JSC::Interpreter::privateExecute):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
* jit/JITOpcodes32_64.cpp:
* jit/JITStubs.cpp:
* jit/JITStubs.h:
Removed op_throw_syntax_error.
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createRegExp):
Renamed; added syntax check.
* parser/JSParser.cpp:
(JSC::JSParser::breakIsValid):
(JSC::JSParser::hasLabel):
(JSC::JSParser::Scope::Scope):
(JSC::JSParser::Scope::setIsFunction):
(JSC::JSParser::Scope::isFunctionBoundary):
(JSC::JSParser::ScopeRef::hasContainingScope):
(JSC::JSParser::ScopeRef::containingScope):
(JSC::JSParser::AutoPopScopeRef::AutoPopScopeRef):
(JSC::JSParser::AutoPopScopeRef::~AutoPopScopeRef):
(JSC::JSParser::AutoPopScopeRef::setPopped):
(JSC::JSParser::popScopeInternal):
(JSC::JSParser::popScope):
(JSC::jsParse):
(JSC::JSParser::JSParser):
(JSC::JSParser::parseProgram):
(JSC::JSParser::parseBreakStatement):
(JSC::JSParser::parseContinueStatement):
(JSC::JSParser::parseReturnStatement):
(JSC::JSParser::parseTryStatement):
(JSC::JSParser::parseFunctionInfo):
(JSC::JSParser::parseExpressionOrLabelStatement):
(JSC::JSParser::parsePrimaryExpression):
* parser/JSParser.h:
* parser/Nodes.h:
* parser/Parser.cpp:
(JSC::Parser::parse):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createRegExp):
Renamed; added syntax check.
* runtime/ExceptionHelpers.cpp:
(JSC::createOutOfMemoryError):
(JSC::throwOutOfMemoryError):
* runtime/ExceptionHelpers.h:
Broke out createOutOfMemoryError.
* runtime/Executable.cpp:
(JSC::EvalExecutable::compileInternal):
(JSC::ProgramExecutable::compileInternal):
(JSC::FunctionExecutable::compileForCallInternal):
(JSC::FunctionExecutable::compileForConstructInternal):
Add check for exception after bytecode generation.
* runtime/RegExpConstructor.cpp:
(JSC::constructRegExp):
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncCompile):
RegExp error prefixes not included in error string.
* yarr/RegexParser.h:
(JSC::Yarr::Parser::parse):
Removed regexBegin/regexEnd/regexError.
* yarr/RegexPattern.cpp:
(JSC::Yarr::RegexPatternConstructor::regexBegin):
Removed regexEnd/regexError.
(JSC::Yarr::compileRegex):
Add call to regexBegin (no longer called from the parser).
* yarr/YarrSyntaxChecker.cpp: Added.
(JSC::Yarr::SyntaxChecker::assertionBOL):
(JSC::Yarr::SyntaxChecker::assertionEOL):
(JSC::Yarr::SyntaxChecker::assertionWordBoundary):
(JSC::Yarr::SyntaxChecker::atomPatternCharacter):
(JSC::Yarr::SyntaxChecker::atomBuiltInCharacterClass):
(JSC::Yarr::SyntaxChecker::atomCharacterClassBegin):
(JSC::Yarr::SyntaxChecker::atomCharacterClassAtom):
(JSC::Yarr::SyntaxChecker::atomCharacterClassRange):
(JSC::Yarr::SyntaxChecker::atomCharacterClassBuiltIn):
(JSC::Yarr::SyntaxChecker::atomCharacterClassEnd):
(JSC::Yarr::SyntaxChecker::atomParenthesesSubpatternBegin):
(JSC::Yarr::SyntaxChecker::atomParentheticalAssertionBegin):
(JSC::Yarr::SyntaxChecker::atomParenthesesEnd):
(JSC::Yarr::SyntaxChecker::atomBackReference):
(JSC::Yarr::SyntaxChecker::quantifyAtom):
(JSC::Yarr::SyntaxChecker::disjunction):
(JSC::Yarr::checkSyntax):
* yarr/YarrSyntaxChecker.h: Added.
Check RegExp syntax.
LayoutTests:
Fix syntax errors in layout tests, and update expected results.
* editing/selection/select-crash-001.html:
* editing/selection/select-crash-002.html:
* fast/canvas/webgl/renderbuffer-initialization.html:
* fast/forms/25153.html:
* fast/forms/textfield-drag-into-disabled.html:
* fast/js/exception-codegen-crash-expected.txt:
* fast/js/exception-codegen-crash.html:
* fast/js/kde/parse-expected.txt:
* fast/js/kde/script-tests/parse.js:
* fast/js/large-expressions-expected.txt:
* fast/js/named-function-expression-expected.txt:
* fast/js/parser-syntax-check-expected.txt:
* fast/js/script-tests/large-expressions.js:
* fast/js/script-tests/named-function-expression.js:
* fast/js/script-tests/parser-syntax-check.js:
* fast/js/sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A11.1_T3-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A11_T3-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A12.1_T3-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A12_T3-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A1_T1-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A1_T2-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A1_T3-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A1_T4-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A5_T1-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A5_T2-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A5_T3-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A6-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A8_T1-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A8_T2-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A1_T1-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A1_T2-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A1_T3-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A1_T4-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A5_T1-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A5_T2-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A5_T3-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A6-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A8_T1-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A8_T2-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T1-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T10-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T2-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T3-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T4-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T5-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T6-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T7-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T8-expected.txt:
* fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T9-expected.txt:
* http/tests/security/isolatedWorld/events.html:
* http/tests/security/isolatedWorld/userGestureEvents.html:
* svg/custom/resources/use-instanceRoot-event-listeners.js:
* svg/custom/rgbcolor-syntax.svg:
* svg/custom/use-instanceRoot-modifications.svg:
* svg/custom/use-property-changes-through-svg-dom.svg:
* webarchive/adopt-attribute-styled-body-webarchive-expected.webarchive:
* webarchive/resources/adopt-attribute-styled-body-iframe.html:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@75408
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2011-01-10 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Bug 52079 - Syntax errors should be early errors.
+
+ Fix syntax errors in layout tests, and update expected results.
+
+ * editing/selection/select-crash-001.html:
+ * editing/selection/select-crash-002.html:
+ * fast/canvas/webgl/renderbuffer-initialization.html:
+ * fast/forms/25153.html:
+ * fast/forms/textfield-drag-into-disabled.html:
+ * fast/js/exception-codegen-crash-expected.txt:
+ * fast/js/exception-codegen-crash.html:
+ * fast/js/kde/parse-expected.txt:
+ * fast/js/kde/script-tests/parse.js:
+ * fast/js/large-expressions-expected.txt:
+ * fast/js/named-function-expression-expected.txt:
+ * fast/js/parser-syntax-check-expected.txt:
+ * fast/js/script-tests/large-expressions.js:
+ * fast/js/script-tests/named-function-expression.js:
+ * fast/js/script-tests/parser-syntax-check.js:
+ * fast/js/sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A11.1_T3-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A11_T3-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A12.1_T3-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.6_Iteration_Statements/12.6.3_The_for_Statement/S12.6.3_A12_T3-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A1_T1-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A1_T2-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A1_T3-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A1_T4-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A5_T1-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A5_T2-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A5_T3-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A6-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A8_T1-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.7_The_continue_Statement/S12.7_A8_T2-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A1_T1-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A1_T2-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A1_T3-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A1_T4-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A5_T1-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A5_T2-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A5_T3-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A6-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A8_T1-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.8_The_break_Statement/S12.8_A8_T2-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T1-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T10-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T2-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T3-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T4-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T5-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T6-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T7-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T8-expected.txt:
+ * fast/js/sputnik/Conformance/12_Statement/12.9_The_return_Statement/S12.9_A1_T9-expected.txt:
+ * http/tests/security/isolatedWorld/events.html:
+ * http/tests/security/isolatedWorld/userGestureEvents.html:
+ * svg/custom/resources/use-instanceRoot-event-listeners.js:
+ * svg/custom/rgbcolor-syntax.svg:
+ * svg/custom/use-instanceRoot-modifications.svg:
+ * svg/custom/use-property-changes-through-svg-dom.svg:
+ * webarchive/adopt-attribute-styled-body-webarchive-expected.webarchive:
+ * webarchive/resources/adopt-attribute-styled-body-iframe.html:
+
2011-01-10 Tony Chang <tony@chromium.org>
Unreviewed, remove duplicate test expectation for gif-loop-count.
<body>
<h1 id="test">The Longest German Word?</h1>
<script type="text/javascript" language="javascript">
- if (!window.layoutTestController)
- return;
- layoutTestController.dumpAsText();
- var element = document.getElementById("test");
- var selection = window.getSelection();
- selection.setPosition(element.firstChild, 2);
- extendSelectionForwardByCharacterCommand();
- copyCommand();
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ var element = document.getElementById("test");
+ var selection = window.getSelection();
+ selection.setPosition(element.firstChild, 2);
+ extendSelectionForwardByCharacterCommand();
+ copyCommand();
+ }
</script>
</body>
</html>
<body>
<h1>The Longest German Word?</h1>
<script type="text/javascript" language="javascript">
- if (!window.layoutTestController)
- return;
- layoutTestController.dumpAsText();
- selectAllCommand();
- copyCommand();
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+ selectAllCommand();
+ copyCommand();
+ }
</script>
</body>
</html>
var canvas = document.getElementById("testbed");
var gl = canvas.getContext("experimental-webgl");
-if (!gl) {
- testFailed('canvas.getContext() failed');
- return false;
-}
+if (gl) {
+ runTest(gl, canvas.width, canvas.height);
-runTest(gl, canvas.width, canvas.height);
+ // Testing that canvas resizing will clear the buffers with 0 instead of the current clear values.
+ gl.clearColor(1, 0, 0, 1);
+ canvas.width += 1;
+ canvas.height += 1;
+ runTest(gl, canvas.width, canvas.height);
-// Testing that canvas resizing will clear the buffers with 0 instead of the current clear values.
-gl.clearColor(1, 0, 0, 1);
-canvas.width += 1;
-canvas.height += 1;
-runTest(gl, canvas.width, canvas.height);
+ // Testing buffer clearing won't change the clear values.
+ var clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
+ shouldBe("clearColor", "[1, 0, 0, 1]");
-// Testing buffer clearing won't change the clear values.
-var clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
-shouldBe("clearColor", "[1, 0, 0, 1]");
-
-successfullyParsed = true;
+ successfullyParsed = true;
+} else
+ testFailed('canvas.getContext() failed');
</script>
<script src="../../js/resources/js-test-post.js"></script>
</body>
<input id="textfield" onFocus="window.scrollBy(0, 40)" value="click in me"><br>
<div style="height: 1500px;">
<script>
-if (!window.layoutTestController)
- return;
-window.layoutTestController.dumpAsText();
-textfield = document.getElementById("textfield");
-// Click near the end of the field so that the caret after all of the text inside it.
-x = textfield.offsetParent.offsetLeft + textfield.offsetLeft + textfield.offsetWidth - 5;
-y = textfield.offsetParent.offsetTop + textfield.offsetTop + textfield.offsetHeight / 2;
-eventSender.mouseMoveTo(x, y);
-eventSender.mouseDown();
-eventSender.mouseUp();
-if (textfield.selectionStart == textfield.value.length && textfield.selectionEnd == textfield.value.length)
- document.body.innerText = "Success"
-else
- document.body.innerText = "Failure. Expected selection to be after all of the text in the text field."
+if (window.layoutTestController) {
+ window.layoutTestController.dumpAsText();
+ textfield = document.getElementById("textfield");
+ // Click near the end of the field so that the caret after all of the text inside it.
+ x = textfield.offsetParent.offsetLeft + textfield.offsetLeft + textfield.offsetWidth - 5;
+ y = textfield.offsetParent.offsetTop + textfield.offsetTop + textfield.offsetHeight / 2;
+ eventSender.mouseMoveTo(x, y);
+ eventSender.mouseDown();
+ eventSender.mouseUp();
+ if (textfield.selectionStart == textfield.value.length && textfield.selectionEnd == textfield.value.length)
+ document.body.innerText = "Success"
+ else
+ document.body.innerText = "Failure. Expected selection to be after all of the text in the text field."
+}
</script>
window.getSelection().setBaseAndExtent(text, 0, text, 1);
-if (!window.layoutTestController)
- return;
+if (window.layoutTestController) {
+ eventSender.mouseMoveTo(textX, textY);
+ eventSender.mouseDown();
+ // leap forward so mouseDown will kick off a drag instead of starting a new selection.
+ eventSender.leapForward(1000);
-eventSender.mouseMoveTo(textX, textY);
-eventSender.mouseDown();
-// leap forward so mouseDown will kick off a drag instead of starting a new selection.
-eventSender.leapForward(1000);
+ eventSender.mouseMoveTo(fieldX, fieldY);
+ eventSender.mouseUp();
-eventSender.mouseMoveTo(fieldX, fieldY);
-eventSender.mouseUp();
-
-layoutTestController.dumpAsText();
-var resultText = "FAIL"
-if (!field.value)
- resultText = "PASS -- http://bugs.webkit.org/show_bug.cgi?id=10177";
-document.body.innerText = resultText;
+ layoutTestController.dumpAsText();
+ var resultText = "FAIL"
+ if (!field.value)
+ resultText = "PASS -- http://bugs.webkit.org/show_bug.cgi?id=10177";
+ document.body.innerText = resultText;
+}
</script>
</body>
-CONSOLE MESSAGE: line 1: ReferenceError: Postfix ++ operator applied to value that is not a reference.
This page tests some conditions that used to cause crashes during codegen.
If you don't crash, you pass.
"(1 = 1).x;"
];
-eval(scripts.join("\n"));
+try {
+ eval(scripts.join("\n"));
+} catch (e) {
+}
</script>
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+PASS function test() { return;}; lab: 1 is 1
+PASS function test() { while(0) break; } lab: 1 is 1
+PASS function test() { while(0) continue; } lab: 1 is 1
+PASS function test() { return lab;} lab: 1 is 1
+PASS function test() { while(0) break lab; } lab: 1 threw exception SyntaxError: Parse error.
+PASS function test() { while(0) continue lab; } lab: 1 threw exception SyntaxError: Parse error.
+PASS function test() { return } lab: 1 is 1
+PASS function test() { while(0) break } lab: 1 is 1
+PASS function test() { while(0) continue } lab: 1 is 1
+PASS function test() { return 0 } lab: 1 is 1
+PASS function test() { while(0) break lab } lab: 1 threw exception SyntaxError: Parse error.
+PASS function test() { while(0) continue lab } lab: 1 threw exception SyntaxError: Parse error.
PASS var éĀʯΈᢨ = 101; éĀʯΈᢨ; is 101
PASS var f÷; threw exception SyntaxError: Parse error.
PASS var \u0061 = 102; a is 102
-function test() { return;}
-function test() { while(0) break; }
-function test() { while(0) continue; }
-
-function test() { return lab;}
-function test() { while(0) break lab; }
-function test() { while(0) continue lab; }
-
-function test() { return }
-function test() { while(0) break }
-function test() { while(0) continue }
-
-function test() { return 0 }
-function test() { while(0) break lab }
-function test() { while(0) continue lab }
-
-lab:
+// Check parsing of nested scopes; a couple of the break/continue to label cases are invalid.
+shouldBe("function test() { return;}; lab: 1", "1");
+shouldBe("function test() { while(0) break; } lab: 1", "1");
+shouldBe("function test() { while(0) continue; } lab: 1", "1");
+
+shouldBe("function test() { return lab;} lab: 1", "1");
+shouldThrow("function test() { while(0) break lab; } lab: 1");
+shouldThrow("function test() { while(0) continue lab; } lab: 1");
+
+shouldBe("function test() { return } lab: 1", "1");
+shouldBe("function test() { while(0) break } lab: 1", "1");
+shouldBe("function test() { while(0) continue } lab: 1", "1");
+
+shouldBe("function test() { return 0 } lab: 1", "1");
+shouldThrow("function test() { while(0) break lab } lab: 1");
+shouldThrow("function test() { while(0) continue lab } lab: 1");
a = 1
b = 123 // comment
PASS eval(repeatedExpression("letterA", "+", 100)) is repeatedString("a", 100)
PASS eval(repeatedExpression("letterA", "+", 1000)) is repeatedString("a", 1000)
PASS eval(repeatedExpression("letterA", "+", 10000)) is repeatedString("a", 10000)
-PASS eval(repeatedExpression("letterA", "+", 100000)) threw exception SyntaxError: Expression too deep.
+PASS eval(repeatedExpression("letterA", "+", 100000)) threw exception Error: Out of memory.
PASS successfullyParsed is true
TEST COMPLETE
recursion is possible, though
PASS var ctr = 3; var x = (function Named(a,b){ if(--ctr) return 2 * Named(a,b); else return a + b; }); x(5,6) is 44
regression test where kjs regarded an anonymous function declaration (which is illegal) as a FunctionExpr
-PASS try { eval("function(){ return 2; };"); return 0; } catch(e) { 1; } is 1
+PASS var hadError = 0; try { eval("function(){ return 2; };"); } catch(e) { hadError = 1; }; hadError; is 1
PASS successfullyParsed is true
TEST COMPLETE
PASS Valid: "function f() { do while (0) if (a) {} else y; while(0) }"
PASS Valid: "if (a) while (b) if (c) with(d) {} else e; else f"
PASS Valid: "function f() { if (a) while (b) if (c) with(d) {} else e; else f }"
-PASS Valid: "break ; break your_limits ; continue ; continue living ; debugger"
-PASS Valid: "function f() { break ; break your_limits ; continue ; continue living ; debugger }"
+PASS Invalid: "break ; break your_limits ; continue ; continue living ; debugger"
+PASS Invalid: "function f() { break ; break your_limits ; continue ; continue living ; debugger }"
PASS Invalid: "debugger X"
PASS Invalid: "function f() { debugger X }"
PASS Invalid: "break 0.2"
PASS Valid: "for (var a = 7, b = c < d >= d ; f()[6]++ ; --i()[1]++ ) {}"
PASS Valid: "function f() { for (var a = 7, b = c < d >= d ; f()[6]++ ; --i()[1]++ ) {} }"
try statement
-PASS Valid: "try { break } catch(e) {}"
-PASS Valid: "function f() { try { break } catch(e) {} }"
+PASS Invalid: "try { break } catch(e) {}"
+PASS Invalid: "function f() { try { break } catch(e) {} }"
PASS Valid: "try {} finally { c++ }"
PASS Valid: "function f() { try {} finally { c++ } }"
PASS Valid: "try { with (x) { } } catch(e) {} finally { if (a) ; }"
shouldBe('eval(repeatedExpression("letterA", "+", 100))', 'repeatedString("a", 100)');
shouldBe('eval(repeatedExpression("letterA", "+", 1000))', 'repeatedString("a", 1000)');
shouldBe('eval(repeatedExpression("letterA", "+", 10000))', 'repeatedString("a", 10000)');
-shouldThrow('eval(repeatedExpression("letterA", "+", 100000))', '"SyntaxError: Expression too deep"');
+shouldThrow('eval(repeatedExpression("letterA", "+", 100000))');
var successfullyParsed = true;
shouldBe("var ctr = 3; var x = (function Named(a,b){ if(--ctr) return 2 * Named(a,b); else return a + b; }); x(5,6)", "44");
debug("regression test where kjs regarded an anonymous function declaration (which is illegal) as a FunctionExpr");
-shouldBe('try { eval("function(){ return 2; };"); return 0; } catch(e) { 1; }', "1");
+shouldBe('var hadError = 0; try { eval("function(){ return 2; };"); } catch(e) { hadError = 1; }; hadError;', "1");
var successfullyParsed = true;
valid ("{ { do do do ; while(0) while(0) while(0) } }");
valid ("do while (0) if (a) {} else y; while(0)");
valid ("if (a) while (b) if (c) with(d) {} else e; else f");
-valid ("break ; break your_limits ; continue ; continue living ; debugger");
+invalid("break ; break your_limits ; continue ; continue living ; debugger");
invalid("debugger X");
invalid("break 0.2");
invalid("continue a++");
debug ("try statement");
-valid ("try { break } catch(e) {}");
+invalid("try { break } catch(e) {}");
valid ("try {} finally { c++ }");
valid ("try { with (x) { } } catch(e) {} finally { if (a) ; }");
invalid("try {}");
+CONSOLE MESSAGE: line 82: SyntaxError: Parse error
S12.6.3_A11.1_T3
-PASS SyntaxError: Undefined label: 'nonexist'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 82: SyntaxError: Parse error
S12.6.3_A11_T3
-PASS SyntaxError: Undefined label: 'nonexist'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 82: SyntaxError: Parse error
S12.6.3_A12.1_T3
-PASS SyntaxError: Undefined label: 'nonexist'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 82: SyntaxError: Parse error
S12.6.3_A12_T3
-PASS SyntaxError: Undefined label: 'nonexist'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 80: SyntaxError: Parse error
S12.7_A1_T1
-PASS SyntaxError: Invalid continue statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 81: SyntaxError: Parse error
S12.7_A1_T2
-PASS SyntaxError: Undefined label: 'LABEL'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 82: SyntaxError: Parse error
S12.7_A1_T3
-PASS SyntaxError: Undefined label: 'LABEL'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 81: SyntaxError: Parse error
S12.7_A1_T4
-PASS SyntaxError: Invalid continue statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 80: SyntaxError: Parse error
S12.7_A5_T1
-PASS SyntaxError: Undefined label: 'LABEL_ANOTHER_LOOP'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 80: SyntaxError: Parse error
S12.7_A5_T2
-PASS SyntaxError: Undefined label: 'IN_DO_FUNC'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 81: SyntaxError: Parse error
S12.7_A5_T3
-PASS SyntaxError: Undefined label: 'LABEL_IN'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 80: SyntaxError: Parse error
S12.7_A6
-PASS SyntaxError: Undefined label: 'LABEL1'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 86: SyntaxError: Parse error
S12.7_A8_T1
-PASS SyntaxError: Undefined label: 'LABEL2'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 87: SyntaxError: Parse error
S12.7_A8_T2
-PASS SyntaxError: Invalid continue statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 80: SyntaxError: Parse error
S12.8_A1_T1
-PASS SyntaxError: Invalid break statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 81: SyntaxError: Parse error
S12.8_A1_T2
-PASS SyntaxError: Undefined label: 'LABEL'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 81: SyntaxError: Parse error
S12.8_A1_T3
-PASS SyntaxError: Invalid break statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 82: SyntaxError: Parse error
S12.8_A1_T4
-PASS SyntaxError: Undefined label: 'LABEL'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 82: SyntaxError: Parse error
S12.8_A5_T1
-PASS SyntaxError: Undefined label: 'LABEL_ANOTHER_LOOP'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 82: SyntaxError: Parse error
S12.8_A5_T2
-PASS SyntaxError: Undefined label: 'IN_DO_FUNC'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 82: SyntaxError: Parse error
S12.8_A5_T3
-PASS SyntaxError: Undefined label: 'LABEL_IN'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 80: SyntaxError: Parse error
S12.8_A6
-PASS SyntaxError: Undefined label: 'LABEL1'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 86: SyntaxError: Parse error
S12.8_A8_T1
-PASS SyntaxError: Undefined label: 'LABEL2'.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 87: SyntaxError: Parse error
S12.8_A8_T2
-PASS SyntaxError: Invalid break statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 79: SyntaxError: Parse error
S12.9_A1_T1
-PASS SyntaxError: Invalid return statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 78: SyntaxError: Parse error
S12.9_A1_T10
-PASS SyntaxError: Invalid return statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 79: SyntaxError: Parse error
S12.9_A1_T2
-PASS SyntaxError: Invalid return statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 79: SyntaxError: Parse error
S12.9_A1_T3
-PASS SyntaxError: Invalid return statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 78: SyntaxError: Parse error
S12.9_A1_T4
-PASS SyntaxError: Invalid return statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 80: SyntaxError: Parse error
S12.9_A1_T5
-PASS SyntaxError: Invalid return statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 80: SyntaxError: Parse error
S12.9_A1_T6
-PASS SyntaxError: Invalid return statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 80: SyntaxError: Parse error
S12.9_A1_T7
-PASS SyntaxError: Invalid return statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 80: SyntaxError: Parse error
S12.9_A1_T8
-PASS SyntaxError: Invalid return statement.
+PASS Expected parsing failure
TEST COMPLETE
+CONSOLE MESSAGE: line 81: SyntaxError: Parse error
S12.9_A1_T9
-PASS SyntaxError: Invalid return statement.
+PASS Expected parsing failure
TEST COMPLETE
<script>\r
\r
// This test is meaningless without layoutTestController.\r
-if (!window.layoutTestController && !window.eventSender)\r
- return;\r
+if (window.layoutTestController && window.eventSender) {\r
\r
-layoutTestController.dumpAsText();\r
-layoutTestController.waitUntilDone();\r
+ layoutTestController.dumpAsText();\r
+ layoutTestController.waitUntilDone();\r
\r
-window.textAttributeEventsCount = 0;\r
-window.xhrEventsCount = 0;\r
-window.functionAttributeEventsCount = 0;\r
-window.addEventListener("message", function(message)\r
-{\r
- layoutTestController.notifyDone();\r
-}, false);\r
-\r
-window.textAttributeEventsCallback = function()\r
-{\r
- if (textAttributeEventsCount++)\r
- document.getElementById("log").innerHTML += "PASS";\r
-}\r
-\r
-function newTest(title)\r
-{\r
- document.getElementById("log").innerHTML += "<br>" + title + ": ";\r
-}\r
+ window.textAttributeEventsCount = 0;\r
+ window.xhrEventsCount = 0;\r
+ window.functionAttributeEventsCount = 0;\r
+ window.addEventListener("message", function(message)\r
+ {\r
+ layoutTestController.notifyDone();\r
+ }, false);\r
\r
-function textAttributeEventListener()\r
-{\r
window.textAttributeEventsCallback = function()\r
{\r
- if (window.alreadyFailed)\r
- return;\r
- document.getElementById("log").innerHTML += "FAIL";\r
- window.alreadyFailed = true;\r
+ if (textAttributeEventsCount++)\r
+ document.getElementById("log").innerHTML += "PASS";\r
}\r
\r
- var test = document.getElementById("test");\r
- test.innerHTML = "<button id='button1' onclick='textAttributeEventsCallback()'></button>";\r
- document.getElementById("button1").click();\r
-}\r
+ function newTest(title)\r
+ {\r
+ document.getElementById("log").innerHTML += "<br>" + title + ": ";\r
+ }\r
\r
-function functionAttributeEventListener()\r
-{\r
- var test = document.getElementById("test");\r
- var button = test.appendChild(document.createElement("button"));\r
- window.functionAttributeEventsCount = 0;\r
- button.onclick = function()\r
+ function textAttributeEventListener()\r
{\r
- if (window.functionAttributeEventsCount++)\r
- document.getElementById("log").innerHTML += "PASS";\r
+ window.textAttributeEventsCallback = function()\r
+ {\r
+ if (window.alreadyFailed)\r
+ return;\r
+ document.getElementById("log").innerHTML += "FAIL";\r
+ window.alreadyFailed = true;\r
+ }\r
+\r
+ var test = document.getElementById("test");\r
+ test.innerHTML = "<button id='button1' onclick='textAttributeEventsCallback()'></button>";\r
+ document.getElementById("button1").click();\r
}\r
- button.style.cssText = "width: 30px;height:30px";\r
- button.click();\r
-}\r
\r
-function xhrEventListener()\r
-{\r
- window.xhrWorld = 1;\r
- var done;\r
- var xhr = new XMLHttpRequest();\r
- xhr.open("GET", "anyfile", true);\r
- xhr.onreadystatechange = function() {\r
- if (done)\r
- return;\r
- done = true;\r
- document.getElementById("log").innerHTML += window.xhrWorld ? "PASS" : "FAIL";\r
- window.postMessage("done", "*");\r
- };\r
- xhr.send(null);\r
-}\r
+ function functionAttributeEventListener()\r
+ {\r
+ var test = document.getElementById("test");\r
+ var button = test.appendChild(document.createElement("button"));\r
+ window.functionAttributeEventsCount = 0;\r
+ button.onclick = function()\r
+ {\r
+ if (window.functionAttributeEventsCount++)\r
+ document.getElementById("log").innerHTML += "PASS";\r
+ }\r
+ button.style.cssText = "width: 30px;height:30px";\r
+ button.click();\r
+ }\r
\r
-function runTestInWorld(worldId, funcName)\r
-{\r
- layoutTestController.evaluateScriptInIsolatedWorld(worldId, String(eval(funcName)) + "\n" + funcName + "();");\r
-}\r
+ function xhrEventListener()\r
+ {\r
+ window.xhrWorld = 1;\r
+ var done;\r
+ var xhr = new XMLHttpRequest();\r
+ xhr.open("GET", "anyfile", true);\r
+ xhr.onreadystatechange = function() {\r
+ if (done)\r
+ return;\r
+ done = true;\r
+ document.getElementById("log").innerHTML += window.xhrWorld ? "PASS" : "FAIL";\r
+ window.postMessage("done", "*");\r
+ };\r
+ xhr.send(null);\r
+ }\r
\r
-function runTest() \r
-{\r
- newTest("Text attribute event listeners should always fire in main world");\r
- runTestInWorld(1, "textAttributeEventListener");\r
- var button1 = document.getElementById("button1");\r
- button1.click();\r
- button1.parentElement.removeChild(button1);\r
- \r
- newTest("Function attribute event listeners should fire in the world where they were created");\r
- runTestInWorld(1, "functionAttributeEventListener");\r
- var testDiv = document.getElementById("test");\r
- // Land somewhere on the button.\r
- eventSender.mouseMoveTo(testDiv.offsetLeft + 5, testDiv.offsetTop + 5);\r
- eventSender.mouseDown();\r
- eventSender.mouseUp();\r
+ function runTestInWorld(worldId, funcName)\r
+ {\r
+ layoutTestController.evaluateScriptInIsolatedWorld(worldId, String(eval(funcName)) + "\n" + funcName + "();");\r
+ }\r
\r
- newTest("XHR attribute event listeners should fire in the world where they were created");\r
- runTestInWorld(1, "xhrEventListener");\r
-}\r
+ function runTest() \r
+ {\r
+ newTest("Text attribute event listeners should always fire in main world");\r
+ runTestInWorld(1, "textAttributeEventListener");\r
+ var button1 = document.getElementById("button1");\r
+ button1.click();\r
+ button1.parentElement.removeChild(button1);\r
+ \r
+ newTest("Function attribute event listeners should fire in the world where they were created");\r
+ runTestInWorld(1, "functionAttributeEventListener");\r
+ var testDiv = document.getElementById("test");\r
+ // Land somewhere on the button.\r
+ eventSender.mouseMoveTo(testDiv.offsetLeft + 5, testDiv.offsetTop + 5);\r
+ eventSender.mouseDown();\r
+ eventSender.mouseUp();\r
\r
+ newTest("XHR attribute event listeners should fire in the world where they were created");\r
+ runTestInWorld(1, "xhrEventListener");\r
+ }\r
+}\r
</script>\r
<body onload="runTest()">\r
<div id="test"></div>\r
<script>\r
\r
// This test is meaningless without a layoutTestController.\r
-if (!window.layoutTestController && !window.eventSender) {\r
- document.getElementById("log").innerHTML += "FAIL\n";\r
- return;\r
-}\r
-\r
-layoutTestController.setCanOpenWindows(true);\r
-layoutTestController.waitUntilDone();\r
-layoutTestController.dumpAsText();\r
-\r
-function newTest(title)\r
-{\r
- document.getElementById("log").innerHTML += "<br>" + title + ": ";\r
-}\r
-\r
-function pass()\r
-{\r
- document.getElementById("log").innerHTML += "PASS\n";\r
- layoutTestController.notifyDone();\r
-}\r
-\r
-// (This function is run within an isolated world)\r
-function userGestureEventListener()\r
-{\r
- // Register an event handler that will try to perform an action that can only be initiated by a user gesture (opening a window).\r
- document.getElementById("button1").onclick = function()\r
+if (window.layoutTestController && window.eventSender) {\r
+\r
+ layoutTestController.setCanOpenWindows(true);\r
+ layoutTestController.waitUntilDone();\r
+ layoutTestController.dumpAsText();\r
+\r
+ function newTest(title)\r
{\r
- window.open("resources/userGestureEvents-second-window.html", "resources/userGestureEvents-second-window.html");\r
+ document.getElementById("log").innerHTML += "<br>" + title + ": ";\r
}\r
-}\r
\r
-function runTestInWorld(worldId, funcName)\r
-{\r
- layoutTestController.evaluateScriptInIsolatedWorld(worldId, String(eval(funcName)) + "\n" + funcName + "();");\r
-}\r
+ function pass()\r
+ {\r
+ document.getElementById("log").innerHTML += "PASS\n";\r
+ layoutTestController.notifyDone();\r
+ }\r
\r
-function runTest() \r
-{\r
- newTest("Event handlers in isolated worlds for user gesture generated events should should the same permissions as handlers within the page.");\r
- runTestInWorld(1, "userGestureEventListener");\r
+ // (This function is run within an isolated world)\r
+ function userGestureEventListener()\r
+ {\r
+ // Register an event handler that will try to perform an action that can only be initiated by a user gesture (opening a window).\r
+ document.getElementById("button1").onclick = function()\r
+ {\r
+ window.open("resources/userGestureEvents-second-window.html", "resources/userGestureEvents-second-window.html");\r
+ }\r
+ }\r
\r
- // Click somewhere on the button!\r
- var testDiv = document.getElementById("test");\r
- eventSender.mouseMoveTo(testDiv.offsetLeft + 5, testDiv.offsetTop + 5);\r
- eventSender.mouseDown();\r
- eventSender.mouseUp();\r
-}\r
+ function runTestInWorld(worldId, funcName)\r
+ {\r
+ layoutTestController.evaluateScriptInIsolatedWorld(worldId, String(eval(funcName)) + "\n" + funcName + "();");\r
+ }\r
+\r
+ function runTest() \r
+ {\r
+ newTest("Event handlers in isolated worlds for user gesture generated events should should the same permissions as handlers within the page.");\r
+ runTestInWorld(1, "userGestureEventListener");\r
+\r
+ // Click somewhere on the button!\r
+ var testDiv = document.getElementById("test");\r
+ eventSender.mouseMoveTo(testDiv.offsetLeft + 5, testDiv.offsetTop + 5);\r
+ eventSender.mouseDown();\r
+ eventSender.mouseUp();\r
+ }\r
\r
+} else\r
+ document.getElementById("log").innerHTML += "FAIL\n";\r
</script>\r
<body onload="runTest()">\r
<div id="test"><button id='button1'></button></div>\r
}
}
-if (!window.eventSender) {
- alert("This test must be run via DRT!");
- return;
-}
-
// Start tests
-eventSender.mouseMoveTo(115, 55);
-driveTests();
+if (window.eventSender) {
+ eventSender.mouseMoveTo(115, 55);
+ driveTests();
+} else
+ alert("This test must be run via DRT!");
}
/* test that incorrect color strings throw an exception */
- var col = document.styleSheets[0].cssRules[0].style.getPropertyCSSValue("fill");
- if (!expectsException(col, "rgb(100%,100%,0%")) return;
- if (!expectsException(col, "rgba(100%,100%,0%")) return;
- if (!expectsException(col, "rgb(100%,100%,r)")) return;
- if (!expectsException(col, "rgb (100%,100%,r)")) return;
- if (!expectsException(col, "rgb(100%, 1, 1)")) return;
- if (!expectsException(col, "hsl(100%,100%,100%)")) return;
- if (!expectsException(col, "yello")) return;
- if (!expectsException(col, "!#fff")) return;
- if (!expectsException(col, "#sdf")) return;
- if (!expectsException(col, "#")) return;
- if (!expectsException(col, "#f")) return;
- if (!expectsException(col, "#ff")) return;
- if (!expectsException(col, "#ffff")) return;
- if (!expectsException(col, "#fffff")) return;
- if (!expectsException(col, "#fffffff")) return;
- if (!expectsException(col, "green,")) return;
- if (!expectsValid(col, "rgb(0, 10, 20)", "#000A14")) return;
- if (!expectsValid(col, "#FFF", "#FFFFFF")) return;
- if (!expectsValid(col, "#FFFFFF", "#FFFFFF")) return;
- if (!expectsValid(col, " green", "#008000")) return;
- if (!expectsValid(col, "green ", "#008000")) return;
- if (!expectsValid(col, "green", "#008000")) return;
+ function testIncorrectColor() {
+ var col = document.styleSheets[0].cssRules[0].style.getPropertyCSSValue("fill");
+ if (!expectsException(col, "rgb(100%,100%,0%")) return;
+ if (!expectsException(col, "rgba(100%,100%,0%")) return;
+ if (!expectsException(col, "rgb(100%,100%,r)")) return;
+ if (!expectsException(col, "rgb (100%,100%,r)")) return;
+ if (!expectsException(col, "rgb(100%, 1, 1)")) return;
+ if (!expectsException(col, "hsl(100%,100%,100%)")) return;
+ if (!expectsException(col, "yello")) return;
+ if (!expectsException(col, "!#fff")) return;
+ if (!expectsException(col, "#sdf")) return;
+ if (!expectsException(col, "#")) return;
+ if (!expectsException(col, "#f")) return;
+ if (!expectsException(col, "#ff")) return;
+ if (!expectsException(col, "#ffff")) return;
+ if (!expectsException(col, "#fffff")) return;
+ if (!expectsException(col, "#fffffff")) return;
+ if (!expectsException(col, "green,")) return;
+ if (!expectsValid(col, "rgb(0, 10, 20)", "#000A14")) return;
+ if (!expectsValid(col, "#FFF", "#FFFFFF")) return;
+ if (!expectsValid(col, "#FFFFFF", "#FFFFFF")) return;
+ if (!expectsValid(col, " green", "#008000")) return;
+ if (!expectsValid(col, "green ", "#008000")) return;
+ if (!expectsValid(col, "green", "#008000")) return;
+ }
+ testIncorrectColor();
</script>
</svg>
<text id="text" x="70" y="70">Test failed.</text>
<script>
-var useElement = document.getElementsByTagName("use")[1];
-if (useElement != useElement.instanceRoot.correspondingUseElement)
- return;
-
-var element = useElement.instanceRoot.correspondingElement;
-if (element != document.getElementById("g"))
- return;
-
-// element.firstChild is a #text node! the next sibling gives the rect
-var rect = element.firstChild.nextSibling;
-if (rect != document.getElementById("rect"))
- return;
-
-// rect.nextSibling is a #text node! the next sibling gives the circle
-var circle = rect.nextSibling.nextSibling;
-if (circle != document.getElementById("circle"))
- return;
-
-rect.setAttribute("fill", "green");
-circle.setAttribute("opacity", "0.8");
-
-document.getElementById("text").firstChild.nodeValue = "Test passed.";
+function runInstanceRootTest() {
+ var useElement = document.getElementsByTagName("use")[1];
+ if (useElement != useElement.instanceRoot.correspondingUseElement)
+ return;
+
+ var element = useElement.instanceRoot.correspondingElement;
+ if (element != document.getElementById("g"))
+ return;
+
+ // element.firstChild is a #text node! the next sibling gives the rect
+ var rect = element.firstChild.nextSibling;
+ if (rect != document.getElementById("rect"))
+ return;
+
+ // rect.nextSibling is a #text node! the next sibling gives the circle
+ var circle = rect.nextSibling.nextSibling;
+ if (circle != document.getElementById("circle"))
+ return;
+
+ rect.setAttribute("fill", "green");
+ circle.setAttribute("opacity", "0.8");
+
+ document.getElementById("text").firstChild.nodeValue = "Test passed.";
+}
+runInstanceRootTest();
</script>
</svg>
var use1 = document.getElementById("use1");
var use2 = document.getElementById("use2");
- if (!use1 || !use2)
- return;
-
- use1.href.baseVal = "#rect";
-
- use2.x.baseVal.value = 200;
- use2.y.baseVal.value = -50;
+ if (use1 && use2) {
+ use1.href.baseVal = "#rect";
+ use2.x.baseVal.value = 200;
+ use2.y.baseVal.value = -50;
+ }
]]>
</script>
</svg>
<dict>
<key>WebResourceData</key>
<string><html><head><script>
-if (!window.parent.bodyToAdopt) {
+if (window.parent.bodyToAdopt) {
+ document.getElementsByTagName("html")[0].appendChild(document.adoptNode(window.parent.bodyToAdopt));
+ window.parent.bodyToAdopt = null;
+} else
alert("window.parent.bodyToAdopt is not set - Are you viewing this page as part of the adopt-attribute-styled-body test?");
- return;
-}
-document.getElementsByTagName("html")[0].appendChild(document.adoptNode(window.parent.bodyToAdopt));
-window.parent.bodyToAdopt = null;
</script>
</head><body id="otherBody" vlink="green" alink="green">
<a href="SomeUnvisitedPage.html">Spaceballs: The Unvisited Link</a><br>
<script>
-if (!window.parent.bodyToAdopt) {
+if (window.parent.bodyToAdopt) {
+ document.getElementsByTagName("html")[0].appendChild(document.adoptNode(window.parent.bodyToAdopt));
+ window.parent.bodyToAdopt = null;
+} else
alert("window.parent.bodyToAdopt is not set - Are you viewing this page as part of the adopt-attribute-styled-body test?");
- return;
-}
-document.getElementsByTagName("html")[0].appendChild(document.adoptNode(window.parent.bodyToAdopt));
-window.parent.bodyToAdopt = null;
</script>
\
yarr/RegexPattern.cpp \
yarr/RegexInterpreter.cpp \
- yarr/RegexJIT.cpp
+ yarr/RegexJIT.cpp \
+ yarr/YarrSyntaxChecker.cpp
# generated headers
JSC_OBJECTS := $(addprefix $(intermediates)/runtime/, \
yarr/RegexPattern.cpp
yarr/RegexInterpreter.cpp
yarr/RegexJIT.cpp
+ yarr/YarrSyntaxChecker.cpp
wtf/DateMath.cpp
wtf/PageAllocationAligned.cpp
+2011-01-10 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Bug 52079 - Syntax errors should be early errors.
+
+ From chapter 16 the spec:
+ An implementation must report most errors at the time the relevant ECMAScript language construct is
+ evaluated. An early error is an error that can be detected and reported prior to the evaluation of
+ any construct in the Program containing the error. An implementation must report early errors in a
+ Program prior to the first evaluation of that Program. Early errors in eval code are reported at
+ the time eval is called but prior to evaluation of any construct within the eval code. All errors
+ that are not early errors are runtime errors.
+
+ An implementation must treat any instance of the following kinds of errors as an early error:
+ * Any syntax error."
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ Added new files.
+ * bytecode/CodeBlock.cpp:
+ Removed op_throw_syntax_error.
+ * bytecode/Opcode.h:
+ Removed op_throw_syntax_error.
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::generate):
+ If m_expressionTooDeep then throw a runtime error.
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ Initialize m_expressionTooDeep.
+ (JSC::BytecodeGenerator::emitThrowExpressionTooDeepException):
+ Sets m_expressionTooDeep.
+ * bytecompiler/BytecodeGenerator.h:
+ Added m_expressionTooDeep, removed emitThrowSyntaxError.
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::RegExpNode::emitBytecode):
+ (JSC::ContinueNode::emitBytecode):
+ (JSC::BreakNode::emitBytecode):
+ (JSC::ReturnNode::emitBytecode):
+ (JSC::LabelNode::emitBytecode):
+ Conditions that threw syntax error are now handled during parsing;
+ during bytecompilation these are now just ASSERTs.
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ * jit/JIT.h:
+ * jit/JITOpcodes.cpp:
+ * jit/JITOpcodes32_64.cpp:
+ * jit/JITStubs.cpp:
+ * jit/JITStubs.h:
+ Removed op_throw_syntax_error.
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::createRegExp):
+ Renamed; added syntax check.
+ * parser/JSParser.cpp:
+ (JSC::JSParser::breakIsValid):
+ (JSC::JSParser::hasLabel):
+ (JSC::JSParser::Scope::Scope):
+ (JSC::JSParser::Scope::setIsFunction):
+ (JSC::JSParser::Scope::isFunctionBoundary):
+ (JSC::JSParser::ScopeRef::hasContainingScope):
+ (JSC::JSParser::ScopeRef::containingScope):
+ (JSC::JSParser::AutoPopScopeRef::AutoPopScopeRef):
+ (JSC::JSParser::AutoPopScopeRef::~AutoPopScopeRef):
+ (JSC::JSParser::AutoPopScopeRef::setPopped):
+ (JSC::JSParser::popScopeInternal):
+ (JSC::JSParser::popScope):
+ (JSC::jsParse):
+ (JSC::JSParser::JSParser):
+ (JSC::JSParser::parseProgram):
+ (JSC::JSParser::parseBreakStatement):
+ (JSC::JSParser::parseContinueStatement):
+ (JSC::JSParser::parseReturnStatement):
+ (JSC::JSParser::parseTryStatement):
+ (JSC::JSParser::parseFunctionInfo):
+ (JSC::JSParser::parseExpressionOrLabelStatement):
+ (JSC::JSParser::parsePrimaryExpression):
+ * parser/JSParser.h:
+ * parser/Nodes.h:
+ * parser/Parser.cpp:
+ (JSC::Parser::parse):
+ * parser/SyntaxChecker.h:
+ (JSC::SyntaxChecker::createRegExp):
+ Renamed; added syntax check.
+ * runtime/ExceptionHelpers.cpp:
+ (JSC::createOutOfMemoryError):
+ (JSC::throwOutOfMemoryError):
+ * runtime/ExceptionHelpers.h:
+ Broke out createOutOfMemoryError.
+ * runtime/Executable.cpp:
+ (JSC::EvalExecutable::compileInternal):
+ (JSC::ProgramExecutable::compileInternal):
+ (JSC::FunctionExecutable::compileForCallInternal):
+ (JSC::FunctionExecutable::compileForConstructInternal):
+ Add check for exception after bytecode generation.
+ * runtime/RegExpConstructor.cpp:
+ (JSC::constructRegExp):
+ * runtime/RegExpPrototype.cpp:
+ (JSC::regExpProtoFuncCompile):
+ RegExp error prefixes not included in error string.
+ * yarr/RegexParser.h:
+ (JSC::Yarr::Parser::parse):
+ Removed regexBegin/regexEnd/regexError.
+ * yarr/RegexPattern.cpp:
+ (JSC::Yarr::RegexPatternConstructor::regexBegin):
+ Removed regexEnd/regexError.
+ (JSC::Yarr::compileRegex):
+ Add call to regexBegin (no longer called from the parser).
+ * yarr/YarrSyntaxChecker.cpp: Added.
+ (JSC::Yarr::SyntaxChecker::assertionBOL):
+ (JSC::Yarr::SyntaxChecker::assertionEOL):
+ (JSC::Yarr::SyntaxChecker::assertionWordBoundary):
+ (JSC::Yarr::SyntaxChecker::atomPatternCharacter):
+ (JSC::Yarr::SyntaxChecker::atomBuiltInCharacterClass):
+ (JSC::Yarr::SyntaxChecker::atomCharacterClassBegin):
+ (JSC::Yarr::SyntaxChecker::atomCharacterClassAtom):
+ (JSC::Yarr::SyntaxChecker::atomCharacterClassRange):
+ (JSC::Yarr::SyntaxChecker::atomCharacterClassBuiltIn):
+ (JSC::Yarr::SyntaxChecker::atomCharacterClassEnd):
+ (JSC::Yarr::SyntaxChecker::atomParenthesesSubpatternBegin):
+ (JSC::Yarr::SyntaxChecker::atomParentheticalAssertionBegin):
+ (JSC::Yarr::SyntaxChecker::atomParenthesesEnd):
+ (JSC::Yarr::SyntaxChecker::atomBackReference):
+ (JSC::Yarr::SyntaxChecker::quantifyAtom):
+ (JSC::Yarr::SyntaxChecker::disjunction):
+ (JSC::Yarr::checkSyntax):
+ * yarr/YarrSyntaxChecker.h: Added.
+ Check RegExp syntax.
+
2011-01-10 Adam Roben <aroben@apple.com>
Roll out r75289
Source/JavaScriptCore/yarr/RegexJIT.h \
Source/JavaScriptCore/yarr/RegexParser.h \
Source/JavaScriptCore/yarr/RegexPattern.cpp \
- Source/JavaScriptCore/yarr/RegexPattern.h
+ Source/JavaScriptCore/yarr/RegexPattern.h \
+ Source/JavaScriptCore/yarr/YarrSyntaxChecker.cpp \
+ Source/JavaScriptCore/yarr/YarrSyntaxChecker.h
if TARGET_WIN32
javascriptcore_sources += \
'yarr/RegexParser.h',
'yarr/RegexPattern.cpp',
'yarr/RegexPattern.h',
+ 'yarr/YarrSyntaxChecker.cpp',
+ 'yarr/YarrSyntaxChecker.h',
]
}
}
runtime/UString.cpp \
yarr/RegexPattern.cpp \
yarr/RegexInterpreter.cpp \
- yarr/RegexJIT.cpp
+ yarr/RegexJIT.cpp \
+ yarr/ YarrSyntaxChecker.cpp
# Generated files, simply list them for JavaScriptCore
RelativePath="..\..\yarr\RegexPattern.h"
>
</File>
+ <File
+ RelativePath="..\..\yarr\YarrSyntaxChecker.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\yarr\YarrSyntaxChecker.h"
+ >
+ </File>
</Filter>
<Filter
Name="jit"
86565743115BE3DA00291F40 /* CString.h in Headers */ = {isa = PBXBuildFile; fileRef = 86565741115BE3DA00291F40 /* CString.h */; settings = {ATTRIBUTES = (Private, ); }; };
865F408810E7D56300947361 /* APIShims.h in Headers */ = {isa = PBXBuildFile; fileRef = 865F408710E7D56300947361 /* APIShims.h */; };
86676D5211FED9BC004B6863 /* BumpPointerAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 86676D4D11FED55D004B6863 /* BumpPointerAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B4012DB8A8100A9FE7B /* YarrSyntaxChecker.cpp */; };
+ 86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B4112DB8A8100A9FE7B /* YarrSyntaxChecker.h */; };
868BFA08117CEFD100B908B1 /* AtomicString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA00117CEFD100B908B1 /* AtomicString.cpp */; };
868BFA09117CEFD100B908B1 /* AtomicString.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA01117CEFD100B908B1 /* AtomicString.h */; settings = {ATTRIBUTES = (Private, ); }; };
868BFA0A117CEFD100B908B1 /* AtomicStringImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA02117CEFD100B908B1 /* AtomicStringImpl.h */; settings = {ATTRIBUTES = (Private, ); }; };
86565741115BE3DA00291F40 /* CString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CString.h; path = text/CString.h; sourceTree = "<group>"; };
865F408710E7D56300947361 /* APIShims.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIShims.h; sourceTree = "<group>"; };
86676D4D11FED55D004B6863 /* BumpPointerAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BumpPointerAllocator.h; sourceTree = "<group>"; };
+ 86704B4012DB8A8100A9FE7B /* YarrSyntaxChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrSyntaxChecker.cpp; path = yarr/YarrSyntaxChecker.cpp; sourceTree = "<group>"; };
+ 86704B4112DB8A8100A9FE7B /* YarrSyntaxChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrSyntaxChecker.h; path = yarr/YarrSyntaxChecker.h; sourceTree = "<group>"; };
867FC35F11B763950025105E /* JavaScriptCore.JSVALUE32_64only.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = JavaScriptCore.JSVALUE32_64only.exp; sourceTree = "<group>"; };
867FC36011B763950025105E /* JavaScriptCore.JSVALUE32only.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = JavaScriptCore.JSVALUE32only.exp; sourceTree = "<group>"; };
867FC36111B763950025105E /* JavaScriptCore.JSVALUE64only.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = JavaScriptCore.JSVALUE64only.exp; sourceTree = "<group>"; };
86EAC48C0F93E8B9008EC948 /* yarr */ = {
isa = PBXGroup;
children = (
+ 86704B4012DB8A8100A9FE7B /* YarrSyntaxChecker.cpp */,
+ 86704B4112DB8A8100A9FE7B /* YarrSyntaxChecker.h */,
86EAC48F0F93E8D1008EC948 /* RegexInterpreter.cpp */,
86EAC4900F93E8D1008EC948 /* RegexInterpreter.h */,
86EAC4910F93E8D1008EC948 /* RegexJIT.cpp */,
14FFF98D12BFFF7500795BB8 /* PageAllocationAligned.h in Headers */,
5135FAF212D26ACE003C083B /* Decoder.h in Headers */,
5135FAF312D26AD1003C083B /* Encoder.h in Headers */,
+ 86704B4312DB8A8100A9FE7B /* YarrSyntaxChecker.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E1EF79AA0CE97BA60088D500 /* UTF8.cpp in Sources */,
868BFA17117CF19900B908B1 /* WTFString.cpp in Sources */,
86D08D5311793613006E5ED0 /* WTFThreadData.cpp in Sources */,
+ 86704B4212DB8A8100A9FE7B /* YarrSyntaxChecker.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
printf("[%4d] throw_reference_error\t %s\n", location, constantName(exec, k0, getConstant(k0)).data());
break;
}
- case op_throw_syntax_error: {
- int k0 = (++it)->u.operand;
- printf("[%4d] throw_syntax_error\t %s\n", location, constantName(exec, k0, getConstant(k0)).data());
- break;
- }
case op_jsr: {
int retAddrDst = (++it)->u.operand;
int offset = (++it)->u.operand;
macro(op_catch, 2) \
macro(op_throw, 2) \
macro(op_throw_reference_error, 2) \
- macro(op_throw_syntax_error, 2) \
\
macro(op_jsr, 3) \
macro(op_sret, 2) \
#endif
}
-void BytecodeGenerator::generate()
+JSObject* BytecodeGenerator::generate()
{
m_codeBlock->setThisRegister(m_thisRegister.index());
symbolTable().clear();
m_codeBlock->shrinkToFit();
+
+ if (m_expressionTooDeep)
+ return createOutOfMemoryError(m_scopeChain->globalObject());
+ return 0;
}
bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
, m_usesExceptions(false)
, m_regeneratingForExceptionInfo(false)
, m_codeBlockBeingRegeneratedFrom(0)
+ , m_expressionTooDeep(false)
{
if (m_shouldEmitDebugHooks)
m_codeBlock->setNeedsFullScopeChain(true);
, m_usesExceptions(false)
, m_regeneratingForExceptionInfo(false)
, m_codeBlockBeingRegeneratedFrom(0)
+ , m_expressionTooDeep(false)
{
if (m_shouldEmitDebugHooks)
m_codeBlock->setNeedsFullScopeChain(true);
, m_usesExceptions(false)
, m_regeneratingForExceptionInfo(false)
, m_codeBlockBeingRegeneratedFrom(0)
+ , m_expressionTooDeep(false)
{
if (m_shouldEmitDebugHooks || m_baseScopeDepth)
m_codeBlock->setNeedsFullScopeChain(true);
instructions().append(addConstantValue(jsString(globalData(), message))->index());
}
-void BytecodeGenerator::emitThrowSyntaxError(const UString& message)
-{
- emitOpcode(op_throw_syntax_error);
- instructions().append(addConstantValue(jsString(globalData(), message))->index());
-}
-
PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally)
{
size_t begin = instructions().size();
// And we could make the caller pass the node pointer in, if there was some way of getting
// that from an arbitrary node. However, calling emitExpressionInfo without any useful data
// is still good enough to get us an accurate line number.
- emitExpressionInfo(0, 0, 0);
- emitThrowSyntaxError("Expression too deep");
+ m_expressionTooDeep = true;
return newTemporary();
}
bool isConstructor() { return m_codeBlock->m_isConstructor; }
- void generate();
+ JSObject* generate();
// Returns the register corresponding to a local variable, or 0 if no
// such register exists. Registers returned by registerFor do not
}
void emitThrowReferenceError(const UString& message);
- void emitThrowSyntaxError(const UString& message);
void emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value);
bool m_usesExceptions;
bool m_regeneratingForExceptionInfo;
CodeBlock* m_codeBlockBeingRegeneratedFrom;
+ bool m_expressionTooDeep;
};
}
return generator.newTemporary();
}
-RegisterID* ThrowableExpressionData::emitThrowSyntaxError(BytecodeGenerator& generator, const UString& message)
-{
- generator.emitExpressionInfo(divot(), startOffset(), endOffset());
- generator.emitThrowSyntaxError(message);
- return generator.newTemporary();
-}
-
// ------------------------------ NullNode -------------------------------------
RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
- RefPtr<RegExp> regExp = generator.globalData()->regExpCache()->lookupOrCreate(m_pattern.ustring(), m_flags.ustring());
- if (!regExp->isValid())
- return emitThrowSyntaxError(generator, makeUString("Invalid regular expression: ", regExp->errorMessage()));
if (dst == generator.ignoredResult())
return 0;
+ RefPtr<RegExp> regExp = generator.globalData()->regExpCache()->lookupOrCreate(m_pattern.ustring(), m_flags.ustring());
+ ASSERT(regExp->isValid());
return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
}
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
LabelScope* scope = generator.continueTarget(m_ident);
-
- if (!scope) {
- if (m_ident.isEmpty())
- return emitThrowSyntaxError(generator, "Invalid continue statement.");
- return emitThrowSyntaxError(generator, makeUString("Undefined label: '", m_ident.ustring(), "'."));
- }
+ ASSERT(scope);
generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
return dst;
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
LabelScope* scope = generator.breakTarget(m_ident);
-
- if (!scope) {
- if (m_ident.isEmpty())
- return emitThrowSyntaxError(generator, "Invalid break statement.");
- return emitThrowSyntaxError(generator, makeUString("Undefined label: '", m_ident.ustring(), "'."));
- }
+ ASSERT(scope);
generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
return dst;
RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
- if (generator.codeType() != FunctionCode)
- return emitThrowSyntaxError(generator, "Invalid return statement.");
+ ASSERT(generator.codeType() == FunctionCode);
if (dst == generator.ignoredResult())
dst = 0;
{
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
- if (generator.breakTarget(m_name))
- return emitThrowSyntaxError(generator, makeUString("Duplicate label: ", m_name.ustring(), "."));
+ ASSERT(!generator.breakTarget(m_name));
RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
RegisterID* r0 = generator.emitNode(dst, m_statement);
exceptionValue = JSValue(createReferenceError(callFrame, message));
goto vm_throw;
}
- DEFINE_OPCODE(op_throw_syntax_error) {
- /* op_throw_syntax_error message(k)
-
- Constructs a new syntax Error instance using the
- original constructor, using constant message as the
- message string. The result is thrown.
- */
- UString message = callFrame->r(vPC[1].u.operand).jsValue().toString(callFrame);
- exceptionValue = JSValue(createSyntaxError(callFrame, message));
- goto vm_throw;
- }
DEFINE_OPCODE(op_end) {
/* end result(r)
DEFINE_OP(op_tear_off_arguments)
DEFINE_OP(op_throw)
DEFINE_OP(op_throw_reference_error)
- DEFINE_OP(op_throw_syntax_error)
DEFINE_OP(op_to_jsnumber)
DEFINE_OP(op_to_primitive)
void emit_op_tear_off_arguments(Instruction*);
void emit_op_throw(Instruction*);
void emit_op_throw_reference_error(Instruction*);
- void emit_op_throw_syntax_error(Instruction*);
void emit_op_to_jsnumber(Instruction*);
void emit_op_to_primitive(Instruction*);
void emit_op_unexpected_load(Instruction*);
stubCall.call();
}
-void JIT::emit_op_throw_syntax_error(Instruction* currentInstruction)
-{
- JITStubCall stubCall(this, cti_op_throw_syntax_error);
- stubCall.addArgument(ImmPtr(JSValue::encode(m_codeBlock->getConstant(currentInstruction[1].u.operand))));
- stubCall.call();
-}
-
void JIT::emit_op_debug(Instruction* currentInstruction)
{
#if ENABLE(DEBUG_WITH_BREAKPOINT)
stubCall.call();
}
-void JIT::emit_op_throw_syntax_error(Instruction* currentInstruction)
-{
- unsigned message = currentInstruction[1].u.operand;
-
- JITStubCall stubCall(this, cti_op_throw_syntax_error);
- stubCall.addArgument(m_codeBlock->getConstant(message));
- stubCall.call();
-}
-
void JIT::emit_op_debug(Instruction* currentInstruction)
{
#if ENABLE(DEBUG_WITH_BREAKPOINT)
VM_THROW_EXCEPTION_AT_END();
}
-DEFINE_STUB_FUNCTION(void, op_throw_syntax_error)
-{
- STUB_INIT_STACK_FRAME(stackFrame);
-
- CallFrame* callFrame = stackFrame.callFrame;
- UString message = stackFrame.args[0].jsValue().toString(callFrame);
- stackFrame.globalData->exception = createSyntaxError(callFrame, message);
- VM_THROW_EXCEPTION_AT_END();
-}
-
DEFINE_STUB_FUNCTION(void, op_debug)
{
STUB_INIT_STACK_FRAME(stackFrame);
void JIT_STUB cti_op_tear_off_activation(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_throw_reference_error(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_op_throw_syntax_error(STUB_ARGS_DECLARATION);
void* JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION);
void* JIT_STUB cti_op_construct_arityCheck(STUB_ARGS_DECLARATION);
void* JIT_STUB cti_op_call_jitCompile(STUB_ARGS_DECLARATION);
return node;
}
- ExpressionNode* createRegex(const Identifier& pattern, const Identifier& flags, int start)
+ ExpressionNode* createRegExp(const Identifier& pattern, const Identifier& flags, int start)
{
+ if (Yarr::checkSyntax(pattern.ustring()))
+ return 0;
RegExpNode* node = new (m_globalData) RegExpNode(m_globalData, pattern, flags);
int size = pattern.length() + 2; // + 2 for the two /'s
setExceptionLocation(node, start, start + size, start + size);
class JSParser {
public:
JSParser(Lexer*, JSGlobalData*, FunctionParameters*, bool isStrictContext, bool isFunction, SourceProvider*);
- bool parseProgram();
+ const char* parseProgram();
private:
struct AllowInOverride {
AllowInOverride(JSParser* parser)
bool strictMode() { return currentScope()->strictMode(); }
bool isValidStrictMode() { return currentScope()->isValidStrictMode(); }
bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); }
- bool breakIsValid() { return currentScope()->breakIsValid(); }
+ bool breakIsValid()
+ {
+ ScopeRef current = currentScope();
+ while (!current->breakIsValid()) {
+ if (!current.hasContainingScope())
+ return false;
+ current = current.containingScope();
+ }
+ return true;
+ }
void pushLabel(const Identifier* label) { currentScope()->pushLabel(label); }
void popLabel() { currentScope()->popLabel(); }
- bool hasLabel(const Identifier* label) { return currentScope()->hasLabel(label); }
+ bool hasLabel(const Identifier* label)
+ {
+ ScopeRef current = currentScope();
+ while (!current->hasLabel(label)) {
+ if (!current.hasContainingScope())
+ return false;
+ current = current.containingScope();
+ }
+ return true;
+ }
enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode };
template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&);
Lexer* m_lexer;
StackBounds m_stack;
bool m_error;
+ const char* m_errorMessage;
JSGlobalData* m_globalData;
JSToken m_token;
bool m_allowsIn;
, m_allowsNewDecls(true)
, m_strictMode(strictMode)
, m_isFunction(isFunction)
+ , m_isFunctionBoundary(false)
, m_isValidStrictMode(true)
, m_loopDepth(0)
, m_switchDepth(0)
return false;
}
- void setIsFunction() { m_isFunction = true; }
+ void setIsFunction()
+ {
+ m_isFunction = true;
+ m_isFunctionBoundary = true;
+ }
bool isFunction() { return m_isFunction; }
+ bool isFunctionBoundary() { return m_isFunctionBoundary; }
bool declareVariable(const Identifier* ident)
{
bool m_allowsNewDecls : 1;
bool m_strictMode : 1;
bool m_isFunction : 1;
+ bool m_isFunctionBoundary : 1;
bool m_isValidStrictMode : 1;
int m_loopDepth;
int m_switchDepth;
}
Scope* operator->() { return &m_scopeStack->at(m_index); }
unsigned index() const { return m_index; }
+
+ bool hasContainingScope()
+ {
+ return m_index && !m_scopeStack->at(m_index).isFunctionBoundary();
+ }
+
+ ScopeRef containingScope()
+ {
+ ASSERT(hasContainingScope());
+ return ScopeRef(m_scopeStack, m_index - 1);
+ }
+
private:
ScopeStack* m_scopeStack;
unsigned m_index;
};
-
+
+ struct AutoPopScopeRef : public ScopeRef {
+ AutoPopScopeRef(JSParser* parser, ScopeRef scope)
+ : ScopeRef(scope)
+ , m_parser(parser)
+ {
+ }
+
+ ~AutoPopScopeRef()
+ {
+ if (m_parser)
+ m_parser->popScope(*this, false);
+ }
+
+ void setPopped()
+ {
+ m_parser = 0;
+ }
+
+ private:
+ JSParser* m_parser;
+ };
+
ScopeRef currentScope()
{
return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1);
return currentScope();
}
- bool popScope(ScopeRef scope, bool shouldTrackClosedVariables)
+ bool popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables)
{
ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1);
ASSERT(m_scopeStack.size() > 1);
m_scopeStack.removeLast();
return result;
}
-
+
+ bool popScope(ScopeRef& scope, bool shouldTrackClosedVariables)
+ {
+ return popScopeInternal(scope, shouldTrackClosedVariables);
+ }
+
+ bool popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables)
+ {
+ scope.setPopped();
+ return popScopeInternal(scope, shouldTrackClosedVariables);
+ }
+
bool declareVariable(const Identifier* ident)
{
unsigned i = m_scopeStack.size() - 1;
ScopeStack m_scopeStack;
};
-int jsParse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, const SourceCode* source)
+const char* jsParse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, const SourceCode* source)
{
JSParser parser(globalData->lexer, globalData, parameters, strictness == JSParseStrict, parserMode == JSParseFunctionCode, source->provider());
return parser.parseProgram();
: m_lexer(lexer)
, m_stack(globalData->stack())
, m_error(false)
+ , m_errorMessage("Parse error")
, m_globalData(globalData)
, m_allowsIn(true)
, m_tokenCount(0)
m_lexer->setLastLineNumber(tokenLine());
}
-bool JSParser::parseProgram()
+const char* JSParser::parseProgram()
{
ASTBuilder context(m_globalData, m_lexer);
if (m_lexer->isReparsing())
ScopeRef scope = currentScope();
SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context);
if (!sourceElements || !consume(EOFTOK))
- return true;
+ return m_errorMessage;
IdentifierSet capturedVariables;
scope->getCapturedVariables(capturedVariables);
CodeFeatures features = context.features();
m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
m_lastLine, context.numConstants(), capturedVariables);
- return false;
+ return 0;
}
bool JSParser::allowAutomaticSemicolon()
next();
if (autoSemiColon()) {
- failIfFalseIfStrict(breakIsValid());
+ failIfFalse(breakIsValid());
return context.createBreakStatement(startCol, endCol, startLine, endLine);
}
matchOrFail(IDENT);
const Identifier* ident = m_token.m_data.ident;
- failIfFalseIfStrict(hasLabel(ident));
+ failIfFalse(hasLabel(ident));
endCol = tokenEnd();
endLine = tokenLine();
next();
next();
if (autoSemiColon()) {
- failIfFalseIfStrict(breakIsValid());
+ failIfFalse(breakIsValid());
return context.createContinueStatement(startCol, endCol, startLine, endLine);
}
matchOrFail(IDENT);
const Identifier* ident = m_token.m_data.ident;
- failIfFalseIfStrict(hasLabel(ident));
+ failIfFalse(hasLabel(ident));
endCol = tokenEnd();
endLine = tokenLine();
next();
template <class TreeBuilder> TreeStatement JSParser::parseReturnStatement(TreeBuilder& context)
{
ASSERT(match(RETURN));
- failIfFalseIfStrict(currentScope()->isFunction());
+ failIfFalse(currentScope()->isFunction());
int startLine = tokenLine();
int endLine = startLine;
int start = tokenStart();
matchOrFail(IDENT);
ident = m_token.m_data.ident;
next();
- ScopeRef catchScope = pushScope();
+ AutoPopScopeRef catchScope(this, pushScope());
failIfFalseIfStrict(catchScope->declareVariable(ident));
catchScope->preventNewDecls();
consumeOrFail(CLOSEPAREN);
template <JSParser::FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool JSParser::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine)
{
- ScopeRef functionScope = pushScope();
+ AutoPopScopeRef functionScope(this, pushScope());
functionScope->setIsFunction();
if (match(IDENT)) {
name = m_token.m_data.ident;
int end = tokenEnd();
consumeOrFail(COLON);
const Identifier* unused = 0;
- if (strictMode() && !m_syntaxAlreadyValidated)
+ if (!m_syntaxAlreadyValidated) {
+ failIfTrue(hasLabel(ident));
pushLabel(ident);
+ }
TreeStatement statement = parseStatement(context, unused);
- if (strictMode() && !m_syntaxAlreadyValidated)
+ if (!m_syntaxAlreadyValidated)
popLabel();
failIfFalse(statement);
return context.createLabelStatement(ident, statement, start, end);
int start = tokenStart();
next();
- return context.createRegex(*pattern, *flags, start);
+ TreeExpression re = context.createRegExp(*pattern, *flags, start);
+ if (!re) {
+ m_errorMessage = Yarr::checkSyntax(pattern->ustring());
+ ASSERT(m_errorMessage);
+ fail();
+ }
+ return re;
}
default:
fail();
enum JSParserStrictness { JSParseNormal, JSParseStrict };
enum JSParserMode { JSParseProgramCode, JSParseFunctionCode };
-int jsParse(JSGlobalData*, FunctionParameters*, JSParserStrictness, JSParserMode, const SourceCode*);
+const char* jsParse(JSGlobalData*, FunctionParameters*, JSParserStrictness, JSParserMode, const SourceCode*);
}
#endif // JSParser_h
protected:
RegisterID* emitThrowReferenceError(BytecodeGenerator&, const UString& message);
- RegisterID* emitThrowSyntaxError(BytecodeGenerator&, const UString& message);
private:
uint32_t m_divot;
Lexer& lexer = *globalData->lexer;
lexer.setCode(*m_source, m_arena);
- int parseError = jsParse(globalData, parameters, strictness, mode, m_source);
+ const char* parseError = jsParse(globalData, parameters, strictness, mode, m_source);
int lineNumber = lexer.lineNumber();
bool lexError = lexer.sawError();
lexer.clear();
if (parseError || lexError) {
*errLine = lineNumber;
- *errMsg = "Parse error";
+ *errMsg = parseError ? parseError : "Parse error";
m_sourceElements = 0;
}
}
#ifndef SyntaxChecker_h
#define SyntaxChecker_h
+#include "YarrSyntaxChecker.h"
+
namespace JSC {
class SyntaxChecker {
public:
ExpressionType createNull() { return NullExpr; }
ExpressionType createBracketAccess(ExpressionType, ExpressionType, bool, int, int, int) { return BracketExpr; }
ExpressionType createDotAccess(ExpressionType, const Identifier&, int, int, int) { return DotExpr; }
- ExpressionType createRegex(const Identifier&, const Identifier&, int) { return RegExpExpr; }
+ ExpressionType createRegExp(const Identifier& pattern, const Identifier&, int) { return Yarr::checkSyntax(pattern.ustring()) ? 0 : RegExpExpr; }
ExpressionType createNewExpr(ExpressionType, int, int, int, int) { return NewExpr; }
ExpressionType createNewExpr(ExpressionType, int, int) { return NewExpr; }
ExpressionType createConditionalExpr(ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; }
JSObject* createErrorForInvalidGlobalAssignment(ExecState* exec, const UString& propertyName)
{
return createReferenceError(exec, makeUString("Strict mode forbids implicit creation of global property '", propertyName, "'"));
-}
+}
+
+JSObject* createOutOfMemoryError(JSGlobalObject* globalObject)
+{
+ return createError(globalObject, "Out of memory");
+}
JSObject* throwOutOfMemoryError(ExecState* exec)
{
- return throwError(exec, createError(exec, "Out of memory"));
+ return throwError(exec, createOutOfMemoryError(exec->lexicalGlobalObject()));
}
JSObject* throwStackOverflowError(ExecState* exec)
JSObject* createTerminatedExecutionException(JSGlobalData*);
JSObject* createStackOverflowError(ExecState*);
JSObject* createStackOverflowError(JSGlobalObject*);
+ JSObject* createOutOfMemoryError(JSGlobalObject*);
JSObject* createUndefinedVariableError(ExecState*, const Identifier&);
JSObject* createNotAnObjectError(ExecState*, JSValue);
JSObject* createInvalidParamError(ExecState*, const char* op, JSValue);
ASSERT(!m_evalCodeBlock);
m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock.get())));
- generator->generate();
-
+ if ((exception = generator->generate())) {
+ m_evalCodeBlock.clear();
+ evalNode->destroyData();
+ return exception;
+ }
+
evalNode->destroyData();
#if ENABLE(JIT)
m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock.get())));
- generator->generate();
+ if ((exception = generator->generate())) {
+ m_programCodeBlock.clear();
+ programNode->destroyData();
+ return exception;
+ }
programNode->destroyData();
ASSERT(!m_codeBlockForCall);
m_codeBlockForCall = adoptPtr(new FunctionCodeBlock(this, FunctionCode, globalObject, source().provider(), source().startOffset(), false));
OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scopeChain, m_codeBlockForCall->symbolTable(), m_codeBlockForCall.get())));
- generator->generate();
+ if ((exception = generator->generate())) {
+ m_codeBlockForCall.clear();
+ body->destroyData();
+ return exception;
+ }
+
m_numParametersForCall = m_codeBlockForCall->m_numParameters;
ASSERT(m_numParametersForCall);
m_numCapturedVariables = m_codeBlockForCall->m_numCapturedVars;
ASSERT(!m_codeBlockForConstruct);
m_codeBlockForConstruct = adoptPtr(new FunctionCodeBlock(this, FunctionCode, globalObject, source().provider(), source().startOffset(), true));
OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scopeChain, m_codeBlockForConstruct->symbolTable(), m_codeBlockForConstruct.get())));
- generator->generate();
+ if ((exception = generator->generate())) {
+ m_codeBlockForConstruct.clear();
+ body->destroyData();
+ return exception;
+ }
+
m_numParametersForConstruct = m_codeBlockForConstruct->m_numParameters;
ASSERT(m_numParametersForConstruct);
m_numCapturedVariables = m_codeBlockForConstruct->m_numCapturedVars;
RefPtr<RegExp> regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags);
if (!regExp->isValid())
- return throwError(exec, createSyntaxError(exec, makeUString("Invalid regular expression: ", regExp->errorMessage())));
+ return throwError(exec, createSyntaxError(exec, regExp->errorMessage()));
return new (exec) RegExpObject(exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp.release());
}
}
if (!regExp->isValid())
- return throwVMError(exec, createSyntaxError(exec, makeUString("Invalid regular expression: ", regExp->errorMessage())));
+ return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage()));
asRegExpObject(thisValue)->setRegExp(regExp.release());
asRegExpObject(thisValue)->setLastIndex(0);
namespace JSC { namespace Yarr {
static const unsigned quantifyInfinite = UINT_MAX;
+#define REGEXP_ERROR_PREFIX "Invalid regular expression: "
enum BuiltInCharacterClassID {
DigitClassID,
*/
const char* parse()
{
- m_delegate.regexBegin();
-
if (m_size > MAX_PATTERN_SIZE)
m_err = PatternTooLarge;
else
parseTokens();
ASSERT(atEndOfPattern() || m_err);
- if (m_err)
- m_delegate.regexError();
- else
- m_delegate.regexEnd();
-
// The order of this array must match the ErrorCode enum.
static const char* errorMessages[NumberOfErrorCodes] = {
0, // NoError
- "regular expression too large",
- "numbers out of order in {} quantifier",
- "nothing to repeat",
- "missing )",
- "unmatched parentheses",
- "unrecognized character after (?",
- "missing terminating ] for character class",
- "range out of order in character class",
- "\\ at end of pattern"
+ REGEXP_ERROR_PREFIX "regular expression too large",
+ REGEXP_ERROR_PREFIX "numbers out of order in {} quantifier",
+ REGEXP_ERROR_PREFIX "nothing to repeat",
+ REGEXP_ERROR_PREFIX "missing )",
+ REGEXP_ERROR_PREFIX "unmatched parentheses",
+ REGEXP_ERROR_PREFIX "unrecognized character after (?",
+ REGEXP_ERROR_PREFIX "missing terminating ] for character class",
+ REGEXP_ERROR_PREFIX "range out of order in character class",
+ REGEXP_ERROR_PREFIX "\\ at end of pattern"
};
return errorMessages[m_err];
*
* void disjunction();
*
- * void regexBegin();
- * void regexEnd();
- * void regexError();
- *
- * Before any call recording tokens are made, regexBegin() will be called on the
- * delegate once. Once parsing is complete either regexEnd() or regexError() will
- * be called, as appropriate.
- *
* The regular expression is described by a sequence of assertion*() and atom*()
* callbacks to the delegate, describing the terms in the regular expression.
* Following an atom a quantifyAtom() call may occur to indicate that the previous
m_alternative = m_pattern.m_body->addNewAlternative();
m_pattern.m_disjunctions.append(m_pattern.m_body);
}
- void regexEnd()
- {
- }
- void regexError()
- {
- }
unsigned setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition)
{
{
RegexPatternConstructor constructor(pattern);
+ constructor.regexBegin();
if (const char* error = parse(constructor, patternString))
return error;
unsigned numSubpatterns = pattern.m_numSubpatterns;
constructor.reset();
+ constructor.regexBegin();
#if !ASSERT_DISABLED
const char* error =
#endif
--- /dev/null
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "YarrSyntaxChecker.h"
+
+#include "RegexParser.h"
+
+namespace JSC { namespace Yarr {
+
+class SyntaxChecker {
+public:
+ void assertionBOL() {}
+ void assertionEOL() {}
+ void assertionWordBoundary(bool) {}
+ void atomPatternCharacter(UChar) {}
+ void atomBuiltInCharacterClass(BuiltInCharacterClassID, bool) {}
+ void atomCharacterClassBegin(bool = false) {}
+ void atomCharacterClassAtom(UChar) {}
+ void atomCharacterClassRange(UChar, UChar) {}
+ void atomCharacterClassBuiltIn(BuiltInCharacterClassID, bool) {}
+ void atomCharacterClassEnd() {}
+ void atomParenthesesSubpatternBegin(bool = true) {}
+ void atomParentheticalAssertionBegin(bool = false) {}
+ void atomParenthesesEnd() {}
+ void atomBackReference(unsigned) {}
+ void quantifyAtom(unsigned, unsigned, bool) {}
+ void disjunction() {}
+};
+
+const char* checkSyntax(const UString& pattern)
+{
+ SyntaxChecker syntaxChecker;
+ return parse(syntaxChecker, pattern);
+}
+
+}} // JSC::YARR
--- /dev/null
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef YarrSyntaxChecker_h
+#define YarrSyntaxChecker_h
+
+#include <UString.h>
+
+namespace JSC { namespace Yarr {
+
+const char* checkSyntax(const UString& pattern);
+
+}} // JSC::YARR
+
+#endif // YarrSyntaxChecker_h
+