@vue/compiler-sfc 3.5.43 → 3.5.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @vue/compiler-sfc v3.5.43
2
+ * @vue/compiler-sfc v3.5.44
3
3
  * (c) 2018-present Yuxi (Evan) You and Vue contributors
4
4
  * @license MIT
5
5
  **/
@@ -25109,11 +25109,18 @@ function transformDestructuredProps(ctx, vueImportAliases) {
25109
25109
  const excludedIds = /* @__PURE__ */ new WeakSet();
25110
25110
  const parentStack = [];
25111
25111
  const propsLocalToPublicMap = /* @__PURE__ */ Object.create(null);
25112
+ const modelOptionNodes = /* @__PURE__ */ new Set();
25113
+ let currentModelOption = null;
25112
25114
  for (const key in ctx.propsDestructuredBindings) {
25113
25115
  const { local } = ctx.propsDestructuredBindings[key];
25114
25116
  rootScope[local] = true;
25115
25117
  propsLocalToPublicMap[local] = key;
25116
25118
  }
25119
+ for (const { runtimeOptionNodes } of Object.values(ctx.modelDecls)) {
25120
+ for (const node of runtimeOptionNodes) {
25121
+ modelOptionNodes.add(node);
25122
+ }
25123
+ }
25117
25124
  function pushScope(isFunctionScope = false) {
25118
25125
  const scope = currentScope = Object.create(currentScope);
25119
25126
  scopeStack.push(scope);
@@ -25185,6 +25192,18 @@ function transformDestructuredProps(ctx, vueImportAliases) {
25185
25192
  });
25186
25193
  }
25187
25194
  function rewriteId(id, parent, parentStack2) {
25195
+ if (currentModelOption) {
25196
+ const isDefault = (currentModelOption.type === "ObjectProperty" || currentModelOption.type === "ObjectMethod") && resolveObjectKey(
25197
+ currentModelOption.key,
25198
+ currentModelOption.computed
25199
+ ) === "default";
25200
+ ctx.error(
25201
+ `\`${DEFINE_MODEL}()\` prop options cannot reference destructured props because they are hoisted outside of the setup() function.` + (isDefault ? ` Use the props argument of the default factory instead, e.g. default: props => props${shared.genPropsAccessExp(
25202
+ propsLocalToPublicMap[id.name]
25203
+ ).slice(`__props`.length)}` : ``),
25204
+ id
25205
+ );
25206
+ }
25188
25207
  if (parent.type === "AssignmentExpression" && id === parent.left || parent.type === "UpdateExpression") {
25189
25208
  ctx.error(`Cannot assign to destructured props as they are readonly.`, id);
25190
25209
  }
@@ -25223,6 +25242,9 @@ function transformDestructuredProps(ctx, vueImportAliases) {
25223
25242
  if (parent && parent.type.startsWith("TS") && !CompilerDOM.TS_NODE_TYPES.includes(parent.type)) {
25224
25243
  return this.skip();
25225
25244
  }
25245
+ if (modelOptionNodes.has(node)) {
25246
+ currentModelOption = node;
25247
+ }
25226
25248
  checkUsage(node, "watch", vueImportAliases.watch);
25227
25249
  checkUsage(node, "toRef", vueImportAliases.toRef);
25228
25250
  if (CompilerDOM.isFunctionType(node)) {
@@ -25268,6 +25290,9 @@ function transformDestructuredProps(ctx, vueImportAliases) {
25268
25290
  },
25269
25291
  leave(node, parent) {
25270
25292
  parent && parentStack.pop();
25293
+ if (node === currentModelOption) {
25294
+ currentModelOption = null;
25295
+ }
25271
25296
  if (CompilerDOM.isFunctionType(node)) {
25272
25297
  popScope(true);
25273
25298
  } else if (node.type === "BlockStatement" && !CompilerDOM.isFunctionType(parent)) {
@@ -26371,7 +26396,7 @@ function mergeSourceMaps(scriptMap, templateMap, templateLineOffset) {
26371
26396
  return generator.toJSON();
26372
26397
  }
26373
26398
 
26374
- const version = "3.5.43";
26399
+ const version = "3.5.44";
26375
26400
  const parseCache = parseCache$1;
26376
26401
  const errorMessages = {
26377
26402
  ...CompilerDOM.errorMessages,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @vue/compiler-sfc v3.5.43
2
+ * @vue/compiler-sfc v3.5.44
3
3
  * (c) 2018-present Yuxi (Evan) You and Vue contributors
4
4
  * @license MIT
5
5
  **/
@@ -214,7 +214,7 @@ const isSVGTag = /* @__PURE__ */ makeMap(SVG_TAGS);
214
214
  const isMathMLTag = /* @__PURE__ */ makeMap(MATH_TAGS);
215
215
  const isVoidTag = /* @__PURE__ */ makeMap(VOID_TAGS);
216
216
 
217
- const specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;
217
+ const specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,playsinline,readonly`;
218
218
  const isBooleanAttr = /* @__PURE__ */ makeMap(
219
219
  specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,inert,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected`
220
220
  );
@@ -4474,7 +4474,8 @@ const errorMessages$1 = {
4474
4474
  [42]: `v-model value must be a valid JavaScript member expression.`,
4475
4475
  [43]: `v-model cannot be used on v-for or v-slot scope variables because they are not writable.`,
4476
4476
  [44]: `v-model cannot be used on a prop, because local prop bindings are not writable.
4477
- Use a v-bind binding combined with a v-on listener that emits update:x event instead.`,
4477
+ Use a v-bind binding combined with a v-on listener that emits update:x event instead.
4478
+ For props declared with defineModel(), assign the returned ref to a variable and use v-model on that variable.`,
4478
4479
  [45]: `v-model cannot be used on a const binding because it is not writable.`,
4479
4480
  [46]: `Error parsing JavaScript expression: `,
4480
4481
  [47]: `<KeepAlive> expects exactly one child component.`,
@@ -7578,13 +7579,15 @@ function requireLib () {
7578
7579
  const arrows = [];
7579
7580
  while (stack.length !== 0) {
7580
7581
  const node = stack.pop();
7581
- if (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement") {
7582
+ if (node.type === "ArrowFunctionExpression") {
7582
7583
  if (node.typeParameters || !node.returnType) {
7583
7584
  this.finishArrowValidation(node);
7584
7585
  } else {
7585
7586
  arrows.push(node);
7586
7587
  }
7587
- stack.push(node.body);
7588
+ if (node.body.type !== "BlockStatement") {
7589
+ stack.push(node.body);
7590
+ }
7588
7591
  } else if (node.type === "ConditionalExpression") {
7589
7592
  stack.push(node.consequent);
7590
7593
  stack.push(node.alternate);
@@ -14754,8 +14757,11 @@ function requireLib () {
14754
14757
  }
14755
14758
  }
14756
14759
  fillOptionalPropertiesForTSESLint(node) {
14757
- var _node$directive, _node$decorators, _node$optional, _node$typeAnnotation, _node$accessibility, _node$decorators2, _node$override, _node$readonly, _node$static, _node$declare, _node$returnType, _node$typeParameters, _node$optional2, _node$optional3, _node$accessibility2, _node$readonly2, _node$static2, _node$declare2, _node$definite, _node$readonly3, _node$typeAnnotation2, _node$accessibility3, _node$decorators3, _node$override2, _node$optional4, _node$id, _node$abstract, _node$declare3, _node$decorators4, _node$implements, _node$superTypeArgume, _node$typeParameters2, _node$declare4, _node$definite2, _node$const, _node$declare5, _node$computed, _node$qualifier, _node$options, _node$declare6, _node$extends, _node$optional5, _node$readonly4, _node$declare7, _node$global, _node$const2, _node$in, _node$out;
14760
+ var _node$phase, _node$directive, _node$decorators, _node$optional, _node$typeAnnotation, _node$accessibility, _node$decorators2, _node$override, _node$readonly, _node$static, _node$declare, _node$returnType, _node$typeParameters, _node$optional2, _node$optional3, _node$accessibility2, _node$readonly2, _node$static2, _node$declare2, _node$definite, _node$readonly3, _node$typeAnnotation2, _node$accessibility3, _node$decorators3, _node$override2, _node$optional4, _node$id, _node$abstract, _node$declare3, _node$decorators4, _node$implements, _node$superTypeArgume, _node$typeParameters2, _node$declare4, _node$definite2, _node$const, _node$declare5, _node$computed, _node$qualifier, _node$options, _node$declare6, _node$extends, _node$optional5, _node$readonly4, _node$declare7, _node$global, _node$const2, _node$in, _node$out;
14758
14761
  switch (node.type) {
14762
+ case "ImportDeclaration":
14763
+ (_node$phase = node.phase) != null ? _node$phase : node.phase = null;
14764
+ return;
14759
14765
  case "ExpressionStatement":
14760
14766
  (_node$directive = node.directive) != null ? _node$directive : node.directive = undefined;
14761
14767
  return;
@@ -22808,10 +22814,12 @@ function requireSourceMapGenerator$1 () {
22808
22814
 
22809
22815
  if (mapping.generatedLine !== previousGeneratedLine) {
22810
22816
  previousGeneratedColumn = 0;
22811
- while (mapping.generatedLine !== previousGeneratedLine) {
22812
- next += ';';
22813
- previousGeneratedLine++;
22814
- }
22817
+ // One ';' per skipped line. Build large gaps with a single flat
22818
+ // string: appending ';' one by one creates a rope node per line, which
22819
+ // can exhaust the heap for a big gap (CVE-2026-93749).
22820
+ var lineDelta = mapping.generatedLine - previousGeneratedLine;
22821
+ next += lineDelta === 1 ? ';' : ';'.repeat(lineDelta);
22822
+ previousGeneratedLine = mapping.generatedLine;
22815
22823
  }
22816
22824
  else {
22817
22825
  if (i > 0) {
@@ -23153,6 +23161,15 @@ function requireQuickSort$1 () {
23153
23161
  return templateFn(comparator);
23154
23162
  }
23155
23163
 
23164
+ let isEvalAllowed = (function () {
23165
+ try {
23166
+ new Function('return 0')();
23167
+ return true;
23168
+ } catch {
23169
+ return false;
23170
+ }
23171
+ })();
23172
+
23156
23173
  /**
23157
23174
  * Sort the given array in-place with the given comparator function.
23158
23175
  *
@@ -23164,7 +23181,7 @@ function requireQuickSort$1 () {
23164
23181
 
23165
23182
  let sortCache = new WeakMap();
23166
23183
  quickSort$1.quickSort = function (ary, comparator, start = 0) {
23167
- let doQuickSort = sortCache.get(comparator);
23184
+ let doQuickSort = isEvalAllowed ? sortCache.get(comparator) : SortTemplate();
23168
23185
  if (doQuickSort === void 0) {
23169
23186
  doQuickSort = cloneSort(comparator);
23170
23187
  sortCache.set(comparator, doQuickSort);
@@ -23193,6 +23210,14 @@ function requireSourceMapConsumer$1 () {
23193
23210
  var base64VLQ = /*@__PURE__*/ requireBase64Vlq$1();
23194
23211
  var quickSort = /*@__PURE__*/ requireQuickSort$1().quickSort;
23195
23212
 
23213
+ // Upper bound for a section's `offset.line` in an indexed source map. A flat
23214
+ // map spends one ';' per generated line, so a tiny indexed map with a huge
23215
+ // offset.line turns into a huge amount of work and memory once its mappings
23216
+ // are copied into a SourceMapGenerator (CVE-2026-93749). Ten million lines is
23217
+ // far beyond any real generated file. Columns are VLQ-encoded as deltas and
23218
+ // don't amplify, so they only need to be valid integers.
23219
+ var MAX_SECTION_OFFSET_LINE = 1e7;
23220
+
23196
23221
  function SourceMapConsumer(aSourceMap, aSourceMapURL) {
23197
23222
  var sourceMap = aSourceMap;
23198
23223
  if (typeof aSourceMap === 'string') {
@@ -24116,6 +24141,7 @@ function requireSourceMapConsumer$1 () {
24116
24141
  line: -1,
24117
24142
  column: 0
24118
24143
  };
24144
+ var maxOffsetLine = 0;
24119
24145
  this._sections = sections.map(function (s) {
24120
24146
  if (s.url) {
24121
24147
  // The url field will require support for asynchronicity.
@@ -24126,12 +24152,32 @@ function requireSourceMapConsumer$1 () {
24126
24152
  var offsetLine = util.getArg(offset, 'line');
24127
24153
  var offsetColumn = util.getArg(offset, 'column');
24128
24154
 
24155
+ if (!isValidOffset(offsetLine) || !isValidOffset(offsetColumn)) {
24156
+ throw new Error('Section offset line and column must be non-negative integers.');
24157
+ }
24158
+ if (offsetLine > MAX_SECTION_OFFSET_LINE) {
24159
+ throw new Error('Section offset line must not exceed ' + MAX_SECTION_OFFSET_LINE + '.');
24160
+ }
24161
+
24129
24162
  if (offsetLine < lastOffset.line ||
24130
24163
  (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) {
24131
24164
  throw new Error('Section offsets must be ordered and non-overlapping.');
24132
24165
  }
24133
24166
  lastOffset = offset;
24134
24167
 
24168
+ var consumer = new SourceMapConsumer(util.getArg(s, 'map'), aSourceMapURL);
24169
+
24170
+ // Offsets of a nested indexed map add up with this one, so apply the
24171
+ // bound to the total.
24172
+ var totalOffsetLine = offsetLine + (consumer._maxOffsetLine || 0);
24173
+ if (totalOffsetLine > MAX_SECTION_OFFSET_LINE) {
24174
+ throw new Error('Section offset line must not exceed ' + MAX_SECTION_OFFSET_LINE +
24175
+ ', including offsets of nested sections.');
24176
+ }
24177
+ if (totalOffsetLine > maxOffsetLine) {
24178
+ maxOffsetLine = totalOffsetLine;
24179
+ }
24180
+
24135
24181
  return {
24136
24182
  generatedOffset: {
24137
24183
  // The offset fields are 0-based, but we use 1-based indices when
@@ -24139,9 +24185,24 @@ function requireSourceMapConsumer$1 () {
24139
24185
  generatedLine: offsetLine + 1,
24140
24186
  generatedColumn: offsetColumn + 1
24141
24187
  },
24142
- consumer: new SourceMapConsumer(util.getArg(s, 'map'), aSourceMapURL)
24188
+ consumer: consumer
24143
24189
  }
24144
24190
  });
24191
+
24192
+ // The largest offset.line of any section, including nested sections.
24193
+ this._maxOffsetLine = maxOffsetLine;
24194
+ }
24195
+
24196
+ /**
24197
+ * Section offsets come from untrusted input and are used as line/column
24198
+ * numbers, so only accept non-negative safe integers (rejects NaN, Infinity,
24199
+ * strings, fractions, etc).
24200
+ */
24201
+ function isValidOffset(aValue) {
24202
+ return typeof aValue === 'number' &&
24203
+ aValue >= 0 &&
24204
+ aValue <= 9007199254740991 && // Number.MAX_SAFE_INTEGER
24205
+ Math.floor(aValue) === aValue;
24145
24206
  }
24146
24207
 
24147
24208
  IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);
@@ -24159,8 +24220,12 @@ function requireSourceMapConsumer$1 () {
24159
24220
  get: function () {
24160
24221
  var sources = [];
24161
24222
  for (var i = 0; i < this._sections.length; i++) {
24162
- for (var j = 0; j < this._sections[i].consumer.sources.length; j++) {
24163
- sources.push(this._sections[i].consumer.sources[j]);
24223
+ // Read the getter once per section: for a nested indexed map it is
24224
+ // itself this getter, and re-reading it per item is exponential in the
24225
+ // nesting depth (CVE-2026-93749).
24226
+ var sectionSources = this._sections[i].consumer.sources;
24227
+ for (var j = 0; j < sectionSources.length; j++) {
24228
+ sources.push(sectionSources[j]);
24164
24229
  }
24165
24230
  }
24166
24231
  return sources;
@@ -24493,6 +24558,13 @@ function requireSourceNode$1 () {
24493
24558
  // to the SourceNode without any mapping.
24494
24559
  // Each line is added as separate string.
24495
24560
  while (lastGeneratedLine < mapping.generatedLine) {
24561
+ if (remainingLinesIndex >= remainingLines.length) {
24562
+ // The generated code is exhausted. Skip the rest instead of adding
24563
+ // empty lines one by one: a mapping may point far past the end of
24564
+ // the code (e.g. an indexed map section with a huge offset.line).
24565
+ lastGeneratedLine = mapping.generatedLine;
24566
+ break;
24567
+ }
24496
24568
  node.add(shiftNextLine());
24497
24569
  lastGeneratedLine++;
24498
24570
  }
@@ -26151,7 +26223,7 @@ const transformFor = createStructuralDirectiveTransform(
26151
26223
  createCompoundExpression([`const _memo = (`, memo.exp, `)`]),
26152
26224
  createCompoundExpression([
26153
26225
  `if (_cached && _cached.el`,
26154
- ...keyExp ? [` && _cached.key === `, keyExp] : [],
26226
+ ...keyExp ? [` && _cached.key === (`, keyExp, `)`] : [],
26155
26227
  ` && ${context.helperString(
26156
26228
  IS_MEMO_SAME
26157
26229
  )}(_cached, _memo)) return _cached`
@@ -28093,7 +28165,8 @@ const transformTransition = (node, context) => {
28093
28165
  if (!node.children.length) {
28094
28166
  return;
28095
28167
  }
28096
- if (hasMultipleChildren(node)) {
28168
+ const multipleChildren = hasMultipleChildren(node);
28169
+ if (multipleChildren) {
28097
28170
  context.onError(
28098
28171
  createDOMCompilerError(
28099
28172
  63,
@@ -28288,8 +28361,9 @@ function stringifyNode(node, context) {
28288
28361
  }
28289
28362
  }
28290
28363
  function stringifyElement(node, context) {
28364
+ var _a;
28291
28365
  let res = `<${node.tag}`;
28292
- let innerHTML = "";
28366
+ let innerHTML = void 0;
28293
28367
  for (let i = 0; i < node.props.length; i++) {
28294
28368
  const p = node.props[i];
28295
28369
  if (p.type === 6) {
@@ -28323,7 +28397,7 @@ function stringifyElement(node, context) {
28323
28397
  )}"`;
28324
28398
  }
28325
28399
  } else if (p.name === "html") {
28326
- innerHTML = evaluateConstant(p.exp);
28400
+ innerHTML = (_a = evaluateConstant(p.exp)) != null ? _a : "";
28327
28401
  } else if (p.name === "text") {
28328
28402
  innerHTML = escapeHtml(
28329
28403
  toDisplayString(evaluateConstant(p.exp))
@@ -28335,7 +28409,7 @@ function stringifyElement(node, context) {
28335
28409
  res += ` ${context.scopeId}`;
28336
28410
  }
28337
28411
  res += `>`;
28338
- if (innerHTML) {
28412
+ if (innerHTML !== void 0) {
28339
28413
  res += innerHTML;
28340
28414
  } else {
28341
28415
  for (let i = 0; i < node.children.length; i++) {
@@ -28557,7 +28631,8 @@ const validateHtmlNesting = (node, context) => {
28557
28631
 
28558
28632
  const DOMNodeTransforms = [
28559
28633
  transformStyle,
28560
- ...[transformTransition, validateHtmlNesting]
28634
+ transformTransition,
28635
+ ...[validateHtmlNesting]
28561
28636
  ];
28562
28637
  const DOMDirectiveTransforms = {
28563
28638
  cloak: noopDirectiveTransform,
@@ -34462,22 +34537,10 @@ function requireStringifier () {
34462
34537
  if (hasRequiredStringifier) return stringifier;
34463
34538
  hasRequiredStringifier = 1;
34464
34539
 
34465
- // Escapes sequences that could break out of an HTML <style> context.
34466
- // Uses CSS unicode escaping (\3c = '<') which is valid CSS and parsed
34467
- // correctly by all compliant CSS consumers.
34468
- const STYLE_TAG = /(<)(\/?style\b)/gi;
34469
- const COMMENT_OPEN = /(<)(!--)/g;
34470
-
34471
34540
  // Characters that end an at-rule name, mirroring RE_AT_END in the tokenizer.
34472
34541
  // Params starting with anything else need a space to stay separate tokens.
34473
34542
  const AT_NAME_END = /[\t\n\f\r "#'()/;[\\\]{}]/;
34474
34543
 
34475
- function escapeHTMLInCSS(str) {
34476
- if (typeof str !== 'string') return str
34477
- if (!str.includes('<')) return str
34478
- return str.replace(STYLE_TAG, '\\3c $2').replace(COMMENT_OPEN, '\\3c $2')
34479
- }
34480
-
34481
34544
  const DEFAULT_RAW = {
34482
34545
  after: '\n',
34483
34546
  beforeClose: '\n',
@@ -34512,11 +34575,12 @@ function requireStringifier () {
34512
34575
  }
34513
34576
 
34514
34577
  // `*--x` is not a custom property: the parser checks the first token, and the
34515
- // `*`/`_` hack prefix moves from `prop` into `before` only after that.
34578
+ // `*`/`_` hack prefix moves from `prop` into `before` only after that. A free
34579
+ // semicolon in front of the declaration also ends up in `before`.
34516
34580
  function isCustomProperty(node) {
34517
34581
  if (!node.prop.startsWith('--')) return false
34518
34582
  let before = node.raws.before;
34519
- return typeof before === 'undefined' || !/\S$/.test(before)
34583
+ return typeof before === 'undefined' || !/[^\s;]$/.test(before)
34520
34584
  }
34521
34585
 
34522
34586
  function pushBody(str, stack, node) {
@@ -34554,17 +34618,17 @@ function requireStringifier () {
34554
34618
 
34555
34619
  function pushBlock(str, stack, node, start) {
34556
34620
  let between = str.raw(node, 'between', 'beforeOpen');
34557
- str.builder(escapeHTMLInCSS(start + between) + '{', node, 'start');
34621
+ str.builder(start + between + '{', node, 'start');
34558
34622
 
34559
34623
  let hasNodes = node.nodes && node.nodes.length;
34560
34624
  let close = () => {
34561
34625
  let after = hasNodes
34562
34626
  ? str.raw(node, 'after')
34563
34627
  : str.raw(node, 'after', 'emptyBody');
34564
- if (after) str.builder(escapeHTMLInCSS(after));
34628
+ if (after) str.builder(after);
34565
34629
  str.builder('}', node, 'end');
34566
34630
  if (node.type === 'rule' && node.raws.ownSemicolon) {
34567
- str.builder(escapeHTMLInCSS(node.raws.ownSemicolon), node, 'end');
34631
+ str.builder(node.raws.ownSemicolon, node, 'end');
34568
34632
  }
34569
34633
  };
34570
34634
 
@@ -34587,7 +34651,7 @@ function requireStringifier () {
34587
34651
  this.block(node, start);
34588
34652
  } else {
34589
34653
  let end = (node.raws.between || '') + (semicolon ? ';' : '');
34590
- this.builder(escapeHTMLInCSS(start + end), node);
34654
+ this.builder(start + end, node);
34591
34655
  }
34592
34656
  }
34593
34657
 
@@ -34622,7 +34686,7 @@ function requireStringifier () {
34622
34686
 
34623
34687
  block(node, start) {
34624
34688
  let between = this.raw(node, 'between', 'beforeOpen');
34625
- this.builder(escapeHTMLInCSS(start + between) + '{', node, 'start');
34689
+ this.builder(start + between + '{', node, 'start');
34626
34690
 
34627
34691
  let after;
34628
34692
  if (node.nodes && node.nodes.length) {
@@ -34632,7 +34696,7 @@ function requireStringifier () {
34632
34696
  after = this.raw(node, 'after', 'emptyBody');
34633
34697
  }
34634
34698
 
34635
- if (after) this.builder(escapeHTMLInCSS(after));
34699
+ if (after) this.builder(after);
34636
34700
  this.builder('}', node, 'end');
34637
34701
  }
34638
34702
 
@@ -34659,7 +34723,7 @@ function requireStringifier () {
34659
34723
  let child = entry.node;
34660
34724
  let before = this.raw(child, 'before');
34661
34725
  if (before) {
34662
- this.builder(entry.document ? before : escapeHTMLInCSS(before));
34726
+ this.builder(before);
34663
34727
  }
34664
34728
 
34665
34729
  if (expandable && child.type === 'rule') {
@@ -34675,7 +34739,7 @@ function requireStringifier () {
34675
34739
  comment(node) {
34676
34740
  let left = this.raw(node, 'left', 'commentLeft');
34677
34741
  let right = this.raw(node, 'right', 'commentRight');
34678
- this.builder(escapeHTMLInCSS('/*' + left + node.text + right + '*/'), node);
34742
+ this.builder('/*' + left + node.text + right + '*/', node);
34679
34743
  }
34680
34744
 
34681
34745
  decl(node, semicolon) {
@@ -34689,7 +34753,7 @@ function requireStringifier () {
34689
34753
  }
34690
34754
 
34691
34755
  if (semicolon) string += ';';
34692
- this.builder(escapeHTMLInCSS(string), node);
34756
+ this.builder(string, node);
34693
34757
  }
34694
34758
 
34695
34759
  document(node) {
@@ -34894,21 +34958,20 @@ function requireStringifier () {
34894
34958
  }
34895
34959
 
34896
34960
  root(node) {
34897
- if (node.source && node.source.input.hasBOM) {
34961
+ let inDocument = node.parent && node.parent.type === 'document';
34962
+ if (!inDocument && node.source && node.source.input.hasBOM) {
34898
34963
  this.builder('\uFEFF', node, 'start');
34899
34964
  }
34900
34965
  this.body(node);
34901
34966
  if (node.raws.after) {
34902
- let after = node.raws.after;
34903
- let isDocument = node.parent && node.parent.type === 'document';
34904
- this.builder(isDocument ? after : escapeHTMLInCSS(after));
34967
+ this.builder(node.raws.after);
34905
34968
  }
34906
34969
  }
34907
34970
 
34908
34971
  rule(node) {
34909
34972
  this.block(node, this.rawValue(node, 'selector'));
34910
34973
  if (node.raws.ownSemicolon) {
34911
- this.builder(escapeHTMLInCSS(node.raws.ownSemicolon), node, 'end');
34974
+ this.builder(node.raws.ownSemicolon, node, 'end');
34912
34975
  }
34913
34976
  }
34914
34977
 
@@ -34941,9 +35004,67 @@ function requireStringify () {
34941
35004
 
34942
35005
  let Stringifier = /*@__PURE__*/ requireStringifier();
34943
35006
 
35007
+ const STYLE_TAG = /(<)(\/?style\b)/gi;
35008
+ const COMMENT_OPEN = /(<)(!--)/g;
35009
+
35010
+ function escapeHTMLInCSS(str) {
35011
+ if (!str.includes('<')) return str
35012
+ return str.replace(STYLE_TAG, '\\3c $2').replace(COMMENT_OPEN, '\\3c $2')
35013
+ }
35014
+
35015
+ class SafeStringifier extends Stringifier {
35016
+ escapeHTML(node, print) {
35017
+ let builder = this.builder;
35018
+ let chunks, css;
35019
+ this.builder = (str, child, type) => {
35020
+ if (chunks) {
35021
+ css += str;
35022
+ chunks.push(str, child, type);
35023
+ } else if (str.includes('<')) {
35024
+ // Dangerous sequences start with `<`, so everything before
35025
+ // the first `<` is safe to pass through. The rest is buffered
35026
+ // to escape it as a whole.
35027
+ css = str;
35028
+ chunks = [str, child, type];
35029
+ } else {
35030
+ builder(str, child, type);
35031
+ }
35032
+ };
35033
+ print();
35034
+ this.builder = builder;
35035
+ if (!chunks) return
35036
+
35037
+ let escaped = escapeHTMLInCSS(css);
35038
+ if (escaped === css) {
35039
+ // Keep the chunks to get a precise source map
35040
+ for (let i = 0; i < chunks.length; i += 3) {
35041
+ builder(chunks[i], chunks[i + 1], chunks[i + 2]);
35042
+ }
35043
+ } else {
35044
+ // Escaping happens only on a hack attempt, source map is not important
35045
+ builder(escaped, node);
35046
+ }
35047
+ }
35048
+
35049
+ root(node) {
35050
+ if (node.parent && node.parent.type === 'document') {
35051
+ // Document raws around the Root hold markup and are kept as is since CSS in Document can be marked with <style>
35052
+ this.escapeHTML(node, () => this.body(node));
35053
+ if (node.raws.after) this.builder(node.raws.after);
35054
+ } else {
35055
+ this.escapeHTML(node, () => super.root(node));
35056
+ }
35057
+ }
35058
+ }
35059
+
34944
35060
  function stringify(node, builder) {
34945
- let str = new Stringifier(builder);
34946
- str.stringify(node);
35061
+ let str = new SafeStringifier(builder);
35062
+ // Root escapes its own output and keeps markup in Document raws
35063
+ if (node.type === 'root' || node.type === 'document') {
35064
+ str.stringify(node);
35065
+ } else {
35066
+ str.escapeHTML(node, () => str.stringify(node));
35067
+ }
34947
35068
  }
34948
35069
 
34949
35070
  stringify_1 = stringify;
@@ -36716,8 +36837,21 @@ function requireList () {
36716
36837
  let inQuote = false;
36717
36838
  let prevQuote = '';
36718
36839
  let escape = false;
36840
+ let inComment = false;
36841
+
36842
+ for (let i = 0; i < string.length; i++) {
36843
+ let letter = string[i];
36844
+
36845
+ if (inComment) {
36846
+ current += letter;
36847
+ if (letter === '*' && string[i + 1] === '/') {
36848
+ current += '/';
36849
+ i += 1;
36850
+ inComment = false;
36851
+ }
36852
+ continue
36853
+ }
36719
36854
 
36720
- for (let letter of string) {
36721
36855
  if (escape) {
36722
36856
  escape = false;
36723
36857
  } else if (letter === '\\') {
@@ -36729,6 +36863,11 @@ function requireList () {
36729
36863
  } else if (letter === '"' || letter === "'") {
36730
36864
  inQuote = true;
36731
36865
  prevQuote = letter;
36866
+ } else if (letter === '/' && string[i + 1] === '*') {
36867
+ current += '/*';
36868
+ i += 1;
36869
+ inComment = true;
36870
+ continue
36732
36871
  } else if (letter === '(') {
36733
36872
  func += 1;
36734
36873
  } else if (letter === ')') {
@@ -36990,16 +37129,22 @@ function requireMapGenerator () {
36990
37129
  }
36991
37130
  }
36992
37131
  } else if (this.css) {
37132
+ // Single forward pass. Removing every annotation from the whole
37133
+ // string separately would be O(n^2) on many annotations.
36993
37134
  let annotation = '/*# sourceMappingURL=';
37135
+ let css = '';
37136
+ let cursor = 0;
36994
37137
  let startIndex;
36995
- while ((startIndex = this.css.lastIndexOf(annotation)) !== -1) {
37138
+ while ((startIndex = this.css.indexOf(annotation, cursor)) !== -1) {
36996
37139
  let endIndex = this.css.indexOf('*/', startIndex + annotation.length);
36997
37140
  if (endIndex === -1) break
36998
- while (startIndex > 0 && this.css[startIndex - 1] === '\n') {
37141
+ while (startIndex > cursor && this.css[startIndex - 1] === '\n') {
36999
37142
  startIndex--;
37000
37143
  }
37001
- this.css = this.css.slice(0, startIndex) + this.css.slice(endIndex + 2);
37144
+ css += this.css.slice(cursor, startIndex);
37145
+ cursor = endIndex + 2;
37002
37146
  }
37147
+ if (cursor > 0) this.css = css + this.css.slice(cursor);
37003
37148
  }
37004
37149
  }
37005
37150
 
@@ -37794,6 +37939,9 @@ function requireParser$1 () {
37794
37939
  let token, type;
37795
37940
  let length = tokens.length;
37796
37941
  let value = '';
37942
+ // Last character of `value`. Reading it from `value` would flatten
37943
+ // the string concatenation on every comment and make parsing O(n^2).
37944
+ let last = '';
37797
37945
  let clean = true;
37798
37946
  let next, prev;
37799
37947
 
@@ -37806,16 +37954,18 @@ function requireParser$1 () {
37806
37954
  prev = tokens[i - 1] ? tokens[i - 1][0] : 'empty';
37807
37955
  next = tokens[i + 1] ? tokens[i + 1][0] : 'empty';
37808
37956
  if (!SAFE_COMMENT_NEIGHBOR[prev] && !SAFE_COMMENT_NEIGHBOR[next]) {
37809
- if (value.slice(-1) === ',') {
37957
+ if (last === ',') {
37810
37958
  clean = false;
37811
37959
  } else {
37812
37960
  value += token[1];
37961
+ last = token[1].slice(-1);
37813
37962
  }
37814
37963
  } else {
37815
37964
  clean = false;
37816
37965
  }
37817
37966
  } else {
37818
37967
  value += token[1];
37968
+ last = token[1].slice(-1);
37819
37969
  }
37820
37970
  }
37821
37971
  if (!clean) {
@@ -38892,7 +39042,7 @@ function requireProcessor$1 () {
38892
39042
 
38893
39043
  class Processor {
38894
39044
  constructor(plugins = []) {
38895
- this.version = '8.5.28';
39045
+ this.version = '8.5.29';
38896
39046
  this.plugins = this.normalize(plugins);
38897
39047
  }
38898
39048
 
@@ -50742,11 +50892,18 @@ function transformDestructuredProps(ctx, vueImportAliases) {
50742
50892
  const excludedIds = /* @__PURE__ */ new WeakSet();
50743
50893
  const parentStack = [];
50744
50894
  const propsLocalToPublicMap = /* @__PURE__ */ Object.create(null);
50895
+ const modelOptionNodes = /* @__PURE__ */ new Set();
50896
+ let currentModelOption = null;
50745
50897
  for (const key in ctx.propsDestructuredBindings) {
50746
50898
  const { local } = ctx.propsDestructuredBindings[key];
50747
50899
  rootScope[local] = true;
50748
50900
  propsLocalToPublicMap[local] = key;
50749
50901
  }
50902
+ for (const { runtimeOptionNodes } of Object.values(ctx.modelDecls)) {
50903
+ for (const node of runtimeOptionNodes) {
50904
+ modelOptionNodes.add(node);
50905
+ }
50906
+ }
50750
50907
  function pushScope(isFunctionScope = false) {
50751
50908
  const scope = currentScope = Object.create(currentScope);
50752
50909
  scopeStack.push(scope);
@@ -50818,6 +50975,18 @@ function transformDestructuredProps(ctx, vueImportAliases) {
50818
50975
  });
50819
50976
  }
50820
50977
  function rewriteId(id, parent, parentStack2) {
50978
+ if (currentModelOption) {
50979
+ const isDefault = (currentModelOption.type === "ObjectProperty" || currentModelOption.type === "ObjectMethod") && resolveObjectKey(
50980
+ currentModelOption.key,
50981
+ currentModelOption.computed
50982
+ ) === "default";
50983
+ ctx.error(
50984
+ `\`${DEFINE_MODEL}()\` prop options cannot reference destructured props because they are hoisted outside of the setup() function.` + (isDefault ? ` Use the props argument of the default factory instead, e.g. default: props => props${genPropsAccessExp(
50985
+ propsLocalToPublicMap[id.name]
50986
+ ).slice(`__props`.length)}` : ``),
50987
+ id
50988
+ );
50989
+ }
50821
50990
  if (parent.type === "AssignmentExpression" && id === parent.left || parent.type === "UpdateExpression") {
50822
50991
  ctx.error(`Cannot assign to destructured props as they are readonly.`, id);
50823
50992
  }
@@ -50856,6 +51025,9 @@ function transformDestructuredProps(ctx, vueImportAliases) {
50856
51025
  if (parent && parent.type.startsWith("TS") && !TS_NODE_TYPES.includes(parent.type)) {
50857
51026
  return this.skip();
50858
51027
  }
51028
+ if (modelOptionNodes.has(node)) {
51029
+ currentModelOption = node;
51030
+ }
50859
51031
  checkUsage(node, "watch", vueImportAliases.watch);
50860
51032
  checkUsage(node, "toRef", vueImportAliases.toRef);
50861
51033
  if (isFunctionType(node)) {
@@ -50901,6 +51073,9 @@ function transformDestructuredProps(ctx, vueImportAliases) {
50901
51073
  },
50902
51074
  leave(node, parent) {
50903
51075
  parent && parentStack.pop();
51076
+ if (node === currentModelOption) {
51077
+ currentModelOption = null;
51078
+ }
50904
51079
  if (isFunctionType(node)) {
50905
51080
  popScope(true);
50906
51081
  } else if (node.type === "BlockStatement" && !isFunctionType(parent)) {
@@ -52034,7 +52209,7 @@ var __spreadValues = (a, b) => {
52034
52209
  }
52035
52210
  return a;
52036
52211
  };
52037
- const version = "3.5.43";
52212
+ const version = "3.5.44";
52038
52213
  const parseCache = parseCache$1;
52039
52214
  const errorMessages = __spreadValues(__spreadValues({}, errorMessages$1), DOMErrorMessages);
52040
52215
  const walk = walk$2;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue/compiler-sfc",
3
- "version": "3.5.43",
3
+ "version": "3.5.44",
4
4
  "description": "@vue/compiler-sfc",
5
5
  "main": "dist/compiler-sfc.cjs.js",
6
6
  "module": "dist/compiler-sfc.esm-browser.js",
@@ -42,15 +42,15 @@
42
42
  },
43
43
  "homepage": "https://github.com/vuejs/core/tree/main/packages/compiler-sfc#readme",
44
44
  "dependencies": {
45
- "@babel/parser": "^7.29.8",
46
- "@vue/compiler-core": "3.5.43",
47
- "@vue/compiler-dom": "3.5.43",
48
- "@vue/compiler-ssr": "3.5.43",
49
- "@vue/shared": "3.5.43",
45
+ "@babel/parser": "^7.29.9",
46
+ "@vue/compiler-core": "3.5.44",
47
+ "@vue/compiler-dom": "3.5.44",
48
+ "@vue/compiler-ssr": "3.5.44",
49
+ "@vue/shared": "3.5.44",
50
50
  "estree-walker": "^2.0.2",
51
51
  "magic-string": "^0.30.21",
52
- "postcss": "^8.5.28",
53
- "source-map-js": "^1.2.1"
52
+ "postcss": "^8.5.29",
53
+ "source-map-js": "^1.2.2"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@babel/types": "^7.29.8",
@@ -62,6 +62,6 @@
62
62
  "postcss-modules": "^6.0.1",
63
63
  "postcss-selector-parser": "^7.1.6",
64
64
  "pug": "^3.0.4",
65
- "sass": "^1.104.1"
65
+ "sass": "^1.105.1"
66
66
  }
67
67
  }