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
5 changes: 3 additions & 2 deletions src/core/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ export namespace HashHelpers
}

export function hashCodeAny(key: any): int {
let keyLocal = key;
const anyPtr = Deref(<Reference<Opaque>> Ref(keyLocal));
// the parameter's own slot: a copy of it in a local is a second reference, which -mm=own
// cannot give an exported function's parameter
const anyPtr = Deref(<Reference<Opaque>> Ref(key));
let anyStruct: Reference<[size: index, type: string, data: byte]> = anyPtr;
return hashCodeBinary(Ref(anyStruct.data), anyStruct.size);
}
Expand Down
10 changes: 10 additions & 0 deletions src/lib.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ declare namespace __Boolean {
function toString(this: boolean): string;
}

@final
declare class Boolean {
private value: boolean;

Expand All @@ -36,6 +37,7 @@ declare namespace __Number {
function toString(this: number, radix?: int): string;
}

@final
declare class Number {
static EPSILON: number;

Expand Down Expand Up @@ -101,6 +103,7 @@ declare namespace __BigInt {
function toString(this: bigint): string;
}

@final
declare class BigInt {
private value: bigint;

Expand All @@ -113,6 +116,7 @@ declare class BigInt {
valueOf(): bigint;
}

@final
declare class Date {
private timestamp: time_t;

Expand Down Expand Up @@ -217,6 +221,7 @@ declare class Date {
[Symbol.toPrimitive](hint: string) : string | number;
}

@final
declare class MatchIndicesResults
{
private match: Opaque | null;
Expand All @@ -232,6 +237,7 @@ declare class MatchIndicesResults
get length(): index;
}

@final
declare class MatchResults
{
private indices_: MatchIndicesResults;
Expand All @@ -253,6 +259,7 @@ declare class MatchResults
get indices(): MatchIndicesResults/* | undefined*/;
}

@final
declare class RegExp {

dotAll: boolean;
Expand Down Expand Up @@ -357,6 +364,7 @@ declare namespace __String {
function valueOf(this: string): string;
}

@final
declare class String {
private value: string;

Expand Down Expand Up @@ -639,6 +647,7 @@ declare namespace Math {
function trunc(x: number): number;
}

@final
declare class Headers {
private names: string[];
private values: string[];
Expand All @@ -660,6 +669,7 @@ declare class Headers {
toRawString(): string;
}

@final
declare class Response {
status: int;
headers: Headers;
Expand Down
30 changes: 15 additions & 15 deletions src/lib.linux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ type errno_t = i32;
type time_t = long;

// locale
declare function setlocale (category: int, locale: string): void;
declare function newlocale (category: int, locale: string, base: Opaque | null): Opaque;
declare function uselocale (locale: Opaque): Opaque;
declare function freelocale (locale: Opaque): void;
@nodrops declare function setlocale (category: int, locale: string): void;
@nodrops declare function newlocale (category: int, locale: string, base: Opaque | null): Opaque;
@nodrops declare function uselocale (locale: Opaque): Opaque;
@nodrops declare function freelocale (locale: Opaque): void;
// LC_TIME

@varargs
declare function snprintf(out: string, n: index, format: string): void;
@nodrops declare function snprintf(out: string, n: index, format: string): void;

export function convertNumber(bufferSize: int, format: string, value: number): string
{
Expand All @@ -36,13 +36,13 @@ export function convertInteger(bufferSize: int, format: string, value: i32): str


// Date & Time
declare function tzset();
@nodrops declare function tzset();
export function init_time() {
tzset();
}

type timeval = [tv_sec: i64, tv_usec: i32];
declare function timespec_get(tv: Reference<timeval>, base: int): int;
@nodrops declare function timespec_get(tv: Reference<timeval>, base: int): int;

const TIME_UTC = 1;
export function getMilliseconds(): i64 {
Expand All @@ -60,7 +60,7 @@ type tm = [tm_sec: i32, tm_min: i32, tm_hour: i32, tm_mday: i32, tm_mon: i32, tm
// struct, and strftime's %z and %Z read the last two, so every C call takes this one.
type c_tm = [tm_sec: i32, tm_min: i32, tm_hour: i32, tm_mday: i32, tm_mon: i32, tm_year: i32, tm_wday: i32, tm_yday: i32, tm_isdst: i32, tm_gmtoff: index, tm_zone: index];

declare function timegm(tv: Reference<c_tm>): long;
@nodrops declare function timegm(tv: Reference<c_tm>): long;
export function makegmtime(year: i32, month: i32, day: i32, hour: i32, minutes: i32, seconds: i32, milliseconds: i32): i64 {
let tm1: c_tm = [seconds, minutes, hour, day, month, year, 0, 0, 0, 0, 0];
const sec = timegm(Ref(tm1));
Expand All @@ -73,7 +73,7 @@ export function makegmtime(year: i32, month: i32, day: i32, hour: i32, minutes:
return sec * 1000 + milliseconds; // return ms
}

declare function mktime(tv: Reference<c_tm>): long;
@nodrops declare function mktime(tv: Reference<c_tm>): long;
export function maketime(year: i32, month: i32, day: i32, hour: i32, minutes: i32, seconds: i32, milliseconds: i32): i64 {
// tm_isdst -1: a local time is in daylight saving time or not as the date says (0 would read
// a summer date as standard time, an hour off)
Expand All @@ -88,8 +88,8 @@ export function maketime(year: i32, month: i32, day: i32, hour: i32, minutes: i3
return sec * 1000 + milliseconds; // return ms
}

declare function gmtime_r(time: Reference<time_t>, tm: Reference<c_tm>) : Reference<c_tm>;
declare function localtime_r(time: Reference<time_t>, tm: Reference<c_tm>) : Reference<c_tm>;
@nodrops declare function gmtime_r(time: Reference<time_t>, tm: Reference<c_tm>) : Reference<c_tm>;
@nodrops declare function localtime_r(time: Reference<time_t>, tm: Reference<c_tm>) : Reference<c_tm>;
function c_time(time: long, isUtc: boolean): c_tm {
let tmDest: c_tm = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let timeInSec: time_t = time / 1000;
Expand Down Expand Up @@ -120,7 +120,7 @@ export function gettimezone(): i32 {
}

// returns `buffer`: a pointer, not copied
declare function ctime_r(time: Reference<time_t>, buffer: string): Opaque;
@nodrops declare function ctime_r(time: Reference<time_t>, buffer: string): Opaque;
export function timestamp_to_string(maxsize: index, time: long): string {
let timeInSec: time_t = time / 1000;
let buffer : char[] = [];
Expand All @@ -130,7 +130,7 @@ export function timestamp_to_string(maxsize: index, time: long): string {
return s;
}

declare function asctime_r(time: Reference<c_tm>, buffer: string): Opaque;
@nodrops declare function asctime_r(time: Reference<c_tm>, buffer: string): Opaque;
export function time_to_string(maxsize: index, time: long, isUtc: boolean): string {
let tm = c_time(time, isUtc);

Expand All @@ -141,7 +141,7 @@ export function time_to_string(maxsize: index, time: long, isUtc: boolean): stri
return s;
}

declare function strftime(out: string, maxsize: index, format: string, tm: Reference<c_tm>): index;
@nodrops declare function strftime(out: string, maxsize: index, format: string, tm: Reference<c_tm>): index;
export function time_format(maxsize: index, format: string, time: long, isUtc: boolean): string {
let tm = c_time(time, isUtc);

Expand All @@ -152,7 +152,7 @@ export function time_format(maxsize: index, format: string, time: long, isUtc: b
return s;
}

declare function strftime_l(out: string, maxsize: index, format: string, tm: Reference<c_tm>, locale: Opaque): index;
@nodrops declare function strftime_l(out: string, maxsize: index, format: string, tm: Reference<c_tm>, locale: Opaque): index;
export function time_format_locale(maxsize: index, format: string, time: long, locale: string, isUtc: boolean): string {
let tm = c_time(time, isUtc);

Expand Down
44 changes: 37 additions & 7 deletions src/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace __Boolean {
}
}

@final
export class Boolean {
public constructor(private value: boolean) {
}
Expand Down Expand Up @@ -65,6 +66,7 @@ namespace __Number {
}
}

@final
export class Number {
public static EPSILON = 2 ** (-52);

Expand Down Expand Up @@ -158,6 +160,7 @@ namespace __BigInt {
}
}

@final
export class BigInt {
public constructor(private value: bigint) {
}
Expand All @@ -175,6 +178,7 @@ export class BigInt {
}
}

@final
export class Date {
private timestamp: time_t;
constructor (valueOrYear?: time_t | i32, monthIndex?: i32, day = 1, hours = 0, minutes = 0, seconds = 0, milliseconds = 0) {
Expand Down Expand Up @@ -436,6 +440,7 @@ export class Date {
}
}

@final
export class MatchIndicesResults
{
constructor(private match: Opaque | null = null, private lastIndex: index = 0) {
Expand All @@ -455,6 +460,7 @@ export class MatchIndicesResults
}
}

@final
export class MatchResults
{
private indices_: MatchIndicesResults = null;
Expand All @@ -479,10 +485,13 @@ export class MatchResults
// TODO: finish it
//if (!this.hasIndices)
// return undefined;
return this.indices_ ??= new MatchIndicesResults(this.match, this.lastIndex);
// a new one each time: it holds no state of its own, and a cached one in a field could
// only be lent out, never returned, under -mm=own
return new MatchIndicesResults(this.match, this.lastIndex);
}
}

@final
export class RegExp
{
dotAll = false;
Expand Down Expand Up @@ -1284,6 +1293,7 @@ class StringIterator implements ClassIterator<string> {
}
*/

@final
export class String {

public constructor(private value: string) {
Expand Down Expand Up @@ -1780,6 +1790,7 @@ enum States {
View = 8,
}

@final
export class ArrayBuffer {

private arrayOfView: char[];
Expand Down Expand Up @@ -1831,7 +1842,7 @@ export class ArrayBuffer {
const newArrayBuffer = new ArrayBuffer(0);
newArrayBuffer.states = this.states | States.NonResizable;
newArrayBuffer.maxByteLength = this.maxByteLength;
newArrayBuffer.arrayOfView = this.arrayOfView.view(start, end);
newArrayBuffer.arrayOfView = this.copyOf(start, end);
return newArrayBuffer;
}

Expand All @@ -1840,7 +1851,11 @@ export class ArrayBuffer {
const newArrayBuffer = new ArrayBuffer(0);
newArrayBuffer.states = this.states;
newArrayBuffer.maxByteLength = this.maxByteLength;
newArrayBuffer.arrayOfView = this.detach();
if (this.arrayOfView != null) {
newArrayBuffer.arrayOfView = this.copyOf(0, this.arrayOfView.length);
}

this.detach();
return newArrayBuffer;
}

Expand All @@ -1850,21 +1865,33 @@ export class ArrayBuffer {
return newArrayBuffer;
}

// The bytes [start, end) in an array of their own. A slice is a copy, as in JavaScript, and a
// transfer copies too: the bytes cannot move out of the field into another object under
// -mm=own, where a read of a field only borrows it.
private copyOf(start: int, end: int): char[] {
let copy: char[] = [];
copy.length = end - start;
for (let i = start; i < end; i++) {
copy[i - start] = this.arrayOfView[i];
}

return copy;
}

private detach() {
this.states |= States.Detached;
const inst = this.arrayOfView;
this.arrayOfView = null;
return inst;
}

// the assignment releases the bytes under rc and own, and leaves them to the collector under gc
[Symbol.dispose]() {
if (this.arrayOfView != null && !this.detached) {
delete this.arrayOfView;
this.arrayOfView = null;
}
}
}

@final
export class Headers {
private names: string[];
private values: string[];
Expand All @@ -1874,7 +1901,9 @@ export class Headers {
this.values = [];

if (init != undefined) {
for (const [k, v] of init) this.set(k, v);
// copies: set may overwrite an element of this.values, and under -mm=own a call that
// may destroy anything cannot be lent the caller's strings
for (const [k, v] of init) this.set(k + "", v + "");
}
}

Expand Down Expand Up @@ -1963,6 +1992,7 @@ export class Headers {
}
}

@final
export class Response {
public constructor(
public status: int,
Expand Down
Loading