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
6 changes: 4 additions & 2 deletions Jint.Benchmark/BuiltinShapeBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ public Engine EngineInitGenerators()
+ "Intl.DateTimeFormat.prototype.resolvedOptions; Intl.NumberFormat.prototype.resolvedOptions;"
+ "Array.prototype.map; Number.prototype.toFixed; Boolean.prototype.valueOf; Error.prototype.toString;"
+ "[].values().next; new Map().keys().next; new Set().values().next; ''[Symbol.iterator]().next;"
+ "String.prototype.slice; Date.prototype.getTime; Set.prototype.union; RegExp.prototype.test;");
+ "String.prototype.slice; Date.prototype.getTime; Set.prototype.union; RegExp.prototype.test;"
+ "Uint8Array.prototype.join;");

[Benchmark]
public Engine EngineInitPrototypes()
Expand All @@ -122,7 +123,8 @@ public Engine EngineInitPrototypes()
+ "Temporal.PlainTime.from; Temporal.PlainYearMonth.from; Temporal.PlainMonthDay.from; Temporal.ZonedDateTime.from;"
+ "Intl.NumberFormat.supportedLocalesOf; Intl.Collator.supportedLocalesOf; Intl.DateTimeFormat.supportedLocalesOf;"
+ "Intl.ListFormat.supportedLocalesOf; Intl.PluralRules.supportedLocalesOf; Intl.RelativeTimeFormat.supportedLocalesOf;"
+ "Intl.Segmenter.supportedLocalesOf; Intl.DisplayNames.supportedLocalesOf; Intl.DurationFormat.supportedLocalesOf;");
+ "Intl.Segmenter.supportedLocalesOf; Intl.DisplayNames.supportedLocalesOf; Intl.DurationFormat.supportedLocalesOf;"
+ "Number.parseInt; Int8Array.from;");

[Benchmark]
public Engine EngineInitConstructors()
Expand Down
13 changes: 13 additions & 0 deletions Jint.SourceGenerators/Attributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,5 +217,18 @@ public JsAliasAttribute(string name, string target)
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}

""";
}
8 changes: 7 additions & 1 deletion Jint.SourceGenerators/Emitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ private static IEnumerable<string> EnumerateAllJsNames(ObjectDefinition obj, IRe
foreach (var name in accessorsByName.Keys) yield return name;
foreach (var thr in obj.ThrowerAccessors) yield return thr.JsName;
foreach (var a in obj.Aliases) yield return a.Name;
foreach (var s in obj.InstanceSlots) yield return s;
}

/// <summary>
Expand Down Expand Up @@ -360,7 +361,7 @@ string SlotExpr(FunctionDefinition? fn) => fn is null
sb.AppendLine();
sb.AppendLine(" private static global::Jint.Native.Object.BuiltinShape BuildBuiltinShape_Generated()");
sb.AppendLine(" {");
sb.Append(" var builder = new global::Jint.Native.Object.BuiltinShape.Builder(").Append(obj.Properties.Count + dataProperties.Count + accessorsByName.Count + obj.Aliases.Count).AppendLine(");");
sb.Append(" var builder = new global::Jint.Native.Object.BuiltinShape.Builder(").Append(obj.Properties.Count + dataProperties.Count + accessorsByName.Count + obj.Aliases.Count + obj.InstanceSlots.Count).AppendLine(");");
// Order matches the dictionary path: properties, then functions, then accessors (each sorted by JsName).
// Static-immutable constants share a process-wide descriptor; other properties are per-realm instance slots.
foreach (var prop in obj.Properties)
Expand Down Expand Up @@ -394,6 +395,11 @@ string SlotExpr(FunctionDefinition? fn) => fn is null
{
sb.Append(" builder.Alias(__Key_").Append(SanitizeIdentifier(alias.Name)).Append(", __Key_").Append(SanitizeIdentifier(alias.Target)).AppendLine(");");
}
// Host-filled instance slots last (the host supplies the descriptor in Initialize via SetBuiltinSlotByName).
foreach (var slot in obj.InstanceSlots)
{
sb.Append(" builder.Instance(__Key_").Append(SanitizeIdentifier(slot)).AppendLine(");");
}
sb.AppendLine(" return builder.Build();");
sb.AppendLine(" }");
sb.AppendLine();
Expand Down
13 changes: 13 additions & 0 deletions Jint.SourceGenerators/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ internal sealed record class ObjectDefinition(
EquatableArray<ThrowerAccessorDefinition> ThrowerAccessors,
EquatableArray<IntrinsicReferenceDefinition> IntrinsicReferences,
EquatableArray<AliasDefinition> Aliases,
EquatableArray<string> InstanceSlots,
EquatableArray<DiagnosticInfo> DiagnosticInfos)
{
public string HintName => string.IsNullOrEmpty(Namespace)
Expand Down Expand Up @@ -138,6 +139,7 @@ public IEnumerable<Diagnostic> Diagnostics
var throwerAccessors = new List<ThrowerAccessorDefinition>();
var intrinsicReferences = new List<IntrinsicReferenceDefinition>();
var aliases = new List<AliasDefinition>();
var instanceSlots = new List<string>();
HashSet<string>? seenFunctionClrNames = null;
HashSet<string>? seenThrowerNames = null;
HashSet<string>? seenIntrinsicReferenceNames = null;
Expand Down Expand Up @@ -206,6 +208,16 @@ public IEnumerable<Diagnostic> Diagnostics
aliases.Add(new AliasDefinition(aliasName!, aliasTarget!));
}

// Class-level [JsInstanceSlot("name")] — a host-filled reserved slot (shape path only).
foreach (var attr in typeSymbol.GetAttributes())
{
if (attr.AttributeClass?.Name != "JsInstanceSlotAttribute") continue;
if (attr.ConstructorArguments.Length == 0) continue;
var slotName = attr.ConstructorArguments[0].Value as string;
if (string.IsNullOrWhiteSpace(slotName)) continue;
instanceSlots.Add(slotName!);
}

foreach (var member in typeSymbol.GetMembers())
{
ct.ThrowIfCancellationRequested();
Expand Down Expand Up @@ -397,6 +409,7 @@ public IEnumerable<Diagnostic> Diagnostics
ThrowerAccessors: throwerAccessors.ToEquatableArray(),
IntrinsicReferences: intrinsicReferences.ToEquatableArray(),
Aliases: aliases.ToEquatableArray(),
InstanceSlots: instanceSlots.ToEquatableArray(),
DiagnosticInfos: diagnostics.ToEquatableArray());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ public JsAliasAttribute(string name, string target)
public string Name { get; }
public string Target { get; }
}

// Class-level, repeats. Reserves a per-realm own-property slot (appended after all other own
// properties, matching a hand-written SetProperty/AddDangerous tail) that the host fills in
// Initialize via SetBuiltinSlotByName(name, descriptor) — for a computed/lazy value the generator
// can't express, e.g. %TypedArray%.prototype.toString aliasing %Array.prototype.toString% lazily.
// Shape hosts only (a non-shaped host just SetProperty()s the value in Initialize as before).
[global::System.AttributeUsage(global::System.AttributeTargets.Class, AllowMultiple = true)]
[global::System.Diagnostics.Conditional("JINT_SOURCE_GENERATORS")]
internal sealed class JsInstanceSlotAttribute : global::System.Attribute
{
public JsInstanceSlotAttribute(string name) { Name = name; }
public string Name { get; }
}
Loading
Loading