diff options
author | 2021-05-13 21:12:41 -0700 | |
---|---|---|
committer | 2021-05-13 21:12:41 -0700 | |
commit | 68aa7762170d06f0e049f8f2ec58c03bbab97dab (patch) | |
tree | c6a287902e6e226b61c5f0a5c1b246b8a65d4eb2 | |
parent | 0666f8151a51ef96daeb8691459313d01730c014 (diff) | |
download | bun-68aa7762170d06f0e049f8f2ec58c03bbab97dab.tar.gz bun-68aa7762170d06f0e049f8f2ec58c03bbab97dab.tar.zst bun-68aa7762170d06f0e049f8f2ec58c03bbab97dab.zip |
w
Former-commit-id: 248d1a7a93512b14ffd7d8a47942361cc0dc8745
-rw-r--r-- | src/js_parser/js_parser.zig | 131 |
1 files changed, 60 insertions, 71 deletions
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig index 0e7227c7c..4441a7867 100644 --- a/src/js_parser/js_parser.zig +++ b/src/js_parser/js_parser.zig @@ -4122,6 +4122,7 @@ pub const P = struct { // Remove any direct children from their parent var scope = p.current_scope; var children = scope.children; + for (p.scopes_in_order.items[scope_index..]) |_child| { const child = _child orelse continue; @@ -4507,9 +4508,7 @@ pub const P = struct { const ref = p.storeNameInRef(name) catch unreachable; - key = p.e(E.String{ - .utf8 = p.lexer.string_literal_slice, - }, loc); + key = p.e(p.lexer.toEString(), loc); if (p.lexer.token != .t_colon and p.lexer.token != .t_open_paren) { const value = p.b(B.Identifier{ .ref = ref }, loc); @@ -5535,9 +5534,7 @@ pub const P = struct { } } - key = p.e(E.String{ - .value = p.lexer.stringToUTF16(name), - }, name_range.loc); + key = p.e(p.lexer.toEString(), name_range.loc); // Parse a shorthand property if (!opts.is_class and kind == .normal and p.lexer.token != .t_colon and p.lexer.token != .t_open_paren and p.lexer.token != .t_less_than and !opts.is_generator and !js_lexer.Keywords.has(name)) { @@ -5562,7 +5559,9 @@ pub const P = struct { .key = key, .value = value, .initializer = initializer, - .flags = Flags.Property{ .was_shorthand = true }, + .flags = Flags.Property{ + .was_shorthand = true, + }, }; } }, @@ -5588,7 +5587,7 @@ pub const P = struct { if (!is_computed) { switch (key.data) { .e_string => |str| { - if (std.mem.eql(u16, str.value, std.unicode.utf8ToUtf16LeStringLiteral("constructor")) or (opts.is_static and std.mem.eql(u16, str.value, std.unicode.utf8ToUtf16LeStringLiteral("prototype")))) { + if (str.eql(string, "constructor") or (opts.is_static and str.eql(string, "prototype"))) { // TODO: fmt error message to include string value. p.log.addRangeError(p.source, key_range, "Invalid field name") catch unreachable; } @@ -5772,8 +5771,8 @@ pub const P = struct { }; } + // Parse an object key/value pair try p.lexer.expect(.t_colon); - const value = try p.parseExprOrBindings(.comma, errors); return G.Property{ @@ -5941,23 +5940,12 @@ pub const P = struct { if (p.lexer.legacy_octal_loc.start > loc.start) { legacy_octal_loc = p.lexer.legacy_octal_loc; } - if (p.lexer.string_literal_is_ascii) { - const expr = p.e(E.String{ - .utf8 = p.lexer.string_literal_slice, - .legacy_octal_loc = legacy_octal_loc, - .prefer_template = p.lexer.token == .t_no_substitution_template_literal, - }, loc); - try p.lexer.next(); - return expr; - } else { - const expr = p.e(E.String{ - .value = p.allocator.dupe(u16, p.lexer.string_literal) catch unreachable, - .legacy_octal_loc = legacy_octal_loc, - .prefer_template = p.lexer.token == .t_no_substitution_template_literal, - }, loc); - try p.lexer.next(); - return expr; - } + var str = p.lexer.toEString(); + str.prefer_template = p.lexer.token == .t_no_substitution_template_literal; + + const expr = p.e(str, loc); + try p.lexer.next(); + return expr; } pub fn parseCallArgs(p: *P) anyerror![]Expr { @@ -7470,17 +7458,10 @@ pub const P = struct { try p.lexer.nextInsideJSXElement(); if (p.lexer.token == .t_string_literal) { previous_string_with_backslash_loc.start = std.math.max(p.lexer.loc().start, p.lexer.previous_backslash_quote_in_jsx.loc.start); - if (p.lexer.string_literal_is_ascii) { - const expr = p.e(E.String{ - .utf8 = p.lexer.string_literal_slice, - }, previous_string_with_backslash_loc.*); - try p.lexer.nextInsideJSXElement(); - return expr; - } else { - const expr = p.e(E.String{ .value = try p.allocator.dupe(u16, p.lexer.string_literal) }, previous_string_with_backslash_loc.*); - try p.lexer.nextInsideJSXElement(); - return expr; - } + const expr = p.e(p.lexer.toEString(), previous_string_with_backslash_loc.*); + + try p.lexer.nextInsideJSXElement(); + return expr; } else { // Use Expect() not ExpectInsideJSXElement() so we can parse expression tokens try p.lexer.expect(.t_open_brace); @@ -7538,7 +7519,7 @@ pub const P = struct { continue; } - var prop_name = p.e(E.String{ .value = p.lexer.stringToUTF16(prop_name_literal) }, key_range.loc); + var prop_name = p.e(E.String{ .utf8 = prop_name_literal }, key_range.loc); // Parse the value var value: Expr = undefined; @@ -7620,14 +7601,7 @@ pub const P = struct { while (true) { switch (p.lexer.token) { .t_string_literal => { - if (p.lexer.string_literal_is_ascii) { - try children.append(p.e(E.String{ - .utf8 = p.lexer.string_literal_slice, - }, loc)); - } else { - try children.append(p.e(E.String{ .value = try p.allocator.dupe(u16, p.lexer.string_literal) }, loc)); - } - + try children.append(p.e(p.lexer.toEString(), loc)); try p.lexer.nextJSXElementChild(); }, .t_open_brace => { @@ -8608,7 +8582,7 @@ pub const P = struct { e_.value = p.visitExprInOut(e_.value, ExprIn{ .assign_target = e_.op.unaryAssignTarget() }); if (SideEffects.toTypeof(e_.value.data)) |typeof| { - return p.e(E.String{ .value = p.lexer.stringToUTF16(typeof) }, expr.loc); + return p.e(E.String{ .utf8 = typeof }, expr.loc); } }, .un_delete => { @@ -8939,7 +8913,6 @@ pub const P = struct { .is_arrow = true, .is_async = e_.is_async, }; - defer p.fn_or_arrow_data_visit = old_fn_or_arrow_data; // Mark if we're inside an async arrow function. This value should be true // even if we're inside multiple arrow functions and the closest inclosing @@ -8947,24 +8920,24 @@ pub const P = struct { // function within the current enclosing function is async. const old_inside_async_arrow_fn = p.fn_only_data_visit.is_inside_async_arrow_fn; p.fn_only_data_visit.is_inside_async_arrow_fn = e_.is_async or p.fn_only_data_visit.is_inside_async_arrow_fn; - defer p.fn_only_data_visit.is_inside_async_arrow_fn = old_inside_async_arrow_fn; p.pushScopeForVisitPass(.function_args, expr.loc) catch unreachable; - defer p.popScope(); - p.visitArgs(e_.args, VisitArgsOpts{ .has_rest_arg = e_.has_rest_arg, .body = e_.body.stmts, .is_unique_formal_parameters = true, }); - p.pushScopeForVisitPass(.function_body, e_.body.loc) catch unreachable; - defer p.popScope(); var stmts_list = List(Stmt).fromOwnedSlice(p.allocator, e_.body.stmts); var temp_opts = PrependTempRefsOpts{ .kind = StmtsKind.fn_body }; p.visitStmtsAndPrependTempRefs(&stmts_list, &temp_opts) catch unreachable; e_.body.stmts = stmts_list.toOwnedSlice(); + p.popScope(); + p.popScope(); + + p.fn_only_data_visit.is_inside_async_arrow_fn = old_inside_async_arrow_fn; + p.fn_or_arrow_data_visit = old_fn_or_arrow_data; }, .e_function => |e_| { p.visitFunc(&e_.func, expr.loc); @@ -9637,6 +9610,7 @@ pub const P = struct { data.value = p.visitExpr(data.value); }, .s_return => |data| { + // Forbid top-level return inside modules with ECMAScript-style exports if (p.fn_or_arrow_data_visit.is_outside_fn_or_arrow) { const where = where: { if (p.es6_export_keyword.len > 0) { @@ -9666,7 +9640,6 @@ pub const P = struct { .s_block => |data| { { p.pushScopeForVisitPass(.block, stmt.loc) catch unreachable; - defer p.popScope(); // Pass the "is loop body" status on to the direct children of a block used // as a loop body. This is used to enable optimizations specific to the @@ -9675,17 +9648,20 @@ pub const P = struct { var _stmts = List(Stmt).fromOwnedSlice(p.allocator, data.stmts); p.visitStmts(&_stmts, kind) catch unreachable; data.stmts = _stmts.toOwnedSlice(); + p.popScope(); } - // trim empty statements - if (data.stmts.len == 0) { - stmts.append(Stmt{ .data = Prefill.Data.SEmpty, .loc = stmt.loc }) catch unreachable; - return; - } else if (data.stmts.len == 1 and !statementCaresAboutScope(data.stmts[0])) { - // Unwrap blocks containing a single statement - stmts.append(data.stmts[0]) catch unreachable; - return; - } + // // trim empty statements + // if (data.stmts.len == 0) { + // stmts.append(Stmt{ .data = Prefill.Data.SEmpty, .loc = stmt.loc }) catch unreachable; + // return; + // } else if (data.stmts.len == 1 and !statementCaresAboutScope(data.stmts[0])) { + // // Unwrap blocks containing a single statement + // stmts.append(data.stmts[0]) catch unreachable; + // return; + // } + stmts.append(stmt.*) catch unreachable; + return; }, .s_with => |data| { notimpl(); @@ -9708,9 +9684,9 @@ pub const P = struct { const effects = SideEffects.toBoolean(data.test_.data); if (effects.ok and !effects.value) { const old = p.is_control_flow_dead; - defer p.is_control_flow_dead = old; p.is_control_flow_dead = true; data.yes = p.visitSingleStmt(data.yes, StmtsKind.none); + p.is_control_flow_dead = old; } else { data.yes = p.visitSingleStmt(data.yes, StmtsKind.none); } @@ -10542,6 +10518,7 @@ pub const P = struct { }, loc); } + // Try separating the list for appending, so that it's not a pointer. fn visitStmts(p: *P, stmts: *List(Stmt), kind: StmtsKind) !void { // Save the current control-flow liveness. This represents if we are // currently inside an "if (false) { ... }" block. @@ -10555,7 +10532,7 @@ pub const P = struct { defer visited.deinit(); defer after.deinit(); - for (stmts.items) |*stmt| { + for (stmts.items) |*stmt, i| { const list = list_getter: { switch (stmt.data) { .s_export_equals => { @@ -10982,8 +10959,23 @@ pub const P = struct { } pub fn init(allocator: *std.mem.Allocator, log: *logger.Log, source: *const logger.Source, define: *Define, lexer: js_lexer.Lexer, opts: Parser.Options) !*P { + var scope_order = try std.ArrayListUnmanaged(?ScopeOrder).initCapacity(allocator, 1); + var scope = try allocator.create(Scope); + scope.* = Scope{ + .members = @TypeOf(scope.members).init(allocator), + .children = @TypeOf(scope.children).init( + allocator, + ), + .generated = @TypeOf(scope.generated).init(allocator), + .kind = .entry, + .label_ref = null, + .parent = null, + }; + + scope_order.appendAssumeCapacity(ScopeOrder{ .loc = locModuleScope, .scope = scope }); + var _parser = try allocator.create(P); - var parser = P{ + _parser.* = P{ .symbol_uses = SymbolUseMap.init(allocator), .call_target = nullExprData, .delete_target = nullExprData, @@ -11009,7 +11001,8 @@ pub const P = struct { .named_exports = @TypeOf(_parser.named_exports).init(allocator), .top_level_symbol_to_parts = @TypeOf(_parser.top_level_symbol_to_parts).init(allocator), .import_namespace_cc_map = @TypeOf(_parser.import_namespace_cc_map).init(allocator), - .scopes_in_order = try std.ArrayListUnmanaged(?ScopeOrder).initCapacity(allocator, 1), + .scopes_in_order = scope_order, + .current_scope = scope, .temp_refs_to_declare = @TypeOf(_parser.temp_refs_to_declare).init(allocator), .relocated_top_level_vars = @TypeOf(_parser.relocated_top_level_vars).init(allocator), .log = log, @@ -11028,10 +11021,6 @@ pub const P = struct { .data = js_ast.AstData.init(allocator), }; - _parser.* = parser; - - _ = try _parser.pushScopeForParsePass(.entry, locModuleScope); - return _parser; } }; |