Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -549,8 +549,16 @@ addObject(BUILTIN_SHAPES, BuiltInMixedReadonlyId, [
[
'map',
addFunction(BUILTIN_SHAPES, [], {
/**
* Note `map`'s arguments are annotated as Effect.ConditionallyMutate as
* calling `<array>.map(fn)` might invoke `fn`, which means replaying its
* effects.
*
* (Note that Effect.Read / Effect.Capture on a function type means
* potential data dependency or aliasing respectively.)
*/
positionalParams: [],
restParam: Effect.Read,
restParam: Effect.ConditionallyMutate,
returnType: {kind: 'Object', shapeId: BuiltInArrayId},
calleeEffect: Effect.ConditionallyMutate,
returnValueKind: ValueKind.Mutable,
Expand All @@ -561,7 +569,7 @@ addObject(BUILTIN_SHAPES, BuiltInMixedReadonlyId, [
'flatMap',
addFunction(BUILTIN_SHAPES, [], {
positionalParams: [],
restParam: Effect.Read,
restParam: Effect.ConditionallyMutate,
returnType: {kind: 'Object', shapeId: BuiltInArrayId},
calleeEffect: Effect.ConditionallyMutate,
returnValueKind: ValueKind.Mutable,
Expand All @@ -572,7 +580,7 @@ addObject(BUILTIN_SHAPES, BuiltInMixedReadonlyId, [
'filter',
addFunction(BUILTIN_SHAPES, [], {
positionalParams: [],
restParam: Effect.Read,
restParam: Effect.ConditionallyMutate,
returnType: {kind: 'Object', shapeId: BuiltInArrayId},
calleeEffect: Effect.ConditionallyMutate,
returnValueKind: ValueKind.Mutable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,16 @@ function inferOperandEffect(state: State, place: Place): null | FunctionEffect {
if (isRefOrRefValue(place.identifier)) {
break;
} else if (value.kind === ValueKind.Context) {
CompilerError.invariant(value.context.size > 0, {
reason:
"[InferFunctionEffects] Expected Context-kind value's capture list to be non-empty.",
loc: place.loc,
});
return {
kind: 'ContextMutation',
loc: place.loc,
effect: place.effect,
places: value.context.size === 0 ? new Set([place]) : value.context,
places: value.context,
};
} else if (
value.kind !== ValueKind.Mutable &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -857,17 +857,19 @@ function inferBlock(
break;
}
case 'ArrayExpression': {
const valueKind: AbstractValue = hasContextRefOperand(state, instrValue)
? {
kind: ValueKind.Context,
reason: new Set([ValueReason.Other]),
context: new Set(),
}
: {
kind: ValueKind.Mutable,
reason: new Set([ValueReason.Other]),
context: new Set(),
};
const contextRefOperands = getContextRefOperand(state, instrValue);
const valueKind: AbstractValue =
contextRefOperands.length > 0
? {
kind: ValueKind.Context,
reason: new Set([ValueReason.Other]),
context: new Set(contextRefOperands),
}
: {
kind: ValueKind.Mutable,
reason: new Set([ValueReason.Other]),
context: new Set(),
};
continuation = {
kind: 'initialize',
valueKind,
Expand Down Expand Up @@ -918,17 +920,19 @@ function inferBlock(
break;
}
case 'ObjectExpression': {
const valueKind: AbstractValue = hasContextRefOperand(state, instrValue)
? {
kind: ValueKind.Context,
reason: new Set([ValueReason.Other]),
context: new Set(),
}
: {
kind: ValueKind.Mutable,
reason: new Set([ValueReason.Other]),
context: new Set(),
};
const contextRefOperands = getContextRefOperand(state, instrValue);
const valueKind: AbstractValue =
contextRefOperands.length > 0
? {
kind: ValueKind.Context,
reason: new Set([ValueReason.Other]),
context: new Set(contextRefOperands),
}
: {
kind: ValueKind.Mutable,
reason: new Set([ValueReason.Other]),
context: new Set(),
};

for (const property of instrValue.properties) {
switch (property.kind) {
Expand Down Expand Up @@ -1593,15 +1597,21 @@ function inferBlock(
}
case 'LoadLocal': {
const lvalue = instr.lvalue;
const effect =
state.isDefined(lvalue) &&
state.kind(lvalue).kind === ValueKind.Context
? Effect.ConditionallyMutate
: Effect.Capture;
CompilerError.invariant(
!(
state.isDefined(lvalue) &&
state.kind(lvalue).kind === ValueKind.Context
),
{
reason:
'[InferReferenceEffects] Unexpected LoadLocal with context kind',
loc: lvalue.loc,
},
);
state.referenceAndRecordEffects(
freezeActions,
instrValue.place,
effect,
Effect.Capture,
ValueReason.Other,
);
lvalue.effect = Effect.ConditionallyMutate;
Expand Down Expand Up @@ -1932,19 +1942,20 @@ function inferBlock(
);
}

function hasContextRefOperand(
function getContextRefOperand(
state: InferenceState,
instrValue: InstructionValue,
): boolean {
): Array<Place> {
const result = [];
for (const place of eachInstructionValueOperand(instrValue)) {
if (
state.isDefined(place) &&
state.kind(place).kind === ValueKind.Context
) {
return true;
result.push(place);
}
}
return false;
return result;
}

export function getFunctionCallSignature(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2269,7 +2269,7 @@ function codegenInstructionValue(
* https://en.wikipedia.org/wiki/List_of_Unicode_characters#Control_codes
*/
const STRING_REQUIRES_EXPR_CONTAINER_PATTERN =
/[\u{0000}-\u{001F}\u{007F}\u{0080}-\u{FFFF}]|"/u;
/[\u{0000}-\u{001F}\u{007F}\u{0080}-\u{FFFF}]|"|\\/u;
function codegenJsxAttribute(
cx: Context,
attribute: JsxAttribute,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@

## Input

```javascript
/**
* Fixture showing `@babel/generator` bug with jsx attribute strings containing
* escape sequences. Note that this is only a problem when generating jsx
* literals.
*
* When using the jsx transform to correctly lower jsx into
* `React.createElement` calls, the escape sequences are preserved correctly
* (see evaluator output).
*/
function MyApp() {
return <input pattern="\w" />;
}

export const FIXTURE_ENTRYPOINT = {
fn: MyApp,
params: [],
};

```

## Code

```javascript
import { c as _c } from "react/compiler-runtime"; /**
* Fixture showing `@babel/generator` bug with jsx attribute strings containing
* escape sequences. Note that this is only a problem when generating jsx
* literals.
*
* When using the jsx transform to correctly lower jsx into
* `React.createElement` calls, the escape sequences are preserved correctly
* (see evaluator output).
*/
function MyApp() {
const $ = _c(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = <input pattern={"\\w"} />;
$[0] = t0;
} else {
t0 = $[0];
}
return t0;
}

export const FIXTURE_ENTRYPOINT = {
fn: MyApp,
params: [],
};

```

### Eval output
(kind: ok) <input pattern="\w">
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Fixture showing `@babel/generator` bug with jsx attribute strings containing
* escape sequences. Note that this is only a problem when generating jsx
* literals.
*
* When using the jsx transform to correctly lower jsx into
* `React.createElement` calls, the escape sequences are preserved correctly
* (see evaluator output).
*/
function MyApp() {
return <input pattern="\w" />;
}

export const FIXTURE_ENTRYPOINT = {
fn: MyApp,
params: [],
};
Loading
Loading