mirror of https://github.com/tc39/test262.git
This commit is contained in:
parent
b07c546b8a
commit
50dd1fbd58
|
@ -0,0 +1,52 @@
|
|||
// Copyright (C) 2018 Amal Hussein. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-atomics.wait
|
||||
description: >
|
||||
False timeout arg should result in an +0 timeout
|
||||
info: |
|
||||
Atomics.wait( typedArray, index, value, timeout )
|
||||
|
||||
4.Let q be ? ToNumber(timeout).
|
||||
...
|
||||
Null Return +0.
|
||||
Boolean If argument is true, return 1. If argument is false, return +0.
|
||||
features: [ Atomics ]
|
||||
includes: [ atomicsHelper.js ]
|
||||
---*/
|
||||
|
||||
function getReport() {
|
||||
var r;
|
||||
while ((r = $262.agent.getReport()) == null)
|
||||
$262.agent.sleep(100);
|
||||
return r;
|
||||
}
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab) {
|
||||
var int32Array = new Int32Array(sab);
|
||||
var start = Date.now();
|
||||
$262.agent.report(Atomics.wait(int32Array, 0, 0, false)); // false => +0
|
||||
$262.agent.report(Date.now() - start);
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
var int32Array = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
||||
|
||||
$262.agent.broadcast(int32Array.buffer);
|
||||
|
||||
$262.agent.sleep(150);
|
||||
|
||||
var atomicsReport = getReport();
|
||||
var timeDiffReport = getReport();
|
||||
|
||||
assert.sameValue(atomicsReport, 'timed-out');
|
||||
|
||||
assert(timeDiffReport >= 0, 'timeout should be a min of 0ms');
|
||||
|
||||
assert(timeDiffReport <= $ATOMICS_MAX_TIME_EPSILON, 'timeout should be a max of $$ATOMICS_MAX_TIME_EPSILON');
|
||||
|
||||
assert.sameValue(Atomics.wake(int32Array, 0), 0);
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (C) 2018 Amal Hussein. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-atomics.wait
|
||||
description: >
|
||||
NaN timeout arg should result in an infinite timeout
|
||||
info: |
|
||||
Atomics.wait( typedArray, index, value, timeout )
|
||||
|
||||
4.Let q be ? ToNumber(timeout).
|
||||
...
|
||||
Undefined Return NaN.
|
||||
5.If q is NaN, let t be +∞, else let t be max(q, 0)
|
||||
features: [ Atomics, SharedArrayBuffer, TypedArray ]
|
||||
---*/
|
||||
|
||||
function getReport() {
|
||||
var r;
|
||||
while ((r = $262.agent.getReport()) == null)
|
||||
$262.agent.sleep(100);
|
||||
return r;
|
||||
}
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab) {
|
||||
var int32Array = new Int32Array(sab);
|
||||
$262.agent.report(Atomics.wait(int32Array, 0, 0, NaN)); // NaN => +Infinity
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
var int32Array = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
||||
|
||||
$262.agent.broadcast(int32Array.buffer);
|
||||
|
||||
$262.agent.sleep(500); // Ample time
|
||||
|
||||
assert.sameValue($262.agent.getReport(), null);
|
||||
|
||||
assert.sameValue(Atomics.wake(int32Array, 0), 1);
|
||||
|
||||
assert.sameValue(getReport(), "ok");
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (C) 2017 Mozilla Corporation. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-atomics.wait
|
||||
description: >
|
||||
Test that Atomics.wait does not time out with a NaN timeout
|
||||
---*/
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab, id) {
|
||||
var ia = new Int32Array(sab);
|
||||
$262.agent.report(Atomics.wait(ia, 0, 0, NaN)); // NaN => Infinity
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
var ia = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
||||
|
||||
$262.agent.broadcast(ia.buffer);
|
||||
$262.agent.sleep(500); // Ample time
|
||||
assert.sameValue($262.agent.getReport(), null);
|
||||
Atomics.wake(ia, 0);
|
||||
assert.sameValue(getReport(), "ok");
|
||||
|
||||
function getReport() {
|
||||
var r;
|
||||
while ((r = $262.agent.getReport()) == null)
|
||||
$262.agent.sleep(100);
|
||||
return r;
|
||||
}
|
|
@ -24,7 +24,6 @@ var poisoned = {
|
|||
};
|
||||
|
||||
assert.throws(RangeError, () => Atomics.wait(int32Array, -Infinity, poisoned, poisoned));
|
||||
assert.throws(RangeError, () => Atomics.wait(int32Array, -0.999, poisoned, poisoned));
|
||||
assert.throws(RangeError, () => Atomics.wait(int32Array, -7.999, poisoned, poisoned));
|
||||
assert.throws(RangeError, () => Atomics.wait(int32Array, -1, poisoned, poisoned));
|
||||
assert.throws(RangeError, () => Atomics.wait(int32Array, -0.00000000000000001, poisoned, poisoned));
|
||||
assert.throws(RangeError, () => Atomics.wait(int32Array, NaN, poisoned, poisoned));
|
||||
assert.throws(RangeError, () => Atomics.wait(int32Array, -300, poisoned, poisoned));
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (C) 2018 Amal Hussein. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-atomics.wait
|
||||
description: >
|
||||
Null timeout arg should result in an +0 timeout
|
||||
info: |
|
||||
Atomics.wait( typedArray, index, value, timeout )
|
||||
|
||||
4.Let q be ? ToNumber(timeout).
|
||||
...
|
||||
Null Return +0.
|
||||
Boolean If argument is true, return 1. If argument is false, return +0.
|
||||
features: [ Atomics ]
|
||||
includes: [ atomicsHelper.js ]
|
||||
---*/
|
||||
|
||||
function getReport() {
|
||||
var r;
|
||||
while ((r = $262.agent.getReport()) == null)
|
||||
$262.agent.sleep(100);
|
||||
return r;
|
||||
}
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab) {
|
||||
var int32Array = new Int32Array(sab);
|
||||
var start = Date.now();
|
||||
$262.agent.report(Atomics.wait(int32Array, 0, 0, null)); // null => +0
|
||||
$262.agent.report(Date.now() - start);
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
var int32Array = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
||||
|
||||
$262.agent.broadcast(int32Array.buffer);
|
||||
|
||||
$262.agent.sleep(150);
|
||||
|
||||
var atomicsReport = getReport();
|
||||
var timeDiffReport = getReport();
|
||||
|
||||
assert.sameValue(atomicsReport, 'timed-out');
|
||||
|
||||
assert(timeDiffReport >= 0, 'timeout should be a min of 0ms');
|
||||
|
||||
assert(timeDiffReport <= $ATOMICS_MAX_TIME_EPSILON, 'timeout should be a max of $$ATOMICS_MAX_TIME_EPSILON');
|
||||
|
||||
assert.sameValue(Atomics.wake(int32Array, 0), 0);
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (C) 2018 Amal Hussein. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-atomics.wait
|
||||
description: >
|
||||
False timeout arg should result in a timeout value of 1
|
||||
info: |
|
||||
Atomics.wait( typedArray, index, value, timeout )
|
||||
|
||||
4.Let q be ? ToNumber(timeout).
|
||||
...
|
||||
Object
|
||||
Apply the following steps:
|
||||
|
||||
Let primValue be ? ToPrimitive(argument, hint Number).
|
||||
Return ? ToNumber(primValue).
|
||||
features: [ Atomics ]
|
||||
includes: [atomicsHelper.js]
|
||||
---*/
|
||||
|
||||
function getReport() {
|
||||
var r;
|
||||
while ((r = $262.agent.getReport()) == null)
|
||||
$262.agent.sleep(100);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab) {
|
||||
var int32Array = new Int32Array(sab);
|
||||
$262.agent.report("A " + Atomics.wait(int32Array, 0, 0, {})); // {} => NaN => Infinity
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
var int32Array = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
||||
|
||||
$262.agent.broadcast(int32Array.buffer);
|
||||
|
||||
$262.agent.sleep(500); // Ample time
|
||||
|
||||
assert.sameValue(Atomics.wake(int32Array, 0), 1);
|
||||
|
||||
assert.sameValue(getReport(), "A ok");
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright (C) 2018 Amal Hussein. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-atomics.wait
|
||||
description: >
|
||||
Passing an object with no callable methods for the timeout param throws
|
||||
info: |
|
||||
Atomics.wait( typedArray, index, value, timeout )
|
||||
|
||||
4.Let q be ? ToNumber(timeout).
|
||||
...
|
||||
Object
|
||||
Apply the following steps:
|
||||
Let primValue be ? ToPrimitive(argument, hint Number).
|
||||
...
|
||||
g. Return ? OrdinaryToPrimitive(input, hint).
|
||||
...
|
||||
6.Throw a TypeError exception.
|
||||
features: [ Atomics ]
|
||||
---*/
|
||||
|
||||
var sab = new SharedArrayBuffer(4);
|
||||
var int32Array = new Int32Array(sab);
|
||||
|
||||
function getReport() {
|
||||
var r;
|
||||
while ((r = $262.agent.getReport()) == null) {
|
||||
$262.agent.sleep(100);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab) {
|
||||
var poisoned = {
|
||||
valueOf: false,
|
||||
toString: false
|
||||
};
|
||||
|
||||
var err;
|
||||
|
||||
try {
|
||||
Atomics.wait(int32Array, 0, 0, poisoned);
|
||||
} catch(e) {
|
||||
err = e.constructor;
|
||||
}
|
||||
|
||||
$262.agent.report(err);
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
var int32Array = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
||||
|
||||
$262.agent.broadcast(int32Array.buffer);
|
||||
|
||||
$262.agent.sleep(150);
|
||||
|
||||
assert.sameValue(getReport(), TypeError);
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (C) 2018 Amal Hussein. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-atomics.wait
|
||||
description: >
|
||||
NaN timeout arg should result in an infinite timeout
|
||||
info: |
|
||||
Atomics.wait( typedArray, index, value, timeout )
|
||||
|
||||
4.Let q be ? ToNumber(timeout).
|
||||
...
|
||||
Undefined Return NaN.
|
||||
5.If q is NaN, let t be +∞, else let t be max(q, 0)
|
||||
features: [ Atomics, SharedArrayBuffer, TypedArray ]
|
||||
---*/
|
||||
|
||||
var NUMAGENT = 2; // Total number of agents started
|
||||
var WAKEUP = 0; // Index all agents are waiting on
|
||||
var WAKECOUNT = 2; // Total number of agents to wake up
|
||||
|
||||
function getReport() {
|
||||
var r;
|
||||
while ((r = $262.agent.getReport()) == null)
|
||||
$262.agent.sleep(100);
|
||||
return r;
|
||||
}
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab) {
|
||||
var int32Array = new Int32Array(sab);
|
||||
$262.agent.report("A " + Atomics.wait(int32Array, 0, 0, NaN)); // NaN => +Infinity
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab) {
|
||||
var int32Array = new Int32Array(sab);
|
||||
$262.agent.report("B " + Atomics.wait(int32Array, 0, 0)); // undefined => NaN => +Infinity
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
var int32Array = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
||||
|
||||
$262.agent.broadcast(int32Array.buffer);
|
||||
|
||||
$262.agent.sleep(500); // Ample time
|
||||
|
||||
assert.sameValue(Atomics.wake(int32Array, WAKEUP, WAKECOUNT), WAKECOUNT);
|
||||
|
||||
var sortedReports = [];
|
||||
for (var i = 0; i < NUMAGENT; i++) {
|
||||
sortedReports.push(getReport());
|
||||
}
|
||||
sortedReports.sort();
|
||||
|
||||
assert.sameValue(sortedReports[0], "A ok");
|
||||
assert.sameValue(sortedReports[1], "B ok");
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright (C) 2018 Amal Hussein. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-atomics.wait
|
||||
description: >
|
||||
Null or false timeout arg should result in an +0 timeout
|
||||
info: |
|
||||
Atomics.wait( typedArray, index, value, timeout )
|
||||
|
||||
4.Let q be ? ToNumber(timeout).
|
||||
...
|
||||
Null Return +0.
|
||||
Boolean If argument is true, return 1. If argument is false, return +0.
|
||||
features: [Atomics]
|
||||
includes: [atomicsHelper.js]
|
||||
---*/
|
||||
|
||||
var NUMREPORTS = 4; // Expected reports output from running agents
|
||||
|
||||
function getReport() {
|
||||
var r;
|
||||
while ((r = $262.agent.getReport()) == null)
|
||||
$262.agent.sleep(100);
|
||||
return r;
|
||||
}
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab) {
|
||||
var int32Array = new Int32Array(sab);
|
||||
var start = Date.now();
|
||||
$262.agent.report("A " + Atomics.wait(int32Array, 0, 0, null)); // null => +0
|
||||
$262.agent.report(Date.now() - start);
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab) {
|
||||
var int32Array = new Int32Array(sab);
|
||||
var start = Date.now();
|
||||
$262.agent.report("B " + Atomics.wait(int32Array, 0, 0, false)); // false => +0
|
||||
$262.agent.report(Date.now() - start);
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
var int32Array = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
||||
|
||||
$262.agent.broadcast(int32Array.buffer);
|
||||
|
||||
$262.agent.sleep(150);
|
||||
|
||||
|
||||
var sortedReports = [];
|
||||
for (var i = 0; i < NUMREPORTS; i++) {
|
||||
sortedReports.push(getReport());
|
||||
}
|
||||
sortedReports.sort();
|
||||
|
||||
assert.sameValue(sortedReports[2], 'A timed-out');
|
||||
assert.sameValue(sortedReports[3], 'B timed-out');
|
||||
assert(sortedReports[0] >= 0 && sortedReports[0] <= $ATOMICS_MAX_TIME_EPSILON, "timeout should be a min of 0ms and max of $ATOMICS_MAX_TIME_EPSILON");
|
||||
assert(sortedReports[1] >= 0 && sortedReports[1] <= $ATOMICS_MAX_TIME_EPSILON, "timeout should be a min of 0ms and max of $ATOMICS_MAX_TIME_EPSILON");
|
||||
|
||||
assert.sameValue(Atomics.wake(int32Array, 0), 0);
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (C) 2018 Amal Hussein. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-atomics.wait
|
||||
description: >
|
||||
Throws a TypeError if timeout arg is a Symbol
|
||||
info: |
|
||||
Atomics.wait( typedArray, index, value, timeout )
|
||||
|
||||
4.Let q be ? ToNumber(timeout).
|
||||
features: [Atomics, Symbol]
|
||||
---*/
|
||||
|
||||
var sab = new SharedArrayBuffer(4);
|
||||
var int32Array = new Int32Array(sab);
|
||||
|
||||
function getReport() {
|
||||
var r;
|
||||
while ((r = $262.agent.getReport()) == null) {
|
||||
$262.agent.sleep(100);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab) {
|
||||
var err;
|
||||
var s = Symbol();
|
||||
|
||||
try {
|
||||
Atomics.wait(int32Array, 0, 0, s);
|
||||
} catch(e) {
|
||||
err = e.constructor;
|
||||
}
|
||||
|
||||
$262.agent.report(err);
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
var int32Array = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
||||
|
||||
$262.agent.broadcast(int32Array.buffer);
|
||||
|
||||
assert.sameValue(getReport(), TypeError);
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (C) 2018 Amal Hussein. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-atomics.wait
|
||||
description: >
|
||||
True timeout arg should result in a timeout value of 1
|
||||
info: |
|
||||
Atomics.wait( typedArray, index, value, timeout )
|
||||
|
||||
4.Let q be ? ToNumber(timeout).
|
||||
...
|
||||
Boolean If argument is true, return 1. If argument is false, return +0.
|
||||
features: [ Atomics ]
|
||||
includes: [atomicsHelper.js]
|
||||
---*/
|
||||
|
||||
function getReport() {
|
||||
var r;
|
||||
while ((r = $262.agent.getReport()) == null)
|
||||
$262.agent.sleep(100);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab) {
|
||||
var int32Array = new Int32Array(sab);
|
||||
var start = Date.now();
|
||||
$262.agent.report(Atomics.wait(int32Array, 0, 0, true)); // true => 1
|
||||
$262.agent.report(Date.now() - start);
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
var int32Array = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
||||
|
||||
$262.agent.broadcast(int32Array.buffer);
|
||||
|
||||
$262.agent.sleep(2);
|
||||
|
||||
var r1 = getReport();
|
||||
|
||||
assert.sameValue(r1, "timed-out");
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (C) 2018 Amal Hussein. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-atomics.wait
|
||||
description: >
|
||||
Undefined timeout arg should result in an infinite timeout
|
||||
info: |
|
||||
Atomics.wait( typedArray, index, value, timeout )
|
||||
|
||||
4.Let q be ? ToNumber(timeout).
|
||||
...
|
||||
Undefined Return NaN.
|
||||
5.If q is NaN, let t be +∞, else let t be max(q, 0)
|
||||
features: [ Atomics, SharedArrayBuffer, TypedArray ]
|
||||
---*/
|
||||
|
||||
var NUMAGENT = 2; // Total number of agents started
|
||||
var WAKEUP = 0; // Index all agents are waiting on
|
||||
var WAKECOUNT = 2; // Total number of agents to wake up
|
||||
|
||||
function getReport() {
|
||||
var r;
|
||||
while ((r = $262.agent.getReport()) == null)
|
||||
$262.agent.sleep(100);
|
||||
return r;
|
||||
}
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab) {
|
||||
var int32Array = new Int32Array(sab);
|
||||
$262.agent.report("A " + Atomics.wait(int32Array, 0, 0, undefined)); // undefined => NaN => +Infinity
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
$262.agent.start(
|
||||
`
|
||||
$262.agent.receiveBroadcast(function (sab) {
|
||||
var int32Array = new Int32Array(sab);
|
||||
$262.agent.report("B " + Atomics.wait(int32Array, 0, 0)); // undefined timeout arg => NaN => +Infinity
|
||||
$262.agent.leaving();
|
||||
})
|
||||
`);
|
||||
|
||||
var int32Array = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
||||
|
||||
$262.agent.broadcast(int32Array.buffer);
|
||||
|
||||
$262.agent.sleep(500); // Ample time
|
||||
|
||||
assert.sameValue($262.agent.getReport(), null);
|
||||
|
||||
assert.sameValue(Atomics.wake(int32Array, WAKEUP, WAKECOUNT), WAKECOUNT);
|
||||
|
||||
var sortedReports = [];
|
||||
for (var i = 0; i < NUMAGENT; i++) {
|
||||
sortedReports.push(getReport());
|
||||
}
|
||||
sortedReports.sort();
|
||||
|
||||
assert.sameValue(sortedReports[0], "A ok");
|
||||
assert.sameValue(sortedReports[1], "B ok");
|
Loading…
Reference in New Issue