Framework updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2026-03-04 23:20:19 +00:00
parent a89daf3d43
commit 3ed8517b2a
891 changed files with 11126 additions and 9600 deletions

View File

@@ -2,7 +2,7 @@
*
* Package: php-parser
* Parse PHP code from JS and returns its AST
* Build: 945ab5fd1635905af6d5 - 2/18/2026
* Build: 8ca15bdec2f54ee92ab1 - 2/21/2026
* Copyright (C) 2021 Glayzzle (BSD-3-Clause)
* @authors https://github.com/glayzzle/php-parser/graphs/contributors
* @url http://glayzzle.com
@@ -343,7 +343,6 @@ AST.prototype.prepare = function (kind, docs, parser) {
var self = this;
// returns the node
var _result = function result() {
var location = null;
var args = Array.prototype.slice.call(arguments);
args.push(docs);
if (self.withPositions || self.withSource) {
@@ -352,7 +351,7 @@ AST.prototype.prepare = function (kind, docs, parser) {
src = parser.lexer._input.substring(start.offset, parser.prev[2]);
}
// if with source, need location on swapLocations function
location = new Location(src, start, new Position(parser.prev[0], parser.prev[1], parser.prev[2]));
var location = new Location(src, start, new Position(parser.prev[0], parser.prev[1], parser.prev[2]));
// last argument is always the location
args.push(location);
}
@@ -4954,7 +4953,7 @@ module.exports = {
var ch = this.input();
if (this.is_WHITESPACE()) {
do {
ch = this.input();
this.input();
} while (this.is_WHITESPACE());
this.unput(1);
return null;
@@ -6951,7 +6950,7 @@ module.exports = {
* ```
*/
read_array: function read_array() {
var expect = null;
var expect;
var shortForm = false;
var result = this.node("array");
if (this.token === this.tok.T_ARRAY) {
@@ -7000,7 +6999,7 @@ module.exports = {
}
var entry = this.node("entry");
var key = null;
var value = null;
var value;
var byRef = false;
var unpack = false;
if (this.token === "&") {
@@ -7428,8 +7427,8 @@ module.exports = {
* ```
*/
read_interface_body: function read_interface_body() {
var result = [],
attrs = [];
var result = [];
var attrs;
while (this.token !== this.EOF && this.token !== "}") {
if (this.token === this.tok.T_COMMENT) {
result.push(this.read_comment());
@@ -7451,7 +7450,6 @@ module.exports = {
this.next();
}
result = result.concat(constants);
attrs = [];
} else if (this.token === this.tok.T_FUNCTION) {
// reads a function
var method = this.read_function_declaration(2, flags, attrs, locStart);
@@ -7460,7 +7458,6 @@ module.exports = {
if (this.expect(";")) {
this.next();
}
attrs = [];
} else {
// raise an error
this.error([this.tok.T_CONST, this.tok.T_FUNCTION]);
@@ -7805,6 +7802,10 @@ module.exports = {
expr = this.read_expr(expr);
}
}
if (this.token === this.tok.T_NULLSAFE_OBJECT_OPERATOR) {
expr = result("nullsafepropertylookup", expr, this.read_what());
expr = this.recursive_variable_chain_scan(expr, false, true);
}
// extra operations :
// $username = $_GET['user'] ?? 'nobody';
@@ -8298,13 +8299,11 @@ module.exports = {
if (this.version < 800) {
this.raiseError("Match statements are not allowed before PHP 8");
}
var cond = null;
var arms = [];
if (this.expect("(")) this.next();
cond = this.read_expr();
var cond = this.read_expr();
if (this.expect(")")) this.next();
if (this.expect("{")) this.next();
arms = this.read_match_arms();
var arms = this.read_match_arms();
if (this.expect("}")) this.next();
return node(cond, arms);
},
@@ -8446,7 +8445,7 @@ module.exports = {
},
handleDereferencable: function handleDereferencable(expr) {
while (this.token !== this.EOF) {
if (this.token === this.tok.T_OBJECT_OPERATOR || this.token === this.tok.T_DOUBLE_COLON) {
if (this.token === this.tok.T_OBJECT_OPERATOR || this.token === this.tok.T_DOUBLE_COLON || this.token === this.tok.T_NULLSAFE_OBJECT_OPERATOR) {
expr = this.recursive_variable_chain_scan(expr, false, false, true);
} else if (this.token === this.tok.T_CURLY_OPEN || this.token === "[") {
expr = this.read_dereferencable(expr);
@@ -8692,7 +8691,6 @@ module.exports = {
var node = this.node("parameter");
var parameterName = null;
var value = null;
var types = null;
var nullable = false;
var readonly = false;
var attrs = [];
@@ -8718,7 +8716,7 @@ module.exports = {
this.next();
nullable = true;
}
types = this.read_types();
var types = this.read_types();
if (nullable && !types) {
this.raiseError("Expecting a type definition combined with nullable operator");
}
@@ -8907,7 +8905,7 @@ module.exports = {
read_if: function read_if() {
var result = this.node("if");
var test = this.next().read_if_expr();
var body = null;
var body;
var alternate = null;
var shortForm = false;
if (this.token === ":") {
@@ -9007,11 +9005,10 @@ module.exports = {
read_while: function read_while() {
var result = this.node("while");
this.expect(this.tok.T_WHILE) && this.next();
var test = null;
var body = null;
var body;
var shortForm = false;
if (this.expect("(")) this.next();
test = this.read_expr();
var test = this.read_expr();
if (this.expect(")")) this.next();
if (this.token === ":") {
shortForm = true;
@@ -9033,8 +9030,7 @@ module.exports = {
var result = this.node("do");
this.expect(this.tok.T_DO) && this.next();
var test = null;
var body = null;
body = this.read_statement();
var body = this.read_statement();
if (this.expect(this.tok.T_WHILE)) {
if (this.next().expect("(")) this.next();
test = this.read_expr();
@@ -9059,7 +9055,7 @@ module.exports = {
var init = [];
var test = [];
var increment = [];
var body = null;
var body;
var shortForm = false;
if (this.expect("(")) this.next();
if (this.token !== ";") {
@@ -9099,13 +9095,12 @@ module.exports = {
read_foreach: function read_foreach() {
var result = this.node("foreach");
this.expect(this.tok.T_FOREACH) && this.next();
var source = null;
var key = null;
var value = null;
var body = null;
var body;
var shortForm = false;
if (this.expect("(")) this.next();
source = this.read_expr();
var source = this.read_expr();
if (this.expect(this.tok.T_AS)) {
this.next();
value = this.read_foreach_variable();
@@ -9689,7 +9684,6 @@ module.exports = {
curly = true;
// dynamic variable name
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1239
name = null;
if (this.next().token === this.tok.T_STRING_VARNAME) {
name = this.node("variable");
var varName = this.text();
@@ -9766,7 +9760,7 @@ module.exports = {
this.next();
var start = this.lexer.yylloc.prev_offset - (isBinary ? 1 : 0);
var value = [];
var type = null;
var type;
if (expect === "`") {
type = this.ast.encapsed.TYPE_SHELL;
} else if (expect === '"') {
@@ -10658,7 +10652,6 @@ module.exports = {
name = this.next().read_expr();
this.expect("}") && this.next();
offset = offset("literal", name, null);
this.expect("(");
} else {
this.error([this.tok.T_VARIABLE, this.tok.T_STRING]);
// graceful mode : set getter as error node and continue
@@ -10671,8 +10664,8 @@ module.exports = {
},
read_what: function read_what() {
var is_static_lookup = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var what = null;
var name = null;
var what;
var name;
switch (this.next().token) {
case this.tok.T_STRING:
what = this.node("identifier");
@@ -10689,6 +10682,15 @@ module.exports = {
this.next();
what = what(name, false);
break;
case this.tok.T_CLASS:
if (!is_static_lookup) {
this.error();
}
what = this.node("identifier");
name = this.text();
this.next();
what = what(name, false);
break;
case "$":
what = this.node();
this.next().expect(["$", "{", this.tok.T_VARIABLE]);

File diff suppressed because one or more lines are too long

View File

@@ -2,7 +2,7 @@
*
* Package: php-parser
* Parse PHP code from JS and returns its AST
* Build: 945ab5fd1635905af6d5 - 2/18/2026
* Build: 8ca15bdec2f54ee92ab1 - 2/21/2026
* Copyright (C) 2021 Glayzzle (BSD-3-Clause)
* @authors https://github.com/glayzzle/php-parser/graphs/contributors
* @url http://glayzzle.com

View File

@@ -1,6 +1,6 @@
{
"name": "php-parser",
"version": "3.3.0",
"version": "3.4.0",
"description": "Parse PHP code from JS and returns its AST",
"main": "src/index.js",
"browser": "dist/php-parser.js",
@@ -59,12 +59,12 @@
"devDependencies": {
"@babel/core": "^7.27.4",
"@babel/preset-env": "^7.27.2",
"@eslint/js": "^9.29.0",
"@eslint/js": "^10.0.1",
"@types/node": "^25.2.3",
"babel-loader": "^10.0.0",
"benchmark": "^2.1.4",
"coveralls": "^3.0.3",
"eslint": "^9.29.0",
"eslint": "^10.0.0",
"eslint-config-prettier": "^10.1.5",
"eslint-plugin-jest": "^29.0.1",
"eslint-plugin-prettier": "^5.5.0",

3
node_modules/php-parser/src/ast.js generated vendored
View File

@@ -364,7 +364,6 @@ AST.prototype.prepare = function (kind, docs, parser) {
const self = this;
// returns the node
const result = function () {
let location = null;
const args = Array.prototype.slice.call(arguments);
args.push(docs);
if (self.withPositions || self.withSource) {
@@ -373,7 +372,7 @@ AST.prototype.prepare = function (kind, docs, parser) {
src = parser.lexer._input.substring(start.offset, parser.prev[2]);
}
// if with source, need location on swapLocations function
location = new Location(
const location = new Location(
src,
start,
new Position(parser.prev[0], parser.prev[1], parser.prev[2]),

View File

@@ -9,10 +9,10 @@ module.exports = {
attributeIndex: 0,
attributeListDepth: {},
matchST_ATTRIBUTE() {
let ch = this.input();
const ch = this.input();
if (this.is_WHITESPACE()) {
do {
ch = this.input();
this.input();
} while (this.is_WHITESPACE());
this.unput(1);
return null;

View File

@@ -14,7 +14,7 @@ module.exports = {
* ```
*/
read_array() {
let expect = null;
let expect;
let shortForm = false;
const result = this.node("array");
@@ -74,7 +74,7 @@ module.exports = {
const entry = this.node("entry");
let key = null;
let value = null;
let value;
let byRef = false;
let unpack = false;

View File

@@ -431,8 +431,8 @@ module.exports = {
* ```
*/
read_interface_body() {
let result = [],
attrs = [];
let result = [];
let attrs;
while (this.token !== this.EOF && this.token !== "}") {
if (this.token === this.tok.T_COMMENT) {
@@ -458,7 +458,6 @@ module.exports = {
this.next();
}
result = result.concat(constants);
attrs = [];
} else if (this.token === this.tok.T_FUNCTION) {
// reads a function
const method = this.read_function_declaration(
@@ -472,7 +471,6 @@ module.exports = {
if (this.expect(";")) {
this.next();
}
attrs = [];
} else {
// raise an error
this.error([this.tok.T_CONST, this.tok.T_FUNCTION]);

View File

@@ -114,6 +114,11 @@ module.exports = {
}
}
if (this.token === this.tok.T_NULLSAFE_OBJECT_OPERATOR) {
expr = result("nullsafepropertylookup", expr, this.read_what());
expr = this.recursive_variable_chain_scan(expr, false, true);
}
// extra operations :
// $username = $_GET['user'] ?? 'nobody';
if (this.token === this.tok.T_COALESCE) {
@@ -678,13 +683,11 @@ module.exports = {
if (this.version < 800) {
this.raiseError("Match statements are not allowed before PHP 8");
}
let cond = null;
let arms = [];
if (this.expect("(")) this.next();
cond = this.read_expr();
const cond = this.read_expr();
if (this.expect(")")) this.next();
if (this.expect("{")) this.next();
arms = this.read_match_arms();
const arms = this.read_match_arms();
if (this.expect("}")) this.next();
return node(cond, arms);
},
@@ -844,7 +847,8 @@ module.exports = {
while (this.token !== this.EOF) {
if (
this.token === this.tok.T_OBJECT_OPERATOR ||
this.token === this.tok.T_DOUBLE_COLON
this.token === this.tok.T_DOUBLE_COLON ||
this.token === this.tok.T_NULLSAFE_OBJECT_OPERATOR
) {
expr = this.recursive_variable_chain_scan(expr, false, false, true);
} else if (this.token === this.tok.T_CURLY_OPEN || this.token === "[") {

View File

@@ -252,7 +252,6 @@ module.exports = {
const node = this.node("parameter");
let parameterName = null;
let value = null;
let types = null;
let nullable = false;
let readonly = false;
let attrs = [];
@@ -290,7 +289,7 @@ module.exports = {
this.next();
nullable = true;
}
types = this.read_types();
const types = this.read_types();
if (nullable && !types) {
this.raiseError(
"Expecting a type definition combined with nullable operator",

View File

@@ -16,7 +16,7 @@ module.exports = {
read_if() {
const result = this.node("if");
const test = this.next().read_if_expr();
let body = null;
let body;
let alternate = null;
let shortForm = false;

View File

@@ -17,11 +17,10 @@ module.exports = {
read_while() {
const result = this.node("while");
this.expect(this.tok.T_WHILE) && this.next();
let test = null;
let body = null;
let body;
let shortForm = false;
if (this.expect("(")) this.next();
test = this.read_expr();
const test = this.read_expr();
if (this.expect(")")) this.next();
if (this.token === ":") {
shortForm = true;
@@ -43,8 +42,7 @@ module.exports = {
const result = this.node("do");
this.expect(this.tok.T_DO) && this.next();
let test = null;
let body = null;
body = this.read_statement();
const body = this.read_statement();
if (this.expect(this.tok.T_WHILE)) {
if (this.next().expect("(")) this.next();
test = this.read_expr();
@@ -69,7 +67,7 @@ module.exports = {
let init = [];
let test = [];
let increment = [];
let body = null;
let body;
let shortForm = false;
if (this.expect("(")) this.next();
if (this.token !== ";") {
@@ -109,13 +107,12 @@ module.exports = {
read_foreach() {
const result = this.node("foreach");
this.expect(this.tok.T_FOREACH) && this.next();
let source = null;
let key = null;
let value = null;
let body = null;
let body;
let shortForm = false;
if (this.expect("(")) this.next();
source = this.read_expr();
const source = this.read_expr();
if (this.expect(this.tok.T_AS)) {
this.next();
value = this.read_foreach_variable();

View File

@@ -357,7 +357,6 @@ module.exports = {
curly = true;
// dynamic variable name
// https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1239
name = null;
if (this.next().token === this.tok.T_STRING_VARNAME) {
name = this.node("variable");
const varName = this.text();
@@ -433,7 +432,7 @@ module.exports = {
this.next();
const start = this.lexer.yylloc.prev_offset - (isBinary ? 1 : 0);
const value = [];
let type = null;
let type;
if (expect === "`") {
type = this.ast.encapsed.TYPE_SHELL;

View File

@@ -105,7 +105,6 @@ module.exports = {
name = this.next().read_expr();
this.expect("}") && this.next();
offset = offset("literal", name, null);
this.expect("(");
} else {
this.error([this.tok.T_VARIABLE, this.tok.T_STRING]);
// graceful mode : set getter as error node and continue
@@ -118,8 +117,8 @@ module.exports = {
},
read_what(is_static_lookup = false) {
let what = null;
let name = null;
let what;
let name;
switch (this.next().token) {
case this.tok.T_STRING:
what = this.node("identifier");
@@ -137,6 +136,15 @@ module.exports = {
this.next();
what = what(name, false);
break;
case this.tok.T_CLASS:
if (!is_static_lookup) {
this.error();
}
what = this.node("identifier");
name = this.text();
this.next();
what = what(name, false);
break;
case "$":
what = this.node();
this.next().expect(["$", "{", this.tok.T_VARIABLE]);